Documentation

Hardware & Servicing

The parts inside each laptop, how they wear, and how players service them.

Every laptop holds real parts, laid out like the Framework Laptop 13 under made-up brands: a mainboard with the processor soldered on and its cooler, two memory sockets, an M.2 SSD, an M.2 Wi-Fi card and a battery. Each part is an inventory item with its own model, serial and condition. What a laptop holds changes how it runs, and players swap, clean and re-paste parts in the service view.

#Parts & Items

There is one item per kind of part, and metadata.model names the exact model. The item names are under hardware.items in Config.

PartItemModels
Mainboardlaptop_mainboardOne per processor, see Boards. Carries its cooler in metadata.cooler
Coolerlaptop_coolerdual ZC-25D (two 5 mm heat pipes), wide ZC-10W (one 10 mm pipe), wide_pcm ZC-10P (one 10 mm pipe and a phase-change pad)
Memorylaptop_ramHalden DDR4-3200 d4_8, d4_16, d4_32 and DDR5-5600 d5_8, d5_16, d5_32, d5_48
SSDlaptop_ssdNordwell nv3_512gb, nv3_1tb (PCIe 3), nv4_512gb, nv4_1tb, nv4_2tb (PCIe 4), nv5_1tb, nv5_2tb (PCIe 5)
Wi-Fi cardlaptop_wifiKestrel Wireless kw6e, kw7 and Meridian mr6e, mr7, Wi-Fi 6E and 7
Batterylaptop_batteryTamsin zb55 (55 Wh) and zb61 (61 Wh)
ToolItemUse
Precision screwdriverlaptop_screwdriverOpens a laptop for service. Never used up
Thermal pastethermal_pasteRe-pastes the processor. 5 uses a tube. A tube with pcm = true in its metadata is a phase-change pad
Compressed aircompressed_airBlows the dust out of the fan. 10 uses a can

Uses left are kept in metadata.uses; an item without it is new, and it is gone after its last use. Digital Den sells parts and tools, see Shop.

#Boards

ModelsGenerationProcessors (cores / threads)SpeedMemoryCooler
kc11_k5, kc11_k7, kc11_k7hKestrel Talon 11K5-N210, K7-N230, K7-N250 (4 / 8)1.30, 1.22, 1.18DDR4dual
kc12_k5, kc12_k7, kc12_k7hKestrel Talon 12K5-P220, K7-P240 (12 / 16), K7-P260 (14 / 20)1.12, 1.06, 1.02DDR4dual
kc13_k5, kc13_k7, kc13_k7hKestrel Talon 13K5-Q340, K7-Q360 (12 / 16), K7-Q370 (14 / 20)1.08, 1.00, 0.96DDR4dual
av7_5, av7_7Arden Vela 4Vela 5 V460 (6 / 12), Vela 7 V480 (8 / 16)1.00, 0.92DDR5dual
ka1_5, ka1_7, ka1_7hKestrel Apex 1Apex 5 A510 (14 / 18), Apex 7 A550, Apex 7 A560 (16 / 22)0.95, 0.88, 0.86DDR5wide
ava_5, ava_7, ava_9Arden Vela AIVela AI 5 X540 (6 / 12), Vela AI 7 X550 (8 / 16), Vela AI 9 X570 (12 / 24)0.90, 0.84, 0.78DDR5wide_pcm

Speed multiplies every wait in the OS, so lower is faster. Memory has to be the board's type, and each board takes only its own cooler. Any SSD, Wi-Fi card or battery fits any board.

Conditions run from 0 to 1, where 1 is as new: wear on an SSD, health with cycles and charge on a battery, dust and paste on a cooler. A memory stick can carry a hidden fault that only shows once the stick is tested (tested).

#Where Parts Are Kept

The laptop item's metadata keeps them under hardware, next to serial, os, skin, finish and ports. Each slot holds the exact part item, {name, metadata}, so a part taken out later is the same item with the same metadata.

lua
hardware = {
    v = 1,
    board = {name = "laptop_mainboard", metadata = {model = "kc13_k7", serial = "MB-4F17-Q2K9", cooler = {model = "dual", dust = 0, paste = 1, pastedAt = 1791676800}}},
    ram0 = {name = "laptop_ram", metadata = {model = "d4_16", serial = "RM-8D2K-77QF"}},
    ram1 = {name = "laptop_ram", metadata = {model = "d4_16", serial = "RM-K4N2-XC9P"}},
    ssd = {name = "laptop_ssd", metadata = {model = "nv4_1tb", serial = "ZL-7Q2K-9F4M", wear = 0, os = "facade"}},
    wifi = {name = "laptop_wifi", metadata = {model = "kw6e"}},
    battery = {name = "laptop_battery", metadata = {model = "zb61", serial = "BT-3MZQ-6H2R", health = 1, cycles = 0, charge = 1}},
    leads = 2,
}

ram0 is the right socket, the one filled first. An empty slot is left out. leads is the number of Wi-Fi antenna leads plugged in. The SSD a laptop comes with has the laptop's own serial, and its os mirrors the item's. With item = false, the server's KVP keeps the hardware by the laptop's serial.

