Sandkit surface map

Everything a Sandustry mod can reach, extracted from the game's own mod bridge rather than transcribed by hand — plus the things it cannot reach, which is the half that usually costs a weekend.

apiVersion 1 main 281 methods worker 88 methods d.ts drift 0 regenerate →

How this was built

Not from the community type definitions, and not from memory. The game ships dist/js/external-mod-runtime.js and external-mod-worker-runtime.js — the bridges that every mod call actually passes through. Those files are the API.

  1. Extract both runtimes from app.asar and parse each namespace group out of the minified source, resolving variable references to their nearest preceding definition.
  2. Record, for every method, its argument count and the engine function it delegates to — the third column in the reference tables below.
  3. Diff the result against a sandkit.d.ts, in both directions.
Result: the community sandkit.d.ts is accurate. 281 main methods and 88 worker methods line up, with no phantom entries in either direction. The one omission is constants (constants.physicsnormal, skip, aggressiveSkip), which the type file does not declare.

The whole pipeline is three commands against your own install, so this page can be regenerated for any build rather than trusted as a snapshot.

Anatomy of a mod

Four surfaces, declared in modinfo.json. Most mods use one; the ones that feel like new game content use three.

entry main.js

Runs on the render thread. Registration, UI, energy, tech, settings, persistence.

Compiled with new Function("__sandkit", …) inside an async IIFE: top-level await works, import and export throw and the entry silently never runs.

workerEntry worker.js

Runs on every simulation thread. The only place that sees individual particles move.

Same wrapper, much smaller API: no settings, no timers, no real UI.

patches.json string patching

Up to 256 patches per mod against any .js under the game's js/ — including bundle.js and simulation-worker.js.

expectedMatches is mandatory, and patches can be grouped so the group rolls back atomically if one member misses.

manifest

dependencies is resolved with a real topological sort with cycle detection; loadOrder breaks ties.

That makes a library mod a supported pattern: publish it, have other mods name it, and load order is guaranteed.

Main vs worker

The single most important distinction in this API, and the one that decides where your code has to live.

Main entryWorker entry
Sees an element movenoyes
Reads mod settingsyesno
Draws UIyestoasts only
Registers structures, tech, energyyesno
Repeating timerstriggersno
Talks to the other sideshared buffersmain.emitEvent
There is no main → worker messaging. Worker → main is a normal event via main.emitEvent, and custom payloads pass through unmapped. The other direction has exactly one channel: a SharedArrayBuffer. The main entry calls shared.buffers.create at top level, the worker calls require on the same key — keys are namespaced per mod on both sides, and main entries always load first. That byte is how a worker learns whether your mod is switched on.

What can I build?

Read this column first. It is the question people actually arrive with.

main threadsimulation workernot in the API
I want to…VerdictHow
Add a new machinesupportedstructures.register plus sprites.loadFromMod. Render size is in pixels at 4 px per cell, so a 16×16 sprite is a 4×4-cell machine. Passing plain name and description strings auto-registers the translation keys.
Make it generate or use powersupportedenergy.registerType(id, "conductor" | "storage"), then addAtCell and consume. Conductors produce into the grid and store nothing themselves.
React to a single particlesupportedWorker only. events.on("element:moved", …) with a guard.
Add a new element or terrainsupportedelements.register and terrains.register. Both hand out numeric type ids as max + 1, which is the drift trap below.
Add a tech-tree nodesupportedtech.registerNode(id, def, { parentId }). Auto-places in the first free slot under the parent; throws on a duplicate id, a missing parent, or a full row.
Add recipes to existing machinessupportedstructures.recipes.register covers the planter box, shaker, kinetic press, condenser, steam dryer, synthesizer, snowmaker and smelter.
Configure a machine as it is placedsupportedstructures.registerPlacementConfig. Values land in structure.data; labels need translation keys for now.
Open a panel on a machine already standingno APIThe vanilla Filter and Sound Box panels are opened by hardcoded structure-id checks hanging off the building session, and no event carries “the player interacted with this structure”. Reachable only by patching.
Draw your own HUDwith careui.overlays.register or ui.inject. The global slot draws over the main menu too — gate on scene.getActive().
Persist data in the savesupportedstorage.get and storage.set, keyed by mod id. storage.local is machine-local instead.
Veto or rewrite an engine callsupportedhooks.intercept to cancel, hooks.modify to rewrite arguments. Available on both threads.
Read or write files, open socketsno APINothing in the surface touches Node. This is the line a third-party loader crosses and a Workshop mod does not.
Run code before the game bootsno APIEntries run during world initialisation, once per process.

Hard limits

Verified in the shipped code, not inferred from silence. These are the ones that change a design.

Entries run once per process

The runtime keeps a set of loaded ids and reports alreadyLoaded on a second world load. Anything skipped because a setting was off stays skipped until the game restarts — so gate behaviour, never registration.

Registration is one-way

energy.registerType, structures.register, addProcessor and event subscriptions cannot be undone at runtime, and addProcessor throws if the structure already has periodic processing.

Uninstalling strands buildings

Mod structures are saved under their string id. Remove the mod and the save keeps entries whose type nothing recognises, which fall back to a plain 4×4 block.

Element type ids drift

Element and matter numbers are handed out as max + 1 at registration, and nothing lets a mod pin its own. Add or remove a type and every number after it shifts while the save still holds the old ones. Structures escape this: their ids are strings, and the numeric block grid is rebuilt from the structure list on load.

Some worker events demand a guard

element:moved and terrain:update throw without one, and the guard must carry exactly one of elementType or terrainType. The simulation only emits these at all when a handler for that type exists.

The engine escape hatch is unversioned

sandkit.engine.api exposes the internal engine and is explicitly not covered by apiVersion — it can change in any patch.

Events & hooks

Ids found in the shipped bundle (45 in total). Payloads for a handful are remapped into a frozen shape for mods; anything the game does not recognise passes through untouched, which is what makes worker → main custom events work.

Lifecycle & world

game:readygame:startedscene:started:gamemods:initializedframe:renderframe:updatetech:unlockedtech:mapUnlockedtutorial:stepChangedtutorial:completedearlyAccess:completestratacore:secured

Building & structures

building:placebuilding:placedbuilding:removedbuilding:blockedbuilding:clearShape

Simulation (worker)

element:movedelement:moveelement:updateelement:blockedelement:durationelement:createdAtelement:removedAtcell:processterrain:updateterrain:destroyed

Player, input & projectiles

player:movedplayer:movementplayer:collision:prepareplayer:position:commitinput:keydowninput:keyupinput:scrollinput:escapeprojectile:hitprojectile:fire:overStructureprojectile:fire:emitOnElementprojectile:travel:prepareprojectile:impact:prepare

Resources & rendering

resource:collectedresource:collection:prepareresource:delivery:prepareworldItem:pickedUprender:pipes

Outlined: a guard is required, or the subscription throws.

Hooks

hooks.intercept cancels an engine call before it happens; hooks.modify rewrites its arguments. The ids are a whitelist kept as a literal in the bundle — these are all of them, not a sample. Some ids appear in the event list too: the event fires after the fact and can only watch, the hook runs first and gets a vote.

Interceptors — cancel the call (18)

action:interceptbuilding:clearShapebuilding:placefire:element:igniteinput:boost-downinput:descend-downinput:escapeinput:keydowninput:keyupinput:scrollinteractable:suppressHoverplacePoints:directionalArrows:isSuppressedplacePoints:isSuppressedplayer:position:commitprogression:purchaseprojectile:fire:overStructureprojectile:hitteleport:effect

Modifiers — rewrite the arguments (15)

building:placement-limitexcavation:prepareflux-emanator:processingplayer:collision:prepareplayer:movementprogression:cost:prepareprojectile:impact:prepareprojectile:travel:preparerender:pipesresource:collection:prepareresource:delivery:preparestructures:moved:preparestructures:removed:preparetrigger:schedule:prepareweapon:reload:prepare

Outlined ids accept a guard option, so a handler can subscribe to only its own structure, weapon or projectile types instead of filtering every call by hand:

