Exports live game state (tech tree, production stats, logistics networks, player inventories, placed buildings, and a RecipeExporter-compatible recipe/prototype dump) as JSON/NDJSON under script-output for a local CLI or AI agent to read. Designed to be near-zero cost when disabled and cheap when enabled: no on_tick polling, engine-aggregated reads over full scans, and an incrementally-maintained building index instead of periodic full scans.
Providing the player with new tools or adjusting the game interface, without fundamentally changing gameplay.
Version: 0.3.6
Date: 2026-07-17
Changes:
- buildings.ndjson entries for assembling machines, furnaces, and rocket
silos now also include entity.modules (installed module contents, same
shape as logistics.json/inventories.json) and entity.circuit (circuit
enable/disable flag, condition, set-recipe and read-contents
automation flags) when configured. Both ride the same change-detection
paths entity.recipe already used (copy/paste, blueprint paste, GUI
close, plus the periodic bounded rescan as the sole backstop for
circuit-driven changes) -- refresh_recipe_if_changed is now
refresh_config_if_changed and diffs all three fields together, still
one "add" upsert per change. See SCHEMA.md buildings.ndjson for the
full field documentation.
- New building-contents.json: per-machine ingredient/output contents and
crafting progress, written every flma-tick-interval for machines whose
exact name is listed in the new flma-contents-tracked-names setting
(comma-separated, empty by default -- the file is never written at
all until this is set). Deliberately not part of buildings.ndjson's
event log since this is dynamic per-craft state; scoped to named
machines so cost is O(#matched machines), never O(#all buildings).
Requires flma-export-buildings also on. See SCHEMA.md
building-contents.json.
Version: 0.3.5
Date: 2026-07-11
Changes:
- buildings.ndjson entries for assembling machines, furnaces, and rocket
silos now include entity.recipe (the currently-configured recipe name)
when one is set. Tracked via on_entity_settings_pasted (copy/paste
tool), on_blueprint_settings_pasted (blueprint over an existing
entity), on_gui_closed (manual GUI recipe pick), plus a new bounded
periodic rescan (rescan_recipes) that is the only way to catch
circuit-network "Set recipe" changes -- Factorio raises no event for
those at all. A recipe change re-emits the existing "add" upsert for
that id; no new op type. Upgrading an existing save with buildings
already tracked triggers one automatic fresh baseline rescan to
backfill recipe on already-placed machines. See SCHEMA.md
buildings.ndjson for the full per-signal coverage/latency table.
Version: 0.3.4
Date: 2026-07-11
Changes:
- Mod portal prep: added thumbnail.png, and fixed title/description in
info.json, which still referenced the MCP bridge removed in favor of
the planner CLI. No export/runtime behavior changed.
Version: 0.3.3
Date: 2026-07-10
Changes:
- recipes.json entities now include a fourth "generator" shape (fluid-driven
electricity generators, e.g. steam-engine, steam-turbine-mk01..04):
max_power_output (W), fluid_usage_per_sec, effectivity, maximum_temperature,
input_fluid. Deliberately excludes "electric-energy-interface" entities
(e.g. pyanodons' wind turbines) -- their power output is live per-instance
state set by their owning mod's own simulation, not static prototype data.
- Crafting-machine and mining-drill entities with a burner energy source now
also report burner_effectivity, needed to compute exact fuel burn rates
from an item's fuel_value (already exported, previously unused downstream).
Version: 0.3.2
Date: 2026-07-07
Changes:
- tech.json per-force entries now include mining_drill_productivity_bonus
(the force's current mining-drill yield bonus, e.g. 0.2 = +20% ore per
mining operation), read straight from LuaForce so it stays correct
regardless of which technologies contributed to it.
Version: 0.3.1
Date: 2026-07-02
Changes:
- Every export file now lives under script-output/flma/<save_id>/ instead
of directly under script-output/flma/, where save_id is a short token
generated once per save and persisted in storage. Previously all saves
on a machine shared the same flat output directory, so switching which
save/server you pointed the bridge at could silently mix or clobber a
different save's buildings.ndjson, tech.json, etc. A new fixed-location
script-output/flma/current-save.json pointer ({"save_id":..., "tick":...})
lets a consumer find the active save's subdirectory without being
reconfigured on every switch; refreshed every export cycle and
immediately when flma-export-enabled turns on. remote.call("flma",
"status") now reports save_id and output_dir.
Version: 0.3.0
Date: 2026-07-02
Features:
- New recipes.json export (script-output/flma/recipes.json): a
RecipeExporter-compatible dump of recipes, items, fluids, crafting
machines/mining drills/resources, technologies, qualities, and item
groups for the player force — replaces needing the separate
RecipeExporter mod and its manual dump_recipes console command, and
always matches the modpack of the running save. Written on init, on mod
configuration changes, when a finished/reversed research actually
unlocks recipes or changes recipe productivity (coalesced via a dirty
flag to at most one write per tick-interval — never periodic), and on
demand via remote.call("flma", "export_recipes").
- Best-effort localised names: the file is written immediately with
internal names only (works headless, no player required); when a player
is connected an async translation pass runs and the file is rewritten
with translated_name filled in on each object. Consumers must fall back
to the internal name. Translation requests are time-sliced (100 per 5
ticks) — issuing all of them in one tick got the requesting client
dropped from the game on a pyanodons-scale prototype set.
Version: 0.2.1
Date: 2026-07-01
Bugfixes:
- production.json has been silently empty (items/fluids always nil) since
the mod was first written. force.get_item_production_statistics and
get_fluid_production_statistics were called as pcall(force.method,
force, surface) — but dot-access on a live LuaForce instance already
returns a bound closure, so re-passing force as an explicit self
argument shifted the real `surface` argument out of position. Fixed to
pcall(force.method, surface). Found and confirmed via RCON, which let
us test the exact call directly against a running game instead of
guessing from the bridge's Python-side tests (which only ever exercised
hand-written fixture JSON, never the actual Lua export).
Additions:
- remote.call("flma", "export_now") forces one export cycle immediately
— useful when the server has no connected players (ticks don't
advance, so on_nth_tick never fires) or for on-demand debugging.
Version: 0.2.0
Date: 2026-07-01
Changes:
- Buildings tracking now also excludes belts/undergrounds/splitters/
loaders, pipes (incl. underground/infinity/heat), electric poles,
inserters, and all rail/rail-signal variants from positional tracking —
still a blocklist by Factorio's built-in entity `type`, so this covers
any mod's custom variants of these (including pyanodons') without
per-mod maintenance. These are extremely high-cardinality on any real
base and were making the baseline scan, the in-memory index, and
compaction all scale far worse than needed.
- The baseline scan's collecting phase now iterates Factorio's own map
chunk grid (32x32 tiles) instead of one find_entities_filtered call per
surface, bounding each tick's cost by chunk density rather than total
base size — a megabase just takes more ticks, never a bigger spike.
- Added a remote interface for debugging without a fresh save:
remote.call("flma", "status") and remote.call("flma",
"reset_buildings") (mod-local storage isn't readable from /c commands).
Version: 0.1.1
Date: 2026-07-01
Bugfixes:
- tech.json was overwritten once per force (player/enemy/neutral all shared
the same file), so only the last-iterated force's data survived. Now
nested per-force like production.json/logistics.json.
- The buildings baseline scan used an unfiltered find_entities_filtered{},
which materializes every entity on a surface (every resource tile,
every tree) before Lua-side filtering, done synchronously per surface.
On a large, fully explored save this froze the game. Now uses a native
type=/invert= filter so the engine excludes non-buildings up front, and
the surface scan itself is time-sliced across ticks.
- Baseline-scan draining and buildings.ndjson compaction wrote one line
per building via a separate write_file call each (tens of thousands of
syscalls in a single tick on a large base). Both now batch into one
write per tick/compaction.
- Compaction previously only checked after destroy events, so a large
build spree (including the baseline scan itself) could grow
buildings.ndjson far past flma-buildings-compact-threshold before ever
compacting. Build events now check too.
Version: 0.1.0
Date: 2026-07-01
Features:
- Initial release. Exports tech tree, production statistics, logistics
network contents, player inventories (opt-in), and an incrementally
maintained placed-building index to script-output/flma/ for the
factorio-live-mcp local bridge.