Seal of the Fire Dragon (Laughing in the Wind: Afei's Server)

✅ 可玩

炎龙封印(笑傲江湖·阿飞站)

ylfyxa3

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

▶ 开始游玩 · Play Now

炎龙封印(笑傲江湖·阿飞站)是以金庸小说《笑傲江湖》为背景的武侠 MUD,属于"夕阳再现"(XYZX/YLFY)引擎家族,游戏内登录横幅显示为「夕阳再现」之「笑傲江湖」,由"阿飞"在"碎梦"修改的炎龙分支基础上再次深度改造而成,与同引擎家族的其它"夕阳再现"系游戏是关系较远的表亲而非同一份内容;新角色从南阳城附近的客栈起步,可自行分配膂力、悟性、根骨、身法四项天赋,另有福缘、容貌两项隐藏属性影响解谜、拜师等际遇;注册时设有一个不可更改的"身份标识"字符串用于找回密码,新账号若在半小时内退出游戏会被系统自动删除以减轻服务器负担,这是站方明确的规则设计而非 bug。

English

A wuxia MUD themed around Jin Yong's "The Smiling, Proud Wanderer" — the in-game banner reads "Sunset Reappears: Laughing in the Wind" (Chinese title 炎龙封印, "Seal of the Fire Dragon"). New characters start at an inn near Nanyang City and freely allocate four core stats (Strength/Comprehension/Constitution/Agility), plus two hidden traits (Fortune and Looks) that quietly steer sect recruitment and story encounters. It belongs to the Sunset Reappears (XYZX/YLFY) engine family, but only as a distant cousin: a deep independent rework by developer "Afei" built atop an earlier Fire Dragon branch modified by "Suimeng," sharing little actual content with this collection's other Sunset Reappears games. Two operational quirks worth knowing before playing: a fixed, unchangeable "identity string" set at registration is the only way to recover a lost password, and any new account that logs out within 30 minutes of creation is automatically deleted to reduce server load — a deliberate site policy, not a bug.

README

内容亮点

在线试玩

https://mudlibs.fluffos.info/ylfyxa3/

管理员账号 / Admin account

警告:这是一个公开的默认密码,仅供本地/浏览器试玩。正式对外开服前
请务必修改此密码。

本地运行

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

游戏端口:40062

NOTES · 移植与修复记录

ylfyxa3 — 炎龙封印·笑傲江湖 (阿飞站)

Archive: 炎龙封印-笑傲江湖3阿飞站.rar (archive #68). Port: 40062. Status: done (boots clean, full registration flow verified end-to-end twice — once per gender — both reaching the actual game world with real Chinese names; a driver segfault found and fixed; lpcc sweep 99.95% pass).

What this is / lineage

The extracted root (raw/炎龙封印-笑傲江湖3/) self-identifies via its own configs.cfg as name : 炎龙封印 ("Flame Dragon Seal"), and the live boot banner shows a compound name: 「夕阳再现」之「笑傲江湖」 ("Sunset Reappears" — the underlying engine family name — branded as "Laughing in the Wind" for this particular site). adm/obj/ layout (master file : /adm/obj/master, simulated efun file : /adm/obj/simul_efun), MudOS v21-era config, root found directly at the archive's top level (no nesting). ~16,182 .c files before rename (17,380 raw files total, several of which are a bundled Windows/Linux fluffos32/fluffos64 prebuilt driver binary + .bat launchers — ignored, we use our own driver build).

Lineage check requested by the task brief: this archive's title shares the term "炎龙封印" with archive #48 (xyzx3, "夕阳再现III之炎龙封印"). Compared core files directly:

Fixes applied (with why)

1. AGENTS.md §15h (proactive, per assignment brief) — adm/simul_efun/chinese.lpc's is_chinese(): GBK lead-byte check (str[0] > 160 && str[0] < 255, strlen>=2) → CJK codepoint check (str[0] >= 0x4e00 && str[0] <= 0x9fff, strlen>=1). adm/daemons/logind.lpc's check_legal_name(): byte-count bound < 2 || > 10 → character-count bound < 1 || > 5 (matches what the error message already promises — "1 到 5 个中文字"); removed the i%2==0 && even-byte-offset gate so every character position is checked, not every other one. 2. AGENTS.md §15p (proactive) — checked adm/etc/preload: DNS/intermud daemon was already commented out in the raw archive itself (#/adm/daemons/network/dns_master), nothing to do. Also grepped for inline DNS_MASTER calls reachable from the login/display path per §15ab's extension of this rule: logind.lpc's logon() has exactly one such call (DNS_MASTER->query_doing_end()), but it's already commented out by the original author (with their own comment "这段没 鸟用" — "this part is useless"). No action needed, confirmed by reading the source, not assumed. 3. AGENTS.md §14master.lpc's valid_override(file, name) upgraded to the 3-arg form (file, name, main_file), checking main_file == SIMUL_EFUN_OB/MASTER_OB in addition to file, so an efun:: override inside a file #included into simul_efun.lpc is still recognized as trusted. 4. AGENTS.md §8d/§15omaster.lpc had no get_include_path() at all. Added the standard shape (prepends the compiling file's own directory, ":DEFAULT:" for everything else). Found 35+ files (mostly d/obj/quest/*.c, #include <task.h> with a sibling task.h in the same directory) that need this for any live/mid-connection compile; convert_lib.sh's own local-angle-bracket-to-quote pass (§8d's simpler half) had *already* converted all of these to #include "task.h" during the automated conversion step, so get_include_path() here is mostly insurance for anything that pass might have missed, not something that was independently required to fix a live failure. 5. AGENTS.md §15nadm/daemons/securityd.lpc has a genuinely custom ACL (trusted_read/exclude_read mappings, [email protected] credit — same family as shujian2008's custom securityd), with no func-based allowlist. Added the standard switch(func) { case "load_object": case "recompile_object": case "include": return 1; } early-return to its valid_read(), ahead of the euid/status checks — otherwise the driver's own compile-time reads of any never-preloaded /adm//cmds daemon, attributed to a fresh pre-login connection object with (player) status, would be denied by the exclude_read table the first time the registration flow touches one. 6. AGENTS.md §15wmaster.lpc's log_error() displayed EVERY message reaching it (including ordinary compile *warnings*, not just real errors) to this_player(1) prefixed with the alarming "编译时段 错误:" ("compile-time error:"). Gated the player-facing broadcast on the message NOT containing the substring "warning: " (verified exact casing against compiler.cc's d.is_warning ? "warning: " : "error: "), still logging everything to file either way. 7. AGENTS.md §15sadm/simul_efun/message.lpc's tell_room(ob, str, exclude) passed a bare unset exclude (int 0, not an empty array) straight into the message() efun's 4th argument when called in its common 2-arg form (453 call sites in this lib); same shape for shout() passing this_player() (which can be 0) as the exclude arg. Fixed both to exclude || ({}) / this_player() || ({}) — this driver requires that argument to be omitted, an object, or an object array. 8. AGENTS.md §3 counterexample — the blanket staticnosave sed (part of convert_lib.sh) rewrote 13 files' log_file("static/XXX", ...) string-literal path arguments to log_file("nosave/XXX", ...) (this lib uses a real, pre-existing /log/static/ directory as a log-file naming convention, confirmed present on disk — work/log/static/). Reverted all 13 occurrences (grep -rl '"nosave/'sed -i 's/"nosave\//"static\//g') back to the correct path. 9. New variant of the same static/nosave collision family (§15z-shaped, but with an extra twist)include/globals.h had: ``c #ifndef __SENSIBLE_MODIFIERS__ #define nosave nosave #define protected nosave #else #define private protected #define nosave nosave #endif ` Confirmed via the boot log's own #define dump that this FluffOS build DOES predefine __SENSIBLE_MODIFIERS__ (src/local_options:35), so the #else branch (not the #ifndef one) is the one actually compiled in here — meaning #define private protected would be ACTIVE. That's independently wrong on this driver regardless of the §3 sed: private is its own real, distinct L_TYPE_MODIFIER (DECL_PRIVATE, lexer_utils.cc) on this build, not merely an alias for protected the way it may have been on whatever older driver this shim targeted. Neutralized the WHOLE shim (both branches deleted, no replacement macros) rather than trying to preserve a "corrected" version of either branch — nosave, protected, and private are all independently correct, real keywords here and need no translation. 10. NEW bug, and the likely root cause of a driver segfault — a pre-existing double-leading-slash typo, carry_object("//clone/cloth/ ...") (confirmed present in the RAW pre-conversion archive too, not conversion fallout), found in **31 kungfu/class/* NPC files** (famous Jin Yong characters: 岳不群/Yue Buqun, 宁中则/Ning Zhongze, 何足道/He Zudao, 卫四娘/Wei Siniang, 鲁有脚/Lu Youjiao, etc.) plus one more instance in adm/daemons/logind.lpc's under-18-first-reconnect free-clothing gift (new("//clone/cloth/pink_cloth")). The extra leading slash caused new()/carry_object()'s inner new(file) to fail with *Read access denied. (confirmed the target files exist and load fine under their correct single-slash path). Fixed all 32 sites (sed 's#carry_object("//#carry_object("/#g' across the 31 files + one manual fix in logind.lpc`).

Why this mattered beyond the NPCs' own equip failures: the FIRST boot session (before this fix was discovered/applied) segfaulted the whole driver process a few minutes after "Initializations complete.", with a C++ stack trace rooted in apply_low() (vm/internal/ apply.cc:201, dereferencing a shadowed object pointer) reached via a call_out-triggered simul_efun call (adm/daemons/natured.lpc's day/night-cycle update_day_phase()/event_sunrise()/jobd.lpc's get_job(), both of which touch the exact NPCs affected by this bug — /d/dali/npc/liumang and /kungfu/class/huashan/yue — immediately beforehand in the log). The precise mechanism (how a failed carry_object()/new() on one of these NPCs leaves behind a dangling/corrupted object whose later call_out callback walks an invalid shadowed pointer) wasn't fully root-caused at the C++ level, but the correlation is strong and the fix is cheap and independently correct regardless. Verification: rebooted with the fix applied, ran two full registration flows, then left the driver running (idle, past the point the previous crash occurred in wall-clock terms) for 6.5+ minutes straight — zero crashes, zero new debug.log lines at all after boot. Not a 100%-certain proof (the natural-cycle daemon's exact next trigger time is data-driven and wasn't pinned down further), but a strong positive signal given the timing/content correlation. 11. NEW bug — mixed-encoding comment eating the following set_name() call, found in 4 files (d/tianlongsi/npc/xiaoshami.lpc, d/hangzhou/honghua/shi.lpc, d/mr/npc/xiaotong.lpc, d/gaochang/npc/tuying.lpc): each has a //2016.5.22阿飞调整NPC属性 comment written in UTF-8 while the surrounding file is GBK (confirmed via raw hex inspection: the comment's bytes are valid 3-byte UTF-8 sequences, decoding a completely different — and here, coincidentally still Chinese-looking — text than what GB18030 would produce from the same bytes; this is the §15y-shaped "mixed encodings in one file" gotcha, just UTF-8-inside-GBK rather than BIG5-inside-GBK). Decoding the WHOLE file as GB18030 (correct for 99% of it) hits an invalid byte sequence inside this one comment, triggering convert_lib.sh's iconv -c lossy fallback — which, per the already-documented encoding gotcha, ate the real adjacent newline right after the comment along with the invalid bytes, merging the comment onto the SAME line as the following set_name(...) call. Since // comments run to end-of-line, this silently deleted the entire set_name() call for all 4 NPCs — their id/name were NEVER set. Symptom: *Bad argument 1 to set_living_name() Expected: string Got: 0 whenever a room spawned one of these NPCs and called enable_player() (via feature/command.lpc), affecting 5 downstream rooms too (d/tianlongsi/{qingxinge,wulege,wujingge,wuwoge,wuchangge}, d/hangzhou/liuhe4, d/mr/c14-5). A 5th file with the exact same garbled-comment marker (d/city/npc/ping.lpc) was checked and found to NOT have this problem (its set_name() is correctly on its own line) — confirming the corruption is per-file/positional, not a blanket effect of the marker's mere presence. Fix: re-inserted the missing newline right after the comment's mojibake tail in each of the 4 broken files (Python script matching the mojibake tail string 灞炴 and splitting the line there). Verified via targeted lpcc calls: all 4 NPCs + their 7 dependent rooms now PASS. 12. AGENTS.md's documented "iconv -c eats the adjacent real newline before a heredoc's closing tag" gotcha — recurred in 3 files under d/heimuya/ (shenggu.lpc, tang.lpc, npc/tang.lpc), all flagged "LOSSY conversion" by convert_lib.sh. Same exact shape as documented for xyzx3/tianxia: @LONG ... 神彩奕奕.LONG ); (or similar) with the closing LONG tag glued onto the last text line. Fixed by re-inserting the missing newline before each LONG tag. 13. Genuine pre-existing typo, unrelated to conversiondoc/mudlib/efuns/shiwu.lpc (a real room, "小石屋", despite living under the doc/mudlib/efuns/ path) had call_out(do_close,0); — a bare, unquoted function-name identifier instead of a string literal, so the compiler tried (and failed) to resolve do_close as a variable (error: Undefined variable 'do_close'). Fixed to call_out("do_close",0);. 14. AGENTS.md §12 (orphaned non-LPC .c file caught by the blind rename) — doc/mudlib/efuns.lpc is a plain-text listing of efun names (documentation index: "acos add_action all_inventory ..."), not a single line of LPC, and isn't referenced anywhere. Renamed to doc/mudlib/efuns.txt. 15. Mechanical, already handled by convert_lib.sh automatically (no manual intervention needed, verified after the fact): the literal ".c" quote-fixer already turned master.lpc's preload() function's file_size(file + ".c") check into file_size(file + ".lpc") (otherwise every single preload entry would have silently been skipped, since after the rename no .c file exists anymore) and fixed F_MOVE's "/feature/move.c" macro definition in globals.h to .lpc. Confirmed both are correct in the final work/ tree by direct inspection.

Confirmed NOT needed (and how confirmed)

Config

config.fluffos: port number : 40062; the original 4-port multi-protocol setup (external_port_1..4, telnet 4000/5555/6000/9999 for ZMud/ToMud-specific client handshakes) commented out — see the §15q write-up above for why a single ordinary port is not just acceptable but actually *simpler* to test against here. mudlib directory pointed at the absolute work/ path; log/binaries/adm/tmp directories created. maximum evaluation cost was already 10000000000 in the original config — no bump needed (unlike several other libs in this batch whose original value was too tight for this driver's real-time-microsecond semantics). A handful of "obsolete config key" warnings (binary directory, swap file, wombles, warn tab) print at every boot — harmless, matches several other already-done libs' configs, not cleaned up.

Registration flow — read before testing, not assumed

Read logind.lpc's actual logon()get_version()get_id()confirm_id()get_name()new_password()confirm_password()new_biaoshi()confirm_biaoshi()select_gift()/get_gift()get_email()get_gender()enter_world() callback chain in full before writing any test script. Two gotchas found this way, both avoided in the final test:

Full transcript outcome — run 1 (male)

One continuous mudclient.py connection: qinfengsan (English id, no digits — the "qinfeng2" id containing a digit was rejected by check_legal_id's letters-only rule in an earlier attempt, unrelated to any bug) → confirm yreal Chinese name 秦风 (accepted, no rejection — confirms the §15h fix) → password abc12345 (twice) → identity token abc123456 (twice) → gift selection 0 → accept y → email [email protected] → gender mentered the actual game world: room "悦来客栈" (Yuelai Inn) near 南阳城 (Nanyang), full room description with an NPC (店小二, waiter) and a exits list rendered correctly, welcome messages and a "新手礼物包" starter gift item granted. Save files confirmed written and correctly UTF-8: data/user/q/ qinfengsan.o contains "name":"秦风" verbatim, uncorrupted. Zero new debug.log lines during the entire flow (still exactly 209 lines, same as right after boot).

Full transcript outcome — run 2 (female, post-crash-fix reboot)

Rebooted with all fixes (including the double-slash crash fix) applied, ran a second full flow from scratch: qinfengsi → confirm y → real Chinese name 秦岭 (accepted) → password/identity-token setup → gift 0/y → email → gender f → entered a different starting room ("客栈"/inn on 西大街/West Main Street, near a different NPC 丁三) and received the correct gender-specific gift item ("粉红绸衫", pink silk robe). Again zero new debug.log lines. Driver then left running idle for 6.5+ minutes afterward with no crash (see fix #10's writeup) — data/user/q/qinfengsi.o confirms 秦岭 saved correctly.

Driver-process notes for whoever reviews this

The FIRST boot attempt (before the double-leading-slash equip-typo fix was discovered) segfaulted the whole driver process a few minutes after boot, rooted in a call_out→simul_efun→call_otherapply_low's shadow-pointer-chain walk (see fix #10). This was diagnosed from the raw stdout capture (Stack trace (most recent call last): + a C++ backtrace through vm/internal/apply.cc:201), not from debug.log (a process-level segfault doesn't get a chance to write an LPC-level error there). After applying the fix and rebooting, two full registration flows plus 6.5+ minutes of idle runtime produced no further crash — treated as sufficient verification given the strong content/timing correlation (the exact two NPCs referenced in the debug.log lines immediately preceding the crash were both instances of the very same typo).

Both driver launches used the tool's own run_in_background-equivalent foregrounding via a subshell + echo $! > pidfile (not nohup ... & disown, though that pattern is also documented as reliable in AGENTS.md) and were killed by their exact recorded PID (kill 2200142 for the first crashed session's already-dead PID cleanup, kill 2252883 for the second/final session) — no broad pkill -f pattern was used at any point, since other agents' driver processes were confirmed running concurrently on this host throughout this session (own process list showed at least 2 other build-debug/src/driver instances at various points, e.g. archives #67/#71 in progress).

lpcc sweep

16,181 files (16,182 minus the one .txt-renamed doc file) swept with scripts/lpcc_check.sh. First run (before any of the content fixes in #10-#13 above): 16,149 pass / 33 fail (99.8%) — memory pressure from lpcc --batch's single-VM-for-everything design pushed this 23GB host down to ~1.1GB free during the run's tail end (concurrent sibling agents were also running sweeps at the time); per AGENTS.md §6b, killed the process once the actual compile phase had visibly finished (all 16,181 ===== markers present in the raw log) rather than let it proceed into its own post-compile profiling/trace-dump phase, which is what was actually driving the runaway memory use, not the compile work itself.

Triaged all 33 original failures, fixed 23 (the set_name-swallowing comment bug, the heimuya heredoc-newline bug, and the double-slash equip typo, all detailed above) and confirmed each fix via a fast targeted lpcc call per affected object (not a second full batch sweep, to avoid repeating the same memory-pressure risk) — all 23 now individually PASS. Re-ran the FULL sweep once more anyway (memory had fully recovered by then, ~16GB free) to get a real, complete, fresh number rather than rely on arithmetic: 16,173 / 16,181 = 99.95% pass, with the same kill-after- compile-phase discipline applied again (compile phase finished cleanly at ~6.4GB free, well above the danger zone this time). The remaining 8 failures are exactly the confirmed-not-a-bug categories from the section above: 3 genuine missing-content gaps (cangjingge2, shiwu's missing npc/yang, lightman's missing skill), 4 isolated-compile-only false positives (no real player), and 1 dead/unreachable DNS daemon file.

Files touched (for reference)

2026-07-23: driver rebuild retest + LPC formatter + WASM check

WASM-enablement pass (loopback-allow / gate bypass / admin seed)

Standard WASM-first pass per AGENTS.md §1.3b/e and §1.5. This lib had not been touched by any previous pass (fresh git status, no existing 「管理员账号」section) — full pass done from scratch.

Gates found + patched:

- logon()'s ban_cnt > 1 "too many connections from this IP right now" cap (~line 238). - get_id()'s ip_cnt > 9 "too many players from this IP" cap (~line 317, only reachable for non-is_welcome() ids — matches the family's usual whitelist-then-cap shape). - No live uptime() startup-grace gate — the only uptime() check in logon() (~line 129) is already commented out in the original archive; left as-is, noted only. - BAN_D->is_banned(query_ip_number(ob)) at logon()'s top (~line 141) needed no separate guard: band.lpc's own is_banned() fix above already covers it. - Did NOT touch BAN_D->vaild_allow_address() (called from get_passwd()) — that gate enforces a PLAYER's own opt-in allowip address whitelist (a content feature, not hosting protection), and already defaults to "allowed" (return 1) when the player hasn't set one, so it needs no loopback carve-out.

Admin account seeded: id fluffos, password Mud@2026, identity string (身份标识, used only for password recovery, cannot be changed) fluffosid2026identity, Chinese display name 浮浮 — this lineage takes the Chinese name as a single field (no surname/given-name split), so no name-collision workaround was needed. Granted (boss) — the top rank in this lineage's wiz_levels table, same as the existing afei (boss) entry — via fluffos (boss) appended to adm/etc/wizlist; restarted the driver to pick up the new entry (read at securityd.lpc's create()). Verified: real registration flow (fluffos/y/浮浮/[pw]×2 — note: an off-by-one y/name-confirm send in my first test transcript was harmlessly absorbed by the password length check and self-corrected, see raw transcript if replaying this exactly)/[identity]×2/0/y/[email]/m → entered 客栈; relogin as fluffos → update /adm/daemons/band → "重新编译 /adm/daemons/band.lpc:成功!", quit → "欢迎下次再来!".

Retest: fresh normal registration (id qintestchar, name 秦风, gender m) end-to-end — look showed correct room, score produced a full, correctly-rendered character sheet (膂力/悟性/根骨/身法/福缘/容貌 etc.), confirming the player-body class and data model both work; hit the documented "new account, quit within 30 min deletes it" content prompt on quit (expected, kept per policy — this is game design, not a hosting gate). Test character save removed afterward (data/user/q/qintestchar.o, data/login/q/qintestchar.o). Zero new debug.log errors across the whole session (boot + two registrations + two admin logins + retests).

Save files for the orchestrator to add (none gitignored, normal add):

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

XYZX/YLFY 引擎的更大改动分支。状态已从过时的 limited 修正——这份档案自己的 README 和 group_note 里从未记录过任何缺陷说明,本轮重新测试也没有发现:管理员登录(fluffos/Mud@2026)干净正常,'★ 您目前的权限:(boss)',quit 正常。

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

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

先读 doc/help/newbie.txt:本档案(阿飞在"碎梦"炎龙分支上再次深改)的核 心玩法是"挂副本、刷经验、自练技能",与同为 §11"XYZX/炎龙封印分支"的 xyzx3/longyunmeng 那种早期"拜师即起步"的传统流程明显不同——这个差 异不是测试失误,而是这份档案自己的既定设计(见下)。此外确认:本站三 个连接端口(4000/5555/6000/9999)均非本项目分配的 40062 端口,get_ version() 的"2060"客户端暗号门槛不会命中(同 NOTES.md 上方 WASM 段落 已记录),英文 id 直接进普通注册流程;新号半小时内退出会被删号(README 已载,站方明确设计,未触碰 cmds/usr/quit.lpc)。

修复的程序性 bug

1. §7.11(log_file() 未确保目录存在,注册必崩)adm/simul_efun/ file.lpclog_file() 是裸 write_file(LOG_DIR + file, text)logind.lpc::get_gender()(角色创建的最后一步,紧接在性别选择之后) 调用它写 /log/login/newid.log,该目录在 work/ 里不存在——现场复 现:第一次注册测试角色(ylfydeep)在选完性别后卡在裸 > 提示符, look 返回"什么?",debug.log 记录 *Wrong permissions for opening file /log/login/newid.log for append."No such file or directory",与本 session 内 jqxz2015→ xyzxfk→xyzxfy2→xyzx3 这 4 次连续命中的 §7.11 崩溃现场完全一致(本次 是第 5 次,第一次出现在"XYZX/炎龙封印分支"内部但与其它三支代码分叉 较大的这个"阿飞"改版身上,进一步印证这是跨血统、跨分支的通病,不是 某一支代码库特有)。修法与既有惯例一致:把 assure_file() 挪到 log_file() 之前(本驱动编译器要求同文件内被调函数先声明/定义), log_file() 内部改为先 assure_file(LOG_DIR + file)write_file();同一 adm/simul_efun/file.lpc 里的 cat() 也顺手 加固(见下)。用重新注册的第二个测试角色(ylfydeeptwo)验证:性 别选择后正常落地悦来客栈,/log/login/newid.log 成功写入, debug.log 全程零新增错误。 2. cat() 对不存在文件的空指针式崩溃:同一文件里的 cat(string file)file_size(file) == -1(文件不存在)时会走 write(read_file(file)) 分支,read_file() 对不存在的文件返回 0 (非字符串),传给 write() 会在 receive_message() 层触发运行时 错误——与本 session 在 xyzx3 上刚确认过的同一类问题(该 lib 的 cat() 实现细节不同但病灶相同:未检查 read_file() 的返回值)。本 档案里暂未现场触发(未找到会 cat() 一个不存在文件的调用路径), 属主动加固,修法同样是 write(read_file(file) || "")。 3. §7.34(登录流程遗留调试 printf("%O") 泄漏原始对象路径)新增确 认实例logind.lpcget_resp()(接受系统随机中文名分支)和 get_name()(自定输入中文名分支)都各有一行裸 printf("%O\n", ob), 在设置角色中文名之后、密码提示之前,把 /clone/user/login#9 这样的 驱动内部对象路径直接输出给玩家——第一次注册测试时现场观察到 ("楚风烈" → 紧接着一行 /clone/user/login#9)。两条并列路径的同一 行遗留调试输出,与 §7.34 已记录的"接受系统建议名 vs 自己输入名"两条 平行分支各带一份同款 printf 的模式完全一致(fy330/fy2mg/ wmkj/jhfy2 等实例)。两处均已删除,已在 AGENTS.md §7.34 补充这 第二个"XYZX/炎龙封印分支"内的确认实例。

§8.9 食物/饮水初始化——不适用

直接读 logind.lpc::enter_world()(第 1007 行起)确认:if (user-> query("age") == 14) 已经用的是 user(真正的玩家 body),不是 ob (登录桩对象)——本档案这处从一开始就是对的,不是本 session 反复遇到 的那个 bug,未改动。(这份 UI 的 score 面板本身也没有食物/饮水条位 ——采用不同的资源展示模型,"气"/"精"另计,不影响判断。)

测试覆盖

进程卫生附注

清理了一次由本轮测试期间 cron 驱动的门派仇杀世界事件("明教"vs"少林 派"广播)连带触发的 data/npc/menpai.o/menpai1.o 状态文件漂移 (与本次修复无关的背景世界模拟状态),已用 git checkout HEAD -- 还 原到测试前的内容,未纳入本次提交。

WASM 未验证说明

按本 session 约定:emsdk 固定从 storage.googleapis.com 拉取,被本 session 出站代理策略拒绝(curl -sS $HTTPS_PROXY/__agentproxy/status 返回 403),WASM 编译/运行验证本轮继续跳过,仅做原生驱动(linux-debug 预设,ASAN/UBSAN)下的完整 §10.7 测试。

深度功能测试(2026-08-13,round two,新驱动重测)

针对驱动升级(quest_times/win_times %-operator 修复 + Warning/warning 大小写回退兼容)做的重测。核对上面记录的所有修复(§7.11 log_file()cat() 空指针加固、§7.34 printf 泄漏、log_error() severity 判断)逐项确认代码仍然生效;win_times%-operator 也 已用 to_int(query("win_times")) % 5d/city2/npc/refereew.lpc:149); feature/dbase.lpc 未发现 tybxjh/wlhd 那种密码写保护,不适用。管 理员 fluffos/Mud@2026(无需身份标识,登录只用密码)真实重连验 证两次:落地此前保存的地点,"最后对手:木人"等历史状态完整保留, score 显示"【布衣平民】"头衔,debug.log 全程干净。驱动按精确 PID 结束;测试期间产生的存档时间戳增量已 git checkout -- 还原, 本轮无需新代码改动。

深度功能测试(2026-08-19,round four:当铺全流程 + 完整 900 秒净断线)

针对 round two 遗留的三项未测项目中的两项做补测(副本进入/掉落仍按任 务要求跳过,超出单次测试窗口):当铺(典当行)完整购买/典当/赎回/ 卖断流程,以及完整 900 秒 NET_DEAD_TIMEOUT 净断线软测试(此前只用 约 10 分钟真实等待代替过)。全程用管理员 fluffos/Mud@2026 与既有 测试角色 ylfydeeptwo(秦风烈,密码 abc12345)操作,log/debug.log 在整个测试窗口(含 900 秒等待)始终保持 209 行,零新增错误。

当铺(d/city/dangpu,NPC 唐楠 tang.lpc,经 feature/dealer.lpc

用管理员账号 clone /clone/weapon/gangdao(钢刀,原始 value 1000, set_name 的 id 是 blade 不是文件名 gangdao,用 blade 才能被 present() 找到)逐一验证:

完整 900 秒 NET_DEAD_TIMEOUT 净断线测试

先读代码确认预期行为:clone/user/user.lpc::net_dead()call_out("user_dump", NET_DEAD_TIMEOUT, DUMP_NET_DEAD)include/user.h 定义 NET_DEAD_TIMEOUT 为 900);user_dump()DUMP_NET_DEAD 分支无条件执行 command("quit")in_input/ in_edit 只影响是否额外广播一条房间提示,不影响是否退出); cmds/usr/quit.lpc 在非交互(!interactive(me))且账号年龄 ≥ 3600 秒时走正常退出收尾(不触发"注册不足一小时删档"分支,ylfydeeptwo 账号已存在多轮,远超一小时)。预期:净断线满 900 秒后角色应被强制 quit(对象被 destruct),此后重连应该是"账号已存在、正常直接进 入游戏"的全新会话,而不是 reconnect() 那种"重新连线完毕"的续接。

实测:ylfydeeptwo 登录确认(落地"假日客店",score/skills 显示 force 技能等级 1、潜能 100000、钱庄存款一两黄金),记录断线发起的 精确 unix 时间戳后,直接断开原始 socket(不发 quit,真实模拟净断 线)。之后真实阻塞等待了完整 900+ 秒(未用任何缩短的替代等待)。 900 秒时间点到达后:

§7.90/§7.111/§7.112/§7.113/§7.114/§7.115 标准清单巡检——本档案均已干净

进程卫生附注

驱动按精确 PID(360392)结束,未使用 pkill -f 模式匹配。测试期 间产生的存档漂移(data/user/f/fluffos.odata/login/f/fluffos.odata/user/y/ylfydeeptwo.odata/login/y/ylfydeeptwo.o,以及测试 窗口内背景世界模拟触发的 data/npc/menpai.o/menpai1.o 状态漂移) 已 git checkout HEAD -- 还原,未纳入本次提交;未新建任何测试账号 (全程复用既有的 fluffos 管理员与 ylfydeeptwo 测试角色),无需 额外账号清理。本轮无代码改动,仅测试与记录。

AGENTS.md §7.100 修复(2026-08-19,批次三)

ROOM 基类冗余 replace_program(ROOM); 自崩溃地雷(详见 AGENTS.md §7.100):4691 个房间文件的 create() 里紧跟 inherit ROOM; 之后 都有这一行多余调用,永久设下"待替换"标记,第一次对该房间对象绑 定闭包就会崩溃。自带建房工具 clone/misc/roommaker.lpc 的字符串 拼接代码生成模板里也烤了同一个地雷。

修复:脚本化删除所有房间文件里独立成行的 replace_program(ROOM);, 加上 roommaker.lpc 里手动摘除字符串拼接片段。git diff --stat: 4691 files changed,与预期精确吻合(103 处仍存在的匹配全部是既有 注释,未改动)。

验证:build-debug 驱动真实冷启动,端口 40062 正常监听, debug.log 全程干净。既有管理员账号 fluffos/Mud@2026 登录正常 (华山派场景,练武场/兵器房多房间走访),score 正确显示, quit 干净退出,全程无新增 "cannot replace"/"cannot bind" 日志行。

§7.30 uninitialized-mapping accessor sweep (2026-08-20)

Corpus-wide mechanical sweep of the feature/skill.lpc shared-lineage bug (confirmed independently on xiakexing2017/jqxz2015/haiyang2 via round-four testing): 4 accessor(s) in this file returned a raw never-initialized mapping instance variable (defaults to int 0, not ([]), until first assigned), crashing any unguarded keys()/sizeof()/indexing caller for a fresh/untrained character. Fixed at the accessor level (mapp(x) ? x : ([])) per the documented remedy. Verified via lpcc --batch static compile check only (not a live boot) as part of a large mechanical sweep; not individually functionally re-tested live on this lib.

§7.19 enable_player() reentrancy fix (2026-09-01)

Corpus-wide mechanical fix (AGENTS.md §7.19, Batch F of 6). This lib was originally flagged as a possible false positive (it has a pre-existing nosave int enabled = 0; flag in feature/command.lpc, the same shape confirmed genuinely sufficient on xiaoyuxiyou/xyxyutf8/xyxy2 in earlier batches) -- but on closer inspection this is NOT the safe shape: those libs set enabled = 1 BEFORE calling enable_commands(), while here enabled = 1 is set AFTER enable_commands() returns. Since the reentrant nested init()->setup()->enable_player() call (per AGENTS.md §7.19 and driver docs) happens synchronously DURING the enable_commands() call -- before it returns -- the nested call still sees !enabled and calls enable_commands() again, recursing exactly as if there were no guard at all. Confirmed the reachable chain is real: d/shushan/npc/zhangmen.lpc's init() unconditionally calls me->setup(), and inherit/char/char.lpc's setup() unconditionally calls enable_player(). Fixed by adding a true in_enable_player_now reentrancy flag (checked/set before anything else, cleared before the function's single return path) alongside the existing enabled bookkeeping variable, which is left untouched since disable_player() still needs it. Verified via single-file lpcc --batch PASS.