Oxidus

⚠️ 受限

oxidus

更新 9fc9998 2026-10-14 源码 下载 ZIP 上游 gesslar/oxidus-mudlib 落后 16 提交

▶ 开始游玩 · 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 (submodule-patch; upstream.auto_rebase: true — pin tracks upstream main). Catalog patches in patches/; driver headers in overlay/. Native play needs a FluffOS build with promise phase 1.5 combinators (promise_all / promise_race / promise_cancel). Site WASM stays limited until the published FluffOS WASM release includes those efuns.

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.

Hosting (2026-09-17) — real submodule-patch

work/ is a git submodule of gesslar/oxidus-mudlib (gitlink mode 160000 — the 2026-09-15 cutover had left a vendored tree in the parent index despite .gitmodules; corrected here so the rebase timer updates a pin, not 1600 tracked files). upstream.auto_rebase is true — the twice-daily rebase timer advances the pin to upstream main when catalog patches still apply cleanly.

Native play requires FluffOS promise phase 1.5 combinators (promise_all / promise_race / promise_cancel). Local ~/src/fluffos/build-debug was rebuilt from origin/master (2c272875, 2026-09-17) and confirms those symbols. Site Pages WASM still ships FluffOS v2026.0901.0, which lacks combinators, so wasm_status is limited until a newer published WASM release includes phase 1.5.

Catalog FluffOS-compat lives in patches/ (applied by python3 scripts/apply_lib_patches.py oxidus / source-zip pack):

Driver headers (include/driver/*.h, including promise.h) and the adm/custom/ first-user seed live in overlay/ (rsync'd onto zip staging).

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 missing — adm/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. 2026-09-15 follow-up: softened the three LPC comments that cited AGENTS.md section numbers (std/living/ed.lpc, adm/obj/master.lpc, adm/simul_efun/hash.lpc) so they say "required by the collection's shared driver build" without implying those constraints are upstream Oxidus policy. Issue #3 closed.

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:449 — new_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)

深度功能测试(§10.7,2026-09-16)— post submodule-patch cutover

Re-verified against the cutover tree: work/ = gesslar/oxidus-mudlib @ b5beb8ab + patches 0001–0003 + overlay/ (driver headers incl. promise.h, adm/custom/first_user). Port 40256. Cutover wiped prior seeds — first admin this pass was olumadmin / account deepox / Mud@2026 (wipe first_user + data if re-testing first-admin on a dirty tree).

2026-09-17 follow-up: upstream.auto_rebase re-enabled; pin tracks main. Local native driver rebuilt with promise phase 1.5. Site WASM release v2026.0901.0 still lacks combinators → wasm_status: limited until the next published FluffOS WASM includes them. The 2026-09-16 WASM pass below was on the pre-combinator pin b5beb8ab.

Native (scripts/tmux_mud.sh)

Continuous play on the patched+overlay work tree: shop (list / buy tunic at the tailor — exact item name required), combat (environment(this_body())->add_inventory("mob/field_mouse") then punch, not kill), halt, clean quit, reconnect as olumadmin@deepox. No new programming bugs vs the 2026-08-31 pass; cutover patches/overlay hold.

WASM

node scripts/wasm_client.js … libs/oxidus with olumadmin@deepox / Mud@2026 → Developer Workroom look / score ("You are Olumadmin, a level 1 human.") / quit ("Y'all come back, now, y'hear?"). Playable. Same first-boot messaging-race noise as §10.7 2026-08-31 (caught, non-fatal).

Cleanup

git -C work reset --hard + apply_lib_patches.py oxidus + overlay rsync; removed throwaway play dirs (olumadmin/, etc.). Patches stay out-of-tree in patches/ / overlay/ — do not commit dirty submodule work tree.

深度功能测试(§10.7,2026-10-05)— 主控 author_file()/domain_file()

共享驱动的 mudlib_stats 包在主控载入时各调用一次 author_file(<主控文件>) 和 domain_file("/")。补丁 0001 加的 stub 里没有这两个 apply,所以每次启动都打印两行 ... in the master file does not work。0001 的 stub 块补上 author_file() / domain_file(),返回 get_root_uid() / get_bb_uid()(ROOT / BACKBONE),正是驱动缺省时用的值(KB 06 §7.222)。写进 0001 而不是新补丁:rebase 脚本单独检查每个补丁,新补丁的上下文会是 0001 加的行(KB 02 §2.3)。site 同构树(pin + 补丁 + overlay)跑 lpcc config.fluffos /nonexistent.lpc 前后对比,只少了这两行。

Deep functional test (§10.7, 2026-10-13): compile warnings 64 -> 0 (catalog patch 0004)

work/ is the upstream submodule, so the in-place warning campaign never scanned it. Scanned in a scratch repo (scripts/submodule_patch_scratch.py build oxidus); it needs the overlay's include/driver/*.h (now laid by scripts/pristine_tree.sh) and an lpcc with the promise combinators (build-debug/src/lpcc, not the older build-debug/bin/lpcc). 490 files compile, 64 warnings -> 0 after the fixer and hand fixes; exported as patches/0004-fix-compile-warnings.patch (byte-for-byte round trip; all four patches apply on the pin). 26 changed objects loaded before and after in fresh drivers: 25 -> 26, no regressions; the patched tree boots to the login prompt.

Bugs behind the warnings: