The recipe conveyors (game_conveyor_<product>_epb) are placed as named child GameObjects in the island_* prefabs (islands_assets_all.bundle), NOT via energy_grid (power grid only) or any config asset. New extractor bundle/extract_conveyor_placements.py walks every island prefab and cross-references production_lines.json -> extracted/conveyor_placements.json. Result: Factorio (energyRods, 80mmT3Cannon, contactGrenades, armorPiercingRocket), Kaiserplatz (energyRods, 40mmT3Cannon), Demo_Wunderinsel (70mmT3Cannon), DeusExMashineSmall (computingModules, coralDust), testIsland(+Tramplers) (the 4 base test conveyors). Corrects the earlier "Armory = Sprengstofffabrik hosts explosives" guess: the LittleFactory/LittleFactoryArmory islands place NO recipe conveyors; grenades/rockets are on Factorio. Unplaced blueprints: explosiveSmall, mechanicalParts (+ the plural armorPiercingRockets, whose singular-named instance is on Factorio).
5.3 KiB
World factory "production lines" (conveyors) — where to find them
The game has fixed single-recipe world structures — item conveyors that run one
recipe (e.g. 1 Raw Aurogen Crystal → 10 Energy Rods). These are a separate mechanic
from the player workbench recipes (which live in extracted/crafting_recipes.json,
sourced from CraftingRecipeBundle assets). This note records where they live so the
data can be re-derived after a game update.
The mechanic
In code it's a "Factory Production Line". It's an Entitas ECS feature, namespace
Hologryph.Sand.Shared.Game.Features.Crafting (see il2cpp/dump.cs):
| Class | Holds |
|---|---|
ProductionLineComponent |
int inputEntityIndex, int outputEntityIndex |
ProductionLineRecipeComponent |
CraftingRecipe recipe ← the recipe |
ProductionLineInputDataComponent / …OutputDataComponent |
bool isLargeItem{Input,Output} |
CraftingRecipe |
CraftingIngredient[] inputIngredients, CraftingIngredient[] outputIngredients, float craftingTimeSeconds |
CraftingIngredient |
string itemId, int amount |
Note CraftingRecipe / CraftingIngredient are the same types the workbench uses —
only the container differs (a workbench holds List<CraftingRecipeBundle> recipeBundles;
a production line holds a single CraftingRecipe on the entity).
Where the data lives
- Bundle:
epb_assets_all.bundle(reachable via thebundles/symlink). - Prefabs:
game_conveyor_*_epb.prefab, underAssets/Content/Game/game_conveyor/.... 14 carry a recipe; 4 of them are namedgame_conveyor_base*(large/small in→out variants) — what distinguishes them from the product-named ones beyond the name is not established here. - Serialization: each prefab GameObject (
m_Name = game_conveyor_<x>_epb) has two components — aTransformand aMonoBehaviourwhose script isEntityBlueprint.EntityBlueprint : SerializedMonoBehaviour(Sirenix Odin), so the component data — including theCraftingRecipe— is in its Odin-serializedserializationData.SerializedBytes, not in plain typetree fields. (Same situation as the loot tables — see TASK.md /extract_loot.py.)
Extraction path (how to read it)
UnityPy (with an IL2CPP TypeTreeGenerator over GameAssembly.dll +
global-metadata.dat) reads the EntityBlueprint MonoBehaviour → pull
serializationData.SerializedBytes → bundle/odin_read.py parses the Odin binary →
walk the tree for the node with inputIngredients / outputIngredients.
venv/bin/python bundle/extract_production_lines.py # -> extracted/production_lines.json
Key item ids seen here: item_crystalHandles = Raw Aurogen Crystal,
item_energyBar = NZ Mk2 Energy Rod, item_blackBox = Black Box,
item_resourceCoralPiece = Coral Chunk. Resolve any id → display name via
extracted/items_registry.json / extracted/item_names.json (built from
CheatItemDefinitionsData).
Island placement — RESOLVED
Each recipe conveyor is placed as a named child GameObject (game_conveyor_<product>_epb)
in the island_* prefab's Transform hierarchy inside islands_assets_all.bundle. It is NOT
in the energy_grid_* blueprint (that holds only EnergyGridDataComponent — the power grid)
and NOT in any config / designed-environment asset. Extract with:
venv/bin/python bundle/extract_conveyor_placements.py # -> extracted/conveyor_placements.json
This walks every island prefab, collects the game_conveyor_<product> children (with local
position) and cross-references each against production_lines.json. Result for this build:
| Island | Recipe conveyors placed |
|---|---|
island_Factorio |
energyRods, 80mmT3Cannon, contactGrenades, armorPiercingRocket* |
island_Kaiserplatz |
energyRods, 40mmT3Cannon |
island_Demo_Wunderinsel |
70mmT3Cannon |
island_DeusExMashineSmall |
computingModules, coralDust |
island_testIsland, island_testIslandTramplers |
the 4 base* conveyors (inv↔large test combos, incl. the 1x wineBox → 1000x coinCrown one) |
Notes / corrections:
- The earlier guess that the
…Armory(Sprengstofffabrik) islands host the explosive / grenade / rocket conveyors is not supported by the placements:island_LittleFactory01-03andisland_LittleFactoryArmory01-03exist (each has anenergy_grid_*) but place no recipe conveyors at all. The grenade (contactGrenades) and rocket (armorPiercingRocket) lines are on Factorio. Factorio is the main multi-product factory here. *Factorio's child is namedgame_conveyor_armorPiercingRocket(singular) while the recipe blueprint isgame_conveyor_armorPiercingRockets(plural) — a name mismatch; same line (→3x item_rocketLauncherAmmoArmorPiercing).- Defined-but-unplaced recipe blueprints in this build:
armorPiercingRockets(plural; the singular instance is on Factorio),explosiveSmall(→5x item_c4Dynamite),mechanicalParts(→item_resourceMetal_t1). - Infrastructure conveyors (
game_conveyorSlotInput,…OutInventory,…OutLargeItem,…InSwitch) accompany the recipe ones on each factory island — these are the input/output ports, not recipes (no underscore afterconveyor= generic infra;game_conveyor_<x>= recipe line).