Definitive island prefab -> in-game name link: each island_* prefab has a child Landmark GameObject (LandmarkBehaviour.name) = the Toponym key, localized via i2 Toponyms/<name>. New bundle/extract_island_names.py -> extracted/island_names.json. Key results: Demo_Wunderinsel=Strudel, Demo_Marktinsel=Segen, Gartenfreude=Insel St. Clemens, DeusExMashineSmall=Rauchwolke, and island_Factorio = Sprengstofffabrik (the explosives factory). The LittleFactory/LittleFactoryArmory prefabs are the Forts. Updates docs/PRODUCTION_LINES.md with in-game names and corrects the earlier Sprengstofffabrik note (it IS the explosives factory -> Factorio, not the Armory islands). Supersedes the name-guesses (e.g. DeusExMashine is Rauchwolke, not Maschineninsel).
100 lines
5.6 KiB
Markdown
100 lines
5.6 KiB
Markdown
# 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 the `bundles/` symlink).
|
|
- **Prefabs:** `game_conveyor_*_epb.prefab`, under
|
|
`Assets/Content/Game/game_conveyor/...`. 14 carry a recipe; 4 of them are named
|
|
`game_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 — a `Transform` and a `MonoBehaviour` whose script is **`EntityBlueprint`**.
|
|
`EntityBlueprint : SerializedMonoBehaviour` (Sirenix Odin), so the component data —
|
|
including the `CraftingRecipe` — is in its **Odin-serialized
|
|
`serializationData.SerializedBytes`**, not in plain typetree fields. (Same situation as
|
|
the loot tables — see [TASK.md](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`.
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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 prefab | In-game name (Toponym) | Recipe conveyors placed |
|
|
|---|---|---|
|
|
| `island_Factorio` | **Sprengstofffabrik** | energyRods, 80mmT3Cannon, contactGrenades, armorPiercingRocket* |
|
|
| `island_Kaiserplatz` | Kaiserplatz | energyRods, 40mmT3Cannon |
|
|
| `island_Demo_Wunderinsel` | **Strudel** | 70mmT3Cannon |
|
|
| `island_DeusExMashineSmall` | Rauchwolke | computingModules, coralDust |
|
|
| `island_testIsland`, `island_testIslandTramplers` | (test, no Landmark) | the 4 `base*` conveyors (inv↔large test combos, incl. `1x wineBox → 1000x coinCrown`) |
|
|
|
|
In-game names come from each island prefab's child `Landmark` (`LandmarkBehaviour.name`) →
|
|
i2 `Toponyms/<name>`; see `bundle/extract_island_names.py` / `extracted/island_names.json`.
|
|
|
|
Notes / corrections:
|
|
- The **Sprengstofffabrik** (explosives factory) is literally **`island_Factorio`** — its
|
|
in-game Landmark name is `Sprengstofffabrik`, and it makes the grenades + AP rockets +
|
|
cannons. So the original "Sprengstofffabrik = explosives" intuition was right; it's just
|
|
that the prefab is `Factorio`, not an `…Armory` island.
|
|
- The `island_LittleFactory01-03` / `…Armory01-03` prefabs are actually the **Forts**
|
|
in-game (Fort Istria/Arpad/Tarnopol and Fort Zimmer/Metternich/Starhemberg) and place **no**
|
|
recipe conveyors.
|
|
- `*` Factorio's child is named `game_conveyor_armorPiercingRocket` (singular) while the recipe
|
|
blueprint is `game_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 after `conveyor` = generic infra; `game_conveyor_<x>` =
|
|
recipe line).
|