hookguard optionmatched against
building:placestructureTypesstructureId
weapon:reload:prepareweaponIdsweaponId
projectile:travel:prepareprojectileTypesprojectileType
projectile:impact:prepareprojectileTypesprojectileType
trigger:schedule:preparetriggerIdstriggerId
resource:collection:prepareresourceIdsresourceId
resource:delivery:prepareresourceIdsresourceId
This is the mechanism behind “no API for that” workarounds. Intercepting input:keydown beats a DOM listener — it sits in the game's own input chain, in order, with a cancel() the game respects. building:place can veto a placement a mod considers invalid, which no event can.

Patching the game

The part most people miss: a plain Workshop mod can already rewrite the game bundle. No loader, no installer, no touching app.asar.

Scope

Any .js under the game's js/. Absolute paths, .. segments and drive letters are rejected.

Discipline

expectedMatches must be a positive integer and the patch is refused if the real count differs — so a game update breaks your mod loudly.

Atomicity

Patches sharing an atomicGroup stage together. One miss rolls the whole group back and marks the rest skipped.

The engine reports every patch resultapplied, actualMatches and a reason such as atomic_group_rolled_back — and shows the player none of it. That gap is a mod waiting to be written.

Main API 281 methods

Sorted by size. Open a namespace for its methods, argument count, and the engine function behind each one.

