Scope: UE4SS Lua mods (and, case by case, native DLLs). For content
mods — tags, textures, maps, sounds — you don't need any of this: upload a
.mjolnir archive at
mjolnircore.com/mods/new.
Why code is different
A Lua mod running under UE4SS has io, os.execute and
package.loadlib — it can write files and load native libraries, which
makes it exactly as powerful as a DLL. There is no reliable way to scan
that power away, so we do not pretend to: everything that executes ships
from this repository, where it arrived as a pull request someone read,
was built by CI, and is covered by a signature the launcher checks
(docs/hub_architecture.md §2).
The trade is real: you cannot ship a script mod in five minutes. In exchange, every player who installs one knows a human read every line.
The pipeline
- Fork and branch. Your mod lives at
mods/<YourModName>/following the layout of the existing mods (Scripts/main.lua, plus amod.jsondeclaringversion,summaryandcategory— the release workflow fails without all three).sluganddefaultare optional; see Shipping by default before reaching for the latter. - Lint clean. CI runs luacheck over
mods/; the release workflow treats warnings as fatal. Run it locally first. - Open a pull request using the code-mod template. Fill in what the mod does, every capability it uses (file I/O, network, input hooks, console commands), and how to test it in game.
- Review. A maintainer reads the code — all of it. Obfuscated, minified, or needlessly clever code is returned, not debated. Budget a round or two of feedback.
- Release. Merged mods ship in the next
mods-v*tag.release-mods.ymlbuilds every mod into a versioned zip, writes a manifest with each artifact's SHA-256, signs the manifest with the release key, and publishes to GitHub Releases andreleases.mjolnircore.com/mods/. The launcher pinskeys/mod-signing.puband installs nothing that fails verification.
Review criteria
Written down so the bar is legible, not vibes:
- Capabilities must be declared. Any use of
io,os,package,loadstring/load,requirebeyond the UE4SS API, or network access must be listed in the PR and justified by the mod's stated purpose. An undeclared capability is an automatic return, however innocent. - No fetched code. A mod may not download, generate, or otherwise acquire code at runtime. What ships is what runs.
- No obfuscation. If a reviewer cannot read it, it does not merge.
- Smallest footprint that works. Hooks are scoped, polling is justified, nothing rummages outside the game and the mod's own directory.
- Plays well with the set. Mods ship together; a mod that breaks another mod, or the base game outside its stated purpose, is returned.
Native DLLs add: source must build reproducibly in CI from what is in the repo, with no prebuilt binaries in the tree, and the bar for accepting one at all is materially higher — expect "can this be Lua?" as the first question.
Shipping by default
"default": true in a mod's mod.json puts it in the set the launcher
installs during setup, without asking. Everything else in the set is
opt-in from My Mods, which lists the whole set so nothing is hidden —
just not installed.
The bar is "a MJOLNIR install does not work without this", not "this is
good and people would like it". Being useful is an argument for being in
the set, not for being installed unasked. In particular, a mod that opens
a channel into the running game, dumps engine internals, or is labelled
experimental does not take the flag no matter how convenient it is for
the people developing it — MJOLNIRBridge evaluates arbitrary Lua on the
game thread, and is exactly the kind of mod that stays opt-in.
Adding the flag is a reviewed change to a file in this repository like any other, and it is reviewed as a decision about every player's machine.
Versioning
The set version (mods-vX.Y.Z) is the unit of release; individual mods
declare their own version in their metadata and it appears in the
manifest. Yanking a bad set is a new tag, never a mutated old one.