Factorio Live Mod Agent


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.

Utilities
a day ago
2.0
8

Changelog

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.