All work

Live

Item integrity and exploit hardening

Keeping player items safe on a live server: a zero-loss migration of every vehicle trunk, an equipment system that recovers stuck items, and fixes for the ways players were duplicating or teleporting items.

Role
Design and implementation, working solo
Stack
Lua (GLua), NutScript, MySQL
Context
Diverge Networks, a live roleplay server with a player-driven economy
Status
Live

The problem

On a roleplay server, items are the economy. A bug that loses an item costs a player hours of play, and a bug that duplicates one devalues everyone else’s. I owned the item layer end to end: moving player storage to a new model without losing anything, and closing the gaps players had found.

Migrating every trunk without losing an item

Each vehicle used to have its own trunk. They were replaced by one shared trunk per character, migrated automatically the first time each character loads after the update.

Trunk migration flow When a character loads, the shared trunk and overflow inventory are loaded. Items from each old trunk move one at a time into the shared trunk, or into overflow if it is full. A failed move puts the item back. Only after every item has moved does the vehicle's database row point at the shared trunk, and then the player is notified. Character loads Load the shared trunk and the overflowinventory, creating them if missing For each old vehicle trunk, move itemsone at a time, in sequence Fits: move it intothe shared trunk Full: move it to overflow,collected at the car dealer A move fails: put the item back, and leavethe vehicle on its old trunk for now Every item moved: update the vehicle'sdatabase row, then notify the player The database only changes once the last item is safe.
The migration runs automatically the first time each character loads after the update.

Video coming soon

A test character with items spread across several vehicle trunks loads in. The shared trunk opens with everything consolidated, then the lost-and-found at the car dealer shows the overflow.

assets/projects/item-integrity/trunk-migration.mp4 (20 to 30 seconds)

A character’s trunks consolidating on first load.

Screenshot coming soon

The shared 10 by 10 trunk inventory, partly filled.

assets/projects/item-integrity/shared-trunk.png (tight crop to the panel)

The shared trunk inventory.

Code excerpt coming soon

The item transfer with fallback and revert, and the migration that only updates the database once every item has moved.

assets/excerpts/trunk-migration.lua

Adapted from production code, lightly edited for readability.

The trade-off

Removing an item and adding it elsewhere isn’t one database transaction, so a server crash between the two steps could still lose that one item. The revert path and the migration log keep that window small and visible, and it was an acceptable risk for a one-time migration.

Equipment that can’t get lost

Equipping clothing moves an item out of the inventory grid into a hidden state. When something went wrong mid-way, items vanished. I rebuilt equipping and unequipping as one promise-based API used by every item type, and added a check on character load that finds items stuck in that hidden state, puts them back, and tells the player what happened.

Closing duplication and teleport exploits

Inventories that fit on the wire

Large inventories were overflowing network buffers when synced to players. I moved inventory and item sync to encoded, compressed payloads with an explicit length prefix.

Screenshot (optional) coming soon

A few lines from the migration log, with player names and IDs removed.

assets/projects/item-integrity/migration-log.png (crop to the relevant lines)

Each transfer is logged.