structuresRegister machines, patch existing ones, query and mutate what is built.31
methodargsengine call
recipes.register
processing.register2structures.processing.register
processing.isEnabledAt2structures.processing.isEnabledAt
processing.setEnabledAt3structures.processing.setEnabledAt
addProcessor2structures.addProcessor
register2structures.register
updateDefinition3structures.updateDefinition
addVariant3structures.addVariant
forEachOfType2structures.forEachOfType
registerPlacementConfig1structures.registerPlacementConfig
getAtCell2structures.getAtCell
getDefinitionByType1structures.getConfig
getUnlockedTypes0structures.getUnlockedTypes
getTypeFromId1structures.resolveTypeName
hasBuiltAtCell2structures.hasBuiltAtCell
isBlockedByPlayerAtCell2structures.isBlockedByPlayer
isLauncherAtCell2structures.isLauncherAt
isType2structures.isType
isTypeAtCell3structures.isTypeAt
isUnlockedByType1structures.isUnlocked
mapValueToSpritesheetIndexstructures.mapValueToSpritesheetIndex
setSpritesheetIndex2structures.setSpritesheetIndex
setSpritesheetIndexAtCell3structures.setSpritesheetIndexAt
setSpritesheetIndexByValue3structures.setSpritesheetIndexByValue
setSpritesheetIndexByValueAtCell4structures.setSpritesheetIndexByValueAt
update2structures.update
setData3structures.setData
buildAtCellWhenIdle4world.runWhenSimulationIdle, structures.build
removeAtCellWhenIdle3world.runWhenSimulationIdle, structures.removeAt
removeBetweenCellsWhenIdle5world.runWhenSimulationIdle, structures.removeBetween
removeAtCellsWhenIdle2world.runWhenSimulationIdle, structures.removeAtPositions
elementsRegister sand, liquid and gas types; read and write individual cells.29
methodargsengine call
getRegisteredTypes0elements.getRegisteredTypes
register1elements.register
updateDefinition2elements.updateDefinition
addInteractionInfo2elements.addInteractionInfo
getTypeFromId1elements.getElementTypeFromId
getNameByType1elements.getName
getDefinitionByType1elements.getConfig
getTypeAtCell2elements.getTypeAtCell
getResolvedTypeAtCell2elements.getResolvedTypeAtCell
getResolvedTypeFromCellId1elements.getResolvedTypeFromCellId
getInfoAtCell2elements.getInfoAtCell
getMatterTypeAtCell2elements.getMatterTypeAtCell
isTypeAtCell3elements.isTypeAt
isFreeFallingAtCell2elements.getResolvedTypeAtCell, elements.isFreeFalling
findFreeCellInStructure3elements.findFreePositionInStructure
createAtCellWhenIdle4world.isCellEmpty, elements.createAt
replaceAtCellWhenIdle4world.getCellId, world.mutateCellWhenIdle, elements.replaceAt
removeAtCellWhenIdle3elements.getResolvedTypeAtCell, elements.removeAt
teleportBetweenCellsWhenIdle4world.getCellId, world.runWhenSimulationIdle, elements.moveAtSimulationIdle
getVelocityAtCell2elements.getResolvedTypeAtCell, elements.getVelocity
setVelocityAtCellWhenIdle3elements.setVelocity
addParticleVelocityAtCellWhenIdle4elements.addParticleVelocity
convertToParticleAtCellWhenIdle3elements.convertToParticle
convertFromParticleAtCellWhenIdle2elements.convertFromParticle
getDataFieldAtCell3elements.getResolvedTypeAtCell, elements.getDataField
setDataFieldAtCellWhenIdle4elements.getResolvedTypeAtCell, elements.setDataField
refreshColorAtCellWhenIdle2elements.refreshColorAt
setPhysicsAtCellWhenIdle3elements.getResolvedTypeAtCell, elements.setPhysics, world.reportActivityToChunk
setDurationAtCellWhenIdle4elements.getResolvedTypeAtCell, elements.setDuration
i18nTranslation keys, locale switching, number formatting.17
methodargsengine call
ti18n.t
registeri18n.register
getLocalei18n.getLocale
hasTranslationi18n.hasTranslation
setLocalei18n.setLocale
getLanguagesi18n.getLanguages
getAvailableLocalesi18n.getAvailableLocales
formatNumberi18n.formatNumber
keyi18n.key
getNamei18n.getName
getDescriptioni18n.getDescription
translatablei18n.translatable
setGlobali18n.setGlobal
getGlobali18n.getGlobal
clearGlobali18n.clearGlobal
getGlobalsi18n.getGlobals
formatKeyForDisplayi18n.formatKeyForDisplay
uiReact injection, overlay slots, toasts, dialogs, controller focus.14
methodargsengine call
update2ui.update
openPauseMenu0ui.openPauseMenu
showTooltip1ui.showTooltip
toast2ui.toast
alert2ui.alert
confirm2ui.confirm
prompt5ui.prompt
overlays.register3ui.overlays.register
overlays.unregister2ui.overlays.unregister
overlays.update1ui.overlays.update
inject2ui.overlays.register, ui.overlays.unregister
navigation.useFocusable
navigation.useFocusScope
navigation.controllerFocusClass
terrainsRegister terrain; read and damage the terrain layer.13
methodargsengine call
register1terrains.register
updateDefinition2terrains.updateDefinition
getTypeFromId1terrains.getTypeByName
getTypeAtCell2terrains.getTypeAtCell
getDataAtCell2terrains.getTerrainData
isAtCell2terrains.isAtCell
isTypeAtCell3terrains.isTypeAtCell
isCellIdTerrainterrains.isCellIdTerrain
createAtCellWhenIdle4world.isCellEmpty, terrains.createAt
replaceAtCellWhenIdle4world.getCellId, world.mutateCellWhenIdle, terrains.replaceAt
removeAtCellWhenIdle3world.getCellId, terrains.isCellIdTerrain, terrains.removeAt
damageAtCell3terrains.damageTerrain
setHpAtCellWhenIdle3terrains.isAtCell, terrains.setTerrainHP
worldCell ids, fog, excavation, dropped world items.13
methodargsengine call
getCellIdAtCell2world.getCellId
isCellEmptyAtCell2world.isCellEmpty
isTerrainAtCell2world.isTerrainAt
runWhenSimulationIdle1world.runWhenSimulationIdle
reportActivityAtCell2world.reportActivityToChunk
excavateAtCell5world.excavate
revealFogAtCell2world.revealFogAtCell
redrawAroundCellWhenIdle3world.mutateCellWhenIdle, world.redrawSurroundingCells
pickups.spawnAtWorld5world.pickups.spawn
pickups.destroy1world.pickups.destroy
pickups.pickUp1world.pickups.pickUp
pickups.getAll0world.pickups.getAll
pickups.getById1world.pickups.getById
playerPosition, movement, inventory, unlocked buildings.12
methodargsengine call
getWorldPosition0player.getPosition
setWorldPosition2player.setPosition
setVelocity2player.setVelocity
setMovementSpeedMultiplier1player.setMovementSpeedMultiplier
setMovementMode1player.setMovementMode
isOnGround0player.isOnGround
teleportToGround0player.teleportToGround
isCollidingWithCell2player.isCollidingWithCell
isWithinRadiusOfCell3player.isWithinRadius
isWorldPositionClear2player.isPositionClear
inventory.addFromId1player.inventory.add
buildings.unlockByType1player.buildings.add
inputKey bindings, mouse cell position, modifier state.10
methodargsengine call
registerBinding3input.registerKeyBinding
getMouseCellPosition0input.getMouseCellPosition
getBoundKeys1input.getBoundKeys
getDisplayKey2input.getDisplayKey
triggerBinding1input.triggerBinding
pressBinding1input.pressBinding
releaseBinding1input.releaseBinding
resetMouseState0input.resetMouseState
isCtrlHeld0input.isCtrlHeld
isAltHeld0input.isAltHeld
projectilesRegister and spawn projectiles.7
methodargsengine call
register1projectiles.register
getDefinitionById1
createBlueprintFromId1projectiles.createBlueprint
getAll0projectiles.getAll
getById1projectiles.getAll
remove1projectiles.remove
spawnAtWorld4projectiles.spawn
soundPlay sounds, layered audio, distance falloff.7
methodargsengine call
play2sound.play
playActive2sound.playActive
playLayers2sound.playLayers
calculateDistanceOptionsAtWorld3sound.calculateDistanceOptions
stopById1sound.stop
stopActive0sound.stopActive
stopAll0sound.stopAll
storagePer-mod persistence — in the save, or machine-local.7
methodargsengine call
ensure1storage.ensure
get2storage.get
set3storage.set
remove2storage.remove
local.getstorage.local.get
local.setstorage.local.set
local.removestorage.local.remove
authorizationWhether the player may build, dig or use tools at a cell.6
methodargsengine call
canBuildAtCell2authorization.canBuild
canGrabAtCell2authorization.canGrab
canUseTool2authorization.canUseTool
canUseToolAtCell3authorization.canUseToolAt
getZoneIdAtCell2authorization.getZoneIdAt
getPlayerZoneId0authorization.getPlayerZoneId
effectsParticles, temporary lights, lasers, distortion waves.6
methodargsengine call
createDistortionWaveAtWorld3effects.createDistortionWave
createEffectAtWorld4effects.createEffect
createLaserAtWorld5effects.createLaser
createLightAtWorld3effects.createLight
createParticlesAtWorld3effects.createParticles
removeLightById1effects.removeLight
energyJoin the power grid, produce and consume energy.6
methodargsengine call
registerType3energy.registerType
addAtCell4energy.add
consume2energy.consume
consumeExcludingNetworkAtCell3energy.consumeExcludingNetwork
getNetworkAtCell2energy.getNetwork
getNetworkFreeCapacityAtCell2energy.getNetworkFreeCapacity
itemsRegister inventory items and tools.6
methodargsengine call
register1items.register
updateDefinition2items.updateDefinition
getDefinitionById1
createFromId1items.create
getActive0items.getActive
isActiveById2items.isActive
lightsTemporary VFX lights and persistent world lights.6
methodargsengine call
vfx.createAtWorld
vfx.removeById
persistent.createAtWorld3lights.persistent.create
persistent.removeAtWorld2lights.persistent.removeAt
persistent.fadeAtWorld3lights.persistent.fadeAt
persistent.markDirty0lights.persistent.markDirty
techRead, patch and add tech-tree nodes.6
methodargsengine call
getDefinitionByIdtech.getDefinition
updateDefinitiontech.updateDefinition
addDefinitiontech.addDefinition
registerNodetech.registerNode
isLockedById1tech.isLocked
setLockedById2tech.setLocked
collectorGold value of cells and pickup notification.5
methodargsengine call
getValueFromCellId1collector.getValueFromCellId
getValueByType1collector.getValueFromElementType
isCellIdCollectable1collector.isCellCollectable
isCellIdCollectableForSprite1collector.isCellCollectableForSprite
notifyPickupAtCell2collector.notifyPickup
spritesLoad textures, including from the mod's own folder.5
methodargsengine call
load3sprites.load
loadFromMod3sprites.load
getById1sprites.get
hideAllPlayerModSprites0sprites.hideAllPlayerModSprites
rotatePlayerModSprites1sprites.rotatePlayerModSprites
upgradesRegister upgrade categories and levels.5
methodargsengine call
registerCategory1upgrades.registerCategory
register1upgrades.register
updateDefinition3upgrades.updateDefinition
getLevelById2upgrades.getLevel
getAvailableLevelById2upgrades.getAvailableLevel
buildingPlacement snapping, blocking, structure selection.4
methodargsengine call
getSnappedPositionAtCell2building.getSnappedCellPosition
isBlockedAtCell2building.isBlockedByTerrainOrElements
cancelPlacement0building.cancelPlacement
selectStructure1building.selectStructure
renderingDraw positions, grid metrics, overlay context, shaders.4
methodargsengine call
getDrawPositionAtCell2rendering.getCellDrawPos
getGridMetrics0rendering.getGridMetrics
getOverlayViewportSize0rendering.getOverlayViewportSize
withOverlayContext1rendering.withOverlayContext
toolsGrabber size and state.4
methodargsengine call
grabber.setSize1tools.setGrabberSize
grabber.getSize0tools.getGrabberSize
grabber.isActive0tools.isGrabberActive
grabber.isLoaded0tools.isGrabberLoaded
utilsDistance, direction, angle, line between points.4
methodargsengine call
getDistanceutils.getDistance
getDirectionutils.getDirection
getAngleutils.getAngle
getCoordinatesBetweenPointsutils.getCoordinatesBetweenPoints
actionThe active and selected action, and its custom data.3
methodargsengine call
getActive0action.getActive
getSelected0action.getSelected
setCustomData1action.setCustomData
assetsAsset URLs and provider selection.3
methodargsengine call
getUrl1(local) x.o
getSelectedProvider1(local) L.Ob
selectProvider2(local) L.jq
cameraFocus and follow.3
methodargsengine call
snapToPlayer0camera.snapToPlayer
setFocusAtWorld2camera.setFocusAtWorld
releaseFocus1camera.releaseFocusToPlayer
mapsActive and available maps; starting a map.3
methodargsengine call
getActive0maps.getActive
getAvailable0maps.getAvailable
start1maps.start
processingRecipes for growers, shakers and the kinetic press.3
methodargsengine call
registerGrower1
registerShaker1
registerKineticPress1
settingsThis mod's own config values and change notifications.3
methodargsengine call
get1
getAll0(local) W.FG
onChange1
cooldownShared cooldown timers.2
methodargsengine call
check2cooldown.check
isReady2cooldown.isReady
discoveriesWhat the player has discovered.2
methodargsengine call
addElementByType1discoveries.addElement
addTerrainByType1discoveries.addTerrain
eventsSubscribe to and emit game events.2
methodargsengine call
on2events.on
emit2events.emit
fireWhether a cell burns, and setting it burning.2
methodargsengine call
canBurnElementAtCell2fire.canBurnElementAt
burnElementAtCellWhenIdle2fire.canBurnElementAt, fire.burnElementAt
gameConfigRead the game's config values.2
methodargsengine call
get1(local) D.nO
getAll0(local) D.dx
gridIterate cells in a rect or circle.2
methodargsengine call
forEachCellInRect5grid.iterateRect
forEachCellInCircle4grid.iterateCircle
hooksIntercept (veto) or modify engine calls.2
methodargsengine call
intercept3hooks.intercept
modify3hooks.modify
patternsCircle patterns and pattern excavation.2
methodargsengine call
createCirclepatterns.createCircle
excavateAtCell6patterns.excavate
randomSeeded integers and floats.2
methodargsengine call
intrandom.int
floatrandom.float
resourcesResource amounts.2
methodargsengine call
collectFluxiteAtCell2resources.collectFluxiteAtCell
updateEnergy2resources.updateEnergy
sharedSharedArrayBuffers — the only main-to-worker channel.2
methodargsengine call
buffers.create2workers.shared.create
buffers.get1workers.shared.get
structureBehaviorsTurn a structure into a conveyor or a launcher.2
methodargsengine call
registerConveyorType2conveyors.registerType
registerLauncherType1launchers.registerType
timeMilliseconds and tick count.2
methodargsengine call
getTimeMs0
getTick0
excavationRegister excavation profiles.1
methodargsengine call
registerProfile2excavation.registerProfile
modsAsset providers from other mods.1
methodargsengine call
getProviders1(local) L.KT
progressionComplete progression steps.1
methodargsengine call
complete1progression.complete
raycastCast a ray through the world.1
methodargsengine call
castFromWorld4raycast.cast
reactionsRegister element reactions.1
methodargsengine call
registerContact1reactions.registerContact
sceneWhich screen is active. MainMenu 1, Intro 2, Deploy 3, Game 4.1
methodargsengine call
getActive0scene.getActive
scheduleDeferred callbacks.1
methodargsengine call
nextTick1schedule.nextTick
signalsRegister a structure as a signal target.1
methodargsengine call
targets.register2signals.targets.register
triggersRegister a repeating timer.1
methodargsengine call
register2triggers.register
workersToggle post-update on the simulation workers.1
methodargsengine call
setPostUpdateEnabled1workers.shared.create