#What Parts Do

The server works all of this out from the hardware it reads; the client never reports any of it.

  • The drive is on the SSD. Drives are keyed by the installed SSD's serial: the OS, account, home folder, history, system log and Crowbar's timer go wherever the SSD goes, so a pulled drive can be read in another laptop. The laptop's own serial stays for traces, the VPN and GetLaptopSerial. A new SSD gets a blank drive the first time it boots, and an installer stick takes over. Without an SSD the boot menu leaves the internal drive out and installers refuse, but USB sticks still boot. See Operating Systems.
  • Speed. The processor, the memory, the SSD and the heat make one factor every wait in the OS is multiplied by, from 0.70 to 1.80. Under 16 GB of working memory is slower, 32 GB and 64 GB are a little faster, and one stick alone runs in single channel. NV3 drives are slower; the boards' M.2 slot is PCIe 4, so an NV5 runs at NV4 speed. An SSD past 90% wear is slower.
  • Heat comes from the cooler's dust and dried paste. Above 0.40 waits stretch up to 1.25 times, and above 0.75 up to 1.45 times. A board without its cooler shows a fan error and powers off.
  • Wi-Fi card. Without one the radio stays off and no hotspot can be joined, but the phone still tethers over USB. A Wi-Fi 7 card reaches hotspots 10% further and makes the Onion network and pages quicker. Antenna leads that are not plugged in cut the range, set by hardware.leads. See Wi-Fi & Browsing.
  • Battery. A laptop put down runs on mains and charges. One in the hands runs on its battery, or on a power bank plugged into it. The OS shows the real charge and health. A laptop without a battery only powers on while it is put down or on a power bank with charge, and picking it up turns it off.
  • needsBattery = false makes a laptop in the hands run as if plugged in: its battery never drains, a laptop without a battery still powers on, and a power bank in it is left alone.
  • What stops it. A laptop without a mainboard does nothing at all, and one without working memory stays black with its power light blinking. A notification tells the player which. Memory of the wrong type or a faulty stick does not count as working.

Memory that went in or came out is trained on the next power-on.

lua
hardware = {
    -- Hotspot range with 0, 1 or 2 of the Wi-Fi card's antenna leads plugged in, times the hotspot's own range
    leads = {[0] = 0.25, [1] = 0.6, [2] = 1.0},
    needsBattery = true,
},

#Wear

Parts wear by the server's clock. Powered hours count while an OS runs on the laptop; a laptop asleep in an inventory gathers no dust. Desktop computers never wear on their own.

PartHow it wearsSetting
Fan dustFills up over powered hours until fully cloggeddustHours = 40
Thermal pasteDries over real days, from new down to a floor. A phase-change pad dries three times slower; a PCM cooler re-pasted with plain paste dries at the paste ratepasteDays = 30, padDays = 90, pasteFloor = 0.3
SSDWears over the powered hours its model is rated for: NV3 300, NV4 500, NV5 600. At full wear it turns read-only—
BatteryDrains while the laptop is powered in the hands, and charges while it is put down. A worn battery runs out sooner. Health drops with each full cycle drained, never under the floorbatteryMinutes = 720, chargeMinutes = 20, healthPerCycle = 0.002, minHealth = 0.5
MemoryEach working stick may turn faulty, rarely. The fault shows once the stick is tested in the firmware's Setup (F2 while the laptop starts)ramFaultChance = 0.005 per 10 powered hours

A full battery at full health lasts 12 hours of use in the hands. A read-only SSD still boots, but the OS refuses to save settings, files, accounts and passwords.

When an SSD turns read-only or a memory stick turns faulty, the server event zyke_laptop:PartWornOut(serial, slotId) fires with the laptop's serial and "ssd", "ram0" or "ram1".

lua
hardware = {
    -- Parts CreatePartMetadata makes with used = true: a random condition, and memory that is faulty this often
    used = {minCondition = 0.55, maxCondition = 0.9, faultChance = 0.15},
    wear = {
        dustHours = 40,
        pasteDays = 30,
        padDays = 90,
        pasteFloor = 0.3,
        batteryMinutes = 720,
        chargeMinutes = 20,
        healthPerCycle = 0.002,
        minHealth = 0.5,
        ramFaultChance = 0.005,
    },
},

#Prebuilts

Laptops come as one of the prebuilts in shared/unlocked/hardware.lua, where you can change them or add your own. Every part gets its own serial when the laptop is made, and a board always comes with its cooler.

PrebuiltBoardMemorySSDWi-FiBattery
legacykc13_k72 x 16 GB DDR4NV4 1 TBkw6ezb61
basickc12_k51 x 8 GB DDR4NV3 512 GBkw6ezb55
standardkc13_k72 x 8 GB DDR4NV4 512 GBkw6ezb61
performanceav7_72 x 16 GB DDR5NV4 1 TBmr6ezb61
flagshipava_92 x 32 GB DDR5NV4 2 TBmr7zb61
diykc13_k5NoneNone, and no OSkw6ezb55
desktopkc13_k72 x 16 GB DDR4NV4 1 TBkw6eNone
lua
Config.Prebuilts = {
    basic = {board = "kc12_k5", ram = {"d4_8"}, ssd = "nv3_512gb", wifi = "kw6e", battery = "zb55"},
    -- Leave a part out for a laptop without it
    diy = {board = "kc13_k5", wifi = "kw6e", battery = "zb55"},
}
  • A laptop item given without metadata becomes hardware.default, basic, the first time it is taken out, with fresh serials.
  • desktop is the desktop computer's, set by computer.prebuilt. It runs on mains and has no battery.
  • The server prints a warning on start for a prebuilt with a model the catalogue doesn't have, or parts that don't fit together.

