Oxidus

✅ 可玩

oxidus

更新 fdf581a 2026-09-12 源码 下载 ZIP 上游 gesslar/oxidus-mudlib

▶ 开始游玩 · Play Now

A genuinely modern, actively-developed, from-scratch FluffOS mudlib (a distant, long-since-diverged fork of LPUniversity), not a legacy archive -- self-hosts its own real unit test suite, documentation site, and agent-coding guides. Account-based login (register an account, then create/select a character; the first character ever created becomes the mud's owner/admin). Real bespoke content: the village of Olum (square, bakery, tailor, financier, a manor interior with an arcanist NPC/spell tree) plus forest/cavern/maze/tunnels/wastes zones.

README

A genuinely modern, actively-developed FluffOS mudlib -- not a 1990s/2000s archive like most of this collection. Self-described as "an effort to create an opinionated base mudlib... a modern and feature-rich codebase for the LPMud community." Written from scratch (a distant fork of LPUniversity that has long since diverged into its own codebase), with its own real unit test suite, its own documentation site (<https://oxidus.online/>), and its own bundled agent-coding guides.

Source: gesslar/oxidus-mudlib on GitHub.

Highlights

Play

Register an account when you first connect (you'll be asked to confirm a password), then create a character under it. Once in the game: look, score, inventory, and the usual movement directions all work as expected; quit saves you and disconnects cleanly, and reconnecting with the same account brings you back to the same character exactly where you left off.

Status

Boots clean natively and plays correctly end-to-end -- registration, character creation, movement through real authored rooms, and the in-game editor were all verified live during onboarding.

WASM status: playable. Shared WASM driver. A hash() simul_efun stub (adm/simul_efun/hash.lpc) covers the missing PACKAGE_CRYPTO efun so std/room/room.lpc compiles. New-account registration (wasmxid / wasmox / Mud@2026) into Village Square of Olum, plus look / score ("You are Wasmox, a level 1 human.") / quit, verified with scripts/wasm_client.js. Play: https://mudlibs.fluffos.info/oxidus/

Onboarding notes

See NOTES.md in this directory for the technical bring-up log: this lib assumed a considerably newer/differently-configured driver build than this corpus's shared one, in three independent ways (async/await support, a bundled driver-headers directory, and the classic-vs-modern in-game editor efun split), all diagnosed and fixed. Also fixed: a private-visibility driver-callback bug in the editor, a redundant restore call that silently stripped a promoted wizard's extra command access on reconnect, and an unconfigured optional GitHub-issue integration that took the whole bug/idea/todo commands down instead of degrading gracefully. See AGENTS.md §7.161, §7.162, and §8.21 for the two most broadly-applicable findings.

NOTES · 移植与修复记录

oxidus — technical notes

Source: gh repo clone gesslar/oxidus-mudlib (cloned 2026-08-28/30). Number 954, port 40256. Status: done — boots clean natively, full registration-to-gameplay playthrough verified live and repeatedly.

What this lib is

A genuinely modern, actively-developed (pushed within the last day as of this session), from-scratch FluffOS mudlib — not a 1990s/2000s legacy archive like nearly everything else in this corpus. Already .lpc throughout, already UTF-8, ships its own AGENTS.md/.claude/skills/ (37 skill files) documenting its own coding conventions, has a real unit test suite under tests/ (STD_TEST framework), and targets a specific, current FluffOS build via its own adm/dist/rebuild pipeline (clones fluffos/fluffos as a submodule and builds it from source with a custom local_options). Ran scripts/convert_lib.sh per §2.3 convention (cheap and safe even though 0 lossy conversions were needed) — it also mechanically rewrote dual-extension .c compatibility guards and English “static” in MSSP comments (fixed 2026-09-10, issue #3). The 46 local angle-bracket includes converted to quotes stay: the shared driver include path does not search the including file's directory (scripts/convert_lib.sh).

8 authored content areas confirmed real (not stock/copied): a village (Olum) with a bakery, tailor, financier, manor interior, an arcanist NPC/spell tree, forest/cavern/maze/tunnels/wastes zones. Account-based login (register an ACCOUNT with a password, then create/select a CHARACTER under it) rather than the straight-into-a-name flow most libs in this corpus use — matches the README's own description. The first character ever created becomes the mud's owner/admin automatically (confirmed live).

Driver-build mismatches found and fixed (see AGENTS.md for the full writeup)

This lib assumes a considerably newer/differently-configured driver than this corpus's shared build had, in three independent ways. All three are documented as new AGENTS.md catalog entries since they're real, generalizable classes other modern-lib onboardings could hit:

1. async/await support was simply not yet built into this session's shared driver — the checked-out ~/src/fluffos was on a local branch (claude/async-phase15) 3 commits ahead of its own origin/master, and the async/await feature itself (858d5da9, merged 2026-08-27) postdated the driver binary's last build (2026-08-21) by 6 days. Not a driver bug — confirmed via a clean minimal repro (async mixed foo() { ... } failed identically in a throwaway single-file test, succeeded after a plain rebuild) before concluding anything. Fixed by rebuilding ~/src/fluffos/build-debug (cmake --build . --target driver lpcc -j8) from the current checkout — a corpus-wide driver rebuild, not an oxidus-specific change, so every other lib in this corpus benefits/is affected by it too going forward. 2. **include/driver/*.h didn't exist** — oxidus's own build pipeline (adm/dist/rebuild) copies the driver's own src/include/*.h (type.h, socket.h, function.h, etc. — "headers shared between driver and mudlib" per their own README) into the mudlib tree at include/driver/ as a build step; this repo's libs/oxidus/work never got that step run. Fixed by copying ~/src/fluffos/src/include/*.h into libs/oxidus/work/include/driver/ once, by hand — this is a one-time bootstrap step, not something that needs to happen on every boot. 3. PACKAGE_UIDS stub applies missingadm/obj/master.lpc had no get_root_uid()/get_bb_uid()/creator_file() at all (this lib doesn't use the UID/euid privilege model — "Oxidus uses the FluffOS privs model, not PACKAGE_UIDS" per its own AGENTS.md), but this corpus's shared driver build has PACKAGE_UIDS compiled in, which exit(-1)s the whole driver at boot without the first two apply. This is the well-catalogued AGENTS.md §7.2 pattern (also just seen again on majik4, §7.160) — fixed with the standard flat "everyone is Root"/"BACKBONE" stub, harmless since oxidus's real security model (path-based ACL + role groups in adm/obj/master/security.lpc) never consults these. 4. OLD_ED vs the modern ed_start()/ed_cmd()/query_ed_mode() trio — new AGENTS.md §7.161. This corpus's shared driver has OLD_ED defined (hundreds of other libs' own wizard editors depend on the classic ed() efun), which compiles the modern efun set out entirely; std/living/ed.lpc's ed_edit() had been rewritten to use them, breaking std/living/body.lpc's ENTIRE inheritance chain (every player/NPC class) at compile time. Fixed by reverting ed_edit() to the classic ed(file, write_fn, exit_fn, restricted) API — simpler than the session-style version it replaced, since the driver owns the whole input loop once ed() is called (no input_to() loop needed).

Real programming bugs fixed (beyond the driver-mismatch items above)

lpcc-only artifact — NOT a real bug (cross-checked against a live boot)

lpcc_check.sh's batch compile-sweep segfaults deterministically at /d/village/bakery (confirmed reproducible: identical crash, same file, same C++ stack trace, on two separate runs). Root cause: FluffOS's main_lpcc.cc unconditionally calls Tracer::start("trace_lpcc.json") at the top of lpcc_main()lpcc ALWAYS runs with the internal profiling Tracer active, unlike a normal driver boot (mainlib.cc only starts it when a --trace-log-style flag is explicitly passed, which nothing in this pipeline does). The crash itself is inside the Tracer's get_trace_id() (a null/garbage function_table[...].funcname pointer reaching std::string's constructor → strlen() segfault) and is reached via a nested call_other → simul_efun evaluate()call_other chain during bakery.lpc's create() (it's the only file in the village using EXT_SHOP_MENU). This looks like a real driver- level bug in the Tracer/frame-bookkeeping code on this session's WIP claude/async-phase15 branch (a code comment elsewhere in the driver already flags a concern about FRAME_ASYNC/FUNC_VARARGS bit overlap in exactly this kind of frame-kind check) — but it is a compile-sweep- tool-only artifact, not a real gameplay bug: bakery loads and plays correctly under the real driver boot (confirmed live — visited the room via a fresh player character, no crash, normal shop room). Per the established "lpcc-vs-live-driver artifact" pattern in this project, flagged here rather than "fixed," and NOT reported as an oxidus bug. The rest of the corpus (482 other files, bakery excluded from that one run) compiles 100% clean via lpcc_check.sh.

Intentionally not "fixed" — real, environment-dependent, by design

Playthrough verification

Full session via scripts/tmux_mud.sh, native driver (~/src/fluffos/build-debug/src/driver config.fluffos, cwd libs/oxidus), port 40256:

Minor unfixed observation (not root-caused, doesn't block anything)

An empty directory named after the character (e.g. wisteria, elarion) appeared at the mudlib ROOT (not under /home/<letter>/<name>/, the correct home-directory location) after the first admin bootstrap login and again after a makedev promotion. Harmless (empty, never referenced by anything observed during the playthrough) and not chased down to a specific line — cwd defaults to /doc (std/living/player.lpc), not a bare name, so the stray mkdir isn't there; likely somewhere in login.lpc's admin/dev promotion path or body_d. Deleted both before committing (test-session cruft, not shipped content). Worth a closer look in a future pass if it turns out to recur for every ordinary character too, rather than just the admin/dev promotion paths tested here.

Issue #3 — conversion corrupted compatibility guards (2026-09-10)

scripts/convert_lib.sh treated every ".c" and every static as a migration token. Restored upstream Oxidus meaning (gesslar/oxidus-mudlib main):

Quoted includes and collection-driver comments are left as shared-build adaptations (documented above), not reverted.

WASM

Not yet WASM-packaged for the browser gallery (§1.4 pass) — this session's scope was native onboarding + bring-up per the standard pipeline; WASM triage left for a follow-up pass, matching the same "native-boot verified, WASM pending" status other very recently onboarded libs in this corpus (e.g. rifts2) currently carry.

WASM measurement (2026-09-03)

meta.json was already playable from the 2026-08-31 deploy-unblock; the README still said "not yet packaged." Cold-boot under the shared ~/src/fluffos/build-wasm reached the account prompt, but every room failed to compile: std/room/room.lpc gmcp_room_info() calls hash("md4", ...) (a PACKAGE_CRYPTO efun the WASM build does not have). Added adm/simul_efun/hash.lpc (compiled only when __PACKAGE_CRYPTO__ is absent; native keeps the real efun) and included it from adm/obj/simul_efun.lpc. After that, scripts/wasm_client.js created account wasmxid / character wasmox / Mud@2026 and landed in Village Square of Olum (five exits), look reprinted the square, score showed "You are Wasmox, a level 1 human." HP 100, quit printed "Y'all come back, now, y'hear?" Shop/combat/death were not exercised this pass. The MEMFS copy does not write the throwaway account back to the host.

§10.7 deep functional test (2026-08-31)

Round-two deep-functional-test pass, going beyond the onboarding playthrough into actual game systems: combat, skills/spells, equipment, shop economy, consumables, death/respawn, and a real quit+reconnect gap. Native driver (~/src/fluffos/build-debug/src/driver config.fluffos, rebuilt since onboarding — confirmed still the correct build, async/await and ed() fixes both still in effect), port 40256, via scripts/tmux_mud.sh. Three accounts used: thornwick/elmswood (first-ever character on this driver boot, auto-admin, used for makedev promotion and eval-assisted mob spawning), briarwyn/willowmere (second character, used only to verify the stray-directory fix), and cinderfall/moonshade (main playthrough character, promoted to developer for gimme/healup).

Upstream movement check (informational, not acted on)

Per the task brief, checked whether gesslar/oxidus-mudlib has moved since this project's clone (2026-08-28/30). It has, substantially: gh api repos/gesslar/oxidus-mudlib/commits?since=2026-08-28T00:00:00Z returns 21 commits between 2026-08-29 16:01 and 2026-08-31 14:02 (today, a few hours before this test pass — gh repo view confirms pushedAt: 2026-08-31T17:44:59Z). Notable commit subjects suggest the areas most likely to have diverged from this snapshot are exactly the two this project's onboarding had the most friction with: the login/account system (login object updated, promise-driven login handshake) and the async/promise infrastructure (gmcp_await, promises header file, request_deadline never fulfils; type it that way, LPCDoc unwraps promises; document the payload). This is informational only per the task brief — not re-synced, not investigated further, and none of the bugs found in this pass were re-checked against the newer upstream code. A future re-onboarding pass should expect the login/async areas in particular to have changed shape.

Bug found and fixed

adm/obj/login.lpc:449new_character()'s home-directory setup call passed the bare character name to assure_dir() instead of a real path, creating a spurious empty directory named after the character at the mudlib ROOT on every single character creation (not just admin/dev promotions) — this closes the "Minor unfixed observation" left open in this lib's own onboarding NOTES.

Confirmed working, no bugs found

Not a bug: two same-id doors in the manor's Foyer

d/village/manor/foyer.lpc has two add_door() calls both using id: "foyer door" (one north-facing to the porch, one east-facing to the salon) with no distinguishing adjective. A bare open door (or open foyer door) in that room correctly reports "There are multiple doors with that name." — looked like a content bug at first (the room's only two exits both blocked), but std/room/door.lpc:add_door() already auto-appends a direction-specific alias (door.name = "<direction> door") to each door's id array specifically to handle this case: open north door / open east door disambiguate correctly and are the intended way to interact with a room that has multiple same-named doors. Confirmed live. Not fixed, because it isn't broken.

Flagged, not fixed: benign first-boot-only messaging race during the very first character's world-entry

Every fresh driver boot's first-ever new_character() call (which is also always the auto-admin bootstrap path) logs 2-3 caught, non-fatal *Object cannot be loaded during compilation. errors from std/ext/messaging.lpc:172 (receive(message)), reached via enter_world()move_living()force_me("look")'s own command_hook() chain. Confirmed genuinely reproducible, not a one-off: it happened identically for elarion (the original onboarding session's first character, 2026-08-30 19:51, per log/runtime) and again for elmswood (this pass's first character, 2026-08-31 12:24) — but did NOT recur for any subsequently-created character on either driver boot (wisteria, briarwyn/willowmere, cinderfall/ moonshade), confirming it's specific to the very-first-ever compile of the full player class hierarchy on a cold boot, not a general messaging bug. enter_world() already wraps the relevant calls in catch(), so nothing crashes, and the player-visible outcome was correct both times (the new admin lands in the Developer Workroom with a correct room description). Root cause not fully chased down (plausibly a COLOUR_D/LINES_D daemon still finishing its own first-ever lazy compile at the exact moment receive() tries to use it) — flagged here per this round's "document honestly rather than guess" instruction rather than risking a speculative fix to first-boot compile ordering.

Flagged, not fixed: defence/defense skill-path spelling split (zero live impact)

Every live combat/spell code path (std/living/combat.lpc, std/living/damage.lpc, cmds/ability/punch.lpc, weapon procs, all five arcanist spell files) consistently uses the Canadian-English spelling "combat.defence.dodge" / "combat.defence.evade" — correct per this project's own mandated Canadian-English house style (AGENTS.md's own example list literally includes "defence"). Live gameplay in this pass confirmed this spelling is what actually gets trained and queried ("You have gained a new skill: combat.defence.dodge."). However, adm/etc/default.lpml's configured default skill tree, and this lib's own .claude/skills/ documentation (combat-system and skills-and-advancement SKILL.md), both use the American spelling "combat.defense.dodge" / "combat.defense.evade" instead. This is a real spelling inconsistency, but has zero live functional impact today: initialize_missing_skills() (the function that would seed the config's "defense"-named default tree onto new characters) is dead code, never called from anywhere in the codebase, so nothing ever tries to reconcile the two trees — every skill node in practice is created lazily by use_skill()'s own auto-creation using whichever spelling the calling code happens to use, and combat code is internally self-consistent. Not fixed: which side is "canonical" here is genuinely ambiguous (more call sites use "defence", but the config schema and generated docs use "defense"), and there is no live bug to reproduce/verify a fix against — flagged for whoever eventually resolves it (initialize_missing_skills() dead code, or the doc spelling, or both) rather than guessed at.

Gotchas hit while testing (useful for future passes on this lib)