Moon Logic

by mk-fg

Adds Lua-programmable circuit network combinator. Based on Sandboxed LuaCombinator and LuaCombinator2 mods. Probably won't work in multiplayer games.

2 months ago
1.0 - 1.1
CC BY-SA 4.0
1 year, 8 months ago
Latest Version:
0.0.78 (2 months ago)
Factorio version:
1.0 - 1.1
26258 times

Important: This mod should probably cause desyncs in multiplayer games
Mod code uses things which are likely to desync mp games, and I only test singleplayer, so it's highly unlikely that it will "just work" in mp.



Adds Moon Logic Combinator that runs Lua code that can read red/green wire signal inputs and set outputs.

Based on other LuaCombinator mods, but instead of adding more complexity and features, mostly removes them to keep it simple and clean.
I.e. no syntax highlighting, code formatting, binding to factorio events, etc.

General principle is that it's not a replacement for Vim/Emacs or some IDE, but just a window where you paste some Lua code/logic or type/edit a couple of lines.
And not a mod development framework either - only a combinator to convert circuit network inputs to outputs, nothing more.

Mostly created because I like using such Lua combinators myself, and all other mods for them seemed to be broken and abandoned atm.
Fixing/maintaining these is much easier without few thousand lines of extra complexity in there.

"Moon Logic" Combinator is because it's programmed in Lua - "moon" in portugese (as Lua itself originates in Brazil).


Mod Options

Startup Mod Settings:

  • Red Wire Label - Lua environment name for in-game "red" circuit network values. Changes all labels in the GUIs as well.
  • Green Wire Label - same as Red Wire Label, but for the other wire color.

These can be useful when playing with other mods that change colors, for labels to match those.
Note that red/green input tables are always available in the environment too, for better code/snippet compability.

  • GUI Signals Update Interval

Interval in game ticks (60 ticks = 1 second at 1x game speed) between updating signal table in the UI.
Only relevant when main combinator UI window is actually open. Default is 1 - update signal side-window on every tick.
Note that with higher interval values, signals flapping on/off synced to it will be impossible to notice there.

  • Enable Code Editing History

Toggles between smooth and pleasant editing or undo/redo buttons on top working for all non-saved code changes.
If you don't use these buttons to undo minor changes (they still keep history of saved changes), be sure to uncheck this.

UI hotkeys can also be customized in the Settings - Controls game menu.

There is an optional hotkey (Ctrl-E) for opening these combinators from anywhere on the map,
which kinda breaks basic game mechanics in a way similar to various "Long Reach" mods,
but can be useful if code breaks too often and is hard to reach for debugging all the time.


Lua Code

Lua is a very simple and easy-to-use programming language, which fits entirely on a couple pages.
This mod allows using it to script factorio circuit network logic directly from within the game.

-- Trivial one-liner examples:

  • Set constant output signal value: out.wood = 1

  • Simple arithmetic on an input: out.wood = red.wood * 5

  • Ever-increasing output counter: out.wood = out.wood + 1

  • Update counter once per second (see game tick): delay, out.wood = 60, out.wood + 1

  • +1 counter every tick while signal-W input is non-zero: delay, irq, out.wood = 2^30, 'signal-W', out.wood + 1

  • Different value on each output wire: out['red/wood'], out['green/wood'] = -3, 10

Click in-game "Quick Reference" button in combinator window for a full list of all special values and APIs there, default hotkeys and other general info.

-- Control any number of things at once:

local our_train = 17 -- hover over train to find out its ID number
local train_loaded, train_unloaded -- locals get forgotten between runs

if red['signal-T'] == our_train then
  if not var.inbound_manifest_checked then
    -- Emit alarm signal for underloaded train arrival while it's on station
    -- Note how outputs persist until they are changed/reset
    out['signal-info'] = red['sulfur'] < 100 or red['solid-fuel'] < 200
    var.inbound_manifest_checked = true

  out['signal-black'] = red.coal < 500 -- load coal
  out['signal-grey'] = red.barrel < 20 -- load barrels

  train_loaded =
    not (out['signal-black'] or out['signal-grey']) -- cargo limit
    or (var.coal == red.coal and var.barrels == red.barrel) -- no change since last check
  var.coal, var.barrels = red.coal, red.barrel -- remember for the next check

  local inbound_cargo = red['sulfur'] + red['solid-fuel']
  train_unloaded = inbound_cargo ~= var.inbound_cargo -- that's "not equals" in Lua
  var.inbound_cargo = inbound_cargo

  out['signal-check'] = train_loaded and train_unloaded -- HONK!
  if out['signal-check']
    then var.inbound_manifest_checked = false end -- reset for the next arrival

  delay = 2 * 60 -- check on cargo loading every other second
  out = {} -- keep inserters idle and environment clean
  delay = 20 * 60 -- check for next train every 20s
  irq = 'signal-T' -- any train on station will interrupt the delay
  irq_min_interval = delay -- to sleep when other train triggers that irq signal