#Older Laptops

A laptop item from before hardware gets hardware.migrated, legacy, on its next take-out: the specs it always showed, its drive kept as the SSD, and its serial, OS, skin, finish and ports left as they were. The write is read back, and a failed one leaves the item as it was to try again next time. With item = false, each laptop gets the same the first time it is taken out.

#Service View

A player opens up a laptop they put down with Service in its options. Every OS on it has to be shut down, nobody else may be using or servicing it, and the player needs a laptop_screwdriver. Desktop computers can't be serviced.

  1. The lid closes and the laptop turns over. Hold E to loosen the seven bottom screws. Backspace cancels.
  2. The laptop turns upright and the input cover comes off. Point at a part, or press Tab to go through them, to outline it and see its name and condition. An empty slot shows a small marker.
  3. Use the keys for the part in focus, listed on screen. Each part that goes in or comes out shows a card at the side of the screen.
  4. Press Backspace to close up, then hold E to tighten the screws. Closing up seats a lifted cooler.
ActionKey
Loosen or tighten the bottom screwsHold E
Pick a partMouse
Next partTab
Take the part outE
Fit a part into an empty slotF, then pick from the parts carried that fit with 1–9
Lift the cooler off the processorE
Seat a lifted coolerF
Blow out the dust (cooler in place) or clean the fan (lifted)C
Re-paste the processor (cooler lifted or out)R
Connect the next Wi-Fi antenna leadL
Back, close up, or cancel before the cover is offBackspace or Escape
  • The mainboard comes out last, with its cooler, after the memory, SSD, Wi-Fi card and battery. Memory, the SSD, the Wi-Fi card and the cooler need a board to go into; the battery does not.
  • A cooler that goes in is set beside the laptop, lifted, and F seats it. Paste put on a bare processor goes under the next cooler that goes in.
  • Blowing out with the cooler in place takes blowOut of the dust; a lifted cooler is cleaned fully.
  • On a PCM cooler, re-pasting uses a phase-change pad if the player carries one, otherwise plain paste.
  • A Wi-Fi card goes in with its antenna leads unplugged, black first, then white. Closing up with a lead out warns once and goes ahead the second time.

The server checks and writes every step against the exact inventory slot as it happens, so a player who walks away, dies or leaves loses nothing, and the laptop is closed up as it is.

lua
hardware = {
    service = {
        enabled = true,
        -- Lets players service laptops they didn't put down, the CanServiceLaptop hook decides who
        others = false,
        -- Items the service view uses, false for no tool needed
        items = {tool = "laptop_screwdriver", paste = "thermal_paste", air = "compressed_air"},
        -- Uses in a new tube of paste and a new can of air
        pasteUses = 5,
        airUses = 10,
        -- Share of the fan's dust a blow-out takes with the cooler in place
        blowOut = 0.7,
    },
},

#Repair Shops

Only the character who put a laptop down may service it. Set service.others = true to let others, and edit CanServiceLaptop(plyId, ownerId) in server/unlocked/hooks.lua to decide who, for example a repair shop's job. CanInstallPart and CanRemovePart(plyId, ownerId, slotId, itemName, metadata) can keep parts from going in or coming out, in the service view and through the exports. Return false and a locale key to refuse. See Can-Check Hooks.

#For Developers

Server exports give and read laptops and parts:

ExportUse
CreateLaptopMetadataMetadata for a new laptop item built as a prebuilt, every serial new
CreatePartMetadataMetadata for a new part item, new, used or at a set condition, with the label and description ox_inventory shows
GetPartInfoWhat a part item is: kind, model, label, spec, condition, fault and the boards it fits
GetLaptopHardwareA copy of a laptop's hardware
SetLaptopHardwareSlotFits a part into, or takes it out of, a laptop item without the service view
RepairLaptopCleans the fan, re-pastes, or brings the battery back to full health
GetLaptopSpecsThe parts, heat and speed factor, worked out as for the OS
WearLaptopWears a laptop on top of its own wear, for a load such as mining
lua
local metadata = exports["zyke_laptop"]:CreateLaptopMetadata("performance", {finish = "midnight"})
exports.ox_inventory:AddItem(plyId, "laptop", 1, metadata)

local stick = exports["zyke_laptop"]:CreatePartMetadata("laptop_ram", "d5_16", {used = true})

The server events zyke_laptop:PartInstalled, zyke_laptop:PartRemoved, zyke_laptop:LaptopServiced and zyke_laptop:PartWornOut fire after a change is written. On the client, IsServicing tells whether the player has the service view open. See Exports & Events.