Worker API 88 methods

A quarter the size, and deliberately so: this thread exists to touch cells fast.

elementsRead and write cells directly — this is where per-particle work belongs.26
methodargsengine call
getTypeFromId1elements.getElementTypeFromId
getDefinitionByType1elements.getConfig
getTypeAtCell2elements.getTypeAtCell
getResolvedTypeAtCell2elements.getResolvedTypeAtCell
getResolvedTypeFromCellId1elements.getResolvedTypeFromCellId
getInfoAtCell2elements.getInfoAtCell
getMatterTypeAtCell2elements.getMatterTypeAtCell
isTypeAtCell3elements.isTypeAt
isFreeFallingAtCell2elements.getResolvedTypeAtCell, elements.isFreeFalling
createAtCell4world.isCellEmpty, elements.createAt
replaceAtCell4elements.replaceAt
removeAtCell3elements.getResolvedTypeAtCell, elements.removeAt
moveBetweenCells4elements.move
teleportBetweenCells4elements.teleport
swapCells4elements.swap
getVelocityAtCell2elements.getResolvedTypeAtCell, elements.getVelocity
setVelocityAtCell3elements.setVelocity
addParticleVelocityAtCell4elements.addParticleVelocity
convertToParticleAtCell3elements.convertToParticle
convertFromParticleAtCell2elements.convertFromParticle
getDataFieldAtCell3elements.getResolvedTypeAtCell, elements.getDataField
setDataFieldAtCell4elements.getResolvedTypeAtCell, elements.setDataField
refreshColorAtCell2elements.refreshColorAt
markMovementBlockedByElementIndex1elements.markMovementBlocked
setPhysicsAtCell3elements.getResolvedTypeAtCell, elements.setPhysics, world.reportActivityToChunk
setDurationAtCell4elements.getResolvedTypeAtCell, elements.setDuration
structuresTest what is built at a cell and read its processing state.14
methodargsengine call
processing.isEnabledAt2structures.processing.isEnabledAt
getAtCell2structures.getAtCell
getDefinitionByType1structures.getConfig
getTypeFromId1structures.resolveTypeName
hasBuiltAtCell2structures.hasBuiltAtCell
isType2structures.isType
isTypeAtCell3structures.isTypeAt
forEachOfType2structures.forEachOfType
update2structures.update
setData3structures.setData
setSpritesheetIndex2structures.setSpritesheetIndex
setSpritesheetIndexAtCell3structures.setSpritesheetIndexAt
setSpritesheetIndexByValue3structures.setSpritesheetIndexByValue
setSpritesheetIndexByValueAtCell4structures.setSpritesheetIndexByValueAt
terrainsRead, create and damage terrain from the simulation thread.11
methodargsengine call
getTypeFromId1terrains.getTypeByName
getTypeAtCell2terrains.getTypeAtCell
getDataAtCell2terrains.getTerrainData
isAtCell2terrains.isAtCell
isTypeAtCell3terrains.isTypeAtCell
isCellIdTerrainterrains.isCellIdTerrain
createAtCell4world.isCellEmpty, terrains.createAt
replaceAtCell4terrains.replaceAt
removeAtCell3world.getCellId, terrains.isCellIdTerrain, terrains.removeAt
damageAtCell3terrains.damageTerrain
setHpAtCell3terrains.setTerrainHP
collectorCollectable value of a cell.5
methodargsengine call
getValueFromCellId1collector.getValueFromCellId
getValueByType1collector.getValueFromElementType
isCellIdCollectable1collector.isCellCollectable
isCellIdCollectableForSprite1collector.isCellCollectableForSprite
notifyPickupAtCell2collector.notifyPickup
worldCell ids, emptiness, activity reporting, excavation.5
methodargsengine call
getCellIdAtCell2world.getCellId
isCellEmptyAtCell2world.isCellEmpty
isTerrainAtCell2world.isTerrainAt
reportActivityAtCell2world.reportActivityToChunk
excavateAtCell5world.excavate
utilsDistance, direction, angle, line between points.4
methodargsengine call
getDistanceutils.getDistance
getDirectionutils.getDirection
getAngleutils.getAngle
getCoordinatesBetweenPointsutils.getCoordinatesBetweenPoints
effectsParticles and lights raised from the worker.3
methodargsengine call
createEffectAtWorld4effects.createEffect
createLightAtWorld3effects.createLight
createParticlesAtWorld3effects.createParticles
playerPlayer position and proximity tests.3
methodargsengine call
getWorldPosition0player.getPosition
isCollidingWithCell2player.isCollidingWithCell
isWithinRadiusOfCell3player.isWithinRadius
eventsSubscribe to simulation events. Some require a guard.2
methodargsengine call
on3
emit3
fireWhether a cell burns, and setting it burning.2
methodargsengine call
canBurnElementAtCell2fire.canBurnElementAt
burnElementAtCell2fire.canBurnElementAt, fire.burnElementAt
hooksIntercept or modify engine calls inside the simulation.2
methodargsengine call
intercept3
modify3
patternsCircle patterns and pattern excavation.2
methodargsengine call
createCirclepatterns.createCircle
excavateAtCell6patterns.excavate
randomSeeded integers and floats.2
methodargsengine call
intrandom.int
floatrandom.float
sharedRead the buffers the main entry created.2
methodargsengine call
buffers.require2workers.shared.get
buffers.get1workers.shared.get
workerThis thread's index and the total thread count.2
methodargsengine call
getIndex0
getCount0
mainEmit an event to the main thread. The only way out.1
methodargsengine call
emitEvent2
mapsThe active map.1
methodargsengine call
getActive0maps.getActive
uiToasts. That is the whole UI surface here.1
methodargsengine call
toast2ui.toast

Value catalogs

The reference tables above say what a mod can call. These are the values worth passing — collected from the same shipped code, so they regenerate with the game.

Sound ids (63)

Everything the game itself passes to its sound engine, playable via sound.play(id, options) — with calculateDistanceOptionsAtWorld for falloff and rateLimitKey so a hundred machines share one voice.

accepting_pianoammo_emptyartifact_shimmerbeadsblipboostboost_overlaybuildbuild4build_startbuild_start2clickcockingcoincollectcyber_clickdenydigdig_2dig_overlaydroidvoice_3eerie_memoryexplosionexplosion2explosion_overlayflamethrowerflamethrower2flamethrower_overlayfluxitefluxite_2fluxite_3force_field_wavesfreezefuture_sirengungun_overlayhummingimpactsjetjet_flybymachinerymachinery_ambiencemachinery_rhythmmachinery_rhythm_2machinery_rhythm_2_bmetallic_crashopenpistolresearchrobomech_servorocket_boosterrocket_explosionrocket_jetrocket_launchrumbleshakesinesprint_booststatic_transmissionsteam_gun_reloadsubtle_shootervacuumvaporize

Structure ambience groups, for the ambienceGroup render field: clearingFrames, conveyors, launchers, shakers, steamTurbines.

gameConfig defaults (81)

What gameConfig.getAll() returns before anything overrides it — including the flags no options screen exposes. customMaps.showCustomMaps and mods.showSubscribedMods ship false: whole features behind a boolean. The procgen subtree is the map generator's own knobs, seed included.

