Naruto

✅ 可玩

火影

huoying

🔑 fluffos / Mud@2026 更新 f62ccf0 2026-09-01 源码 下载 ZIP

▶ 开始游玩 · Play Now

本游戏自称 火影(英文 Naruto),`master.lpc`/`simul_efun.lpc` 等文件头把底层引擎归功于 Annihilator(muds.net)的 "Neolith 0.0.2"(2000 年9月),是 "ES2"(东方故事Ⅱ)引擎家族的一员,与本项目中的武汉站、雪影奇缘同宗,血缘上也与 es1_win、esI、kxkj、haiyang2 等更远支相关。以日本动漫《火影忍者》为题材(`globals.h` 里甚至留有一行被注释掉的 `MUD_NAME`"火影忍者"),登录界面带有取材自台湾站点的精美 ANSI 彩色 ASCII 艺术 Logo。存档里的忍术/查克拉技能与装备模板库其实相当可观,但内容并不完整:实机测试确认这份快照里实际可通行的房间只有巫师公会设施(公告板、举报处、议事厅等 5 间),并未随附可探索的忍者村/江湖地图,`START_ROOM` 直接硬编码指向巫师公会——更像是引擎与框架的技术快照,而非完整的关卡内容包。

English

The game calls itself Huoying (Naruto); its master.lpc/simul_efun.lpc/chinese.lpc headers credit the underlying engine to Annihilator (muds.net) as "Neolith 0.0.2" (09/07/2000), placing it in the same ES II (Eastern Story II) engine family as this project's wuhanzhan (A Chinese Odyssey) and yueyingqiyuan (Moon Love Story), and more distantly es1_win/esI/kxkj/haiyang2. Themed after the Naruto anime -- globals.h even carries a commented-out MUD_NAME of "火影忍者" ("Fire Shadow Ninja") -- with a fairly elaborate ANSI color ASCII-art login banner sourced from a Taiwanese site. Content is honestly thin: the archive carries a substantial jutsu/chakra-skill/equipment template library, but live testing found only five navigable rooms, all wizard-guild facilities (noticeboard, complaints desk, meeting hall) -- START_ROOM is hardcoded straight to the wizard guild, with no explorable ninja-village map shipped in this snapshot.

README

内容亮点

在线试玩

https://mudlibs.fluffos.info/huoying/

管理员账号 / Admin account

警告:Mud@2026 是本地游玩用的公开默认密码。若要正式对外开放主机,
请先修改此密码(或从 wizlist 中删除该账号)。

本地运行

cd libs/huoying
~/src/fluffos/build-debug/src/driver config.fluffos

游戏端口:40059

NOTES · 移植与修复记录

huoying — 火影 / "Naruto" (ES2 mudlib, Annihilator lineage)

