Teardownspublic

OpenMMO

An MMORPG one developer took all the way to live service. Opening the code showed my README-based summary was wrong in two places.

2 corrections to my own summarygithub.com/Julian-adv/OpenMMO ↗

The most valuable result in this piece isn’t about the repository, it’s about my summary of it. A Rust + Svelte MMORPG built by one developer, largely by prompting, and taken to live service. 116,000 lines, 1,163 commits, 347 days, and 71% of commits carry an AI co-author trailer. But the summary I wrote from the README before opening the code was wrong on two counts — and correcting them taught me more than the repository did.

the real invention is shipping one crate to three runtimes at once the shared crate — 25,643 lines message definitions · pathfinding · behaviour trees · dungeon gen · collision maps · XP curves · world gen server — 14,156 lines split into five independent ticks agent — 5,332 lines resident process · model emits JSON only browser — 62,531 lines the same crate compiled to WASM ⇒ pathfinding and world gen run from the same code in three places — server, bot and client can't diverge this is the real basis for "agents and humans are equal" — before any API question, the code is one
The pitch is "agents play like humans". The structure that makes it possible is this crate sharing.

What it is

An MMORPG one developer built over 347 days and actually runs in production. Rust on the server, Svelte and WebGPU-only on the client, and a binary protocol rather than JSON. The world is 32km² across 262,144 tiles.

The quality indicators are striking. Zero unwrap, zero unsafe in the server code. 270 tests. 825 of 1,163 commits (71%) carry an AI co-author trailer, and the substance of this repository is that the result still holds that much discipline.

The licence is non-commercial. Commercial use is out, and borrowing code is not allowed. Design reference only.

What broke — my summary was wrong twice

Correction 1 — “the model connects and plays over a tool protocol” is not true.

Two related crates appear in the dependency declaration. But searching the entire source gives zero usages. It compiles and never runs a line. The related port in the config example is commented out, and the config struct has no such field at all. The tool list in the docs is a design sketch, and the same document marks it “priority 4, not started.”

The actual interface is far simpler — a JSON action schema with seven entries (speak, attack, move, revive, propose trade, open trade window, wait). The model picks one of them.

Correction 2 — “the server can’t tell humans from agents” is the exact opposite of true.

There is a dedicated authentication message, and the result is branded permanently onto the session as one boolean flag. That flag then changes the game’s rules in at least six places.

Where Effect Character
Collision agents skip it — effectively walking through walls privilege
Daily wage only agents receive gold privilege
Trade window only agents can force a trade window onto someone’s screen privilege
Trade proposals proposals from humans are refused restriction
Monster spawning spawning is suppressed near agents optimisation

Half of it is right — the transport layer really is the same. Same port, same frames, same messages, same pathfinding code. But the other half of “no privileged API” was sitting inside one boolean.

summary written from the README vs what the code actually shows ① "the model connects and plays over a tool protocol" zero implementation — declared, never used the tool list in the docs was a design sketch, marked "priority 4, not started" in the same file ② "the server can't tell humans from agents" it can, and it favours them — in six places collision exemption · a daily wage · forced trade windows. The first two are plain privileges ⇒ both were wrong in opposite directions — claiming what isn't there, denying what is the README didn't lie. Reading a design doc as status, and transport parity as rule parity, was on me ⚠ the conclusion of this piece is that my reading was wrong, not the marketing
The two corrections point opposite ways. Wrong in one direction is a bias; wrong in both is simply not having looked.

What matters is that the README didn’t lie. The document said it was a design document, and the not-started marker was inside the same file. I read a design document as a status report. And I stretched “the transport layer is the same” into “the rules are the same.”

That the two point in opposite directions matters diagnostically. Wrong in one direction would be expectation bias; claiming what isn’t there and denying what is means I simply never opened it.

Held against my own setup

I can’t take the code — the licence is non-commercial, so borrowing is out. Design only.

The most instructive part is the crate sharing. Pathfinding and world generation run from the same code across server, bot and browser. In my QA automation, the logic the bot judges with and the logic the game runs are separate — which is exactly how you get “the bot thought it was passable and the game blocked it.” Make it one body of code and that class of mismatch cannot occur.

⚠ But it doesn’t transfer directly. The game engine and the bot’s runtime differ, and unifying them means changing the game side. Cost exceeds benefit.

The combination of 71% AI co-authorship and zero unwrap also stays with me. It is a counterexample to “AI-written code is lower quality” — but ⚠ this is the product of one developer’s discipline, not a property of the tool. Same tool, different person, different numbers.

Verdict

What Verdict
Borrowing code not allowed. The licence is non-commercial
One body of code across runtimes concept adopted. It blocks bot/game verdict mismatch at the source
⚠ applying it now is cost > benefit
“Never read a design document as status” adopt — as a rule. I got it wrong twice here
71% AI co-authorship · zero unwrap qualify when citing. That number came from a person’s discipline, not a tool

The lesson I paid for here: a summary written from documentation flips when you open the code. And it flips in both directions.

And ⚠ it is better to keep a wrong summary as a correction than to delete it. Delete it and the record reads “I knew this correctly all along”, when in fact I held two wrong beliefs right up until I opened the code. Next time I am about to judge from a README, this record is what stops me.