gameConfigevery default, in source order81
keydefault
version"…"
fps60
lockFpsfalse
chunkSize40
cellSize4
gravity"…"
upflow"…"
snapGridCellSize4
startingResources0
debug.activefalse
debug.showUnderlyingCellsInStructurestrue
debug.drawChunksfalse
debug.drawChunkFade60
debug.drawRulersfalse
debug.showThreadLoadtrue
debug.controlstrue
debug.defaultBaseHue35
debug.brushSize3
debug.brushShape"circle"
debug.brushThrottle0
debug.highlightBrushtrue
debug.preventDuplicateCellsfalse
debug.doNotDrawStructuresfalse
debug.stopOnDebugCellUpdatefalse
debug.overrideLightSizefalse
debug.overrideTerrainShadowfalse
debug.lightSize700
debug.terrainShadowValue0.995
debug.flashlight.brightness2
debug.flashlight.size200
debug.flashlight.duration100
debug.flashlight.color"[…]"
debug.gameOfLife"…"
debug.countEventsfalse
debug.strictSafeguardsfalse
debug.showLightsfalse
debug.showProximityFadetrue
debug.showFiltersfalse
debug.showAuthorizationZonesfalse
debug.showProximityFadeSelectedOnlyfalse
debug.selectedLightIndex-1
debug.cellInspectorfalse
debug.badDisplaysfalse
debug.i18nDebug.mode"off"
debug.i18nDebug.pseudo.bracketstrue
debug.i18nDebug.pseudo.accentCharstrue
debug.i18nDebug.pseudo.padPercent0.3
debug.i18nDebug.randomScript.script"chinese"
debug.i18nDebug.randomScript.lengthMultiplier1
conveyorDefaultSpeed0.05
useMultithreadingtrue
useExperimentalRendererfalse
obstacleBreakpoint100
playerSize.width12
playerSize.height30
matrixCompression.padding100
blueprintEncoding"binary"
mods.showSubscribedModsfalse
customMaps.showCustomMapsfalse
procgen.useProcgenMaptrue
procgen.showGeneratedMapfalse
procgen.logPerformancetrue
procgen.logVerbosity1
procgen.params.width3840
procgen.params.height3840
procgen.params.scale0.005
procgen.params.threshold0.02
procgen.params.cellSize1
procgen.params.seed"…"
procgen.prefabPlacementBufferCells20
procgen.mossPatchMinDepthCells30
procgen.caveRegionLights.brightness1
procgen.caveRegionLights.size200
procgen.leftWall.enabledfalse
procgen.leftWall.startPosition0.2
procgen.leftWall.steepness0.01
procgen.leftWall.noiseAmount0.15
procgen.leftWall.entrance.enabledfalse
procgen.leftWall.entrance.width200
procgen.leftWall.entrance.height120
procgen.saveGeneratedMapfalse

window.electron (65)

The Electron preload bridge. Mod entries run in the same renderer, so all of it is reachable from a mod: openDevTools(), save export and import, the local-mods folder, Workshop subscription management.

window.electronthe preload bridge, as shipped65
method
window.electron.getPlatformSync()
window.electron.getIsSteamDeckSync()
window.electron.getPreferredSystemLanguagesSync()
window.electron.onAppSuspend(callback)
window.electron.onAppResume(callback)
window.electron.diagnostics()
window.electron.checkLicense()
window.electron.writeGameEvent(eventName, dimensions, measurements)
window.electron.platformPrimeAchievements(ids)
window.electron.platformShowReauthPrompt(reason)
window.electron.appQuit()
window.electron.openExternalBrowser(url)
window.electron.onXboxUserSignedOut(callback)
window.electron.onXboxLicenseLost(callback)
window.electron.onXboxUserSignedIn(callback)
window.electron.save(id, name, data)
window.electron.saveSerialized(id, name, dataJson, metadata)
window.electron.load(id)
window.electron.deleteSave(id)
window.electron.loadRaw(name)
window.electron.exportSave(id)
window.electron.importSave(bytes)
window.electron.getSaveFiles()
window.electron.getSaveFolder()
window.electron.localMods.getFolder()
window.electron.localMods.openFolder()
window.electron.localMods.list()
window.electron.localMods.upload(modId)
window.electron.getLastPlayedGameSync()
window.electron.saveLastPlayedGame(game)
window.electron.clearLastPlayedGame()
window.electron.saveExistsSync(id)
window.electron.getSettingsSync()
window.electron.saveSettings(settings)
window.electron.setFullscreen(shouldBeFullscreen)
window.electron.openDevTools()
window.electron.isFilePatchingActiveSync()
window.electron.platform.isInitialized()
window.electron.platform.getPlayerName()
window.electron.platform.getPlayerId()
window.electron.platform.getAppId()
window.electron.platform.unlockAchievement(achievementId)
window.electron.platform.isAchievementUnlocked(achievementId)
window.electron.platform.clearAchievement(achievementId)
window.electron.platform.cloudSave(fileName, data)
window.electron.platform.cloudLoad(fileName)
window.electron.platform.cloudFileExists(fileName)
window.electron.platform.cloudDelete(fileName)
window.electron.platform.cloudSync()
window.electron.platform.workshop.subscribe(itemId)
window.electron.platform.workshop.unsubscribe(itemId)
window.electron.platform.workshop.installInfo(itemId)
window.electron.platform.workshop.downloadInfo(itemId)
window.electron.platform.workshop.getState(itemId)
window.electron.platform.workshop.getSubscribedItems()
window.electron.platform.workshop.getItem(itemId)
window.electron.platform.workshop.download(itemId, highPriority)
window.electron.platform.workshop.getSandkitMods()
window.electron.platform.overlay.openUrl(url)
window.electron.log(level, scope, message)
window.electron.getSystemInfo()
window.electron.customMaps.save(id, name, data)
window.electron.customMaps.load(id)
window.electron.customMaps.list()
window.electron.customMaps.delete(id)
None of this is covered by apiVersion. It is the same category as sandkit.engine.api: real, useful, and free to change in any patch. Wrap every call, fail soft.

Beyond api

sandkit.api is not the whole object a mod is handed. Three more members sit next to it, none of them a method, which is why none of them appears in the tables above — and why a mod cannot draw a single button without one of them.

sandkit.enums (22 / 323)

The game's own enumerations, re-exported member by member. These are the numbers the API expects: ui.update(enums.ComponentId.Hotbar), scene.getActive() === enums.Scene.MainMenu, a key state compared against enums.KeyState.Pressed. Writing the literal instead works right up until a patch renumbers it.

