Worked example: a Minecraft modmanaged JVM backendtier W, sandboxed
Farm Watch counts your animals without knowing it is Minecraft.
The same source compiles for Black Ops II. It names capabilities, not a game: entities, their positions, the camera, and a panel. The managed backend resolves symbols by reflection instead of pattern scanning, and nothing above the contract notices.
AXIOM.TOML
id = "dev.carson.farmwatch" version = "0.2.0" tier = "wasm" entry = "farmwatch.wasm" [[targets]] game = "mojang.minecraft" builds = ">=26.0" [capabilities] require = [ "entities", "transform", "camera", "overlay", "input"] [config.radius] label = "Radius" type = "range" unit = "blocks" min = 8 max = 64 default = 32
It never names
A class or a mapping
An address or an offset
A mod loader or a game version
The backend it is running on
src/main.cpp
#include <axiom/surface.hpp> using namespace axiom; struct FarmWatch final : Mod { void on_load(Context& ctx) override { ctx.config().bind("radius", &radius_); ctx.input().bind(Key::F, "toggle"); } void on_frame(Frame& f) override { counts_ = {}; marks_.clear(); if (!shown_) return; // one crossing for every live entity auto ids = f.entities().alive(); auto pos = f.entities().positions(ids); auto eye = f.camera().position; for (std::size_t i = 0; i < ids.size(); ++i) { auto kind = f.entities().kind(ids[i]); if (!is_livestock(kind)) continue; if (distance(eye, pos[i]) > radius_) continue; counts_[kind]++; if (auto s = f.camera().project(pos[i])) marks_.push_back(*s); } } void on_draw(ui::Surface& ui) override { if (!shown_) return; auto p = ui.panel("Farm Watch", ui::Anchor::TopRight); p.text("within {} blocks", radius_); p.separator(); for (auto const& [kind, n] : counts_) p.text("{:<10} {}", name_of(kind), n); for (auto const& m : marks_) p.marker(m); ui.submit(std::move(p)); } void on_event(Event& e) override { if (e.binding() == "toggle") shown_ = !shown_; } bool shown_ = true; float radius_ = 32.0f; std::map<EntityKind, int> counts_; std::vector<ui::Point> marks_; }; AXIOM_MOD(FarmWatch);
In game
What the managed backend changes
Symbols come from reflection
No pattern scanning, no offsets. The pack maps question names onto classes and fields, so a Minecraft update needs a pack bump and nothing else.
memory.protect is refused
The JVM backend declares 8 of 9 primitives. This mod never asked for it, so it loads clean.
Hooks are bytecode transforms
Same hook.install call, a different implementation underneath. This mod uses events instead and needs no hooks at all.
Rebuilt for Black Ops II, the same source needs one line changed: the target in the manifest. Everything it calls resolves on both backends.
builds in 1.9 s112 kB0.3 ms a frame