Archive: 火影.rar (archive #65; byte-identical duplicate 火影 (1).rar already flagged in AGENTS.md's Duplicate archives table and NOT re-processed). Port: 40059. Status: done (boots clean, full registration flow verified end-to-end with a real Chinese name including reconnect + quit, lpcc sweep 98.1% pass).

What this is

config.cfg's own name field says 火影 (matches the archive title), and the header comment identifies the underlying engine: Neolith 0.0.2 by Annihilator (09/07/2000) — this is the ES2 mudlib lineage (Annihilator, muds.net), the same family as wuhanzhan/kxkj/ yueyingqiyuan (archives #53/#54/#58) — confirmed via master.lpc's own copyright header ("This program is a part of ES2 mudlib... Annihilator <[email protected]>") repeated verbatim across master.lpc, simul_efun.lpc, chinese.lpc, logind.lpc, securityd.lpc, virtuald.lpc, etc.

include/globals.h has #define MUD_NAME_INTERMUD "Naruto", #define MUD_NAME_ABBR "Naruto", and a commented-out #define MUD_NAME "火影忍者" ("Naruto" literally, "Fire Shadow Ninja") — confirms the lib is genuinely Naruto-themed, not just coincidentally named. The archive's own included 火影说明.txt (author's readme, by "AKAI", 2006.09) says it was found on a Taiwan site and redistributed because it looks especially good over ZMUD's ANSI-art client — this checks out at connect time: the MOTD includes real, quite elaborate ANSI-art banner graphics (a large multi-color logo) that render correctly once terminal codes pass through untouched.

Root: raw/火影/ (one level, not nested further). config.cfg: master file : /adm/obj/master, simulated efun file : /adm/obj/simul_efun, mudlib directory : .. Modest-sized archive: 572 raw files, 466 real LPC (.c.lpc) source files — no bundled driver source, no mega-lib concerns.

Conversion (convert_lib.sh)

Clean pass, no manual stragglers found afterward (verified with the standard file -b re-scan for .lpc/.h files, and grep for .c" leftovers/directories literally named *.c — zero hits on both). Numbers: 572 files total, 471 converted GB18030→UTF-8, 70 already-UTF-8, 0 lossy, 31 skipped-binary (real binaries: mudos.exe, .b binary dumps, a few .o genuinely-binary saves). 466 .lpc files after rename, 168 literal .c" refs fixed automatically, 42 files touched by staticnosave.

New encoding gotcha found here: a config file can be genuinely

MIXED GBK+BIG5, and GB18030 decode does NOT error on the BIG5 bytes

config.cfg's name : 火影 line is correctly GBK (bb f0 d3 b0 decodes to 火影 under GBK/GB18030) — but the file's own header comment block (# Neolith 0.0.2 ..., # Annihilator (09/07/2000)) and its default fail message/default error message values are genuinely BIG5-encoded (Traditional Chinese), left over from the original Taiwan author and apparently never touched by whoever re-encoded the rest of the lib's .lpc source to Simplified/GBK for redistribution. Confirmed byte-for-byte with Python (b'\xab\xfc\xa5O...'.decode('big5') → "指令錯誤,請輸入 help cmds 了解各項指令用法..." — coherent Traditional Chinese; the same bytes under GBK decode to visible mojibake: "���O岿粇�A叫块�J help cmds..."). The dangerous part: iconv -f GB18030 does NOT throw an error on these BIG5 byte sequences — GBK/BIG5 byte-ranges overlap enough that the bytes decode to *some* valid-looking (but wrong) codepoints, so convert_lib.sh's lossy-conversion detection (which only catches genuine decode *failures*) can't catch this at all. Manually identified the 4 affected lines (grep -na '[^\x00-\x7F]' config.cfg to enumerate every non-ASCII line, then spot-decoded each candidate both ways and compared for coherent output) and rebuilt config.fluffos decoding those specific lines with BIG5 and everything else with GB18030. Low real-world impact here (only affects 2 cosmetic player-facing messages plus code comments, not gameplay), but this is a new variant worth watching for on any other Taiwan-origin ES2/Neolith-family lib: a per-line mixed-encoding file where the wrong codec still "succeeds" silently is a strictly harder case than the previously-documented whole-file BIG5-fallback scenario, since there's no error to trigger a retry — only a manual read-through catches it. Did NOT find this issue anywhere in the actual .lpc source tree (spot-checked several files, including long room/item descriptions — all read as coherent Simplified Chinese, i.e. genuinely GBK throughout).

Fixes applied (mudlib-side, before/during first boot)

1. AGENTS.md §4 — master.lpc's valid_read/valid_write lazy

load_object(SECURITY_D) recursion, confirmed via lpcc before ever attempting a full driver boot

The original code already wrapped the lazy load in catch():

nosave int valid_read( string file, mixed user, string func ) {
    object ob;
    if( !catch(ob = load_object(SECURITY_D)) && objectp(ob) )
        return (int)SECURITY_D->valid_read(file, user, func);
    return 1;
}

This looked like it should already be safe (§4's catalog entry describes the UNGUARDED variant as the bug) — but running lpcc on logind.lpc (which pulls in the full chain including securityd.lpc) produced exactly §4's signature symptom anyway: a flood of Too deep recursion. / Error in error handler: *Too deep recursion. rooted at master.lpc:292 (the valid_read line). Root cause is exactly as §4 describes: catch() only protects the control flow of *that specific call* — it does nothing to prevent the driver's own error-reporting path from calling back into valid_read/valid_write (to check permission to write the error/log) as a brand-new outer call, which retries the same disallowed load_object() again, ad infinitum, overflowing the C++ call stack regardless of the inner catch(). Lesson for future libs: don't assume a catch()-wrapped load_object(SECURITY_D) is automatically safe just because it superficially matches the "fixed" shape — always verify with a real lpcc compile of a file that pulls in the daemon chain (not just eyeballing the source) before concluding §4 doesn't apply.

Fix: added the standard re-entrancy-flag guard (loading_security_d) to both valid_write and valid_read in master.lpc, matching the shape already in the catalog. Re-ran lpcc on logind.lpc afterward: zero recursion, zero errors, full compile chain succeeds (confirmed by reading the complete lpcc output, not just grepping for "error").

2. AGENTS.md §15h — is_chinese() GBK-byte-range check and

check_legal_name()'s byte-count bounds/loop, in adm/simul_efun/chinese.lpc and adm/daemons/logind.lpc

Verified via the interactive registration test below (a real 2-character name "秦风" and a 3-character name "王小虎" both accepted correctly and advanced past check_legal_name to world entry) — not just a standalone lpcc-dumped function check.

3. Port-hardcoded master.lpc connect() dispatch via MUD_PORT

new gotcha, not previously in the catalog

master.lpc's connect(int port) switches on the literal incoming port number (case MUD_PORT: ... case HTTP_PORT: ...), where MUD_PORT/ HTTP_PORT are #defined in include/globals.h to the archive's *original* hardcoded ports (8000/8015). Since every lib in this batch gets assigned a different sequential port (here, 40059) that has no relationship to the archive's original port numbers, the switch fell through with no matching case and no default, so connect() implicitly returned nothing — every single connection attempt was rejected outright at the TCP layer with Can not accept connection from ... due to error in connect()., before logon() or any LPC login code ever ran at all (no compile error, no debug.log error beyond that one line — this is a classic "boots clean, but every real connection instantly fails" trap, easy to miss if you only check for compile errors and the "Accepting telnet connections" banner). Fixed by updating MUD_PORT in globals.h from 8000 to 40059 to match config.fluffos's actual port number. Check for this on any other lib in this ES2/Neolith lineage (or any lib whose master.lpc connect() dispatches on a literal port number) — grep master.lpc for connect(int port) and a switch/if on the parameter, and cross-check every compared constant against the lib's actual assigned port before the first real client-connect test (a bare lpcc sweep or a telnet-less driver boot will NOT catch this, since connect() is only exercised by a real incoming socket).

4. AGENTS.md §15w — log_error() broadcasting compile *warnings* to

players as scary "compile-time error" messages

master.lpc's log_error(file, message) (bound to APPLY_LOG_ERROR) unconditionally did if(this_player(1)) efun::write("编译时段错误﹕" + message) for every message reaching it — and this driver funnels every soft compile *warning* (Illegal to declare nosave function, Unused local variable, Unknown #pragma, ignored, etc. — all harmless, expected noise from this batch's staticnosave conversion and old #pragmas) through that same apply, not just genuine fatal errors like the original author assumed. Reproduced directly: the very first registration test (character "秦风") spammed dozens of 编译时段错误:... warning: ... lines to the connecting player as soon as gender selection triggered the lazy compile of /std/char.lpc and its ~30-file inherit chain (/feature/char/*.lpc, /std/room.lpc, /std/bboard.lpc, etc.). Fixed by gating the player-facing efun::write on the message NOT containing the substring "warning:" (kept the unconditional file-log write for every message, warnings included). Re-ran the identical registration test afterward (fresh id "qiufeng") — zero spam, debug.log still cleanly split into a normal boot-time trace, not evidence the warnings simply stopped occurring.

5. A pre-existing single-file typo, world/eq/leg/gai.lpc (§10-family:

missing/misplaced string-literal quote)

set_name(HIG"阿盖\"NOR, ({ "gai" }) ); has a stray backslash directly before the closing quote of the "阿盖" name literal — confirmed present byte-for-byte in the RAW pre-conversion archive too (5c 22 right after the GBK bytes for "盖"), so this is a genuine original-author typo, not conversion fallout. The escaped quote makes the string literal swallow everything up to the next real unescaped quote, producing a cascade of confusing "Illegal character 0xNN" errors on later, perfectly-valid UTF-8 Chinese text further down the same file (once the parser is desynced from being "inside a string" when it shouldn't be, subsequent real string literals get read as raw source tokens instead). Fixed by removing the stray backslash: set_name(HIG"阿盖"NOR, ({ "gai" }) );. Low-impact (a single leg-armor item, "阿盖" — an obvious Naruto/Rock Lee/"Gai-sensei" reference given the theme), but a one-line fix worth taking since it was trivial and matches a cataloged pattern.

Checked and confirmed NOT applicable (verified by reading the actual

source, not assumed)

adm/etc/preload — DNS/intermud daemon (§15p)

Already had /adm/daemons/network/dns_master commented out in the ORIGINAL archive (#/adm/daemons/network/dns_master — the # was already there pre-conversion, not something this pass added). Preload list left as-is (11 active entries: securityd, virtuald, logind, cmd_d, chinesed, emoted, aliasd, fingerd, channeld, natured, enterd) — boots in a few seconds, no hang observed.

Boot + registration-flow verification

Booted ~/src/fluffos/build-debug/src/driver config.fluffos from libs/huoying/ (per AGENTS.md §6 — log directory is CWD-relative; created libs/huoying/log/ as a sibling of config.fluffos, separate from libs/huoying/work/log/). Clean boot: all 11 preload daemons load with only cosmetic warnings (Unknown #pragma, ignored, Unused local variable, Illegal to declare nosave function — all expected/harmless per §3/§15w), Accepting telnet connections on 0.0.0.0:40059. / Initializations complete., zero fatal errors in debug.log.

Full registration-flow transcript (via scripts/mudclient.py, one continuous connection), reading adm/daemons/logind.lpc's actual input_to callback chain first (logonget_idconfirm_idnew_passwordconfirm_passwordget_emailget_genderget_nameenter_world) rather than inferring it from prompt text — no hidden pre-id gate found in this lib (unlike §15q/precedent libs):

--send "qiufeng"        # English id (get_id, 3-10 lowercase letters)
--send "y"               # confirm new-character creation (confirm_id)
--send "test12345"       # password (new_password, >=5 chars)
--send "test12345"       # password confirmation (confirm_password)
--send "[email protected]"  # email (get_email, format-checked)
--send "f"                # gender (get_gender)
--send "秦风"            # REAL Chinese name (get_name -> check_legal_name)
--send "look"
--send "quit"

Result: prompts advanced correctly at every step; "秦风" (2 real Chinese characters) was accepted by check_legal_name (no rejection message), immediately followed by 目前权限:(player) (confirms make_body/enter_world executed, not a silent stall) and then the full MOTD banner, the game's opening-room description ("巫师神殿" — Wizard's Temple), and 你连线进入这个世界。 ("You have connected into this world.") — full success into actual gameplay, not just past the name prompt. Zero "编译时段错误"/error text of any kind reached the player after the §15w fix (compare against the FIRST test run, before that fix, which did show ~40 lines of warning-spam during this exact same step).

Second pass, reconnect + quit (separate connection, same character):

--send "qiufeng"
--send "test12345"      # get_passwd (existing save found)
--send "look"
--send "quit"

Result: 重新连线完毕。 ("Reconnect complete") → room re-displayed correctly (with a wandering NPC, "龙虾", visibly present) → 你重新连线回到这个世界。look re-displayed the room → quit欢迎下次再来!你(qiufeng) 离开游戏。 (clean disconnect message). Confirms save/restore and the full session lifecycle work, not just first-time character creation.

Third pass with a fresh id and a 3-character Chinese name ("王小虎") also succeeded identically, confirming the fix isn't a fluke tied to one specific name length.

lpcc sweep

scripts/lpcc_check.sh libs/huoying/config.fluffos libs/huoying/work: 457/466 pass (98.1%). Remaining 9 failures, all read individually (not just pattern-matched) and confirmed independent, pre-existing archive gaps/incompatibilities rather than conversion bugs — left unfixed per the "breadth over depth" policy, documented here as known issues:

Process notes

2026-07-23 re-verification pass (driver rebuild + formatter + WASM)

WASM-enablement pass (2026-07: loopback-allow + throttle exemptions + admin seeding)

Standard pass per AGENTS.md §1.3b/e + §1.5. Gates found and patched (loopback = 127.0.0.1/127.*/empty/non-string/malformed IP, defending against the WASM query_ip_number() garbage-return bug):

- :120ENABLE_ANTISPAM per-IP registration throttle in logon() ("创造的人物太多" ≥10 registrations per IP per reset → reject); - :180ENABLE_BAN_SITE banned_ip/banned_hostname pattern gate in get_id() (both lists ship empty, but the gate is live); - :589check_ip() per-account IP whitelist (okip property): loopback always passes.

Admin account: fluffos / Mud@2026 / 浮浮, registered through the real native flow (id → y → password ×2 → email → gender m → Chinese name). Granted (admin) via adm/etc/wizlist (added fluffos (admin) alongside the original acme (admin)). Verified after restart: login shows 目前权限﹕(admin), wizard-vision file paths visible in room descriptions, update /world/area/wizard/guildhall recompiles the room. Save files (must be committed): work/data/user/f/fluffos.o, work/data/login/f/fluffos.o.

Retest: fresh registration (秦风/ceshizhe) end-to-end + look/score/quit clean; fluffos login + update clean; a stray typo character (flufos) created during testing was deleted; one single "Too long evaluation" eval-cost overrun was observed once in world/area/wizard NPC-inventory creation during a first-touch lazy-compile burst (content-side, did not recur on subsequent sessions, unrelated to this pass's patches); data/chinese.o runtime churn reverted.

Dual-mode verification pass (2026-07-24)

深度功能测试 / Deep functional test (round two, AGENTS.md §10.7)

One continuous native-driver session via scripts/mudclient.py (port 40059), test character qftester/秦风 (password Test1234, [email protected], male).

Verified working, zero runtime errors in debug.log/driver stdout across the whole session (only harmless pre-existing compile warnings — unused locals, unknown #pragma): full registration wizard (id → confirm → password ×2 → email → gender → Chinese name), MOTD pagination, look/score/i all render correctly with no ANSI/formatting corruption, clean quit, prompt reconnect after both a clean quit and a simulated net-dead (raw socket abrupt-close) disconnect — both resumed in the exact correct room with no state loss and no §7.20/§7.36-class stranding.

Scope-limiting discovery, not a bug: include/login.h's START_ROOM is hardcoded to /world/area/wizard/guildhall.lpc (the wizard-staff guildhall — bug-report board, academy, propose room, meeting room, "black magic" bug-squashing room), and world/area/ contains only the wizard/ subtree — there is no other room/zone anywhere in this archive. Confirmed this is a property of the archive itself, not a conversion gap: substantial NPC/weapon/food/item template content exists under world/npc, world/eq, world/item, etc. (466 .lpc files total), but with no non-wizard rooms to place any of it in, none of it is reachable through normal navigation. This means the lib is playable end-to-end for what geography exists, but the round-two checklist's combat/skill-learning/sect-join/shop steps could not be exercised — not because of a bug, but because there is genuinely no ordinary-player game world to test them in. Documenting honestly rather than fabricating a test of content that isn't there.

Not verified live (only reachable via a genuinely unfinished part of the archive, or requiring a full 900s wait not attempted this pass given the above): a full-duration net-dead force-quit; skill learning; sect/ faction join; shop purchase; combat/death. The training-dummy object world/npc/stake.lpc (accept_fight() unconditionally returns 1, a real safe-sparring NPC) exists in the archive but isn't placed in any reachable room either.

No bugs found or fixed this pass — the lib is clean for everything actually reachable. No code changes; test character save data removed after testing.

WASM 修复摘要(迁移自 meta.json 的 group_note)

Naruto 题材的 ES2/Neolith 引擎 mudlib(火影);这是正统、可游玩的原版——hy2(078,火影 (2).rar)是同一份压缩包的第二次上传,确认除排版外逐字节相同,而且它自己的 duplicate_of 已经正确指回这个 slug。这份档案自己的 duplicate_of 之前被误设成一个不存在的压缩包文件名(火影.rar),现已清除。

§7.86 跨库扫描修复(留言板 post 崩溃)

§7.114 fix: private input_line() broke multi-line to/board/mail/chfn input (2026-08-19)

Same ES2-ancestry bug as zzhj/shzs/dfgs2 (AGENTS.md §7.114): work/feature/user/edit.lpc (this lib's F_EDIT mixin, inherited by obj/user.lpc) declared its input_to() re-arm target private: private void input_line(string line, string text, function callback). The recursive re-arm from inside input_line() silently failed to register once reached through the inherited mixin, so any multi-line .-terminated input session (board post, to, mail, chfn) dropped everything after the first line. Fix: dropped private.

Live-verified on a fresh driver boot (port 40059), fresh character (秦三八/qinsanba): to say → two lines of text → . → resulting say output showed both lines (你说道﹕test line one\ntest line two), not truncated after line 1. Killed the driver by exact PID when done.

Files modified this pass:

§7.100 sub-threshold instance (2026-08-20)

Found during the §7.100 tail-sweep (below the original 166-lib survey's

=100-occurrence threshold, never checked). 7 live

replace_program(ROOM); occurrences: 5 room files under world/area/wizard/*.lpc (bug.lpc, propose.lpc, newbie.lpc, guildhall.lpc, academy.lpc) plus this lib's own room-building tool obj/roommaker.lpc's string-builder template (mixed tab/space-indent variant, hand-fixed). A full post-fix grep confirms 0 live occurrences remain. Verified via a clean native driver boot (zero new debug.log errors, port listening, killed by exact PID after ~8s).

§7.126 sibling-sweep fix: stale pre-.lpc extension in AREA save data (2026-08-28)

Flagged in AGENTS.md §7.126 as a sibling worth checking (originally found on naruto, same ES2/Neolith "Annihilator" AREA-engine lineage). std/area/map.lpc's file_path() has the identical macro-placeholder resolution shape as naruto's, with no strip of a stale trailing .c left over from this project's own .c.lpc conversion pass. Unlike naruto (210 affected save files), this lib's built-out AREA-grid world is much smaller — only 2 .o save files exist under world/area/, with exactly 1 stale __DIR__...c" reference (world/area/wizard/wizard.o). Fixed with the identical choke-point strip in file_path() regardless of the small blast radius, since the fix is a no-op for already-correct .lpc-suffixed values and costs nothing to apply. Verified via a clean native driver boot; not independently live-reproduced by walking onto the specific affected exit tile (small enough impact that a from-scratch reproduction wasn't warranted given the fix is a verbatim, already live-verified port from naruto).

§10.7 deep functional test, round three (2026-09-01): actually exercising the wizard-guildhall's own content

Given round two's finding that the entire reachable game world is the 5-room wizard guildhall (bug/black-magic room, academy, propose room, meeting room, guildhall itself — world/area/ has no other subtree), this pass's angle was to actually USE every one of those rooms' real commands rather than just visiting them, plus adversarial input and a fresh look at the enable_commands()/net-dead/currency bug classes flagged this session on unrelated lineages.

Bug board (bug.lpc room → /daemon/board/bug, the §7.86 fix): live-verified for real this time — west to the black-magic room, post <title> / body / . succeeded cleanly, read 1 displayed the posted message correctly, board listing updated ([ 1 张留言 ]). Also threw adversarial post content at it (%n%d%s in the title, %s plus odd characters in the body) — the board's title/body fields are stored and displayed as plain data, never passed through sprintf/printf as part of a format string, so no crash. Zero debug.log errors.

Academy (/daemon/board/design) and propose room (/daemon/board/propose): both are the same BULLETIN_BOARD base class as the bug board with just a different board_id/location — confirmed by reading daemon/board/design.lpc and propose.lpc alongside bug.lpc (near-identical create() bodies). No separate custom command surface beyond the inherited board verbs already exercised above, so a second live post there would just be retesting the identical inherited code path — not repeated.

Meeting room (meetingroom.lpc) — real bug found and fixed (new catalog entry, see below): its own say/start/over verbs are a genuinely custom, non-board command surface. start/over are wizard-gated and log cleanly via a safely-parameterized sprintf. But say's own meeting-transcript logger built its sprintf format string by directly concatenating the raw player-typed message onto a string literal, instead of passing the message as a %s-bound argument. Live-reproduced as fluffos (admin) with an active meeting: typing say hello %s world %d test while meeting_trigger was set threw *(s)printf(): More arguments specified than passed. (arg: 1) straight to the player's screen (caught by the driver's own top-level command handler, so it doesn't crash the process, but it's a real, easily-triggered runtime error visible to any non-wizard player in the room during a meeting, not just the wizard who started it). Fixed by splitting the format string from the data: sprintf("%s说道﹕%s\n", this_player()->name(1), msg). Verified live: after a wizard update of the room, the identical %s/%d-laden message now logs and speaks normally with zero errors. New AGENTS.md §-worthy bug class: a user-supplied string spliced directly into a sprintf/printf format string (as opposed to passed as a %s argument) lets any embedded % directive in player input crash the call — grep pattern sprintf("[^"]*"\s*\+\s*<var> (a literal format-string prefix concatenated with a variable, not passed as a trailing argument) is a good detector. Checked the rest of this lib's sprintf call sites for the same shape (cmds/usr/tell.lpc, cmds/usr/reply.lpc) — both already correctly pass the user message as a %s argument, not spliced into the format text, so they're safe; only meetingroom.lpc had the bug.

Sibling check: naruto (same ES2/Neolith "Annihilator" lineage, already cross-referenced for the §7.126 AREA-save fix) has the byte-shape-identical bug in its own world/area/wizard/meetingroom.lpc's say() — fixed there too (sprintf("%s說道﹕%s\n", this_player()->name(1), msg)), verified with a standalone lpcc config.fluffos /world/area/wizard/meetingroom compile (clean, no errors) since naruto's own driver wasn't booted this pass.

§7.19-class reentrancy check: grepped every file calling enable_commands/enable_player for a co-located init() (the shape that crashes a room's first-ever visit via NPC setup()/reset_me() recursion). Only hit is feature/char/command.lpc's own enable_player(), called from the player's own login/reconnect path, not from any NPC's init() — no candidate NPC in this lib's tiny reachable world has this shape. Not applicable here.

Currency/query_autoload() check (the severe fysjmb/Fengyun- lineage §7.199 bug): std/money.lpc here already has string query_autoload() { return query_amount() + ""; } live and uncommented — not the Fengyun lineage, not affected.

Net-dead / tell_room() 2-arg wrapper crash (the dtsl §10.7 severity escalation): huoying was already confirmed clean for the related heart_beat-loss-on-reconnect bug class in an earlier corpus sweep (2026-08-19 batch 1). This pass additionally confirms the message()/tell_room() wrapper itself is already on the safe, guarded form (adm/simul_efun/message.lpc's message("tell_room", str, ob, exclude || ({}));, applied as the §15s fix at onboarding) — not re-triggered by anything exercised this pass. Did not attempt the full 900s net-dead wait live (no new evidence surfaced this pass suggesting this lib's user_dump() path has the unguarded-wrapper shape that made it worth the wait on dtsl); low remaining-risk given the wrapper fix is already in place and independently verified.

Adversarial input: over-length email (5000 chars) correctly rejected by the existing 64-char bound with a clean re-prompt, no crash; a name containing a stray Latin %s inside otherwise-Chinese text was rejected/re-prompted by check_legal_name() with no error; board posts with %n%d%s-laden titles/bodies rendered as inert plain text. Zero debug.log runtime errors across the whole adversarial pass.

Files modified this pass:

Test character saves (advtest, hytestone) and incidental board/ admin-account save churn removed after testing; driver killed by exact PID.