enums.CellType31
membervalue
Empty0
Element1
Dirt2
SporeSoil3
Fog4
FogJetpackBlock5
FogWater6
FreezingIceSoil7
Divider8
Grass9
Moss10
GoldSoil11
Petal12
FogLava13
Fluxite14
Block15
SlidingBlock16
SlidingBlockLeft17
SlidingBlockRight18
ConveyorLeft19
ConveyorRight20
ShakerLeft21
ShakerRight22
Stone23
VelocitySoaker24
Ice25
Grower26
NascentWater27
SandiumSoil28
Obsidian29
Crackstone30
enums.ElementType20
membervalue
Sand1
Particle2
Water3
WetSand4
Sandium5
Residue6
Gold7
Gloom8
Shake9
Steam10
Fire11
FreezingIce12
Flame13
BurntResidue14
Seed15
WetSeed16
Seedling17
Petalium18
Lava19
Basalt20
enums.MatterType8
membervalue
Solid1
Liquid2
Particle3
Gas4
Static5
Slushy6
Wisp7
Powder8
enums.StructureType27
membervalue
ConveyorLeft1
ConveyorRight2
ShakerLeft3
ShakerRight4
LauncherUp5
LauncherLeft6
LauncherRight7
SplitterLeft8
SplitterRight9
Dropper10
Foundation11
FoundationAngledLeft12
FoundationTriangleLeftDel13
FoundationAngledRight14
FoundationTriangleRightDel15
Collector16
FilterLeft17
FilterRight18
SlidingFoundation19
VelocitySoaker20
Grower21
SoundBox22
Pipe23
Pump24
LiquidVent25
Light26
FluxEmanator27
enums.ItemType4
membervalue
Weapon1
Tool2
Consumable3
Mod4
enums.ItemId16
membervalue
Shovel1
Grabber2
Demolisher3
GrapplingHook4
Vacuum5
Gun6
Copier7
RocketLauncher8
Digger9
Shotgun10
Teleporter11
Flamethrower12
PipeRemover13
Hauler14
Cryoblaster15
MegaShotgun16
enums.ProjectileType6
membervalue
Bullet1
Rocket2
GrapplingHook3
Fire4
Digger5
Mod6
enums.ActionType4
membervalue
Weapon1
Building2
Tool3
Mod4
enums.ActionState3
membervalue
Start1
Active2
End3
enums.AbilityType4
membervalue
Dig1
Shoot2
Spray3
Laser4
enums.ReloadType3
membervalue
Clip1
Single2
OverTime3
enums.ComponentId28
membervalue
Hotbar1
SoundBoxConfig2
Root4
Menu5
Management6
FilterConfig7
Resources8
TechTree9
Tutorial10
Loader11
Options12
ShortcutHelper13
Upgrades14
Tooltip15
Notifications16
Objectives17
DroneAdminList18
HotbarOverlays19
IntroScreen20
StoryNotifications21
FactoryProgress22
Dialogs23
GlobalOverlays24
Lexicon25
ModsScreen26
CustomMapsScreen27
CinematicPanel28
Feedback29
enums.KeyBinding27
membervalue
OpenBuildMenu"OpenBuildMenu"
GrapplingHook"GrapplingHook"
Escape"Escape"
OpenTechTree"OpenTechTree"
OpenInventory"OpenInventory"
ReverseBuildDirection"ReverseBuildDirection"
Marquee"Marquee"
Pause"Pause"
Copy"Copy"
Paste"Paste"
Flip"Flip"
Delete"Delete"
PauseCamera"PauseCamera"
OpenUpgrades"OpenUpgrades"
BuildMode"BuildMode"
Demolish"Demolish"
Hover"Hover"
Ruler"Ruler"
Left"Left"
Right"Right"
Boost"Boost"
Descend"Descend"
SprintBoost"SprintBoost"
OverrideReplaceStructures"OverrideReplaceStructures"
QuickSave"QuickSave"
QuickLoad"QuickLoad"
ToggleGameHud"ToggleGameHud"
enums.KeyState5
membervalue
Up1
Down2
Pressed3
Released4
All5
enums.BuildMode2
membervalue
Linear1
Rectangular2
enums.BuildingClearance4
membervalue
Available1
FullyBlocked2
PartiallyBlocked3
CanBeReplaced4
enums.AuthorizationType6
membervalue
NoJetpack1
NoGrab2
NoBuild3
NoTool4
NoExcavation5
NoToolExceptFlamethrower6
enums.DroneType2
membervalue
Digger1
Hauler2
enums.WorldItemType4
membervalue
Artifact1
GlyphKey2
Stratacore3
Orb4
enums.Scene4
membervalue
MainMenu1
Intro2
Deploy3
Game4
enums.Tech110
membervalue
Shaker1
Conveyors2
Guns13
Filters14
Flamethrower5
Gun6
KineticPress7
Guns28
Drones19
Upgrading210
Filters211
Upgrading312
Upgrading413
Upgrading514
Upgrading615
Upgrading716
Upgrading817
Upgrading918
Upgrading1019
PlanterBox20
Thermo21
Rocket22
Pipes23
StaticLights24
Drones225
Smelter26
Tools427
Guns328
Pipes229
ConveyorsMk230
Lights231
Refining632
Refining733
Guns434
Guns535
Tools536
Tools637
Filters338
Filters439
Pipes340
Pipes441
Logistics342
Logistics443
Lights344
Lights445
Drones346
Drones447
Alien48
Electricity49
AlienCore50
Emanators151
AlienPlasmaConduits52
AlienQuantumMatrix53
AlienPlasmaCore54
AlienVoidEngine55
FlareGun56
Sweeper57
Utilities358
Cryoblaster59
Vacuum60
Utilities661
Utilities762
Filters63
AdvancedFilters64
Infrastructure365
Decorations166
Decorations267
Decorations368
Blocks169
Drill70
SteamTurbine71
Electricity372
Electricity473
Logic174
Logic275
Logic376
Logic477
Various178
Various279
Various380
Locator81
QuantumPortal82
VoidRift83
Blink84
Recall85
ImplosionGun86
Refining887
Tools788
Diggers89
Haulers90
Map91
ColoringTool92
SignalGate93
GrapplingHook94
GlassFoundation95
PrecisionTools96
SignalDevices97
SignalControls98
LogicGates99
RetroConsole100
WallTool101
Corraller102
PlainFoundation103
ClearingFrame104
Heatmap105
MiningLaser106
GoldBattery107
Hover108
SprintBoost109
CritterFence110
enums.TechStatus5
membervalue
Available0
Visible1
Researched2
Unknown3
Hidden4

sandkit.react (18.3.1)

A frozen copy of the game's own React. Mod components render inside the game's tree, so hooks work normally — but they have to come from here, because a second copy of React in one tree does not.

ChildrenComponentFragmentProfilerPureComponentStrictModeSuspensecloneElementcreateContextcreateElementcreateFactorycreateRefforwardRefisValidElementlazymemostartTransitionuseCallbackuseContextuseDebugValueuseDeferredValueuseEffectuseIduseImperativeHandleuseInsertionEffectuseLayoutEffectuseMemouseReduceruseRefuseStateuseSyncExternalStoreuseTransitionversion
The whole public surface of this React is present, hooks included. ui.inject and ui.overlays.register take components built with it; an entry cannot use JSX, so it is react.createElement by hand or a small h() helper.

sandkit.state (424 / 1362)

The live game state, and the same object as sandkit.engine.state. It is where mods go when the API has no getter — the energy buffer, the open windows, the resource counts. Nothing about its shape is in the shipped code, so this table is measured from a running game: names, types and sizes only, never values.

Three levels deep on this page. The dump goes to 4 and holds 1362 paths in all — data/state.json has the rest. Branches keyed by id rather than shaped — whichever mods are installed, whichever tech a save has — are kept as a node with their children dropped, since walking them describes one machine rather than the game: state.sandkit (1038), state.session.lexicon.entriesById (337), state.store.mods (120), state.store.player.tech (71), state.shared.mods (19), state.session.settings.externalModSettings (14).

