Does BAR compile Lua code or just interpret it

Understanding how the Spring engine processes Lua mods, why LuaJIT is not used, and what that means for widget performance.

Tags: beyond all reason lua, interpreted, compiled, luajit, sync issues, mod performance

Lua in BAR is interpreted, not compiled

BAR runs Lua through the standard Spring engine interpreter. The Lua code in your widgets, gadgets, and mod scripts gets parsed and executed line by line at runtime. There is no ahead-of-time compilation step that converts Lua to native bytecode before loading.

This matters because interpreted code runs slower than compiled code. Global variable lookups happen fresh every time the code accesses them. There is no compiler optimization pass that hoists reads into local variables automatically.

Why LuaJIT is not used

LuaJIT brings massive speedups, easily ten times faster on many workloads. BAR does not use it because of synchronization concerns. In a multiplayer RTS, every client must produce identical simulation results. Even a tiny divergence means desyncs that tear a match apart.

LuaJIT introduces subtle differences in floating point behavior across platforms and optimization paths. The Spring engine team chose stability over raw speed. Every player getting the same result matters more than any single player running faster.

Writing faster code without a compiler

Without compiler optimization, Lua performance depends entirely on how you write the code. Local variable access in Lua is significantly faster than global lookup. Wrapping repeated table accesses into locals at function scope is the single most effective optimization.

For BAR widgets, this pattern works well:

local UnitDefs = UnitDefs
local Spring_GetUnitPosition = Spring.GetUnitPosition

local function checkUnit(unitID)
  local x, y, z = Spring_GetUnitPosition(unitID)
  local ud = UnitDefs[unitID]
  -- work here uses locals, not globals
end

Preprocessor tools can automate this transformation across large files. The output is longer and less readable, but it runs faster. Apply this to hot-path code only.

Gadget and widget load paths

If you modify a gadget file like unit_customicons.lua and the game does not pick up your changes, the issue is usually one of the following:

  • The file sits in the wrong directory relative to the game search path
  • A mod or pack overrides the base file and loads after your edit
  • The gadget is disabled in the lobby configuration

Reference the specific line where the gadget code loads custom parameters. For unit custom icons the relevant code lives at the specific line in the BAR repository under luarules/gadgets/unit_customicons.lua. If changes do not take effect, trace from that entry point forward.

Learn with people who value clarity

Troubleshooting mod code goes faster when you can ask someone who has already solved the problem. Creed of Champions welcomes BAR players across the full skill range. The community values patient explanation and hands-on learning over competitive gatekeeping.

[Crd] The removal of toxicity, the goal of fun and learning, makes for a refreshing spot to play and spend time. It has also made a game with plenty of complexity a bit less daunting to dive into.

Check out the BAR YouTube channel for more modding content.

Advertisement