This is **Luprex**, a game engine built on top of Unreal that uses Lua as its scripting language.
The system consists of two parts:
1. The Luprex DLL. Stores the state of the world. Handles networking and lua scripting. The networking is automatic, scripters don't write networking code. The luprex DLL is event-driven, deterministic, OS-independent, no I/O. Pure standard-compliant C++. Organized as a library with struct `EngineWrapper` as the top-level API.
2. The Unreal-based Driver. Its job is to peer into the luprex DLL and render whatever it sees. It is also responsible for sending OS events (like TCP/IP events) into the Luprex DLL. Uses struct EngineWrapper access the Luprex DLL. There's also a command-line driver for the game's server.
The luprex DLL never calls into the Unreal driver. Output goes through polled buffers. This separation enables deterministic replay for debugging: the driver logs all events, and can replay them to reproduce crashes.
-`Source/Integration/` — Game module C++ source (Unreal-side driver code)
-`Content/` — Unreal assets
-`Docs/` — Documentation. When trying to understand this system, start with the markdown files in the Docs directory.
-`Config/` — Unreal config files
-`EnginePatches/` — Custom engine modifications
## Architecture: World Models and Predictive Reexecution
There are four types of world models, each a separate `World` instance with its own Lua interpreter:
- **Master** (server, one) — authoritative state, executes commands immediately when they arrive.
- **Server-synchronous** (server, one per client) — executes commands when the acknowledgement is issued.
- **Client-synchronous** (client, one) — executes commands when the same acknowledgement arrives; determinism keeps it in perfect sync with its server-synchronous counterpart.
- **Asynchronous** (client, one) — snapshot of client-synchronous with predictions applied for responsive rendering; rolled back when server confirms.
The synchronous models lag behind the master but stay in lockstep with each other. The asynchronous model fills the latency gap for the player.
Two update channels flow into the synchronous models:
1.**Command acknowledgements** — for the client's own actions, keeping the two synchronous models in lockstep.
Lua scripts have no access to the Unreal API whatsoever. The scripter works with plain Lua tables, animation queues of key-value tuples, and coroutines. There are no "unreal bindings." The Luprex DLL is engine-agnostic — Unreal (or any other front end) interprets the animation queues and renders accordingly.
Small concessions to reality exist in animation step tuples:
-`bp` — names which Tangible Actor blueprint to use for rendering
-`mat_color` — a persistent value that hints at material color
These are still just key-value data; the script never touches the Unreal API directly.
## Architecture: Tangibles
Tangibles are game objects. Each has:
- A **Lua table** — the scripter stores arbitrary game data here.
- An **animation queue** — a fixed-length sequence of key-value animation steps.
- A **C++ tangible** — holds the ID, animation queue, positional tracker, etc.
- A **metatable** — engine-reserved; contains __id, __index (class), __threads.
Animation steps contain **transient** values (like `action`) that don't propagate, and **persistent** values (like `xyz`, `facing`, `plane`) that carry forward automatically.
On the Unreal side, **Tangible Actor blueprints** (TangibleStaticMesh, TangibleSkeletalMesh, TangibleCharacter) monitor the animation queue and perform the visual animations. Custom blueprints can interpret the queue in any way they want.
- **Patched Lua runtime** — deterministic table iteration, deterministic table length, flag bits on tables, generalized less-than, C++ exceptions instead of longjmp, and more. See `Docs/A-Summary-of-our-Lua-Patches.md`.
- **LuaStack API** — custom C++ API replacing the standard Lua C API. Uses `LuaDefStack`/`LuaExtStack` with `LuaArg`/`LuaVar`/`LuaRet` slots mapped to stack positions. See `Docs/Our-In-House-Lua-API.md`.
- **LuaDefine macro** — declares Lua-callable C++ functions and auto-registers them in a global registry for automatic insertion into the Lua environment.
- **eng::malloc heap** — custom deterministic memory allocator for the driven portion, ensuring reproducible addresses during replay.
The driven portion must be fully deterministic so that synchronous models stay in lockstep and event replay works. Rules: no true random numbers, no iterating unordered maps, no real-time clocks, no threads (with carefully sandboxed exceptions). See `Docs/The-Event-Driven-Structure-of-the-Engine.md`.
Look-at widgets, hotkeys, and menus are built on top of this. The menu system is implemented entirely in "user space" Lua and blueprint code. See `Docs/Displaying-Widget-Blueprints.md`.
Blueprints are automatically exported to readable text files in `Saved/BlueprintExports/` whenever they are saved in the editor. This lets Claude Code read blueprint logic. See `Docs/Blueprint Text Export.md` for format details. Source: `Source/Integration/BlueprintExporter.h/.cpp` and `Source/Integration/Integration.cpp`.
- When the user gives a direct command, execute it. But when proposing changes on your own initiative, describe the plan and get approval before editing files.
- When writing UFUNCTIONs that take an `AActor*`, `UObject*`, or similar "self" parameter, add `DefaultToSelf` meta to that pin. Most functions should have this on the obvious pin so the user doesn't have to manually wire it in blueprints.