As comments in the code might suggest already, it's a train station automation example.

-- Toy example - 7-segment digit display for a ticking 0-9 counter:

local digit_segments = { -- segments to light up for 0, 1, 2, 3, ...
out, var.n = {}, (var.n or 0) % 10 + 1
for c in digit_segments[var.n]:gmatch('.') do out['signal-'..c] = 1 end
delay = 60

Blueprint for lamp segments used in the above example (A-F go clockwise from top, G is the middle one),
for "Import String" button in the shortcut bar at the bottom of the screen:


(adapted from this post in the old LuaCombinator forum thread)

-- What is all this dark magic?

See Lua 5.2 Reference Manual. I also like quick pdf reference here.

Runtime errors in the code will raise global alert on the map, set "mlc-error" output on the combinator (can catch these on Programmable Speakers), and highlight the line where it happened. Syntax errors are reported on save immediately. See in-game help window for some extra debugging options.

Regular combinators are best for simple things, as they work ridiculously fast on every tick. Fancy programmable ones are no replacement for them.


Known Issues and quirks

  • There are some known limitations wrt storing/copying combinator code via blueprints:

  • Hotkeys for save/undo/redo/etc don't work when code textbox is focused, you need to press Esc or otherwise unfocus it first.

  • Cursor position when clicking on the code box can be weird and unintiutive - just click again if you don't see it on the spot.

Huge thanks to ixu and completion for testing the mod extensively and reporting dozens of bugs here.



  • Nice and useful Circuit Network extensions:

    • Switch Button - On/Off switch with configurable signal.

      Kinda like Pushbutton, but signal is persistent, not just pulse, which is easier to work with from any kind of delayed checks.
      Works from anywhere on the (radar-covered) map by default, and can be flipped by simple left-click or E key.

    • Nixie Tubes - a nice display for signal values.

      Integrated Circuitry has even more display options and a neat wire support posts.

    • Time Series Graphs - time-series monitoring/graphing system for your network.

    • Colored Signals, Schall Virtual Signal - more signals to use on the network.

    • RadioNetwork, Factorio LAN, etc - to link remote networks together and control things from afar.

  • This mod base/predecessors:

  • Other programmable logic combinator mods, in no particular order:

    • LuaCombinator 3 - successor to LuaCombinator 2.

      Unfortunately quite buggy, never worked right for me, and way-way overcomplicated, exposing pretty much whole factorio Lua modding API instead of simple inputs-and-outputs sandbox for in-game combinator logic. Seem to be abandoned at the moment (2020-08-31).

      There's also LuaCombinator 3 Fixed, which probably works better with current factorio and other mods.

    • fCPU - simple cpu emulator, allowing to code logic in custom assembly language.

      Actually takes in-game ticks to run its assembly instructions for additional challenge.
      Stands somewhere in-between gate/cmos logic of vanilla factorio and high-level scripting like Lua here.
      Has great documentation, including in-game one.

    • Improved Combinator - factorio combinator combinator.

      Combines operations of any number of factorio combinators into one processing pipeline.
      Nice to save space and make vanilla simple combinator logic more tidy, without the confusing mess of wires.

    • Advanced Combinator - like Improved Combinator, but allows more advanced logic.

    • MicroController - similar to fCPU above, runs custom assembly instructions on factorio ticks.

    • Programmable Controllers - adds whole toolkit of components to build von Neumann architecture machine.

      Kinda like fCPU and MicroController as a starting point, but with extensible architecture, power management and peripherals.

  • Github repo link


If you like this mod and want to support it, buy yourself a coffee or something, idk.