Wi-Fi & Browsing
Hotspots, phone tethering, tracing a player, the browsers, protection tiers and visit traces.
#Hotspots
The laptop needs a network to be online. Hotspots sit at real places on the map, such as the airport, cafés, shops, hospitals, police stations, bars and garages across Los Santos, Sandy Shores, Grapeseed and Paleto Bay. Out in the hills there are none. Settings lists the hotspots in range with their signal. The laptop rejoins the networks a character joined before, with their passwords, and when the player walks out of range it switches to the phone, or goes offline without one.
shared/unlocked/hotspots.lua lists the hotspots. It reaches every client, so it never holds a password.
| Key | Description |
|---|---|
id | Laptops remember networks by it. Renaming one makes them forget it. |
ssid | The name players see, the same in every language. |
coords | Where the router sits. Height counts too, so a rooftop can be out of reach of the street. |
range | Metres the signal reaches. The bars drop with the distance. |
secured | Needs the password set in server/unlocked/hotspots.lua. |
luaConfig.Hotspots = {
{id = "legion_square", ssid = "LS City Free WiFi", coords = vec3(215.09, -805.17, 30.81), range = 70.0, secured = false},
{id = "mission_row_pd", ssid = "LSPD-MissionRow", coords = vec3(425.1, -979.5, 30.7), range = 60.0, secured = true},
}
#Passwords
server/unlocked/hotspots.lua holds the passwords of the secured hotspots, by id, and never leaves the server. A secured hotspot without a password there, such as the FIB surveillance van or Fort Zancudo, can never be joined. Hand the passwords out in roleplay: a barista writing it on a cup, a job sharing its office's network, a contact selling it.
luaHotspotPasswords = {
mission_row_pd = "Pr0tect&Serve",
}
#Who May Join
The server checks every join: the hotspot exists, the laptop has a Wi-Fi card, the player is in range, the password matches, and CanJoinHotspot in server/unlocked/hooks.lua allows it. Return false and a locale key to keep a network for a job. See Can-Check Hooks.
lua---@param plyId integer
---@param hotspotId string @ Id from shared/unlocked/hotspots.lua
---@return boolean allowed
---@return string? reason
function CanJoinHotspot(plyId, hotspotId)
if (hotspotId == "mission_row_pd" and not Z.isJob(plyId, "police")) then return false, "wifi:cannotJoin" end
return true
end
#Phone Tether
The player's phone goes everywhere with them: the laptop tethers to it anywhere, under a name such as "Linus's Phone". It tethers over USB, so it works without a Wi-Fi card.
luawifi = {
phone = {
-- false keeps players online only at hotspots
enabled = true,
-- Item the player has to carry to tether, false for none
item = false,
},
},
#Wi-Fi Card & Antenna Leads
Hotspots need the laptop's Wi-Fi card. Without one the laptop only tethers to the phone. The card's generation and how many of its antenna leads are plugged in set how far hotspots reach. See What Parts Do.
#Tracing a Player
While a player has a laptop's OS on screen, their own or someone else's, the server knows which network it is online through. GetLaptopNetwork returns {kind, id, ssid, coords}: kind is "phone" or "hotspot", and coords is where the traffic comes from, the hotspot's location or the player's own position for their phone. A police trace or an alert therefore lands on the café, not on the player.
lualocal network = exports["zyke_laptop"]:GetLaptopNetwork(plyId)
if (not network) then return end -- No laptop on screen, or offline
alertPolice(network.coords, ("Suspicious traffic on %s"):format(network.ssid))
It returns nil when the player has no laptop on screen or is offline, and checks the network again on every call: a laptop that left a hotspot's range counts as on the phone, or offline without one. A page that needs the internet can refuse players without a connection.
The server event zyke_laptop:NetworkChanged(plyId, network) fires with the player's new network, nil when they closed the screen, went offline or left the server.
luaAddEventHandler("zyke_laptop:NetworkChanged", function(plyId, network)
if (not network) then return end
-- Where each player last went online from, for a trace later
lastUplinks[plyId] = {ssid = network.ssid, coords = network.coords, at = os.time()}
end)
Facade, Lumen and Solace booted from the drive also write every network they join to the drive's system log.
#Browsers
Every OS ships its own browser, with its own default search engine.
| OS | Browser | Search engine |
|---|---|---|
| Facade 11 Pro | Ledge | Bling (bling.com) |
| Lumen | Emberfox | QuackQuackGo (quackquackgo.com) |
| Solace | Savanna | QuackQuackGo (quackquackgo.com) |
| Veil | Veil Browser | Hush (hush.onion) |
Sites are either ordinary clearnet addresses, such as bling.com, or .onion addresses.
- On Facade, Lumen and Solace, clearnet sites open over the laptop's Wi-Fi or phone. Bling and QuackQuackGo list the clearnet sites, built in and registered, and leave onion sites to Hush.
.onionsites need the Onion network on every OS. Without it the browser explains that the address is an onion site and links Onion Connection, the app that connects. On Facade, Lumen and Solace it is downloaded from the app store first.connectionin the config sets how long connecting takes.- Veil sends everything through the Onion network, so Veil Browser opens nothing until it is connected.
check.oniontells the player whether their traffic goes through the Onion network.
#Directories
LS Pages, at lspages.com, is the directory of the public web: every listed clearnet site, built in and registered, grouped by category, with a search field. It follows the registry while it is open, so a site appears as soon as its resource registers it, marked as new, and disappears when the resource stops. Onion sites are never listed there; the Onion Directory at directory.onion lists those.
The new tab page of Ledge, Emberfox and Savanna has a tile for up to eleven registered clearnet sites, and one for LS Pages with all of them. Veil Browser's new tab page links only onion sites. In Bling and QuackQuackGo, a result shows its category after the address, which opens that section of LS Pages.
To add your own sites, see Apps & Sites.
#Protection Tiers
Protection is optional on Facade, Lumen and Solace and comes in three tiers, shown in the address bar and in the site information:
| Tier | How |
|---|---|
| Direct | No protection. |
| VPN | A one-click toggle in Facade's quick settings, Lumen's system menu, Solace's Quick Controls and the browser's menu. It needs the laptop online, connects in a moment and shows a shield while it is on. The server keeps it, tied to that laptop and OS, and drops it when the OS powers off. |
| Onion | The Onion connection. It also covers clearnet sites while it is up. |
Veil is always onion and has no VPN. GetBrowsingTier returns a player's tier on the server.
#Visit Traces
When a player opens a monitored site, the server records what their tier leaves behind. Players never see traces. By default:
| Tier | What is recorded |
|---|---|
| Direct | The character, the laptop's serial, the network it is online through and where the player stood. |
| VPN | The laptop's serial. |
| Onion | Nothing. |
The tier is worked out on the server: Veil is always onion, the VPN is the one the server keeps, and the Onion connection the OS reports only counts while the server sees the laptop online. The visit itself is reported by the player's client, so treat traces as roleplay evidence, not proof.
browsing in the config:
luabrowsing = {
vpn = {
-- false removes the VPN for the whole server
enabled = true,
-- Milliseconds the VPN takes to connect
connectDuration = 2500,
},
-- "monitored" records only monitored sites, "all" every site a player opens
record = "monitored",
-- Addresses recorded with record = "monitored", such as "lifeinvader.com"
monitored = {},
-- Days traces are kept, older ones are deleted on start and once a day
retentionDays = 14,
-- Visits a player may report per window, the rest are not recorded
rateLimit = {count = 20, seconds = 10},
-- What the server records about a visit, by tier
traces = {
direct = {"character", "serial", "network", "coords"},
vpn = {"serial"},
onion = {},
},
},
A site is monitored when it is in monitored, registered with monitored = true, or marked with SetSiteMonitored. Police or hacker resources read traces with GetSiteVisitTraces, and the server event zyke_laptop:SiteVisited(host, url, trace) passes each one as it is recorded. The serial in a trace leads to the laptop's owner, see For Police Resources.
The zyke_laptop_site_visits table is created on start.
#Keyboard Shortcuts
Every browser takes Google Chrome's Windows and Linux shortcuts, as far as it has the feature. They act only in the focused browser window, also while the focus is in the address bar or a page's text field, and leave text editing keys such as Ctrl+A, Ctrl+C and Ctrl+Z alone. The menus show them next to their entries.
| Keys | Action |
|---|---|
| Ctrl+L, Alt+D, F6 | Select the address bar. |
| Ctrl+K, Ctrl+E | Empty the address bar for a search. |
| Ctrl+Enter in the address bar | Complete a name to www.<name>.com. |
| Escape in the address bar | Put the address back and return to the page. |
| Ctrl+T | Open a new tab. |
| Ctrl+W, Ctrl+F4 | Close the tab. Closing the last tab closes the window. |
| Ctrl+Shift+T | Reopen the last closed tab. |
| Ctrl+Tab, Ctrl+PageDown | Go to the next tab. |
| Ctrl+Shift+Tab, Ctrl+PageUp | Go to the previous tab. |
| Ctrl+Shift+] / Ctrl+Shift+[ | Solace only: next / previous tab, as Solace's app switcher takes Ctrl+Tab. |
| Ctrl+1 to Ctrl+8, Ctrl+9 | Go to that tab, or the last one. |
| Ctrl+R, F5, Ctrl+Shift+R, Ctrl+F5, Shift+F5 | Reload the page. |
| Alt+Left / Alt+Right | Go back / forward. |
| Alt+Home | Open the home page in the tab. |
| Ctrl+D | Bookmark the page, or edit its bookmark. |
| Alt+F, Alt+E | Open the browser's menu. |
| Ctrl+Shift+W, Ctrl+Shift+Q, Ctrl+Q | Close the browser. |
| Ctrl+Shift+U, Ctrl+Shift+L | Veil Browser only: New Identity and New Circuit for this Site. |
Keys pressed inside a registered site go to its own page first. With the JavaScript SDK included, the page passes these shortcuts on to the browser; a page without it keeps them to itself.