Migrating From GLua

Lux migration is not a line-by-line rewrite. Start by moving handwritten load order, globals, and runtime SERVER/CLIENT branching into the Lux module model.

Replace Loaders with Imports

Loader migration
AddCSLuaFile("cl_panel.lua")
include("shared.lua")
include("sv_store.lua")

The GMod backend generates loader files from the resolved module graph.

Replace if SERVER Blocks with Realm Blocks

Realm block migration
function ENT:Initialize()
  self:SetNoDraw(true)

  if SERVER then
    self:PhysicsInitBox(Vector(-20, -20, 0), Vector(20, 20, 86))
  end
end

The server block is emitted only into server-capable artifacts. Shared code outside that block still cannot call server-only APIs.

Realm block generated shape
fn ENT:Initialize() {
  self:SetCustomCollisionCheck(true)

  server {
    self:PhysicsInitBox(Vector(-20, -20, 0), Vector(20, 20, 86))
  }
}

Split Large Files into Parts

Do not create a fake package just because one file got too large. Put related files under the same module directory:

console/
  module.lux
  cl_commands.lux
  cl_status.lux
  cl_install.lux

All part files share module-private top-level declarations. Use part order only when non-function top-level initialization must happen in a specific sequence.

Part order
part order { "module", "cl_commands", "cl_status", "cl_install" }

Keep Public API Small

Public name mapping
local player_inventory = {}

export { p_inv = player_inventory }

Other modules import the public name.

Import public name
import { p_inv as inventory } from "../inventory"

The internal name player_inventory remains private.