Files
claudetools/projects/factorio-quality-mod/factorio-mod-anatomy.md
Mike Swanson 30841fbfb1 sync: auto-sync from GURU-5070 at 2026-06-23 20:23:47
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-06-23 20:23:47
2026-06-23 20:25:46 -07:00

78 lines
3.9 KiB
Markdown

# Anatomy of a Factorio mod (2.0 / Space Age) — reference
> Research (Grok 4.3 live web, 2026-06-23) cross-checked against Claude's knowledge. For the
> deterministic-quality mod project — see `DESIGN.md`.
## 1. Package
- Mod = folder or zip. **Distribution zip:** `modname_1.2.3.zip` containing one top folder
`modname_1.2.3/`. **Dev:** an unzipped folder (can be named just `modname`) in the mods dir.
- Mods dir: Windows `%APPDATA%\Factorio\mods`, Linux `~/.factorio/mods`, macOS
`~/Library/Application Support/factorio/mods`. `mod-list.json` tracks enabled mods.
- Folder/zip name must agree with `name` + `version` in `info.json`.
## 2. `info.json` (mod root)
- **Required:** `name`, `version`, `title`, `author`. **Always set** `factorio_version` ("2.0").
- `dependencies` prefixes: *(none)* = required · `!` incompatible · `?` optional · `(?)` hidden
optional · `~` required but does NOT affect load order. Version ops `>= <= = < >`. `base` is
auto-depended unless overridden.
## 3. Load stages (strict phases, across all mods at once, dependency-ordered)
| Stage | Files (in order) | Purpose | Game access? |
|---|---|---|---|
| **Settings** | `settings.lua``settings-updates.lua``settings-final-fixes.lua` | Define mod settings; 3 types: `startup`, `runtime-global`, `runtime-per-user` | No |
| **Data (prototypes)** | `data.lua``data-updates.lua``data-final-fixes.lua` | Build prototypes into global `data.raw` via `data:extend{...}` (items/entities/recipes/tech/…). Build-once, frozen. Can read other mods' prototypes + `settings.startup`. | **No** (no game/state) |
| **Control (runtime)** | `control.lua` (+ `require`d files) | Only stage that runs in a loaded save. Event-driven scripting. | **Yes** |
**Control essentials:**
```lua
script.on_init(fn) -- once, new save / mod added
script.on_load(fn) -- every load; MUST NOT write storage
script.on_configuration_changed(fn)-- mod/version/prototype change → migrations
script.on_event(defines.events.on_tick, fn)
```
- **`storage`** = persistent per-mod saved table. **(Was `global` in 1.1 — renamed in 2.0.)**
- Also `remote` (inter-mod), `commands` (custom `/cmds`), `game`, `defines`.
- Data stage CANNOT touch runtime; control stage CANNOT define prototypes.
## 4. Other standard files
- `locale/<lang>/*.cfg` — INI with `[category]` sections (`[item-name]`, `[entity-name]`,
`[recipe-name]`, `[mod-setting-name]`, …).
- `graphics/`, `sounds/` — assets.
- `migrations/``*.lua` run as control code on loading an older save; `*.json` for prototype renames.
- `changelog.txt` — strict format: 99-hyphen separators, `Version:` / `Date:` headers, 2-space
category headers (`Bugfixes:`), 4-space `- ` entries.
- `thumbnail.png` — mod portal (~144px+).
## 5. Asset paths
`"__modname__/graphics/x.png"`. Specials: `__base__` (base game assets/prototypes), `__core__` (engine).
## 6. Settings access from control.lua
`settings.startup["k"].value` · `settings.global["k"].value` ·
`settings.get_player_settings(player)["k"].value`.
## 7. Tooling
- `lua-api.factorio.com` — versioned; **prototype docs (data) vs runtime API docs are separate**.
- VS Code + **FMTK** (Factorio Modding Tool Kit) + sumneko Lua → autocomplete/diagnostics.
- Wiki `Tutorial:Modding`; portal `mods.factorio.com`. Debug: `log()`, `serpent.block()`, F4 menu,
`--instrument-mod`, `/c` console.
## 8. 2.0 vs 1.1 must-knows
- `global`**`storage`**.
- **Quality / Space Age / Elevated Rails are separate mods** — depend on `quality` / `space-age`
explicitly when using their features.
- Versioned API docs; `factorio_version: "2.0"`.
- Quality fields touch nearly every item/entity prototype; rail/fluid/inserter changes; Space Age
adds planets/space platforms.
## Minimal skeleton
```
my-mod/
├─ info.json
├─ settings.lua (optional)
├─ data.lua
├─ control.lua
├─ changelog.txt
├─ thumbnail.png
└─ locale/en/locale.cfg
```