A Lua debugger for Scrap Mechanic. Hooks the game's Lua VM, embeds EmmyLuaDebugger, and exposes it to the in-game environment so you can attach a debugger from your editor and step through Scrap Mechanic's Lua scripts (and your own mod code).
You'll need xmake and Git LFS (the logo .blend source is stored in LFS).
git lfs install # one-time, per machine, only needed for .blend file (not needed for compiling)
git clone https://github.com/BenMcAvoy/SM-LuaDebugger.git
cd SM-LuaDebugger
xmake f -m release
xmakeThe output DLL ends up under build/.
You need to inject the DLL into ScrapMechanic.exe before a world is loaded, ideally right at game startup, before you hit the main menu. Once a world is up, the Lua VM is already initialized and the hook won't take.
How you inject it is up to you. Anything that does a CreateRemoteThread + LoadLibrary into the game process is fine.
Once injected, the debugger listens on 127.0.0.1:9966. A message box pops up to confirm it's ready, at which point you can attach from your editor.
Scrap Mechanic ships with a sandboxed Lua environment, so the standard debug library isn't normally reachable from mod code. SM-LuaDebugger fixes that:
- The
debugtable is made available insideunsafe_env(sounsafe_env.debugworks from any context that already has access tounsafe_env). - The Emmy debugger API is installed onto the
debugtable asdebug.emmy, which is the entry point you'll use for anything beyond just attaching.
In practice the listener is already started for you, so you usually don't need to touch debug.emmy directly. Just attach from your editor. But if you want to drive it manually, the relevant calls are:
-- already done automatically on startup, but for reference:
debug.emmy.tcpListen("127.0.0.1", 9966)
-- force a breakpoint from code:
debug.emmy.breakHere()See the EmmyLuaDebugger docs for the full API.
Install the EmmyLua extension, then create a debug configuration that attaches to 127.0.0.1:9966.
You'll also want an .emmyrc.json at the root of whatever Lua project / mod folder you're working in, so the analyzer knows it's Lua 5.1 and can find your library stubs:
{
"workspace": {
"$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json",
"runtime": {
"version": "Lua5.1"
},
"library": ["C:/Users/Ben/LuaLibs/sm.lua"]
}
}Swap the library path for wherever you keep your Scrap Mechanic Lua stubs.
- Hooks
LuaVM::Initializevia MinHook to grab thelua_State*the moment a new VM is created. - Drops
emmy_core.dll(embedded in the binary) to a temp file withFILE_FLAG_DELETE_ON_CLOSE,LoadLibrarys it, and immediately closes the handle so the file is unlinked from disk while the loaded image stays mapped. - Calls
luaopen_emmy_coreagainst the game's Lua state, starts the TCP listener, and exposesemmyondebug.emmy(andunsafe_env.debug.emmyif that table exists). - Also hooks
BuildChunkNameso chunk names come through as full paths instead of Lua's truncated"..."form, which otherwise confuses EmmyLua's source resolution.
Every push builds the DLL and a Thunderstore-ready zip in GitHub Actions, and every release asset is published with a signed SLSA build provenance attestation tied to the workflow run and commit that produced it. This means you can prove a given SM-LuaDebugger.dll came from this repo's CI and wasn't tampered with.
To verify a downloaded asset (zip or DLL), install the GitHub CLI and run:
gh attestation verify SM-LuaDebugger.zip --repo BenMcAvoy/SM-LuaDebugger
gh attestation verify SM-LuaDebugger.dll --repo BenMcAvoy/SM-LuaDebuggerA passing check confirms the file was built by this repository's Build workflow on a GitHub-hosted runner, against a specific commit SHA (printed in the output).
Each release also includes a SHA256SUMS.txt so you can sanity-check the hash before importing the attestation:
sha256sum -c SHA256SUMS.txt- EmmyLuaDebugger, the actual debugger engine doing all the heavy lifting. This project is essentially glue to get it talking to Scrap Mechanic's Lua VM.
- EmmyLua analyzer / VSCode extension for the editor-side experience.
- MinHook for function hooking.
- xmake as the build system.
This is a tool for poking at Scrap Mechanic's Lua scripts for modding and debugging purposes. Don't use it on multiplayer servers you don't own, don't be a jerk about it, etc.