state.environmentbuild and platform4
pathtypesize
state.environmentobject2
state.environment.contextnumber
state.environment.multithreadingobject1
state.environment.multithreading.simulationobject16
state.sandkitthe mod layer itself — reflects whichever mods are installed1
pathtypesize
state.sandkitobject7
state.sessionthis run only: input, windows, camera, rendering, settings193
pathtypesize
state.sessionobject51
state.session.actionobject3
state.session.action.customDatanull
state.session.action.pointobject2
state.session.action.stateobject3
state.session.actionLockedboolean
state.session.ambienceobject5
state.session.ambience.clearingFramesobject2
state.session.ambience.conveyorsobject2
state.session.ambience.launchersobject2
state.session.ambience.shakersobject2
state.session.ambience.steamTurbinesobject2
state.session.animationsobject1
state.session.animations.playerobject3
state.session.buildingobject6
state.session.building.activeStructureTypenull
state.session.building.amountOfTilesnumber
state.session.building.ignoreAngleLockboolean
state.session.building.lockedAnglenull
state.session.building.placingboolean
state.session.building.startobject2
state.session.buttonsobject1
state.session.buttons.pressedboolean
state.session.cacheobject2
state.session.cache.pipesobject4
state.session.cache.structuresobject4
state.session.cameraobject2
state.session.camera.xnumber
state.session.camera.ynumber
state.session.cheatobject1
state.session.cheat.bypassCostsboolean
state.session.cinematicundefined
state.session.colorsobject1
state.session.colors.schemeobject2
state.session.constructionobject3
state.session.construction.demolisherActiveboolean
state.session.construction.marqueeActiveboolean
state.session.construction.rulerActiveboolean
state.session.debugobject1
state.session.debug.brushobject4
state.session.effectsarray0
state.session.explosionsarray0
state.session.externalModsobject6
state.session.externalMods.diagnosticsarray of object3
state.session.externalMods.missingSavedModsarray of string3
state.session.externalMods.orderedModsarray of object14
state.session.externalMods.statusesarray of object14
state.session.externalMods.workerEntriesarray of object1
state.session.externalMods.workerResultsarray of object8
state.session.factoryProcessRatesFloat64Array4
state.session.inputobject9
state.session.input.actionobject2
state.session.input.bindingStatesobject0
state.session.input.currentLastKeystring
state.session.input.currentLastKeyCodestring
state.session.input.deckCursorobject5
state.session.input.deckLastManagementTabstring
state.session.input.keysobject57
state.session.input.modestring
state.session.input.mouseobject10
state.session.lerpCameraboolean
state.session.lexiconobject3
state.session.lexicon.compiledboolean
state.session.lexicon.entriesarray of object337
state.session.lexicon.entriesByIdobject337
state.session.lightZonesarray of array150
state.session.lightsarray of null100
state.session.mainSensorCacheobject1
state.session.mainSensorCache.cacheobject1
state.session.modsobject1
state.session.mods.signalsobject13
state.session.monitorobject1
state.session.monitor.threadsarray of object8
state.session.movementSpeedMultipliernumber
state.session.musicobject2
state.session.music.ambientobject1
state.session.music.engineobject30
state.session.nextTickCallbacksarray0
state.session.notificationsobject2
state.session.notifications.storyarray0
state.session.notifications.toaststring
state.session.overrideCameraboolean
state.session.pausedboolean
state.session.platformstring
state.session.prefabWorldItemCacheobject1
state.session.prefabWorldItemCache.cacheobject10
state.session.reconModeboolean
state.session.renderingobject24
state.session.rendering.backgroundChannelobject2
state.session.rendering.canvasobject0
state.session.rendering.channelobject2
state.session.rendering.foregroundChannelobject2
state.session.rendering.foregroundOffscreenCanvasobject0
state.session.rendering.foregroundOffscreenContextobject0
state.session.rendering.imagesobject102
state.session.rendering.obstacleCanvasobject0
state.session.rendering.obstacleChannelobject2
state.session.rendering.obstacleContextobject0
state.session.rendering.obstacleOffscreenCanvasobject0
state.session.rendering.obstacleOffscreenContextobject0
state.session.rendering.offscreenCanvasobject0
state.session.rendering.offscreenContextobject0
state.session.rendering.offscreenOutlineCanvasobject0
state.session.rendering.offscreenOutlineContextobject0
state.session.rendering.overlayCanvasobject0
state.session.rendering.overlayContextobject0
state.session.rendering.pixiobject43
state.session.rendering.worldCanvasobject0
state.session.rendering.worldChannelobject2
state.session.rendering.worldContextobject0
state.session.rendering.worldOffscreenCanvasobject0
state.session.rendering.worldOffscreenContextobject0
state.session.resolutionobject2
state.session.resolution.heightnumber
state.session.resolution.widthnumber
state.session.runtimestring
state.session.savingboolean
state.session.scalenumber
state.session.settingsobject23
state.session.settings.autosaveIntervalnumber
state.session.settings.cursorScalenumber
state.session.settings.disableBackgroundShaderboolean
state.session.settings.disableShadowsboolean
state.session.settings.externalModSettingsobject14
state.session.settings.focusLossobject3
state.session.settings.frameRateCapnumber
state.session.settings.hardModeboolean
state.session.settings.hotbarCountnumber
state.session.settings.hybridSchedulingboolean
state.session.settings.keyBindingsobject66
state.session.settings.localestring
state.session.settings.lockHotbarboolean
state.session.settings.lockSkyColorboolean
state.session.settings.pipesModeViewboolean
state.session.settings.schedulingModenumber
state.session.settings.settingsVersionnumber
state.session.settings.showFpsboolean
state.session.settings.soundobject3
state.session.settings.uiScalenumber
state.session.settings.upgradesHideMaxboolean
state.session.settings.videoZoomnumber
state.session.settings.windowModestring
state.session.soundBoxobject1
state.session.soundBox.selectedNoteobject2
state.session.soundEngineobject8
state.session.soundEngine.audioContextobject0
state.session.soundEngine.gateobject1
state.session.soundEngine.globalVolumenumber
state.session.soundEngine.limiterobject0
state.session.soundEngine.masterGainobject0
state.session.soundEngine.mutedboolean
state.session.soundEngine.outputLimiterobject0
state.session.soundEngine.sfxobject106
state.session.sprintBoostobject2
state.session.sprintBoost.meternumber
state.session.sprintBoost.rechargingboolean
state.session.teleportZoneCacheobject1
state.session.teleportZoneCache.cacheobject270
state.session.timestepobject2
state.session.timestep.frameDurationnumber
state.session.timestep.lastTimenumber
state.session.triggersarray of object26
state.session.uiobject9
state.session.ui.dialogsarray0
state.session.ui.discoveryPopupsarray0
state.session.ui.hudHiddenboolean
state.session.ui.introScreenobject1
state.session.ui.listenersobject24
state.session.ui.nextListenerIdnumber
state.session.ui.overlaysobject2
state.session.ui.tooltipobject2
state.session.ui.visibleboolean
state.session.viewobject4
state.session.view.maxZoomnumber
state.session.view.minZoomnumber
state.session.view.zoomnumber
state.session.view.zoomDirtyboolean
state.session.visualParticlesarray of object94
state.session.windowsobject13
state.session.windows.blueprintsobject1
state.session.windows.buildingobject3
state.session.windows.conservatoryobject1
state.session.windows.customMapsScreenobject1
state.session.windows.feedbackobject1
state.session.windows.inventoryobject1
state.session.windows.lexiconobject1
state.session.windows.loaderobject1
state.session.windows.menuobject1
state.session.windows.modsScreenobject1
state.session.windows.optionsobject1
state.session.windows.techTreeobject2
state.session.windows.upgradesobject1
state.session.zoomLevelnumber
state.sharedSharedArrayBuffers the simulation threads write into83
pathtypesize
state.sharedobject33
state.shared.actionStateUint8Array3
state.shared.authorizationobject3
state.shared.authorization.dataUint8Array14745600
state.shared.authorization.heightnumber
state.shared.authorization.widthnumber
state.shared.collectorGoldCountUint8Array921600
state.shared.conveyorBeltsAnimationIndexUint8Array8
state.shared.debugobject1
state.shared.debug.cellPosUint16Array2
state.shared.energyUint32Array1
state.shared.energyBatteryDirtyUint8Array921600
state.shared.energyChangeUint32Array4
state.shared.goldUint32Array1
state.shared.goldChangeUint32Array4
state.shared.hybridSchedulingUint8Array1
state.shared.listenerPosFloat32Array2
state.shared.managerPerformanceFloat32Array23
state.shared.mapDataobject3
state.shared.mapData.dataUint8Array58982400
state.shared.mapData.heightnumber
state.shared.mapData.widthnumber
state.shared.modsobject19
state.shared.mouseobject1
state.shared.mouse.worldPositionUint16Array2
state.shared.mutationSyncInt32Array1
state.shared.naturalAmbienceFloat32Array8
state.shared.playerPosFloat32Array2
state.shared.productionPointsUint32Array1
state.shared.reservoirUint16Array1
state.shared.schedulingModeUint8Array1
state.shared.shadowMapobject3
state.shared.shadowMap.dataUint8Array14745600
state.shared.shadowMap.heightnumber
state.shared.shadowMap.widthnumber
state.shared.simobject20
state.shared.sim.cellIdsUint32Array14745600
state.shared.sim.chunkHeightnumber
state.shared.sim.chunkShouldUpdateUint8Array9216
state.shared.sim.chunkShouldUpdateNextUint8Array9216
state.shared.sim.chunkSizenumber
state.shared.sim.chunkWidthnumber
state.shared.sim.damagedGroundobject2
state.shared.sim.elementCapacitynumber
state.shared.sim.elementDataobject25
state.shared.sim.elementSlabsExhaustedUint32Array1
state.shared.sim.freeDamagedIdCountUint32Array1
state.shared.sim.freeDamagedIdsUint32Array999000
state.shared.sim.heightnumber
state.shared.sim.idStatsUint32Array420
state.shared.sim.liveElementCountUint32Array1
state.shared.sim.nextDamagedIdUint32Array1
state.shared.sim.nextElementSlabUint32Array1
state.shared.sim.overflowPoolUint32Array100001
state.shared.sim.terrainTypeUint8Array1001
state.shared.sim.widthnumber
state.shared.wallDataobject4
state.shared.wallData.dataUint8Array14745600
state.shared.wallData.heightnumber
state.shared.wallData.paletteDataUint8Array1020
state.shared.wallData.widthnumber
state.shared.waterPresenceZonesUint8Array14400
state.shared.waterPresenceZonesHeightnumber
state.shared.waterPresenceZonesWidthnumber
state.shared.workQueueobject14
state.shared.workQueue.chunkCountnumber
state.shared.workQueue.chunkDoneUint8Array9216
state.shared.workQueue.chunkHeightnumber
state.shared.workQueue.chunkWidthnumber
state.shared.workQueue.columnCostsFloat32Array768
state.shared.workQueue.columnDoneUint8Array96
state.shared.workQueue.countersUint32Array4
state.shared.workQueue.effectiveModeUint8Array1
state.shared.workQueue.evenTasksUint32Array9216
state.shared.workQueue.hotColumnsUint8Array96
state.shared.workQueue.hotRemainingInt32Array96
state.shared.workQueue.oddTasksUint32Array9216
state.shared.workQueue.taskCountsUint32Array2
state.shared.workQueue.workerCountnumber
state.shared.workerCompletionFloat32Array16
state.shared.workerDetailEnabledUint8Array1
state.shared.workerDetailPerformanceFloat32Array104
state.shared.workerPerformanceFloat32Array32
state.storesaved with the world: resources, structures, progression143
pathtypesize
state.storeobject34
state.store.achievementsobject14
state.store.achievements.ANCIENT_TECHNOLOGYboolean
state.store.achievements.AURA_EXTRACTORboolean
state.store.achievements.CONSERVATORY_CURATORboolean
state.store.achievements.CRITTER_CATCHERboolean
state.store.achievements.FINAL_SCHEMATICboolean
state.store.achievements.FIRST_BLOOMboolean
state.store.achievements.FIRST_SPARKboolean
state.store.achievements.FLUX_IT_UPboolean
state.store.achievements.FULL_CIRCLEboolean
state.store.achievements.GOLD_IN_THE_BINboolean
state.store.achievements.PROMOTION_PROTOCOLboolean
state.store.achievements.QUARTERMASTERboolean
state.store.achievements.STRATACORE_SECUREDboolean
state.store.achievements.VOID_TOUCHEDboolean
state.store.conservatoryobject1
state.store.conservatory.ticketsnumber
state.store.createdVersionstring
state.store.creaturesobject5
state.store.creatures.eyesobject2
state.store.creatures.lumlingobject2
state.store.creatures.resinWeaverobject2
state.store.creatures.shineletobject2
state.store.creatures.voidgrazerobject2
state.store.discoveriesobject2
state.store.discoveries.elementsarray of number45
state.store.discoveries.terrainsarray of number21
state.store.dronesarray of object1
state.store.factoryLevelCapnull
state.store.gloomobject1
state.store.gloom.emitterPositionsarray0
state.store.hintsobject6
state.store.hints.angleLockShownboolean
state.store.hints.conservatoryIntroSeenboolean
state.store.hints.freezingIceSoilFireboolean
state.store.hints.hoverIntroToastSeenboolean
state.store.hints.nonDestructibleboolean
state.store.hints.upgradesIntroSeenboolean
state.store.integrityobject2
state.store.integrity.cheatsUsedboolean
state.store.integrity.modsUsedboolean
state.store.lockedTechsobject2
state.store.lockedTechs.aurixiteCrystallizerboolean
state.store.lockedTechs.voidOrbboolean
state.store.machineryEngineobject1
state.store.machineryEngine.runLaunchersboolean
state.store.metaobject8
state.store.meta.autosaveSlotnumber
state.store.meta.elementCapacitynumber
state.store.meta.nextIdobject3
state.store.meta.seedstring
state.store.meta.ticknumber
state.store.meta.timenumber
state.store.meta.worldIdstring
state.store.meta.worldNamestring
state.store.modsobject34
state.store.objectivesobject1
state.store.objectives.activearray0
state.store.optionsobject6
state.store.options.buildModenumber
state.store.options.buildModeIndicesobject5
state.store.options.defaultFilterobject2
state.store.options.sandkitPlacementConfigobject1
state.store.options.shortcutHelperVisibleboolean
state.store.options.techTreePanobject2
state.store.ownerundefined
state.store.pipesarray of object413
state.store.playerobject17
state.store.player.actionobject2
state.store.player.buildingsarray of number61
state.store.player.cooldownsobject3
state.store.player.grapplingHookboolean
state.store.player.heightnumber
state.store.player.hotbarobject3
state.store.player.inventoryarray of object32
state.store.player.isHoveringboolean
state.store.player.onGroundboolean
state.store.player.speedCapOverdriveobject2
state.store.player.techobject71
state.store.player.thresholdobject2
state.store.player.velocityobject2
state.store.player.weaponsMetaobject1
state.store.player.widthnumber
state.store.player.xnumber
state.store.player.ynumber
state.store.productionPointsnumber
state.store.progressionobject2
state.store.progression.dungeonsobject1
state.store.progression.upgradesUnlockedboolean
state.store.projectilesarray0
state.store.pumpsCachearray of object51
state.store.queuearray0
state.store.resourcesobject4
state.store.resources.artifactsobject2
state.store.resources.energynumber
state.store.resources.fluxitenumber
state.store.resources.goldnumber
state.store.sceneobject3
state.store.scene.activenumber
state.store.scene.startnumber
state.store.scene.triggersarray of object3
state.store.stratacoresarray of string1
state.store.structuresarray of object35956
state.store.tutorialobject4
state.store.tutorial.activeboolean
state.store.tutorial.currentStepnumber
state.store.tutorial.dataobject0
state.store.tutorial.transitioningToNextStepboolean
state.store.upgradesobject16
state.store.upgrades.cryoblasterobject1
state.store.upgrades.diggerobject4
state.store.upgrades.drillobject1
state.store.upgrades.flamethrowerobject2
state.store.upgrades.grabberobject3
state.store.upgrades.gunobject5
state.store.upgrades.haulerobject2
state.store.upgrades.implosionGunobject1
state.store.upgrades.jetpackobject2
state.store.upgrades.laserobject3
state.store.upgrades.locatorobject1
state.store.upgrades.rocketLauncherobject4
state.store.upgrades.shovelobject3
state.store.upgrades.sweeperobject3
state.store.upgrades.thrusterobject1
state.store.upgrades.vacuumobject2
state.store.versionstring
state.store.viabilityobject3
state.store.viability.goldSpentnumber
state.store.viability.levelnumber
state.store.viability.peakEnergynumber
state.store.worldobject10
state.store.world.deferredChunkReportsarray0
state.store.world.fixturesarray of object70
state.store.world.groundHorizonarray of number3840
state.store.world.horizonarray of number3840
state.store.world.lightsarray of object561
state.store.world.matrixTraverseDirectionnumber
state.store.world.sensorsarray of object1
state.store.world.sizeobject2
state.store.world.teleportZonesarray of object306
state.store.world.updatedElementIndicesarray0
state.store.worldItemsarray of object1
Not covered by apiVersion, and not even stable within one. This is a description of one world on one build. Read from it and a patch makes a mod wrong; write to it and a patch makes a save wrong. Every access wrapped, every read checked.

Traps

Collected the expensive way, across eight mods.

Entries are scripts, not modules

An import or export throws Unexpected token 'export' and the entry silently never runs. Nothing in the UI says so.

Write scene gating as a hide-list

Injected UI sits in the global overlay slot, draws above the main menu, and stays mounted after leaving a world. Suppress on scenes you positively recognise as menus — a wrong guess in a show-list blanks your UI everywhere.

Never wrap registration in a quiet helper

A silent try/catch around energy.registerType can hide a total failure. Registration cannot be retried, so it has to fail loudly.

Validate before launching the game

workshop-mods.js and local-mod-publisher.js can be pulled out of app.asar and called directly: loadCandidate for the manifest and entries, validatePreview for the image, and the same new Function wrapper for syntax. Catches everything but runtime behaviour, with no restart.

Effect callbacks differ per entry point

energy.addAtCell reads onPathCharged but never calls onSourceAdded — that one only fires from the batch API, which mods do not get. It returns the amount the network accepted, which is the right thing to gate feedback on.

A mod appears in Options only if it has settings

No non-empty configSchema, no entry in the mods screen — and the game has no built-in way to disable a mod without unsubscribing, so an enabled field is worth making a convention.