Как это собрано
Не по community-типам и не по памяти. Игра поставляет dist/js/external-mod-runtime.js и external-mod-worker-runtime.js — мосты, через которые реально проходит каждый вызов мода. Эти файлы и есть API.
- Извлечь оба рантайма из
app.asarи разобрать каждую группу неймспейсов прямо из минифицированного кода, разрешая ссылки на переменные к ближайшему предшествующему определению. - Записать для каждого метода число аргументов и функцию движка, в которую он делегирует — это третья колонка в таблицах справочника ниже.
- Сдиффить результат с
sandkit.d.tsв обе стороны.
sandkit.d.ts точен. 281 методов main и 88 методов worker сходятся, фантомных записей нет ни в одну сторону. Единственный пробел — constants (constants.physics → normal, skip, aggressiveSkip), которого в файле типов нет.Весь пайплайн — три команды по твоей собственной установке, так что эту страницу можно пересобрать под любую сборку игры, а не верить ей как снимку.
Устройство мода
Четыре поверхности, объявляются в modinfo.json. Большинству модов хватает одной; те, что ощущаются как новый игровой контент, используют три.
entry main.js
Работает в потоке рендера. Регистрация, UI, энергия, дерево технологий, настройки, сохранение данных.
Компилируется через new Function("__sandkit", …) внутри асинхронной IIFE: await на верхнем уровне работает, а import и export бросают исключение — и энтри молча не запускается вообще.
workerEntry worker.js
Работает в каждом симуляционном потоке. Единственное место, которое видит движение отдельных частиц.
Обёртка та же, API заметно меньше: ни настроек, ни таймеров, ни полноценного UI.
patches.json строковый патчинг
До 256 патчей на мод по любому .js внутри игровой папки js/ — включая bundle.js и simulation-worker.js.
expectedMatches — обязательное поле, а патчи можно группировать так, что при промахе одного откатывается вся группа.
манифест
dependencies разрешается настоящей топологической сортировкой с детекцией циклов; loadOrder разрешает ничьи.
Благодаря этому мод-библиотека — штатно поддержанный паттерн: публикуешь её, другие моды указывают её id, порядок загрузки гарантирован.
Main против worker
Самое важное различие во всём этом API и то, которое решает, где вообще может жить твой код.
| Энтри main | Энтри worker | |
|---|---|---|
| Видит движение элемента | нет | да |
| Читает настройки мода | да | нет |
| Рисует UI | да | только тосты |
| Регистрирует постройки, технологии, энергию | да | нет |
| Повторяющиеся таймеры | triggers | нет |
| Говорит с другой стороной | shared buffers | main.emitEvent |
main.emitEvent, и произвольный payload проходит без преобразований. В обратную сторону канал ровно один: SharedArrayBuffer. Энтри main вызывает shared.buffers.create на верхнем уровне, воркер — require по тому же ключу; ключи с обеих сторон неймспейсятся по id мода, а энтри main всегда грузятся первыми. Именно через этот байт воркер узнаёт, включён ли твой мод.Что можно построить?
Читать надо с этой колонки. Именно с этим вопросом сюда и приходят.
| Я хочу… | Вердикт | Как |
|---|---|---|
| Добавить новую машину | можно | structures.register плюс sprites.loadFromMod. Размер рендера задаётся в пикселях, клетка — 4 px, поэтому спрайт 16×16 даёт машину 4×4 клетки. Если передать name и description обычными строками, ключи перевода зарегистрируются сами. |
| Чтобы она вырабатывала или тратила энергию | можно | energy.registerType(id, "conductor" | "storage"), дальше addAtCell и consume. Проводники отдают в сеть и сами ничего не хранят. |
| Отреагировать на отдельную частицу | можно | Только в воркере. events.on("element:moved", …) с гвардом. |
| Добавить новый элемент или террейн | можно | elements.register и terrains.register. Оба раздают числовые id как max + 1 — отсюда дрейф, описанный ниже. |
| Добавить узел в дерево технологий | можно | tech.registerNode(id, def, { parentId }). Сам ставит узел в первый свободный слот под родителем; бросает исключение при дубликате id, отсутствующем родителе или заполненном ряде. |
| Добавить рецепты существующим машинам | можно | structures.recipes.register покрывает planter box, шейкер, kinetic press, конденсатор, паровую сушилку, синтезатор, снеговик и плавильню. |
| Настроить машину в момент постройки | можно | structures.registerPlacementConfig. Значения попадают в structure.data; подписи пока требуют ключей перевода. |
| Открыть панель у уже стоящей машины | нет API | Ванильные панели Фильтра и Sound Box открываются захардкоженными проверками по id постройки, висящими на building-сессии, и ни одно событие не сообщает «игрок взаимодействовал с этой постройкой». Достижимо только патчингом. |
| Нарисовать свой HUD | осторожно | ui.overlays.register или ui.inject. Слот global рисуется и поверх главного меню — гейти по scene.getActive(). |
| Сохранять данные в сейв | можно | storage.get и storage.set по id мода. storage.local — наоборот, привязка к машине. |
| Отменить или переписать вызов движка | можно | hooks.intercept чтобы отменить, hooks.modify чтобы переписать аргументы. Доступно в обоих потоках. |
| Читать и писать файлы, открывать сокеты | нет API | Ничто в этой поверхности не касается Node. Это и есть черта, которую переходит сторонний загрузчик и не переходит мод из Workshop. |
| Выполнить код до старта игры | нет API | Энтри выполняются при инициализации мира, один раз за процесс. |
Жёсткие ограничения
Проверено по поставляемому коду, а не выведено из молчания. Именно эти вещи меняют архитектуру.
Энтри выполняются один раз за процесс
Рантайм держит множество загруженных id и на второй загрузке мира репортит alreadyLoaded. Всё, что ты пропустил из-за выключенной настройки, останется пропущенным до перезапуска игры — поэтому гейтить надо поведение, а не регистрацию.
Регистрация необратима
energy.registerType, structures.register, addProcessor и подписки на события нельзя отменить в рантайме, а addProcessor бросает исключение, если у постройки уже есть периодическая обработка.
Удаление мода оставляет постройки-сироты
Постройки модов сохраняются под своим строковым id. Удали мод — и в сейве останутся записи с типом, который никто не узнаёт; они откатятся к обычному блоку 4×4.
Числовые id элементов дрейфуют
Номера элементов и материй раздаются как max + 1 при регистрации, и закрепить свой номер мод не может никак. Добавь или убери тип — и все номера после него сдвинутся, тогда как сейв всё ещё хранит старые. Постройки от этого защищены: их id строковые, а числовая блок-сетка перестраивается из списка построек при загрузке.
Некоторым событиям воркера гвард обязателен
element:moved и terrain:update без него бросают исключение, и гвард должен нести ровно одно из elementType или terrainType. Симуляция вообще не эмитит эти события, пока нет обработчика на соответствующий тип.
Аварийный люк в движок не версионируется
sandkit.engine.api отдаёт внутренний движок и явно не покрывается apiVersion — может измениться в любом патче.
События и хуки
Id, найденные в поставляемом бандле (всего 45). Payload у нескольких штук перекладывается для модов в замороженную форму; всё, чего игра не узнаёт, проходит нетронутым — благодаря этому и работают собственные события из worker в main.
Жизненный цикл и мир
Строительство и постройки
Симуляция (worker)
Игрок, ввод и снаряды
Ресурсы и рендеринг
Обведены те, которым нужен гвард — иначе подписка бросит исключение.
Хуки
hooks.intercept отменяет вызов движка до того, как он случится; hooks.modify переписывает его аргументы. Список id — литеральный белый список в бандле, то есть здесь он полный, а не выборочный. Часть id встречается и в списке событий: событие срабатывает постфактум и может только смотреть, хук выполняется первым и имеет право голоса.
Перехватчики — отменяют вызов (18)
Модификаторы — переписывают аргументы (15)
Обведённые id принимают гвард-опцию: обработчик подписывается только на свои типы структур, оружия или снарядов, вместо того чтобы фильтровать каждый вызов вручную:
| хук | гвард-опция | сверяется с |
|---|---|---|
building:place | structureTypes | structureId |
weapon:reload:prepare | weaponIds | weaponId |
projectile:travel:prepare | projectileTypes | projectileType |
projectile:impact:prepare | projectileTypes | projectileType |
trigger:schedule:prepare | triggerIds | triggerId |
resource:collection:prepare | resourceIds | resourceId |
resource:delivery:prepare | resourceIds | resourceId |
input:keydown лучше DOM-слушателя: он стоит в собственной цепочке ввода игры, по порядку, и его cancel() игра уважает. building:place может запретить постройку, которую мод считает недопустимой, — ни одно событие этого не умеет.Патчинг игры
То, что большинство упускает: обычный мод из Workshop уже умеет переписывать бандл игры. Без загрузчика, без инсталлятора, не трогая app.asar.
Область
Любой .js внутри игровой папки js/. Абсолютные пути, сегменты .. и буквы дисков отклоняются.
Дисциплина
expectedMatches обязан быть положительным целым, и патч отклоняется, если реальное число совпадений другое — так обновление игры ломает мод громко.
Атомарность
Патчи с общим atomicGroup применяются вместе. Один промах откатывает всю группу, остальные помечаются пропущенными.
applied, actualMatches и reason вроде atomic_group_rolled_back — и не показывает игроку ничего из этого. Вот эта дыра и ждёт своего мода.Main API 281 методов
Отсортировано по размеру. Раскрой неймспейс, чтобы увидеть методы, число аргументов и функцию движка за каждым из них.
structuresРегистрация машин, патчинг существующих, чтение и изменение построенного.31
| метод | арг. | вызов движка |
|---|---|---|
recipes.register | — | — |
processing.register | 2 | structures.processing.register |
processing.isEnabledAt | 2 | structures.processing.isEnabledAt |
processing.setEnabledAt | 3 | structures.processing.setEnabledAt |
addProcessor | 2 | structures.addProcessor |
register | 2 | structures.register |
updateDefinition | 3 | structures.updateDefinition |
addVariant | 3 | structures.addVariant |
forEachOfType | 2 | structures.forEachOfType |
registerPlacementConfig | 1 | structures.registerPlacementConfig |
getAtCell | 2 | structures.getAtCell |
getDefinitionByType | 1 | structures.getConfig |
getUnlockedTypes | 0 | structures.getUnlockedTypes |
getTypeFromId | 1 | structures.resolveTypeName |
hasBuiltAtCell | 2 | structures.hasBuiltAtCell |
isBlockedByPlayerAtCell | 2 | structures.isBlockedByPlayer |
isLauncherAtCell | 2 | structures.isLauncherAt |
isType | 2 | structures.isType |
isTypeAtCell | 3 | structures.isTypeAt |
isUnlockedByType | 1 | structures.isUnlocked |
mapValueToSpritesheetIndex | — | structures.mapValueToSpritesheetIndex |
setSpritesheetIndex | 2 | structures.setSpritesheetIndex |
setSpritesheetIndexAtCell | 3 | structures.setSpritesheetIndexAt |
setSpritesheetIndexByValue | 3 | structures.setSpritesheetIndexByValue |
setSpritesheetIndexByValueAtCell | 4 | structures.setSpritesheetIndexByValueAt |
update | 2 | structures.update |
setData | 3 | structures.setData |
buildAtCellWhenIdle | 4 | world.runWhenSimulationIdle, structures.build |
removeAtCellWhenIdle | 3 | world.runWhenSimulationIdle, structures.removeAt |
removeBetweenCellsWhenIdle | 5 | world.runWhenSimulationIdle, structures.removeBetween |
removeAtCellsWhenIdle | 2 | world.runWhenSimulationIdle, structures.removeAtPositions |
elementsРегистрация песка, жидкостей и газов; чтение и запись отдельных клеток.29
| метод | арг. | вызов движка |
|---|---|---|
getRegisteredTypes | 0 | elements.getRegisteredTypes |
register | 1 | elements.register |
updateDefinition | 2 | elements.updateDefinition |
addInteractionInfo | 2 | elements.addInteractionInfo |
getTypeFromId | 1 | elements.getElementTypeFromId |
getNameByType | 1 | elements.getName |
getDefinitionByType | 1 | elements.getConfig |
getTypeAtCell | 2 | elements.getTypeAtCell |
getResolvedTypeAtCell | 2 | elements.getResolvedTypeAtCell |
getResolvedTypeFromCellId | 1 | elements.getResolvedTypeFromCellId |
getInfoAtCell | 2 | elements.getInfoAtCell |
getMatterTypeAtCell | 2 | elements.getMatterTypeAtCell |
isTypeAtCell | 3 | elements.isTypeAt |
isFreeFallingAtCell | 2 | elements.getResolvedTypeAtCell, elements.isFreeFalling |
findFreeCellInStructure | 3 | elements.findFreePositionInStructure |
createAtCellWhenIdle | 4 | world.isCellEmpty, elements.createAt |
replaceAtCellWhenIdle | 4 | world.getCellId, world.mutateCellWhenIdle, elements.replaceAt |
removeAtCellWhenIdle | 3 | elements.getResolvedTypeAtCell, elements.removeAt |
teleportBetweenCellsWhenIdle | 4 | world.getCellId, world.runWhenSimulationIdle, elements.moveAtSimulationIdle |
getVelocityAtCell | 2 | elements.getResolvedTypeAtCell, elements.getVelocity |
setVelocityAtCellWhenIdle | 3 | elements.setVelocity |
addParticleVelocityAtCellWhenIdle | 4 | elements.addParticleVelocity |
convertToParticleAtCellWhenIdle | 3 | elements.convertToParticle |
convertFromParticleAtCellWhenIdle | 2 | elements.convertFromParticle |
getDataFieldAtCell | 3 | elements.getResolvedTypeAtCell, elements.getDataField |
setDataFieldAtCellWhenIdle | 4 | elements.getResolvedTypeAtCell, elements.setDataField |
refreshColorAtCellWhenIdle | 2 | elements.refreshColorAt |
setPhysicsAtCellWhenIdle | 3 | elements.getResolvedTypeAtCell, elements.setPhysics, world.reportActivityToChunk |
setDurationAtCellWhenIdle | 4 | elements.getResolvedTypeAtCell, elements.setDuration |
i18nКлючи перевода, смена локали, форматирование чисел.17
| метод | арг. | вызов движка |
|---|---|---|
t | — | i18n.t |
register | — | i18n.register |
getLocale | — | i18n.getLocale |
hasTranslation | — | i18n.hasTranslation |
setLocale | — | i18n.setLocale |
getLanguages | — | i18n.getLanguages |
getAvailableLocales | — | i18n.getAvailableLocales |
formatNumber | — | i18n.formatNumber |
key | — | i18n.key |
getName | — | i18n.getName |
getDescription | — | i18n.getDescription |
translatable | — | i18n.translatable |
setGlobal | — | i18n.setGlobal |
getGlobal | — | i18n.getGlobal |
clearGlobal | — | i18n.clearGlobal |
getGlobals | — | i18n.getGlobals |
formatKeyForDisplay | — | i18n.formatKeyForDisplay |
uiВнедрение React, слоты оверлеев, тосты, диалоги, фокус геймпада.14
| метод | арг. | вызов движка |
|---|---|---|
update | 2 | ui.update |
openPauseMenu | 0 | ui.openPauseMenu |
showTooltip | 1 | ui.showTooltip |
toast | 2 | ui.toast |
alert | 2 | ui.alert |
confirm | 2 | ui.confirm |
prompt | 5 | ui.prompt |
overlays.register | 3 | ui.overlays.register |
overlays.unregister | 2 | ui.overlays.unregister |
overlays.update | 1 | ui.overlays.update |
inject | 2 | ui.overlays.register, ui.overlays.unregister |
navigation.useFocusable | — | — |
navigation.useFocusScope | — | — |
navigation.controllerFocusClass | — | — |
terrainsРегистрация террейна; чтение и повреждение слоя террейна.13
| метод | арг. | вызов движка |
|---|---|---|
register | 1 | terrains.register |
updateDefinition | 2 | terrains.updateDefinition |
getTypeFromId | 1 | terrains.getTypeByName |
getTypeAtCell | 2 | terrains.getTypeAtCell |
getDataAtCell | 2 | terrains.getTerrainData |
isAtCell | 2 | terrains.isAtCell |
isTypeAtCell | 3 | terrains.isTypeAtCell |
isCellIdTerrain | — | terrains.isCellIdTerrain |
createAtCellWhenIdle | 4 | world.isCellEmpty, terrains.createAt |
replaceAtCellWhenIdle | 4 | world.getCellId, world.mutateCellWhenIdle, terrains.replaceAt |
removeAtCellWhenIdle | 3 | world.getCellId, terrains.isCellIdTerrain, terrains.removeAt |
damageAtCell | 3 | terrains.damageTerrain |
setHpAtCellWhenIdle | 3 | terrains.isAtCell, terrains.setTerrainHP |
worldId клеток, туман, раскопки, выпавшие предметы.13
| метод | арг. | вызов движка |
|---|---|---|
getCellIdAtCell | 2 | world.getCellId |
isCellEmptyAtCell | 2 | world.isCellEmpty |
isTerrainAtCell | 2 | world.isTerrainAt |
runWhenSimulationIdle | 1 | world.runWhenSimulationIdle |
reportActivityAtCell | 2 | world.reportActivityToChunk |
excavateAtCell | 5 | world.excavate |
revealFogAtCell | 2 | world.revealFogAtCell |
redrawAroundCellWhenIdle | 3 | world.mutateCellWhenIdle, world.redrawSurroundingCells |
pickups.spawnAtWorld | 5 | world.pickups.spawn |
pickups.destroy | 1 | world.pickups.destroy |
pickups.pickUp | 1 | world.pickups.pickUp |
pickups.getAll | 0 | world.pickups.getAll |
pickups.getById | 1 | world.pickups.getById |
playerПозиция, движение, инвентарь, разблокированные постройки.12
| метод | арг. | вызов движка |
|---|---|---|
getWorldPosition | 0 | player.getPosition |
setWorldPosition | 2 | player.setPosition |
setVelocity | 2 | player.setVelocity |
setMovementSpeedMultiplier | 1 | player.setMovementSpeedMultiplier |
setMovementMode | 1 | player.setMovementMode |
isOnGround | 0 | player.isOnGround |
teleportToGround | 0 | player.teleportToGround |
isCollidingWithCell | 2 | player.isCollidingWithCell |
isWithinRadiusOfCell | 3 | player.isWithinRadius |
isWorldPositionClear | 2 | player.isPositionClear |
inventory.addFromId | 1 | player.inventory.add |
buildings.unlockByType | 1 | player.buildings.add |
inputПривязки клавиш, позиция мыши в клетках, состояние модификаторов.10
| метод | арг. | вызов движка |
|---|---|---|
registerBinding | 3 | input.registerKeyBinding |
getMouseCellPosition | 0 | input.getMouseCellPosition |
getBoundKeys | 1 | input.getBoundKeys |
getDisplayKey | 2 | input.getDisplayKey |
triggerBinding | 1 | input.triggerBinding |
pressBinding | 1 | input.pressBinding |
releaseBinding | 1 | input.releaseBinding |
resetMouseState | 0 | input.resetMouseState |
isCtrlHeld | 0 | input.isCtrlHeld |
isAltHeld | 0 | input.isAltHeld |
projectilesРегистрация и спавн снарядов.7
| метод | арг. | вызов движка |
|---|---|---|
register | 1 | projectiles.register |
getDefinitionById | 1 | — |
createBlueprintFromId | 1 | projectiles.createBlueprint |
getAll | 0 | projectiles.getAll |
getById | 1 | projectiles.getAll |
remove | 1 | projectiles.remove |
spawnAtWorld | 4 | projectiles.spawn |
soundПроигрывание звуков, слои, затухание по расстоянию.7
| метод | арг. | вызов движка |
|---|---|---|
play | 2 | sound.play |
playActive | 2 | sound.playActive |
playLayers | 2 | sound.playLayers |
calculateDistanceOptionsAtWorld | 3 | sound.calculateDistanceOptions |
stopById | 1 | sound.stop |
stopActive | 0 | sound.stopActive |
stopAll | 0 | sound.stopAll |
storageХранение данных мода — в сейве или локально на машине.7
| метод | арг. | вызов движка |
|---|---|---|
ensure | 1 | storage.ensure |
get | 2 | storage.get |
set | 3 | storage.set |
remove | 2 | storage.remove |
local.get | — | storage.local.get |
local.set | — | storage.local.set |
local.remove | — | storage.local.remove |
authorizationМожно ли игроку строить, копать и применять инструменты в клетке.6
| метод | арг. | вызов движка |
|---|---|---|
canBuildAtCell | 2 | authorization.canBuild |
canGrabAtCell | 2 | authorization.canGrab |
canUseTool | 2 | authorization.canUseTool |
canUseToolAtCell | 3 | authorization.canUseToolAt |
getZoneIdAtCell | 2 | authorization.getZoneIdAt |
getPlayerZoneId | 0 | authorization.getPlayerZoneId |
effectsЧастицы, временные источники света, лучи, волны искажения.6
| метод | арг. | вызов движка |
|---|---|---|
createDistortionWaveAtWorld | 3 | effects.createDistortionWave |
createEffectAtWorld | 4 | effects.createEffect |
createLaserAtWorld | 5 | effects.createLaser |
createLightAtWorld | 3 | effects.createLight |
createParticlesAtWorld | 3 | effects.createParticles |
removeLightById | 1 | effects.removeLight |
energyВход в энергосеть, выработка и потребление энергии.6
| метод | арг. | вызов движка |
|---|---|---|
registerType | 3 | energy.registerType |
addAtCell | 4 | energy.add |
consume | 2 | energy.consume |
consumeExcludingNetworkAtCell | 3 | energy.consumeExcludingNetwork |
getNetworkAtCell | 2 | energy.getNetwork |
getNetworkFreeCapacityAtCell | 2 | energy.getNetworkFreeCapacity |
itemsРегистрация предметов инвентаря и инструментов.6
| метод | арг. | вызов движка |
|---|---|---|
register | 1 | items.register |
updateDefinition | 2 | items.updateDefinition |
getDefinitionById | 1 | — |
createFromId | 1 | items.create |
getActive | 0 | items.getActive |
isActiveById | 2 | items.isActive |
lightsВременный свет для эффектов и постоянный свет в мире.6
| метод | арг. | вызов движка |
|---|---|---|
vfx.createAtWorld | — | — |
vfx.removeById | — | — |
persistent.createAtWorld | 3 | lights.persistent.create |
persistent.removeAtWorld | 2 | lights.persistent.removeAt |
persistent.fadeAtWorld | 3 | lights.persistent.fadeAt |
persistent.markDirty | 0 | lights.persistent.markDirty |
techЧтение, правка и добавление узлов дерева технологий.6
| метод | арг. | вызов движка |
|---|---|---|
getDefinitionById | — | tech.getDefinition |
updateDefinition | — | tech.updateDefinition |
addDefinition | — | tech.addDefinition |
registerNode | — | tech.registerNode |
isLockedById | 1 | tech.isLocked |
setLockedById | 2 | tech.setLocked |
collectorЦенность клеток в золоте и уведомление о подборе.5
| метод | арг. | вызов движка |
|---|---|---|
getValueFromCellId | 1 | collector.getValueFromCellId |
getValueByType | 1 | collector.getValueFromElementType |
isCellIdCollectable | 1 | collector.isCellCollectable |
isCellIdCollectableForSprite | 1 | collector.isCellCollectableForSprite |
notifyPickupAtCell | 2 | collector.notifyPickup |
spritesЗагрузка текстур, в том числе из папки самого мода.5
| метод | арг. | вызов движка |
|---|---|---|
load | 3 | sprites.load |
loadFromMod | 3 | sprites.load |
getById | 1 | sprites.get |
hideAllPlayerModSprites | 0 | sprites.hideAllPlayerModSprites |
rotatePlayerModSprites | 1 | sprites.rotatePlayerModSprites |
upgradesРегистрация категорий улучшений и уровней.5
| метод | арг. | вызов движка |
|---|---|---|
registerCategory | 1 | upgrades.registerCategory |
register | 1 | upgrades.register |
updateDefinition | 3 | upgrades.updateDefinition |
getLevelById | 2 | upgrades.getLevel |
getAvailableLevelById | 2 | upgrades.getAvailableLevel |
buildingПривязка к сетке при постройке, блокировка, выбор постройки.4
| метод | арг. | вызов движка |
|---|---|---|
getSnappedPositionAtCell | 2 | building.getSnappedCellPosition |
isBlockedAtCell | 2 | building.isBlockedByTerrainOrElements |
cancelPlacement | 0 | building.cancelPlacement |
selectStructure | 1 | building.selectStructure |
renderingПозиции отрисовки, метрики сетки, контекст оверлея, шейдеры.4
| метод | арг. | вызов движка |
|---|---|---|
getDrawPositionAtCell | 2 | rendering.getCellDrawPos |
getGridMetrics | 0 | rendering.getGridMetrics |
getOverlayViewportSize | 0 | rendering.getOverlayViewportSize |
withOverlayContext | 1 | rendering.withOverlayContext |
toolsРазмер и состояние захвата.4
| метод | арг. | вызов движка |
|---|---|---|
grabber.setSize | 1 | tools.setGrabberSize |
grabber.getSize | 0 | tools.getGrabberSize |
grabber.isActive | 0 | tools.isGrabberActive |
grabber.isLoaded | 0 | tools.isGrabberLoaded |
utilsРасстояние, направление, угол, линия между точками.4
| метод | арг. | вызов движка |
|---|---|---|
getDistance | — | utils.getDistance |
getDirection | — | utils.getDirection |
getAngle | — | utils.getAngle |
getCoordinatesBetweenPoints | — | utils.getCoordinatesBetweenPoints |
actionАктивное и выбранное действие и его произвольные данные.3
| метод | арг. | вызов движка |
|---|---|---|
getActive | 0 | action.getActive |
getSelected | 0 | action.getSelected |
setCustomData | 1 | action.setCustomData |
assetsURL ассетов и выбор провайдера.3
| метод | арг. | вызов движка |
|---|---|---|
getUrl | 1 | (local) x.o |
getSelectedProvider | 1 | (local) L.Ob |
selectProvider | 2 | (local) L.jq |
cameraФокус и слежение.3
| метод | арг. | вызов движка |
|---|---|---|
snapToPlayer | 0 | camera.snapToPlayer |
setFocusAtWorld | 2 | camera.setFocusAtWorld |
releaseFocus | 1 | camera.releaseFocusToPlayer |
mapsАктивная и доступные карты; запуск карты.3
| метод | арг. | вызов движка |
|---|---|---|
getActive | 0 | maps.getActive |
getAvailable | 0 | maps.getAvailable |
start | 1 | maps.start |
processingРецепты для грядки, шейкера и kinetic press.3
| метод | арг. | вызов движка |
|---|---|---|
registerGrower | 1 | — |
registerShaker | 1 | — |
registerKineticPress | 1 | — |
settingsСобственные настройки мода и уведомления об их изменении.3
| метод | арг. | вызов движка |
|---|---|---|
get | 1 | — |
getAll | 0 | (local) W.FG |
onChange | 1 | — |
cooldownОбщие таймеры перезарядки.2
| метод | арг. | вызов движка |
|---|---|---|
check | 2 | cooldown.check |
isReady | 2 | cooldown.isReady |
discoveriesЧто игрок уже открыл.2
| метод | арг. | вызов движка |
|---|---|---|
addElementByType | 1 | discoveries.addElement |
addTerrainByType | 1 | discoveries.addTerrain |
eventsПодписка на игровые события и их отправка.2
| метод | арг. | вызов движка |
|---|---|---|
on | 2 | events.on |
emit | 2 | events.emit |
fireГорит ли клетка и поджигание.2
| метод | арг. | вызов движка |
|---|---|---|
canBurnElementAtCell | 2 | fire.canBurnElementAt |
burnElementAtCellWhenIdle | 2 | fire.canBurnElementAt, fire.burnElementAt |
gameConfigЧтение конфигурации игры.2
| метод | арг. | вызов движка |
|---|---|---|
get | 1 | (local) D.nO |
getAll | 0 | (local) D.dx |
gridОбход клеток в прямоугольнике или круге.2
| метод | арг. | вызов движка |
|---|---|---|
forEachCellInRect | 5 | grid.iterateRect |
forEachCellInCircle | 4 | grid.iterateCircle |
hooksПерехват (отмена) или изменение вызовов движка.2
| метод | арг. | вызов движка |
|---|---|---|
intercept | 3 | hooks.intercept |
modify | 3 | hooks.modify |
patternsКруговые паттерны и раскопки по паттерну.2
| метод | арг. | вызов движка |
|---|---|---|
createCircle | — | patterns.createCircle |
excavateAtCell | 6 | patterns.excavate |
randomЦелые и вещественные из сидированного генератора.2
| метод | арг. | вызов движка |
|---|---|---|
int | — | random.int |
float | — | random.float |
resourcesКоличество ресурсов.2
| метод | арг. | вызов движка |
|---|---|---|
collectFluxiteAtCell | 2 | resources.collectFluxiteAtCell |
updateEnergy | 2 | resources.updateEnergy |
sharedSharedArrayBuffer — единственный канал из main в worker.2
| метод | арг. | вызов движка |
|---|---|---|
buffers.create | 2 | workers.shared.create |
buffers.get | 1 | workers.shared.get |
structureBehaviorsПревращение постройки в конвейер или лаунчер.2
| метод | арг. | вызов движка |
|---|---|---|
registerConveyorType | 2 | conveyors.registerType |
registerLauncherType | 1 | launchers.registerType |
timeМиллисекунды и счётчик тиков.2
| метод | арг. | вызов движка |
|---|---|---|
getTimeMs | 0 | — |
getTick | 0 | — |
excavationРегистрация профилей раскопок.1
| метод | арг. | вызов движка |
|---|---|---|
registerProfile | 2 | excavation.registerProfile |
modsПровайдеры ассетов из других модов.1
| метод | арг. | вызов движка |
|---|---|---|
getProviders | 1 | (local) L.KT |
progressionЗавершение шагов прогрессии.1
| метод | арг. | вызов движка |
|---|---|---|
complete | 1 | progression.complete |
raycastЛуч сквозь мир.1
| метод | арг. | вызов движка |
|---|---|---|
castFromWorld | 4 | raycast.cast |
reactionsРегистрация реакций между элементами.1
| метод | арг. | вызов движка |
|---|---|---|
registerContact | 1 | reactions.registerContact |
sceneКакой экран активен. MainMenu 1, Intro 2, Deploy 3, Game 4.1
| метод | арг. | вызов движка |
|---|---|---|
getActive | 0 | scene.getActive |
scheduleОтложенные колбэки.1
| метод | арг. | вызов движка |
|---|---|---|
nextTick | 1 | schedule.nextTick |
signalsРегистрация постройки как цели сигнала.1
| метод | арг. | вызов движка |
|---|---|---|
targets.register | 2 | signals.targets.register |
triggersРегистрация повторяющегося таймера.1
| метод | арг. | вызов движка |
|---|---|---|
register | 2 | triggers.register |
workersПереключение post-update на симуляционных воркерах.1
| метод | арг. | вызов движка |
|---|---|---|
setPostUpdateEnabled | 1 | workers.shared.create |
Worker API 88 методов
Вчетверо меньше, и это намеренно: этот поток существует, чтобы быстро трогать клетки.
elementsПрямое чтение и запись клеток — здесь и место работе с отдельными частицами.26
| метод | арг. | вызов движка |
|---|---|---|
getTypeFromId | 1 | elements.getElementTypeFromId |
getDefinitionByType | 1 | elements.getConfig |
getTypeAtCell | 2 | elements.getTypeAtCell |
getResolvedTypeAtCell | 2 | elements.getResolvedTypeAtCell |
getResolvedTypeFromCellId | 1 | elements.getResolvedTypeFromCellId |
getInfoAtCell | 2 | elements.getInfoAtCell |
getMatterTypeAtCell | 2 | elements.getMatterTypeAtCell |
isTypeAtCell | 3 | elements.isTypeAt |
isFreeFallingAtCell | 2 | elements.getResolvedTypeAtCell, elements.isFreeFalling |
createAtCell | 4 | world.isCellEmpty, elements.createAt |
replaceAtCell | 4 | elements.replaceAt |
removeAtCell | 3 | elements.getResolvedTypeAtCell, elements.removeAt |
moveBetweenCells | 4 | elements.move |
teleportBetweenCells | 4 | elements.teleport |
swapCells | 4 | elements.swap |
getVelocityAtCell | 2 | elements.getResolvedTypeAtCell, elements.getVelocity |
setVelocityAtCell | 3 | elements.setVelocity |
addParticleVelocityAtCell | 4 | elements.addParticleVelocity |
convertToParticleAtCell | 3 | elements.convertToParticle |
convertFromParticleAtCell | 2 | elements.convertFromParticle |
getDataFieldAtCell | 3 | elements.getResolvedTypeAtCell, elements.getDataField |
setDataFieldAtCell | 4 | elements.getResolvedTypeAtCell, elements.setDataField |
refreshColorAtCell | 2 | elements.refreshColorAt |
markMovementBlockedByElementIndex | 1 | elements.markMovementBlocked |
setPhysicsAtCell | 3 | elements.getResolvedTypeAtCell, elements.setPhysics, world.reportActivityToChunk |
setDurationAtCell | 4 | elements.getResolvedTypeAtCell, elements.setDuration |
structuresПроверка, что построено в клетке, и чтение состояния обработки.14
| метод | арг. | вызов движка |
|---|---|---|
processing.isEnabledAt | 2 | structures.processing.isEnabledAt |
getAtCell | 2 | structures.getAtCell |
getDefinitionByType | 1 | structures.getConfig |
getTypeFromId | 1 | structures.resolveTypeName |
hasBuiltAtCell | 2 | structures.hasBuiltAtCell |
isType | 2 | structures.isType |
isTypeAtCell | 3 | structures.isTypeAt |
forEachOfType | 2 | structures.forEachOfType |
update | 2 | structures.update |
setData | 3 | structures.setData |
setSpritesheetIndex | 2 | structures.setSpritesheetIndex |
setSpritesheetIndexAtCell | 3 | structures.setSpritesheetIndexAt |
setSpritesheetIndexByValue | 3 | structures.setSpritesheetIndexByValue |
setSpritesheetIndexByValueAtCell | 4 | structures.setSpritesheetIndexByValueAt |
terrainsЧтение, создание и повреждение террейна из симуляционного потока.11
| метод | арг. | вызов движка |
|---|---|---|
getTypeFromId | 1 | terrains.getTypeByName |
getTypeAtCell | 2 | terrains.getTypeAtCell |
getDataAtCell | 2 | terrains.getTerrainData |
isAtCell | 2 | terrains.isAtCell |
isTypeAtCell | 3 | terrains.isTypeAtCell |
isCellIdTerrain | — | terrains.isCellIdTerrain |
createAtCell | 4 | world.isCellEmpty, terrains.createAt |
replaceAtCell | 4 | terrains.replaceAt |
removeAtCell | 3 | world.getCellId, terrains.isCellIdTerrain, terrains.removeAt |
damageAtCell | 3 | terrains.damageTerrain |
setHpAtCell | 3 | terrains.setTerrainHP |
collectorСобираемая ценность клетки.5
| метод | арг. | вызов движка |
|---|---|---|
getValueFromCellId | 1 | collector.getValueFromCellId |
getValueByType | 1 | collector.getValueFromElementType |
isCellIdCollectable | 1 | collector.isCellCollectable |
isCellIdCollectableForSprite | 1 | collector.isCellCollectableForSprite |
notifyPickupAtCell | 2 | collector.notifyPickup |
worldId клеток, пустота, отметка активности, раскопки.5
| метод | арг. | вызов движка |
|---|---|---|
getCellIdAtCell | 2 | world.getCellId |
isCellEmptyAtCell | 2 | world.isCellEmpty |
isTerrainAtCell | 2 | world.isTerrainAt |
reportActivityAtCell | 2 | world.reportActivityToChunk |
excavateAtCell | 5 | world.excavate |
utilsРасстояние, направление, угол, линия между точками.4
| метод | арг. | вызов движка |
|---|---|---|
getDistance | — | utils.getDistance |
getDirection | — | utils.getDirection |
getAngle | — | utils.getAngle |
getCoordinatesBetweenPoints | — | utils.getCoordinatesBetweenPoints |
effectsЧастицы и свет, поднятые из воркера.3
| метод | арг. | вызов движка |
|---|---|---|
createEffectAtWorld | 4 | effects.createEffect |
createLightAtWorld | 3 | effects.createLight |
createParticlesAtWorld | 3 | effects.createParticles |
playerПозиция игрока и проверки близости.3
| метод | арг. | вызов движка |
|---|---|---|
getWorldPosition | 0 | player.getPosition |
isCollidingWithCell | 2 | player.isCollidingWithCell |
isWithinRadiusOfCell | 3 | player.isWithinRadius |
eventsПодписка на события симуляции. Некоторым нужен гвард.2
| метод | арг. | вызов движка |
|---|---|---|
on | 3 | — |
emit | 3 | — |
fireГорит ли клетка и поджигание.2
| метод | арг. | вызов движка |
|---|---|---|
canBurnElementAtCell | 2 | fire.canBurnElementAt |
burnElementAtCell | 2 | fire.canBurnElementAt, fire.burnElementAt |
hooksПерехват и изменение вызовов движка внутри симуляции.2
| метод | арг. | вызов движка |
|---|---|---|
intercept | 3 | — |
modify | 3 | — |
patternsКруговые паттерны и раскопки по паттерну.2
| метод | арг. | вызов движка |
|---|---|---|
createCircle | — | patterns.createCircle |
excavateAtCell | 6 | patterns.excavate |
randomЦелые и вещественные из сидированного генератора.2
| метод | арг. | вызов движка |
|---|---|---|
int | — | random.int |
float | — | random.float |
sharedЧтение буферов, созданных энтри main.2
| метод | арг. | вызов движка |
|---|---|---|
buffers.require | 2 | workers.shared.get |
buffers.get | 1 | workers.shared.get |
workerИндекс этого потока и общее число потоков.2
| метод | арг. | вызов движка |
|---|---|---|
getIndex | 0 | — |
getCount | 0 | — |
mainОтправка события в главный поток. Единственный выход отсюда.1
| метод | арг. | вызов движка |
|---|---|---|
emitEvent | 2 | — |
mapsАктивная карта.1
| метод | арг. | вызов движка |
|---|---|---|
getActive | 0 | maps.getActive |
uiТосты. Это весь здешний UI.1
| метод | арг. | вызов движка |
|---|---|---|
toast | 2 | ui.toast |
Каталоги значений
Таблицы выше говорят, что мод может вызвать. Здесь — значения, которые стоит передавать: собраны из того же кода игры, поэтому перегенерируются вместе с ней.
Идентификаторы звуков (63)
Всё, что сама игра передаёт своему звуковому движку, — проигрывается через sound.play(id, options); затухание по расстоянию даёт calculateDistanceOptionsAtWorld, а rateLimitKey позволяет сотне машин звучать одним голосом.
Ambience-группы структур для поля ambienceGroup в render: clearingFrames, conveyors, launchers, shakers, steamTurbines.
Дефолты gameConfig (81)
То, что возвращает gameConfig.getAll(), пока его никто не переопределил, — включая флаги, которых нет ни в одном меню настроек. customMaps.showCustomMaps и mods.showSubscribedMods поставляются со значением false: целые фичи за одним булем. Поддерево procgen — ручки генератора карт, вплоть до seed.
gameConfigвсе дефолты, в порядке исходника81
| ключ | дефолт |
|---|---|
version | "…" |
fps | 60 |
lockFps | false |
chunkSize | 40 |
cellSize | 4 |
gravity | "…" |
upflow | "…" |
snapGridCellSize | 4 |
startingResources | 0 |
debug.active | false |
debug.showUnderlyingCellsInStructures | true |
debug.drawChunks | false |
debug.drawChunkFade | 60 |
debug.drawRulers | false |
debug.showThreadLoad | true |
debug.controls | true |
debug.defaultBaseHue | 35 |
debug.brushSize | 3 |
debug.brushShape | "circle" |
debug.brushThrottle | 0 |
debug.highlightBrush | true |
debug.preventDuplicateCells | false |
debug.doNotDrawStructures | false |
debug.stopOnDebugCellUpdate | false |
debug.overrideLightSize | false |
debug.overrideTerrainShadow | false |
debug.lightSize | 700 |
debug.terrainShadowValue | 0.995 |
debug.flashlight.brightness | 2 |
debug.flashlight.size | 200 |
debug.flashlight.duration | 100 |
debug.flashlight.color | "[…]" |
debug.gameOfLife | "…" |
debug.countEvents | false |
debug.strictSafeguards | false |
debug.showLights | false |
debug.showProximityFade | true |
debug.showFilters | false |
debug.showAuthorizationZones | false |
debug.showProximityFadeSelectedOnly | false |
debug.selectedLightIndex | -1 |
debug.cellInspector | false |
debug.badDisplays | false |
debug.i18nDebug.mode | "off" |
debug.i18nDebug.pseudo.brackets | true |
debug.i18nDebug.pseudo.accentChars | true |
debug.i18nDebug.pseudo.padPercent | 0.3 |
debug.i18nDebug.randomScript.script | "chinese" |
debug.i18nDebug.randomScript.lengthMultiplier | 1 |
conveyorDefaultSpeed | 0.05 |
useMultithreading | true |
useExperimentalRenderer | false |
obstacleBreakpoint | 100 |
playerSize.width | 12 |
playerSize.height | 30 |
matrixCompression.padding | 100 |
blueprintEncoding | "binary" |
mods.showSubscribedMods | false |
customMaps.showCustomMaps | false |
procgen.useProcgenMap | true |
procgen.showGeneratedMap | false |
procgen.logPerformance | true |
procgen.logVerbosity | 1 |
procgen.params.width | 3840 |
procgen.params.height | 3840 |
procgen.params.scale | 0.005 |
procgen.params.threshold | 0.02 |
procgen.params.cellSize | 1 |
procgen.params.seed | "…" |
procgen.prefabPlacementBufferCells | 20 |
procgen.mossPatchMinDepthCells | 30 |
procgen.caveRegionLights.brightness | 1 |
procgen.caveRegionLights.size | 200 |
procgen.leftWall.enabled | false |
procgen.leftWall.startPosition | 0.2 |
procgen.leftWall.steepness | 0.01 |
procgen.leftWall.noiseAmount | 0.15 |
procgen.leftWall.entrance.enabled | false |
procgen.leftWall.entrance.width | 200 |
procgen.leftWall.entrance.height | 120 |
procgen.saveGeneratedMap | false |
window.electron (65)
Preload-мост Electron. Моды исполняются в том же renderer, поэтому всё это достижимо из мода: openDevTools(), экспорт и импорт сейвов, папка локальных модов, управление подписками Workshop.
window.electronpreload-мост, как он поставляется65
| метод |
|---|
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) |
apiVersion. Та же категория, что sandkit.engine.api: настоящее, полезное и вольно меняться в любом патче. Оборачивайте каждый вызов, падайте мягко.За пределами api
sandkit.api — не весь объект, который получает мод. Рядом лежат ещё три члена, и ни один из них не метод: поэтому их нет в таблицах выше, и поэтому же без них не нарисовать ни одной кнопки.
sandkit.enums (22 / 323)
Перечисления самой игры, переэкспортированные поимённо. Это те числа, которых API и ждёт: ui.update(enums.ComponentId.Hotbar), scene.getActive() === enums.Scene.MainMenu, сравнение состояния клавиши с enums.KeyState.Pressed. Написать литерал вместо этого можно — ровно до патча, который перенумерует.
enums.CellType31
| член | значение |
|---|---|
Empty | 0 |
Element | 1 |
Dirt | 2 |
SporeSoil | 3 |
Fog | 4 |
FogJetpackBlock | 5 |
FogWater | 6 |
FreezingIceSoil | 7 |
Divider | 8 |
Grass | 9 |
Moss | 10 |
GoldSoil | 11 |
Petal | 12 |
FogLava | 13 |
Fluxite | 14 |
Block | 15 |
SlidingBlock | 16 |
SlidingBlockLeft | 17 |
SlidingBlockRight | 18 |
ConveyorLeft | 19 |
ConveyorRight | 20 |
ShakerLeft | 21 |
ShakerRight | 22 |
Stone | 23 |
VelocitySoaker | 24 |
Ice | 25 |
Grower | 26 |
NascentWater | 27 |
SandiumSoil | 28 |
Obsidian | 29 |
Crackstone | 30 |
enums.ElementType20
| член | значение |
|---|---|
Sand | 1 |
Particle | 2 |
Water | 3 |
WetSand | 4 |
Sandium | 5 |
Residue | 6 |
Gold | 7 |
Gloom | 8 |
Shake | 9 |
Steam | 10 |
Fire | 11 |
FreezingIce | 12 |
Flame | 13 |
BurntResidue | 14 |
Seed | 15 |
WetSeed | 16 |
Seedling | 17 |
Petalium | 18 |
Lava | 19 |
Basalt | 20 |
enums.MatterType8
| член | значение |
|---|---|
Solid | 1 |
Liquid | 2 |
Particle | 3 |
Gas | 4 |
Static | 5 |
Slushy | 6 |
Wisp | 7 |
Powder | 8 |
enums.StructureType27
| член | значение |
|---|---|
ConveyorLeft | 1 |
ConveyorRight | 2 |
ShakerLeft | 3 |
ShakerRight | 4 |
LauncherUp | 5 |
LauncherLeft | 6 |
LauncherRight | 7 |
SplitterLeft | 8 |
SplitterRight | 9 |
Dropper | 10 |
Foundation | 11 |
FoundationAngledLeft | 12 |
FoundationTriangleLeftDel | 13 |
FoundationAngledRight | 14 |
FoundationTriangleRightDel | 15 |
Collector | 16 |
FilterLeft | 17 |
FilterRight | 18 |
SlidingFoundation | 19 |
VelocitySoaker | 20 |
Grower | 21 |
SoundBox | 22 |
Pipe | 23 |
Pump | 24 |
LiquidVent | 25 |
Light | 26 |
FluxEmanator | 27 |
enums.ItemType4
| член | значение |
|---|---|
Weapon | 1 |
Tool | 2 |
Consumable | 3 |
Mod | 4 |
enums.ItemId16
| член | значение |
|---|---|
Shovel | 1 |
Grabber | 2 |
Demolisher | 3 |
GrapplingHook | 4 |
Vacuum | 5 |
Gun | 6 |
Copier | 7 |
RocketLauncher | 8 |
Digger | 9 |
Shotgun | 10 |
Teleporter | 11 |
Flamethrower | 12 |
PipeRemover | 13 |
Hauler | 14 |
Cryoblaster | 15 |
MegaShotgun | 16 |
enums.ProjectileType6
| член | значение |
|---|---|
Bullet | 1 |
Rocket | 2 |
GrapplingHook | 3 |
Fire | 4 |
Digger | 5 |
Mod | 6 |
enums.ActionType4
| член | значение |
|---|---|
Weapon | 1 |
Building | 2 |
Tool | 3 |
Mod | 4 |
enums.ActionState3
| член | значение |
|---|---|
Start | 1 |
Active | 2 |
End | 3 |
enums.AbilityType4
| член | значение |
|---|---|
Dig | 1 |
Shoot | 2 |
Spray | 3 |
Laser | 4 |
enums.ReloadType3
| член | значение |
|---|---|
Clip | 1 |
Single | 2 |
OverTime | 3 |
enums.ComponentId28
| член | значение |
|---|---|
Hotbar | 1 |
SoundBoxConfig | 2 |
Root | 4 |
Menu | 5 |
Management | 6 |
FilterConfig | 7 |
Resources | 8 |
TechTree | 9 |
Tutorial | 10 |
Loader | 11 |
Options | 12 |
ShortcutHelper | 13 |
Upgrades | 14 |
Tooltip | 15 |
Notifications | 16 |
Objectives | 17 |
DroneAdminList | 18 |
HotbarOverlays | 19 |
IntroScreen | 20 |
StoryNotifications | 21 |
FactoryProgress | 22 |
Dialogs | 23 |
GlobalOverlays | 24 |
Lexicon | 25 |
ModsScreen | 26 |
CustomMapsScreen | 27 |
CinematicPanel | 28 |
Feedback | 29 |
enums.KeyBinding27
| член | значение |
|---|---|
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
| член | значение |
|---|---|
Up | 1 |
Down | 2 |
Pressed | 3 |
Released | 4 |
All | 5 |
enums.BuildMode2
| член | значение |
|---|---|
Linear | 1 |
Rectangular | 2 |
enums.BuildingClearance4
| член | значение |
|---|---|
Available | 1 |
FullyBlocked | 2 |
PartiallyBlocked | 3 |
CanBeReplaced | 4 |
enums.AuthorizationType6
| член | значение |
|---|---|
NoJetpack | 1 |
NoGrab | 2 |
NoBuild | 3 |
NoTool | 4 |
NoExcavation | 5 |
NoToolExceptFlamethrower | 6 |
enums.DroneType2
| член | значение |
|---|---|
Digger | 1 |
Hauler | 2 |
enums.WorldItemType4
| член | значение |
|---|---|
Artifact | 1 |
GlyphKey | 2 |
Stratacore | 3 |
Orb | 4 |
enums.Scene4
| член | значение |
|---|---|
MainMenu | 1 |
Intro | 2 |
Deploy | 3 |
Game | 4 |
enums.Tech110
| член | значение |
|---|---|
Shaker | 1 |
Conveyors | 2 |
Guns1 | 3 |
Filters1 | 4 |
Flamethrower | 5 |
Gun | 6 |
KineticPress | 7 |
Guns2 | 8 |
Drones1 | 9 |
Upgrading2 | 10 |
Filters2 | 11 |
Upgrading3 | 12 |
Upgrading4 | 13 |
Upgrading5 | 14 |
Upgrading6 | 15 |
Upgrading7 | 16 |
Upgrading8 | 17 |
Upgrading9 | 18 |
Upgrading10 | 19 |
PlanterBox | 20 |
Thermo | 21 |
Rocket | 22 |
Pipes | 23 |
StaticLights | 24 |
Drones2 | 25 |
Smelter | 26 |
Tools4 | 27 |
Guns3 | 28 |
Pipes2 | 29 |
ConveyorsMk2 | 30 |
Lights2 | 31 |
Refining6 | 32 |
Refining7 | 33 |
Guns4 | 34 |
Guns5 | 35 |
Tools5 | 36 |
Tools6 | 37 |
Filters3 | 38 |
Filters4 | 39 |
Pipes3 | 40 |
Pipes4 | 41 |
Logistics3 | 42 |
Logistics4 | 43 |
Lights3 | 44 |
Lights4 | 45 |
Drones3 | 46 |
Drones4 | 47 |
Alien | 48 |
Electricity | 49 |
AlienCore | 50 |
Emanators1 | 51 |
AlienPlasmaConduits | 52 |
AlienQuantumMatrix | 53 |
AlienPlasmaCore | 54 |
AlienVoidEngine | 55 |
FlareGun | 56 |
Sweeper | 57 |
Utilities3 | 58 |
Cryoblaster | 59 |
Vacuum | 60 |
Utilities6 | 61 |
Utilities7 | 62 |
Filters | 63 |
AdvancedFilters | 64 |
Infrastructure3 | 65 |
Decorations1 | 66 |
Decorations2 | 67 |
Decorations3 | 68 |
Blocks1 | 69 |
Drill | 70 |
SteamTurbine | 71 |
Electricity3 | 72 |
Electricity4 | 73 |
Logic1 | 74 |
Logic2 | 75 |
Logic3 | 76 |
Logic4 | 77 |
Various1 | 78 |
Various2 | 79 |
Various3 | 80 |
Locator | 81 |
QuantumPortal | 82 |
VoidRift | 83 |
Blink | 84 |
Recall | 85 |
ImplosionGun | 86 |
Refining8 | 87 |
Tools7 | 88 |
Diggers | 89 |
Haulers | 90 |
Map | 91 |
ColoringTool | 92 |
SignalGate | 93 |
GrapplingHook | 94 |
GlassFoundation | 95 |
PrecisionTools | 96 |
SignalDevices | 97 |
SignalControls | 98 |
LogicGates | 99 |
RetroConsole | 100 |
WallTool | 101 |
Corraller | 102 |
PlainFoundation | 103 |
ClearingFrame | 104 |
Heatmap | 105 |
MiningLaser | 106 |
GoldBattery | 107 |
Hover | 108 |
SprintBoost | 109 |
CritterFence | 110 |
enums.TechStatus5
| член | значение |
|---|---|
Available | 0 |
Visible | 1 |
Researched | 2 |
Unknown | 3 |
Hidden | 4 |
sandkit.react (18.3.1)
Замороженная копия React самой игры. Компоненты мода рендерятся внутри её дерева, поэтому хуки работают как обычно — но брать их надо отсюда: вторая копия React в одном дереве работать не будет.
ui.inject и ui.overlays.register принимают собранные им компоненты; JSX в entry недоступен, так что это react.createElement руками или маленький помощник h().sandkit.state (424 / 1362)
Живое состояние игры, тот же объект, что и sandkit.engine.state. Сюда идут, когда в API нет геттера: буфер энергии, открытые окна, счётчики ресурсов. О его форме в поставляемом коде нет ничего, поэтому таблица снята с запущенной игры — только имена, типы и размеры, без значений.
На странице — три уровня. Дамп снят до 4 и содержит 1362 путей целиком: остальное в data/state.json. Ветки, ключи которых — id, а не структура (какие моды установлены, какие технологии в сейве), оставлены узлом без детей: обход описывал бы одну машину, а не игру — 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.environmentсборка и платформа4
| путь | тип | размер |
|---|---|---|
state.environment | object | 2 |
state.environment.context | number | |
state.environment.multithreading | object | 1 |
state.environment.multithreading.simulation | object | 16 |
state.sandkitсам слой модов — отражает то, что установлено у снявшего дамп1
| путь | тип | размер |
|---|---|---|
state.sandkit | object | 7 |
state.sessionтолько этот запуск: ввод, окна, камера, рендеринг, настройки193
| путь | тип | размер |
|---|---|---|
state.session | object | 51 |
state.session.action | object | 3 |
state.session.action.customData | null | |
state.session.action.point | object | 2 |
state.session.action.state | object | 3 |
state.session.actionLocked | boolean | |
state.session.ambience | object | 5 |
state.session.ambience.clearingFrames | object | 2 |
state.session.ambience.conveyors | object | 2 |
state.session.ambience.launchers | object | 2 |
state.session.ambience.shakers | object | 2 |
state.session.ambience.steamTurbines | object | 2 |
state.session.animations | object | 1 |
state.session.animations.player | object | 3 |
state.session.building | object | 6 |
state.session.building.activeStructureType | null | |
state.session.building.amountOfTiles | number | |
state.session.building.ignoreAngleLock | boolean | |
state.session.building.lockedAngle | null | |
state.session.building.placing | boolean | |
state.session.building.start | object | 2 |
state.session.buttons | object | 1 |
state.session.buttons.pressed | boolean | |
state.session.cache | object | 2 |
state.session.cache.pipes | object | 4 |
state.session.cache.structures | object | 4 |
state.session.camera | object | 2 |
state.session.camera.x | number | |
state.session.camera.y | number | |
state.session.cheat | object | 1 |
state.session.cheat.bypassCosts | boolean | |
state.session.cinematic | undefined | |
state.session.colors | object | 1 |
state.session.colors.scheme | object | 2 |
state.session.construction | object | 3 |
state.session.construction.demolisherActive | boolean | |
state.session.construction.marqueeActive | boolean | |
state.session.construction.rulerActive | boolean | |
state.session.debug | object | 1 |
state.session.debug.brush | object | 4 |
state.session.effects | array | 0 |
state.session.explosions | array | 0 |
state.session.externalMods | object | 6 |
state.session.externalMods.diagnostics | array of object | 3 |
state.session.externalMods.missingSavedMods | array of string | 3 |
state.session.externalMods.orderedMods | array of object | 14 |
state.session.externalMods.statuses | array of object | 14 |
state.session.externalMods.workerEntries | array of object | 1 |
state.session.externalMods.workerResults | array of object | 8 |
state.session.factoryProcessRates | Float64Array | 4 |
state.session.input | object | 9 |
state.session.input.action | object | 2 |
state.session.input.bindingStates | object | 0 |
state.session.input.currentLastKey | string | |
state.session.input.currentLastKeyCode | string | |
state.session.input.deckCursor | object | 5 |
state.session.input.deckLastManagementTab | string | |
state.session.input.keys | object | 57 |
state.session.input.mode | string | |
state.session.input.mouse | object | 10 |
state.session.lerpCamera | boolean | |
state.session.lexicon | object | 3 |
state.session.lexicon.compiled | boolean | |
state.session.lexicon.entries | array of object | 337 |
state.session.lexicon.entriesById | object | 337 |
state.session.lightZones | array of array | 150 |
state.session.lights | array of null | 100 |
state.session.mainSensorCache | object | 1 |
state.session.mainSensorCache.cache | object | 1 |
state.session.mods | object | 1 |
state.session.mods.signals | object | 13 |
state.session.monitor | object | 1 |
state.session.monitor.threads | array of object | 8 |
state.session.movementSpeedMultiplier | number | |
state.session.music | object | 2 |
state.session.music.ambient | object | 1 |
state.session.music.engine | object | 30 |
state.session.nextTickCallbacks | array | 0 |
state.session.notifications | object | 2 |
state.session.notifications.story | array | 0 |
state.session.notifications.toast | string | |
state.session.overrideCamera | boolean | |
state.session.paused | boolean | |
state.session.platform | string | |
state.session.prefabWorldItemCache | object | 1 |
state.session.prefabWorldItemCache.cache | object | 10 |
state.session.reconMode | boolean | |
state.session.rendering | object | 24 |
state.session.rendering.backgroundChannel | object | 2 |
state.session.rendering.canvas | object | 0 |
state.session.rendering.channel | object | 2 |
state.session.rendering.foregroundChannel | object | 2 |
state.session.rendering.foregroundOffscreenCanvas | object | 0 |
state.session.rendering.foregroundOffscreenContext | object | 0 |
state.session.rendering.images | object | 102 |
state.session.rendering.obstacleCanvas | object | 0 |
state.session.rendering.obstacleChannel | object | 2 |
state.session.rendering.obstacleContext | object | 0 |
state.session.rendering.obstacleOffscreenCanvas | object | 0 |
state.session.rendering.obstacleOffscreenContext | object | 0 |
state.session.rendering.offscreenCanvas | object | 0 |
state.session.rendering.offscreenContext | object | 0 |
state.session.rendering.offscreenOutlineCanvas | object | 0 |
state.session.rendering.offscreenOutlineContext | object | 0 |
state.session.rendering.overlayCanvas | object | 0 |
state.session.rendering.overlayContext | object | 0 |
state.session.rendering.pixi | object | 43 |
state.session.rendering.worldCanvas | object | 0 |
state.session.rendering.worldChannel | object | 2 |
state.session.rendering.worldContext | object | 0 |
state.session.rendering.worldOffscreenCanvas | object | 0 |
state.session.rendering.worldOffscreenContext | object | 0 |
state.session.resolution | object | 2 |
state.session.resolution.height | number | |
state.session.resolution.width | number | |
state.session.runtime | string | |
state.session.saving | boolean | |
state.session.scale | number | |
state.session.settings | object | 23 |
state.session.settings.autosaveInterval | number | |
state.session.settings.cursorScale | number | |
state.session.settings.disableBackgroundShader | boolean | |
state.session.settings.disableShadows | boolean | |
state.session.settings.externalModSettings | object | 14 |
state.session.settings.focusLoss | object | 3 |
state.session.settings.frameRateCap | number | |
state.session.settings.hardMode | boolean | |
state.session.settings.hotbarCount | number | |
state.session.settings.hybridScheduling | boolean | |
state.session.settings.keyBindings | object | 66 |
state.session.settings.locale | string | |
state.session.settings.lockHotbar | boolean | |
state.session.settings.lockSkyColor | boolean | |
state.session.settings.pipesModeView | boolean | |
state.session.settings.schedulingMode | number | |
state.session.settings.settingsVersion | number | |
state.session.settings.showFps | boolean | |
state.session.settings.sound | object | 3 |
state.session.settings.uiScale | number | |
state.session.settings.upgradesHideMax | boolean | |
state.session.settings.videoZoom | number | |
state.session.settings.windowMode | string | |
state.session.soundBox | object | 1 |
state.session.soundBox.selectedNote | object | 2 |
state.session.soundEngine | object | 8 |
state.session.soundEngine.audioContext | object | 0 |
state.session.soundEngine.gate | object | 1 |
state.session.soundEngine.globalVolume | number | |
state.session.soundEngine.limiter | object | 0 |
state.session.soundEngine.masterGain | object | 0 |
state.session.soundEngine.muted | boolean | |
state.session.soundEngine.outputLimiter | object | 0 |
state.session.soundEngine.sfx | object | 106 |
state.session.sprintBoost | object | 2 |
state.session.sprintBoost.meter | number | |
state.session.sprintBoost.recharging | boolean | |
state.session.teleportZoneCache | object | 1 |
state.session.teleportZoneCache.cache | object | 270 |
state.session.timestep | object | 2 |
state.session.timestep.frameDuration | number | |
state.session.timestep.lastTime | number | |
state.session.triggers | array of object | 26 |
state.session.ui | object | 9 |
state.session.ui.dialogs | array | 0 |
state.session.ui.discoveryPopups | array | 0 |
state.session.ui.hudHidden | boolean | |
state.session.ui.introScreen | object | 1 |
state.session.ui.listeners | object | 24 |
state.session.ui.nextListenerId | number | |
state.session.ui.overlays | object | 2 |
state.session.ui.tooltip | object | 2 |
state.session.ui.visible | boolean | |
state.session.view | object | 4 |
state.session.view.maxZoom | number | |
state.session.view.minZoom | number | |
state.session.view.zoom | number | |
state.session.view.zoomDirty | boolean | |
state.session.visualParticles | array of object | 94 |
state.session.windows | object | 13 |
state.session.windows.blueprints | object | 1 |
state.session.windows.building | object | 3 |
state.session.windows.conservatory | object | 1 |
state.session.windows.customMapsScreen | object | 1 |
state.session.windows.feedback | object | 1 |
state.session.windows.inventory | object | 1 |
state.session.windows.lexicon | object | 1 |
state.session.windows.loader | object | 1 |
state.session.windows.menu | object | 1 |
state.session.windows.modsScreen | object | 1 |
state.session.windows.options | object | 1 |
state.session.windows.techTree | object | 2 |
state.session.windows.upgrades | object | 1 |
state.session.zoomLevel | number |
state.sharedSharedArrayBuffer-ы, в которые пишут потоки симуляции83
| путь | тип | размер |
|---|---|---|
state.shared | object | 33 |
state.shared.actionState | Uint8Array | 3 |
state.shared.authorization | object | 3 |
state.shared.authorization.data | Uint8Array | 14745600 |
state.shared.authorization.height | number | |
state.shared.authorization.width | number | |
state.shared.collectorGoldCount | Uint8Array | 921600 |
state.shared.conveyorBeltsAnimationIndex | Uint8Array | 8 |
state.shared.debug | object | 1 |
state.shared.debug.cellPos | Uint16Array | 2 |
state.shared.energy | Uint32Array | 1 |
state.shared.energyBatteryDirty | Uint8Array | 921600 |
state.shared.energyChange | Uint32Array | 4 |
state.shared.gold | Uint32Array | 1 |
state.shared.goldChange | Uint32Array | 4 |
state.shared.hybridScheduling | Uint8Array | 1 |
state.shared.listenerPos | Float32Array | 2 |
state.shared.managerPerformance | Float32Array | 23 |
state.shared.mapData | object | 3 |
state.shared.mapData.data | Uint8Array | 58982400 |
state.shared.mapData.height | number | |
state.shared.mapData.width | number | |
state.shared.mods | object | 19 |
state.shared.mouse | object | 1 |
state.shared.mouse.worldPosition | Uint16Array | 2 |
state.shared.mutationSync | Int32Array | 1 |
state.shared.naturalAmbience | Float32Array | 8 |
state.shared.playerPos | Float32Array | 2 |
state.shared.productionPoints | Uint32Array | 1 |
state.shared.reservoir | Uint16Array | 1 |
state.shared.schedulingMode | Uint8Array | 1 |
state.shared.shadowMap | object | 3 |
state.shared.shadowMap.data | Uint8Array | 14745600 |
state.shared.shadowMap.height | number | |
state.shared.shadowMap.width | number | |
state.shared.sim | object | 20 |
state.shared.sim.cellIds | Uint32Array | 14745600 |
state.shared.sim.chunkHeight | number | |
state.shared.sim.chunkShouldUpdate | Uint8Array | 9216 |
state.shared.sim.chunkShouldUpdateNext | Uint8Array | 9216 |
state.shared.sim.chunkSize | number | |
state.shared.sim.chunkWidth | number | |
state.shared.sim.damagedGround | object | 2 |
state.shared.sim.elementCapacity | number | |
state.shared.sim.elementData | object | 25 |
state.shared.sim.elementSlabsExhausted | Uint32Array | 1 |
state.shared.sim.freeDamagedIdCount | Uint32Array | 1 |
state.shared.sim.freeDamagedIds | Uint32Array | 999000 |
state.shared.sim.height | number | |
state.shared.sim.idStats | Uint32Array | 420 |
state.shared.sim.liveElementCount | Uint32Array | 1 |
state.shared.sim.nextDamagedId | Uint32Array | 1 |
state.shared.sim.nextElementSlab | Uint32Array | 1 |
state.shared.sim.overflowPool | Uint32Array | 100001 |
state.shared.sim.terrainType | Uint8Array | 1001 |
state.shared.sim.width | number | |
state.shared.wallData | object | 4 |
state.shared.wallData.data | Uint8Array | 14745600 |
state.shared.wallData.height | number | |
state.shared.wallData.paletteData | Uint8Array | 1020 |
state.shared.wallData.width | number | |
state.shared.waterPresenceZones | Uint8Array | 14400 |
state.shared.waterPresenceZonesHeight | number | |
state.shared.waterPresenceZonesWidth | number | |
state.shared.workQueue | object | 14 |
state.shared.workQueue.chunkCount | number | |
state.shared.workQueue.chunkDone | Uint8Array | 9216 |
state.shared.workQueue.chunkHeight | number | |
state.shared.workQueue.chunkWidth | number | |
state.shared.workQueue.columnCosts | Float32Array | 768 |
state.shared.workQueue.columnDone | Uint8Array | 96 |
state.shared.workQueue.counters | Uint32Array | 4 |
state.shared.workQueue.effectiveMode | Uint8Array | 1 |
state.shared.workQueue.evenTasks | Uint32Array | 9216 |
state.shared.workQueue.hotColumns | Uint8Array | 96 |
state.shared.workQueue.hotRemaining | Int32Array | 96 |
state.shared.workQueue.oddTasks | Uint32Array | 9216 |
state.shared.workQueue.taskCounts | Uint32Array | 2 |
state.shared.workQueue.workerCount | number | |
state.shared.workerCompletion | Float32Array | 16 |
state.shared.workerDetailEnabled | Uint8Array | 1 |
state.shared.workerDetailPerformance | Float32Array | 104 |
state.shared.workerPerformance | Float32Array | 32 |
state.storeсохраняется с миром: ресурсы, структуры, прогресс143
| путь | тип | размер |
|---|---|---|
state.store | object | 34 |
state.store.achievements | object | 14 |
state.store.achievements.ANCIENT_TECHNOLOGY | boolean | |
state.store.achievements.AURA_EXTRACTOR | boolean | |
state.store.achievements.CONSERVATORY_CURATOR | boolean | |
state.store.achievements.CRITTER_CATCHER | boolean | |
state.store.achievements.FINAL_SCHEMATIC | boolean | |
state.store.achievements.FIRST_BLOOM | boolean | |
state.store.achievements.FIRST_SPARK | boolean | |
state.store.achievements.FLUX_IT_UP | boolean | |
state.store.achievements.FULL_CIRCLE | boolean | |
state.store.achievements.GOLD_IN_THE_BIN | boolean | |
state.store.achievements.PROMOTION_PROTOCOL | boolean | |
state.store.achievements.QUARTERMASTER | boolean | |
state.store.achievements.STRATACORE_SECURED | boolean | |
state.store.achievements.VOID_TOUCHED | boolean | |
state.store.conservatory | object | 1 |
state.store.conservatory.tickets | number | |
state.store.createdVersion | string | |
state.store.creatures | object | 5 |
state.store.creatures.eyes | object | 2 |
state.store.creatures.lumling | object | 2 |
state.store.creatures.resinWeaver | object | 2 |
state.store.creatures.shinelet | object | 2 |
state.store.creatures.voidgrazer | object | 2 |
state.store.discoveries | object | 2 |
state.store.discoveries.elements | array of number | 45 |
state.store.discoveries.terrains | array of number | 21 |
state.store.drones | array of object | 1 |
state.store.factoryLevelCap | null | |
state.store.gloom | object | 1 |
state.store.gloom.emitterPositions | array | 0 |
state.store.hints | object | 6 |
state.store.hints.angleLockShown | boolean | |
state.store.hints.conservatoryIntroSeen | boolean | |
state.store.hints.freezingIceSoilFire | boolean | |
state.store.hints.hoverIntroToastSeen | boolean | |
state.store.hints.nonDestructible | boolean | |
state.store.hints.upgradesIntroSeen | boolean | |
state.store.integrity | object | 2 |
state.store.integrity.cheatsUsed | boolean | |
state.store.integrity.modsUsed | boolean | |
state.store.lockedTechs | object | 2 |
state.store.lockedTechs.aurixiteCrystallizer | boolean | |
state.store.lockedTechs.voidOrb | boolean | |
state.store.machineryEngine | object | 1 |
state.store.machineryEngine.runLaunchers | boolean | |
state.store.meta | object | 8 |
state.store.meta.autosaveSlot | number | |
state.store.meta.elementCapacity | number | |
state.store.meta.nextId | object | 3 |
state.store.meta.seed | string | |
state.store.meta.tick | number | |
state.store.meta.time | number | |
state.store.meta.worldId | string | |
state.store.meta.worldName | string | |
state.store.mods | object | 34 |
state.store.objectives | object | 1 |
state.store.objectives.active | array | 0 |
state.store.options | object | 6 |
state.store.options.buildMode | number | |
state.store.options.buildModeIndices | object | 5 |
state.store.options.defaultFilter | object | 2 |
state.store.options.sandkitPlacementConfig | object | 1 |
state.store.options.shortcutHelperVisible | boolean | |
state.store.options.techTreePan | object | 2 |
state.store.owner | undefined | |
state.store.pipes | array of object | 413 |
state.store.player | object | 17 |
state.store.player.action | object | 2 |
state.store.player.buildings | array of number | 61 |
state.store.player.cooldowns | object | 3 |
state.store.player.grapplingHook | boolean | |
state.store.player.height | number | |
state.store.player.hotbar | object | 3 |
state.store.player.inventory | array of object | 32 |
state.store.player.isHovering | boolean | |
state.store.player.onGround | boolean | |
state.store.player.speedCapOverdrive | object | 2 |
state.store.player.tech | object | 71 |
state.store.player.threshold | object | 2 |
state.store.player.velocity | object | 2 |
state.store.player.weaponsMeta | object | 1 |
state.store.player.width | number | |
state.store.player.x | number | |
state.store.player.y | number | |
state.store.productionPoints | number | |
state.store.progression | object | 2 |
state.store.progression.dungeons | object | 1 |
state.store.progression.upgradesUnlocked | boolean | |
state.store.projectiles | array | 0 |
state.store.pumpsCache | array of object | 51 |
state.store.queue | array | 0 |
state.store.resources | object | 4 |
state.store.resources.artifacts | object | 2 |
state.store.resources.energy | number | |
state.store.resources.fluxite | number | |
state.store.resources.gold | number | |
state.store.scene | object | 3 |
state.store.scene.active | number | |
state.store.scene.start | number | |
state.store.scene.triggers | array of object | 3 |
state.store.stratacores | array of string | 1 |
state.store.structures | array of object | 35956 |
state.store.tutorial | object | 4 |
state.store.tutorial.active | boolean | |
state.store.tutorial.currentStep | number | |
state.store.tutorial.data | object | 0 |
state.store.tutorial.transitioningToNextStep | boolean | |
state.store.upgrades | object | 16 |
state.store.upgrades.cryoblaster | object | 1 |
state.store.upgrades.digger | object | 4 |
state.store.upgrades.drill | object | 1 |
state.store.upgrades.flamethrower | object | 2 |
state.store.upgrades.grabber | object | 3 |
state.store.upgrades.gun | object | 5 |
state.store.upgrades.hauler | object | 2 |
state.store.upgrades.implosionGun | object | 1 |
state.store.upgrades.jetpack | object | 2 |
state.store.upgrades.laser | object | 3 |
state.store.upgrades.locator | object | 1 |
state.store.upgrades.rocketLauncher | object | 4 |
state.store.upgrades.shovel | object | 3 |
state.store.upgrades.sweeper | object | 3 |
state.store.upgrades.thruster | object | 1 |
state.store.upgrades.vacuum | object | 2 |
state.store.version | string | |
state.store.viability | object | 3 |
state.store.viability.goldSpent | number | |
state.store.viability.level | number | |
state.store.viability.peakEnergy | number | |
state.store.world | object | 10 |
state.store.world.deferredChunkReports | array | 0 |
state.store.world.fixtures | array of object | 70 |
state.store.world.groundHorizon | array of number | 3840 |
state.store.world.horizon | array of number | 3840 |
state.store.world.lights | array of object | 561 |
state.store.world.matrixTraverseDirection | number | |
state.store.world.sensors | array of object | 1 |
state.store.world.size | object | 2 |
state.store.world.teleportZones | array of object | 306 |
state.store.world.updatedElementIndices | array | 0 |
state.store.worldItems | array of object | 1 |
apiVersion и нестабильно даже внутри одной версии. Это описание одного мира на одной сборке. Читаешь — патч сделает мод неправильным; пишешь — патч сделает неправильным сейв. Каждое обращение в обёртке, каждое чтение с проверкой.Грабли
Собрано дорогой ценой на восьми модах.
Энтри — это скрипты, а не модули
import или export бросает Unexpected token 'export', и энтри молча не запускается. В интерфейсе об этом не сказано нигде.
Гейтинг по сценам пиши как hide-list
Внедрённый UI сидит в слоте оверлеев global, рисуется поверх главного меню и остаётся смонтированным после выхода из мира. Прячь на тех сценах, которые ты уверенно опознал как меню: неверная догадка в show-list гасит твой UI вообще везде.
Никогда не оборачивай регистрацию в тихий хелпер
Молчаливый try/catch вокруг energy.registerType способен скрыть полный отказ. Регистрацию нельзя повторить, поэтому падать она должна громко.
Проверяй до запуска игры
workshop-mods.js и local-mod-publisher.js достаются из app.asar и вызываются напрямую: loadCandidate для манифеста и энтри, validatePreview для картинки и та же обёртка new Function для синтаксиса. Ловит всё, кроме поведения в рантайме, и не требует перезапуска.
Колбэки эффектов зависят от точки входа
energy.addAtCell читает onPathCharged, но никогда не вызывает onSourceAdded — тот срабатывает только из batch-API, которого модам не дают. Зато возвращает объём, который сеть реально приняла, и вот на него эффекты и надо вешать.
Мод виден в настройках, только если у него есть настройки
Нет непустой configSchema — нет строки на экране модов. А выключить мод без отписки игра штатно не умеет, так что поле enabled стоит сделать общей договорённостью.