mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-14 15:24:52 +09:00
4.1 KiB
4.1 KiB
Crafting-Recipe Overlay for Minimap & Timelapse
Overview
Records which recipe every crafting machine is running, streams live changes to web clients, and replays them frame-perfectly in timelapse mode. The solution:
- Works for all forces & surfaces
- Scales to millions of events using compact binary storage
- Allows cheap frustum-culling using 256×256 map tiles
- Uses append-only storage so historical data is never rewritten
Architecture
Event Flow
sequenceDiagram
participant Lua as Factorio Lua (minimap.lua)
participant Host as Host/Instance plugin (instance.ts)
participant Ctl as Controller plugin (controller.ts)
participant UI as Web clients
Lua->>Host: ipc-minimap:recipe_data (JSON)
Host->>Ctl: RecipeDataEvent
Ctl-->>UI: RecipeDataEvent (broadcast)
UI->>Ctl: GetRawRecipeTileRequest (HTTP / cluster bus)
Ctl-->>UI: Raw recipe tile (.recipes)
Messages
| Message | Direction | Purpose |
|---|---|---|
RecipeDataEvent |
instance → controller → web | Single recipe change (live) |
GetRawRecipeTileRequest/Response |
web → controller | Fetches binary recipe tile |
Storage Format
Tile Organization
Uses same 256×256 world-unit tiles as terrain data.
Filename: <instance>_<surface>_<force>_<tileX>_<tileY>.recipes
Stored in: database_directory/minimap_recipe_tiles/
Binary Record Format (append-only)
All numbers big-endian.
| Bytes | Field | Description |
|---|---|---|
| 1 | type |
0=DictEntry, 1=SetRecipe, 2=ClearRecipe |
| DictEntry (0) | ||
| 2 | index (uint16) |
Dictionary ID (0-65535) |
| 1 | len (uint8) |
UTF-8 byte length |
| n | name bytes | Recipe name string |
| SetRecipe (1) | ||
| 4 | sec (uint32) |
⌊tick / 60⌋ timestamp |
| 1 | px (uint8) |
X position in tile (0-255) |
| 1 | py (uint8) |
Y position in tile (0-255) |
| 2 | index (uint16) |
Dictionary ID |
| ClearRecipe (2) | ||
| 4 | sec (uint32) |
⌊tick / 60⌋ timestamp |
| 1 | px (uint8) |
X position in tile (0-255) |
| 1 | py (uint8) |
Y position in tile (0-255) |
Dictionary entries are written only when a previously unseen recipe name is required for that tile.
Space Efficiency
- ~8x more compact than JSON format
- Dictionary compression eliminates recipe name repetition
- Per-tile dictionaries keep indices small (uint16 sufficient)
Playback
Live Mode
RecipeDataEventbroadcasts likeTileDataEvent- Web UI maintains
Map<posKey, recipeName>for instant icon updates - Icons render using Factorio sprite metadata
Timelapse Mode
- Downloads
.recipesfiles viaGetRawRecipeTileRequest - Parses binary format using shared
parseRecipeTileBinary()utility - Applies Set/Clear records up to selected timeline tick
- Integrates with existing terrain timelapse system
Scalability
| Metric | Estimate |
|---|---|
| Assemblers per large factory | ~50,000 |
| Avg recipe changes per machine | ~5 lifetime |
| Bytes per Set/Clear record | 8 bytes |
| Total storage per instance | ~2 MB |
| Max recipes per tile | <1,000 (well under 65K limit) |