Documentation

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.

KeyDescription
idLaptops remember networks by it. Renaming one makes them forget it.
ssidThe name players see, the same in every language.
coordsWhere the router sits. Height counts too, so a rooftop can be out of reach of the street.
rangeMetres the signal reaches. The bars drop with the distance.
securedNeeds the password set in server/unlocked/hotspots.lua.
lua
Config.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.

lua
HotspotPasswords = {
    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.

lua
wifi = {
    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.

lua
local 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.

lua
AddEventHandler("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.

OSBrowserSearch engine
Facade 11 ProLedgeBling (bling.com)
LumenEmberfoxQuackQuackGo (quackquackgo.com)
SolaceSavannaQuackQuackGo (quackquackgo.com)
VeilVeil BrowserHush (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.
  • .onion sites 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. connection in the config sets how long connecting takes.
  • Veil sends everything through the Onion network, so Veil Browser opens nothing until it is connected.
  • check.onion tells 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:

TierHow
DirectNo protection.
VPNA 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.
OnionThe 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:

TierWhat is recorded
DirectThe character, the laptop's serial, the network it is online through and where the player stood.
VPNThe laptop's serial.
OnionNothing.

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:

lua
browsing = {
    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.

KeysAction
Ctrl+L, Alt+D, F6Select the address bar.
Ctrl+K, Ctrl+EEmpty the address bar for a search.
Ctrl+Enter in the address barComplete a name to www.<name>.com.
Escape in the address barPut the address back and return to the page.
Ctrl+TOpen a new tab.
Ctrl+W, Ctrl+F4Close the tab. Closing the last tab closes the window.
Ctrl+Shift+TReopen the last closed tab.
Ctrl+Tab, Ctrl+PageDownGo to the next tab.
Ctrl+Shift+Tab, Ctrl+PageUpGo 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+9Go to that tab, or the last one.
Ctrl+R, F5, Ctrl+Shift+R, Ctrl+F5, Shift+F5Reload the page.
Alt+Left / Alt+RightGo back / forward.
Alt+HomeOpen the home page in the tab.
Ctrl+DBookmark the page, or edit its bookmark.
Alt+F, Alt+EOpen the browser's menu.
Ctrl+Shift+W, Ctrl+Shift+Q, Ctrl+QClose the browser.
Ctrl+Shift+U, Ctrl+Shift+LVeil 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.