Weiming Kongjian (Jianghu Fengyun: Sunset Reappears)

✅ 可玩

未明空间 (Weiming Kongjian / "wmkj")

wmkj

🔑 fluffos / Mud@2026 更新 ad9ca1d 2026-09-04 源码 下载 ZIP

▶ 开始游玩 · Play Now

原始压缩包自称"未明空间",但实际连接后显示的游戏名是"江湖风云之夕阳再现",作者"龙宝宝(xiha)"在 2001 年发布了这份单机存档供他人自行搭建服务器游玩,内容因此定格在当年的版本状态,而非持续运营的活跃游戏;这是"夕阳再现"(Sunset Reappears)引擎系列的一个真正血统分支,与本项目中的 `xyzxfk`、`jhfy`、`xyzx`、`jhfy3`、`xajh4gkb`、`xyzxyl201412` 等同源但各自独立开发,并非简单换皮(本项目里另有一批同样打着"夕阳再现"招牌、实为不同"天涯"家族的档案如 `xysylmhb`/`xyzxiiylzymh`/`yzxiiizylfy`/`xyzx3`,品牌名称不能作为判断血统的依据)。新角色从传统武侠"武庙"踏入江湖,登场时公共频道会广播"听说又来了一位叫做XXX的少年侠士",死亡则有完整的鬼门关体验("白无常"接引,复活落脚武庙,这套死亡系统设计与同血统的 `bixiecanyang` 相同);除共享血统外,本档案还有自己独有的内容——一个以浪客剑心/明治剑客风格为主题的"飞天御剑"门派区域,以及围绕真实存在的"狂风快剑"剑法展开的西夏军队任务线。

English

Archived as "Weiming Kongjian" but branded in-game as "Jianghu Fengyun: Sunset Reappears" — a 2001 single-player snapshot released by its author, 龙宝宝 (xiha), for others to run on their own servers, so its content is frozen at that release rather than a continuously-operated game. New characters step into a traditional wuxia jianghu from the Martial Temple (武庙), announced server-wide with a "a young hero named XXX has just arrived" broadcast; death sends players through a full underworld sequence escorted by 白无常 (the White Guard of Impermanence) before reviving back at the temple, a death-system design shared with this collection's bixiecanyang. Beyond its shared "Sunset Reappears" engine ancestry (also seen in this collection's xyzxfk and jhfy, each independently developed rather than a simple reskin — distinct from another group of same-named archives here that actually descend from an unrelated "Tianya" codebase), this archive has its own distinctive content: a "Feitian Yujian" sect area themed after the Rurouni Kenshin/Meiji-swordsman genre, and a Western-Xia-army questline built around a genuine "Kuangfeng Kuaijian" (Gale Blade) sword technique.

README

内容亮点

深度功能测试新发现的 bug(详见 NOTES.md)

adm/daemons/logind.lpc 有两处 §7.34 调试用 printf("%O\n", ob) 残留和一处 §8.9 食物/饮水初始化误判对象的 bug——已修复。死亡系统的 d/death/npc/wgargoyle.lpc(白无常,实际生效)有 AGENTS.md §7.68 归档的复活软锁死 bug,已按已验证的修法修复;同一个 bug 也出现在两 个确认不可达的死代码文件(bgargoyle.lpcd/shaolin/npc/ yu-zu2.lpc)里,一并修复以防未来被重新接线。另外发现但未能在 本轮定位根因的一个更深的独立问题:即使 §7.68 修复让五阶段死亡对 话完整走完、reincarnate() 也确认执行成功,紧接着的 ob->move(REVIVE_ROOM) 调用之后角色仍然没有真正传送到武庙,且 debug.log/driver 自身输出全程没有任何报错线索——用调试探针确认 了具体卡住的位置,但受限于本轮时间预算未能找到确切原因,已诚实记 录为待后续排查的新发现,不是被这次修复引入的问题(没有这次修复, 死亡对话根本走不完,问题只会更早出现)。

在线试玩

https://mudlibs.fluffos.info/wmkj/

管理员账号 / Admin account

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

本地运行

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

游戏端口:40049

NOTES · 移植与修复记录

wmkj — 未明空间

Archive: 未明空间.rar (#55). Port: 40049. Status: done (boots clean, full registration flow verified end-to-end twice, with two different real Chinese names, both reaching the actual game world).

What this is

The archive's own raw/wmkjlib/README.txt (GBK, converted before reading) identifies it explicitly: this is a single-player/offline snapshot of 未明空间 ("Unnamed/Unclear Space", "wmkj"), dumped by its author "龙宝宝 (xiha)" on Dec 13, 2001, described as "a backup from the end of September [2001]" made obsolete by later changes, released for other players to run standalone. The raw root directory is literally wmkjlib/, and the mudlib itself lives at wmkjlib/world/ (identified via wmkjlib/config.jh's master file : /adm/obj/master / mudlib directory : ./world directives) — the slug wmkj is a pinyin transliteration of 未明空间 chosen for this port, it does not appear literally in the archive.

The archive also bundles a second text file, 小熊泥苑.txt — this is not specific to this game; it's the generic download-site boilerplate/branding for 小熊泥苑 (dtxy.126.com, a mudlib-hosting site seen bundled with several other unrelated archives in this project, e.g. shujian2008/sjtx2) and its body text is actually about a completely different game ("狂想"/Kuangxiang), not 未明空间 — a site-wide readme that got bundled with this download by habit, not a clue about wmkj's own lineage. Ignored for lineage purposes.

Live banner identifies the actual displayed game name as "江湖风云" ("Jianghu Fengyun") "之 夕阳再现" (adm/daemons/logind.lpc's logon() banner) — i.e. wmkj is itself a rebrand/fork of the 夕阳再现 ("Sunset Reappears") lineage already seen twice in this project (archives #46 xyzxfk and #47 xyzxfy2). Confirmed via md5sum: adm/simul_efun/chinese.c is byte-identical to xyzxfk's copy (961d77af057bb93db320af05be5883fc), while master.c/logind.c/ securityd.c all differ (not a duplicate archive — a genuine, separately maintained fork sharing a common ancestor, same pattern as previously documented "similar titles/some shared files ≠ full shared lineage"). u/snow/logind.c (a per-wizard sandbox copy) exists in both archives too.

Layout: adm/{daemons,obj,simul_efun,etc,etcc,tmp} (not adm/single/). Uses feature/dbase.lpc's real local set/query/delete (inherit F_DBASE) for per-object property storage — not the nitan-family shared-simul_efun-dbase architecture bug (confirmed by reading feature/dbase.lpc directly: real local functions, no bare efun::set/query/delete calls anywhere in the lib — grep came up empty). ~11,736 raw files, 10,641 .lpc files after the rename — a mid-sized lib for this batch.

Fixes applied

1. AGENTS.md §15h, standard shape, adm/simul_efun/chinese.lpc's is_chinese(): GBK lead-byte range check (strlen(str)>=2 && str[0]>160 && str[0]<255) rewritten to a CJK Unicode codepoint check (strlen(str)>=1 && str[0]>=0x4e00 && str[0]<=0x9fff). 2. AGENTS.md §15h, check_legal_name() in adm/daemons/logind.lpc (this lib has no separate named.lpc-based check_legal_name — it's defined directly in logind.lpc): - Byte-count bound strlen(name) < 2 || > 10 → character-count bound < 1 || > 5 (the message text, "必须是 1 到 5 个中文字", already stated the correct intended character count). - Sliding check i%2==0 && !is_chinese(name[i..<0]) (alternating GBK-lead-byte offsets, checking a variable-length tail slice) → !is_chinese(name[i..i]) on every index (one whole character per index now, no <0]-tail-slice trick needed since is_chinese only ever inspected str[0]). 3. AGENTS.md §15h, adm/daemons/named.lpc's PATH() macro + sliding-window invalid_new_name() (applied proactively per standing policy even though this file turned out to be dead code — see "Confirmed NOT needed" below for how that was verified): - PATH(name) macro: name[0..1] ("first GBK char") → name[0..0] (first character). - strlen(name) < 2 empty-name guards (4 call sites: remove_name, map_name, who_is, invalid_new_name) → < 1. - invalid_new_name()'s combined-length guard strlen(name) < 4< 2; sliding-window loop bound i <= l - 4i <= l - 2; 2-character-equivalent windows name[i..i+3] (4 bytes) → name[i..i+1]; 3-character-equivalent windows name[i..i+5] (6 bytes) → name[i..i+2]; corresponding i+6<=l guard → i+3<=l. 4. AGENTS.md §15p: adm/etc/preload had /adm/daemons/network/dns_master live — commented it out proactively before the first boot attempt. 5. AGENTS.md §8d/§15o: adm/obj/master.lpc had no get_include_path() apply at all. Added the standard shape (prepend the compiling file's own directory, fall back to :DEFAULT:). This is a correct, harmless, by-the-book fix per the documented pattern — see "Confirmed NOT needed" below for the important caveat that it did not turn out to be the actual cause of this lib's largest lpcc-sweep failure cluster (verified by direct A/B testing, not assumed). 6. AGENTS.md §8b (new mudlib-bug instance, same shape as the xzyx finding): message_combatd(msg, me, victim) is called from adm/daemons/combatd.lpc and two kungfu/skill/*.lpc files, but was never defined anywhere in this lib. Every call site passes the same 3 args as message_vision, so added it as a plain alias varargs void message_combatd(string msg, object me, object you) { message_vision(msg, me, you); } in adm/simul_efun/message.lpc, placed after message_vision's own definition (§8b same-file ordering gotcha). 7. AGENTS.md §11 (copy-paste bug, new instance): clone/weapon/panguanbi.lpc (判官笔, "judge's writing-brush") did inherit PEN; ... init_pen(25);PEN/init_pen are not defined *anywhere* in this archive (no /inherit/weapon/pen.lpc exists at all). The file's own description text ("这是一柄普通的精钢剑" — "an ordinary refined-steel sword") and its material/unit fields match the SWORD template exactly, confirming this was cloned from a sword weapon file and half-renamed. Fixed to inherit SWORD; ... init_sword(25); (matching /inherit/weapon/sword.lpc's real init_sword(int damage, int flag) signature). 8. Pre-existing typo, new instance: d/wudang/taoyuan/tyroad{4,5,6,7}.lpc all had #include __DIR_"feng.h" (missing the second underscore in __DIR__, a genuinely undefined macro/token) — the intended header d/wudang/feng.h (defining look_feng(), referenced via (:look_feng:) in each room's item_desc) is one directory up from taoyuan/, not in the same directory, so even a correct __DIR__"feng.h" wouldn't have resolved it. Fixed to #include "../feng.h" in all 4 files (confirmed correct against d/wudang/wulao.lpc/sanlao.lpc/etc, which already correctly #include "feng.h" from d/wudang/ itself). 9. Pre-existing missing-opening-quote typos (AGENTS.md §10-shape, several new instances, confirmed against the raw pre-conversion GBK bytes — not an encoding artifact): a set("long", <bare Chinese text> with no opening " before the text (closing " present or, in one case, also missing) in: - d/quanzhen/hudi6.lpc, d/quanzhen_old/hudi4.lpc, d/quanzhen_old/hudi6.lpc (a third, separate copy of the exact same "小湖底" room text under a different directory — found only after re-sweeping post-fix) — added the missing opening ". - d/quanzhen_old/hudi5.lpc — missing both opening and closing quote/\n around the same text block — added both. - d/player/fyue_room.lpc — same shape, one "long" description missing its opening quote (and a trailing \n" before the closing paren) — fixed. - d/city/sj.lpc — a much larger instance: the whole do_out() / look_out() tail of the file had every string literal argument written bare with no quotes at all (add_action(do_out, out), message_vision($N大喊一声...\n, me), me->move(__DIR__guangchang), me->command(chat 啊~~~), me->set_temp(die_for,...), a bare return <text>;, etc — a decorative, non-critical "jump off the world's edge" easter-egg room, not on the boot/registration path). Quoted every literal to match evident intent; also initialized the previously-unset object me; to this_player() (the function is bound via add_action, so this_player() is the correct actor — the original code declared but never assigned me before using it).

Confirmed NOT needed (verified by reading source, not assumed)

The get_include_path() investigation (§8d/§15o) — added the fix, but it wasn't the actual cause

The lpcc sweep's largest single failure cluster (30 files, all under u/snow/wudujiao/ and u/fyue/, personal wizard-zone content) all showed error: Cannot #include globals.h cascading into Undefined variable/syntax error noise for macros like NPC/SWORD/ ITEM that globals.h itself defines. This matched the documented §15o shape closely enough that get_include_path() was added to master.lpc proactively (a correct, harmless improvement, kept in the final code) — but re-running the sweep after adding it changed nothing (still exactly 30 failures in that category). Direct A/B testing (adding/removing the apply, lpcc --batch on the same file list) confirmed the fix had zero effect on this specific cluster.

Further isolation testing revealed the real cause: compiling any single file completely alone via lpcc --batch — including files proven to load perfectly cleanly in a real driver boot, e.g. /d/city/wumiao (one of the 4 actual player start rooms, exercised directly by the interactive registration test below with zero errors) — reliably FAILS the same way, while the exact same file passes when compiled as part of the full ~10,641-file batch. This is a pure artifact of lpcc --batch/a from-scratch VM session needing some amount of "warm-up" compiling before certain inherit chains resolve correctly when tested against a near-empty file list — not a real bug, and not specific to the wizard-zone files (confirmed by reproducing it on an unrelated, known-good start room). Matches AGENTS.md §6b's guidance exactly ("verify against the real full-driver boot log before trusting an lpcc-only failure... if grep for the error string comes up empty in an actual driver boot log, it's a sweep artifact"): grepping log/debug.log from both real interactive sessions for wumiao, kedian, yandang, or any Cannot #include string returns nothing but clean compile-note lines, confirming these 30 (and likely a good fraction of the other 335 no-error-message "Fail to load object" entries — see lpcc pass-rate section below) are sweep-only noise, not live bugs. get_include_path() was kept anyway since it's a correct, free improvement per the documented pattern, just not the fix for this particular cluster.

Registration-flow verification (the critical check)

Read adm/daemons/logind.lpc's full callback chain (logon → get_id → confirm_id → get_name/get_resp → new_password → confirm_password → select_gift/set_gift → get_gift → get_email → get_gender → init_new_player/enter_world) before scripting the test. No hidden pre-id BIG5/student/client-version gate in this lib — the very first prompt ("请输入您的英文名字:") really is get_id, gated only by check_legal_id() (3-14 lowercase English letters) and a banned_id/"guest" substring check.

Test 1python3 scripts/mudclient.py 127.0.0.1 40049 --timeout 25 --idle 2 --send "qinfeng" --send "y" --send "秦风" --send "test1234" --send "test1234" --send "0" --send "y" --send "[email protected]" --send "m" --send "look" --send "quit":

Then applied the remaining fixes (get_include_path, message_combatd, panguanbi, feng.h, the 6 missing-quote files) — since LPC objects don't recompile just from editing the file on disk, restarted the driver process and re-ran a second, independent full registration test with a different name to confirm nothing regressed:

Test 2 — same script, --send "linfeng" / --send "林风" (different id and Chinese name, to avoid the first test's now-existing save file): accepted through the identical full chain, landed in a different start room this time (random(4) picked "北疆小镇" / "Northern Frontier Town", /d/xingxiu/beijiang) confirming the start_room random-pick logic itself works, saw the correct channel broadcast (听说又来了一位叫做林风的少年侠士), look/quit both worked. debug.log for both sessions greps clean for error/Undefined function/Read access denied/Bad argument/ segmentation (only benign config-echo lines and the pre-existing, intentional log_error()-to-player mechanism that surfaces harmless Unknown #pragma, ignored compile warnings live to whoever triggers a lazy compile — original mudlib behavior, not a bug introduced here).

Both driver processes were killed after their respective tests; no driver process is left running on port 40049.

lpcc_check.sh sweep

10,641 files total. Ran 4 times as fixes were discovered (each re-run confirmed via free -h/a memory-watching background monitor that this mid-sized lib never came close to the host's 23GB capacity — peak usage stayed well under half of available RAM throughout, no need to abort per §6b):

| Pass | Result | |---|---| | 1 (pre-fix) | 10138 / 10641 = 95.3% | | 2 (+ get_include_path, panguanbi) | 10139 / 10641 (get_include_path fix confirmed NOT the cause of the big cluster — see investigation above) | | 3 (+ message_combatd, feng.h×4, 5 missing-quote fixes) | 10151 / 10641 | | 4 (+ 1 more duplicate missing-quote file found post-sweep) | 10152 / 10641 = 95.4% (final) |

Triage of the remaining 489 failures (categorized by error text, per AGENTS.md §6b):

Encoding

convert_lib.sh's automated pass: 11,325 converted cleanly, 340 already-UTF-8, 62 lossy (invalid bytes dropped — mostly NPC/room files under d/shushan/npc/, d/quanzhen*/obj/bookshelf.c, and a few .bek/map/log data files), 6 skipped as genuinely binary. Re-ran the AGENTS.md straggler check (file -b not reporting text/script/empty for any .lpc/.h) afterward: only one false-positive hit (d/emei/shenshuige.lpc, a short room file that file's heuristic misclassified as "data" despite being valid, clean UTF-8 — verified by hand, no action needed).

Config

config.fluffos adapted from wmkjlib/config.jh (labeled "MudOS 0.9.20"). Original port number : 6666 replaced with 40049 (this project's port assignment for archive #55, per TODO.md's sequential scheme after 40046-40048 reserved for archives #52-54). mudlib directory points at libs/wmkj/work (absolute path). All other directives (master file, simulated efun file, include directories, etc) carried over unchanged; standard modern-FluffOS tuning knobs (time to clean up, maximum evaluation cost, etc) copied from the same template used for the last several libs in this batch (matches xiakexing3's config.fluffos shape).

Re-verification pass (driver rebuild + LPC formatter + WASM build)

WASM-enablement pass (loopback-allow / throttle exemption / admin seeding)

Gates found and patched (AGENTS.md §1.3b/§1.3e/§1.5):

Retrofitted fail-open → fail-closed (2026-07-24): the three band.lpc spots (is_banned(), vaild_allow_address()) and the logind.lpc get_id() per-IP login cap were all originally written so that ANY malformed/non-string ip bypassed the gate, not just genuine loopback — defensive against the old WASM driver bug where query_ip_number() returned garbage for every WASM connection. That driver bug is now fixed (WASM reports a clean "127.0.0.1" same as native), so there is no remaining justification for "can't parse it" ⇒ "must be loopback". Changed: - band.lpc is_banned(): !stringp(site) || site=="127.0.0.1" || strsrch(site,"127.")==0 || sscanf(site,"%*d.%*d.%*d.%*d")!=4 (any unparseable site returns "not banned") → stringp(site) && (site=="127.0.0.1" || strsrch(site,"127.")==0) for the bypass — a non-string site now falls through to the pre-existing if (!site) return 1;/sscanf-based logic below, same as the original pre-WASM code. - band.lpc vaild_allow_address(): same shape fix, plus an added if (!stringp(vip)) return 0; right after the loopback check (deny rather than crash on a non-string ip reaching the allow-list regexp() call below). - logind.lpc get_id(): the per-IP login-cap condition required stringp(query_ip_number(ob)) to be true before the cap would even apply (ip != "127.0.0.1" && stringp(ip) && strsrch(ip,"127.")!=0 && wiz_level<2) — so a non-string ip made the whole condition false and skipped the cap entirely. Introduced a cur_ip/is_local_conn pair computed once (stringp(cur_ip) && (cur_ip=="127.0.0.1" || strsrch(cur_ip,"127.")==0)) and gated the cap on !is_local_conn instead — a non-string ip is no longer local, so the cap still applies to it.

Pre-existing re-login bug found and fixed during this pass:

Admin account: id fluffos, password Mud@2026, name 浮浮, granted (boss) (same rank as the shipped hfzz admin; BOS_PATH command dirs) via adm/etc/wizlist. Verified post-restart: re-login lands in 客店, update /adm/daemons/logind → 成功, clean quit.

Save files for the orchestrator to force-add (untracked, not gitignored):

Retest: fresh registration (qinshiyi / 秦十一) end-to-end with look/score/quit all correct; zero 执行时段错误 in both sessions; test char removed (fluffos kept).

Re-retest after the fail-closed retrofit (2026-07-24): fresh boot, fresh registration (id qretest, real Chinese name 秦风九, talent 0 then y) through look/score/quit — landed in a random starting scene, score output correct, clean quit farewell. fluffos/Mud@2026 admin (boss) login re-verified: look then update /adm/daemons/logind重新编译 /adm/daemons/logind.lpc:成功!, then clean quit. Zero 执行时段错误 lines in debug.log for the whole session. Test char qretest removed afterward; fluffos kept.

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

"夕阳再现"衍生引擎上的一款独立游戏。状态已从过时的 limited 修正——这份档案自己的 README 里从未记录过任何缺陷说明,本轮重新测试也没有发现:管理员登录(fluffos/Mud@2026)干净正常,等级确认("您目前权限:(boss)"),进入起始区域,quit 干净。记录了一处不阻断游戏的历史遗留美观性 bug(本轮未修):某个房间的夜间氛围文字里有一处没有被替换掉的字面 '%s'。

深度功能测试(§10.7,2026-08-04)

原生 driver(端口 40049)跑了一遍超出注册流程的完整游玩。这份档案 和 bixiecanyang 同属"夕阳再现"血统(同源 chinese.lpc/securityd.lpc 等工具文件),注册流程也高度相似:单组密码、天赋可选 1-4 项自定或 0=全随机、六项天赋(含福缘/容貌两项隐藏属性)、email、性别。

主动检查命中 3 处,都在 adm/daemons/logind.lpc:两处紧挨在 ob->set("name", ...) 之前的 printf("%O\n", ob) 调试残留(§7.34, 随机取名/手动取名两条平行路径各一处,和 bixiecanyang 逐字节相同 的形状);enter_world() 里食物/饮水初始化用错对象的经典 §8.9 bug(ob->query("age") 应为 user->query("age"))。三处均已修 复;注册后食物/饮水显示 280/280(满值),确认 §8.9 修复生效。 command_hookfeature/command.lpc)是干净的 nomask,没有 private,不是 bug;没有 MESSAGE_D-> 未防护调用;全树 UTF-8 解码 扫描没有发现 extensionless GBK 文本残留(唯一的 6 个解码失败文件全 部确认是二进制可执行档、tar 归档或巫师私人调试日志,不是应该转码 的内容);feature/alias.lpc 没有 command("quit"),不适用 §7.72 那类 flood-kick bug。

注册与游玩:注册测试角色,落在"铁枪庙"(随机起始点之一,另有 "客店""嘉兴南门"等),携带"法传送帖"道具。探索了客店(有间客栈)、 钱庄方向的南大街、当铺、天安门广场等区域,地图连通性正常。

死亡系统:修复了标准的 §7.68,但同时发现并诚实记录了一个更深、 未能在本轮定位根因的独立异常d/death/npc/{wgargoyle,bgargoyle}.lpc (只有 wgargoyle.lpc 真正生效,DEATH_ROOM 宏指向它所在的 d/death/gate.lpcbgargoyle.lpc 未被任何房间引用,是死代码) 和 d/shaolin/npc/yu-zu2.lpc(同样是被 yu-zu.lpc 取代的死代码, 和 jyqxc/syxjl/wmkj 此前发现的同一个监狱机制 bug 一致)都有 标准的 if (!ob || !present(ob)) return; 复活软锁死守卫,已按已 验证的修法全部拆分修复。

现场测试时发现:死亡后被"四只乌鸦"或"小贩"这类极弱的 NPC 杀死 (战力 300 左右,说明测试角色初始战斗力极低,"攻击力:1",几乎任 何 NPC 都能致命——这是内容/数值现象,不是 bug),落到"鬼门关", "白无常"在场。用临时插入的 tell_object 调试探针逐行追踪确认: 五阶段死亡对话在 §7.68 修复后能完整走完(stage 从 0 递增到 4, 每条 death_msg 文本都正确显示),ob->reincarnate() 也确认执行 成功(探针显示 ghost=0),但紧接着的 ob->move(REVIVE_ROOM) 调用之后,连一条最简单、不涉及任何字符串拼接或返回值处理的 tell_object 探针都没有再显示过——反复用不同测试角色、不同起始 房间复现了同样的结果:五段对话全部显示完毕后,角色仍然留在"鬼门 关",只收到白无常的日常闲聊(chat_msg),从未真正传送到"武庙"。 debug.log 和 driver 自身的 stdout(boot.log)全程没有任何报 错,driver 进程本身也没有崩溃。追查了 feature/move.lpcmove() 自己的"如果身上有装备就先卸下"逻辑(if (query("equipped") && !this_object()->unequip()) return notify_fail(...),怀疑 notify_fail() 在没有活跃玩家指令的 call_out 语境下可能返回一个 让调用方误判的值)、reincarnate() 内部 UPDATE_D->check_user()is_ghost() 时序等几个假设,但在本轮的时间预算内未能定位到确 切根因就没有继续深挖,也没有做任何"猜测性"修复——诚实记录为一 个新发现、尚未解决的独立异常,不是 §7.68 那个已经验证过的 bug 类,也没有被本次的 §7.68 修复引入(§7.68 修复本身已经证明是正 确的:如果没有这个修复,五阶段对话根本不可能完整走完)。已将调试 探针代码全部还原,不带任何调试残留提交。建议下一次有余力时,从 feature/move.lpcmove() 全函数体(不只是 equip 检查那一段) 逐行插桩来精确定位。

quit 正常退出,driver 全程存活未崩溃。debug.log 全程没有真实 的 error:/denied/Bad argument/Too deep recursion 行。 formatter 检查(改动文件均已是干净格式或首次接触触发全文件重排 版,语义改动已逐一核对)、git status --short libs/wmkj/ 复查均 确认改动范围干净——四处源码修改是跟踪变更,测试角色的新存档保持未 跟踪、未提交。

更正(2026-08-05):§7.68 复活软锁"修复"已撤销

上面提到的"鬼魂离开/不在场时被永久放弃复活流程"曾被当作 AGENTS.md §7.68 记录的一类 bug 修复(把单次判定改成每 5 秒重试)。经用户指出并 重新审视:这更可能是有意的游戏设计,不是 bug——大多数这类档案里 鬼魂根本无法自行移动,所以"不在场"要么从未真正发生,要么是"离开去 在阴间游荡,想回来时再走回这个房间、流程会通过 init() 重新从头开始" 这种有意为之的宽松机制,而不是需要强制追上玩家的错误。强行重试还可能 引入新问题:如果鬼魂之后又走回这个房间,旧的重试和 init() 重新触发的 新一轮流程可能同时运行,导致对话重叠错乱。已把这处改动撤销,恢复成 原始的 if (!ob || !present(ob)) return; 单次判定写法(bmxkx2001 除外——那份档案里这确实是一个真实存在、经过实际复现验证的 bug:鬼魂 本身完全无法移动,是另一个不相关的 NPC 强行把鬼魂拖走导致的)。详见 AGENTS.md §7.68 顶部的撤销说明。

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

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

Re-tested against the freshly-rebuilt build-debug/src/driver(post 全库 quest_times/win_times %-operator 修复 + Warning/warning 驱动文本回退)。log_error()adm/obj/master.lpc)已经在更早一 轮正确修复过,管理员账号(fluffos/Mud@2026adm/etc/wizlist 已有 fluffos (boss))此前的存档也已经真正可用——feature/ dbase.lpc 检查确认这份档案不属于 tybxjh/wlhd 那个"天涯" 血统,没有那条会拦截首次密码设置的防劫持保护,存档文件里 password 字段本身就有正确的哈希值,直接登录 + update 验证全部 一次通过。本轮只发现并修复了 log_file() 一处。

发现并修复的 PROGRAMMING bug

1. log_file()adm/simul_efun/file.lpc)完全没有 assure_file() 保护(AGENTS.md §7.11-class 的又一确认实例)adm/daemons/ logind.lpcget_gender()(新角色注册流程的最后一步)紧跟 着调用 log_file("login/newid.log", ...)。已补上 assure_file(LOG_DIR + file);(含前向声明)。

Proactive checks(无需改动)

实测过程

用已提交的 fluffos/Mud@2026 直接登录(本代码线无双密码机制, 只有一个普通密码),断线重连("重新连线完毕")+ update /adm/simul_efun/file(就是本轮改过的文件,"重新编译...成功!") 均一次通过验证。

发现但未修复:多条 debug.log 记录,均为既有游戏内容问题(世界

模拟背景活动,和注册/登录/管理员流程无关)

登录测试期间 log/debug.log 新增了不少条目,追查后确认全部是背景 世界模拟活动触发的既有内容问题,和本轮任何改动都无关: adm/daemons/feizeid.lpc(飞贼精灵)的 choose_npc() 传了一个 int(0)call_other();某个帮会房间 inherit 了一个不存在的 文件 /u/xiha/banghui/bhnpc;两处 NPC create()set_skill() 引用了并不存在的技能名(kuang-jian/feitian-yujianliu)。这些都 是纯内容/数据层面的既有问题,按项目惯例不在本轮 §10.7 标准检查范 围内展开修复,如实记录。log/debug.log 里没有任何和 log_error()/log_file()/注册/登录路径相关的条目。驱动最终按精 确 PID kill,ps -p 确认已退出。

已清理

后续处理(2026-08-13):上面三项被记录为"世界内容问题、暂不修复"的发现,逐一深挖并按可行程度修复

用户明确要求把上面标记为"内容层面既有问题、本轮不修"的三项拿回来 实际修:feizeid.lpccall_other(0,...)、缺失的 /u/xiha/banghui/bhnpc、以及 kuang-jian/feitian-yujianliu 两个 不存在的技能名。三项各自的根因、范围比原始记录深很多,逐一说明:

1. adm/daemons/feizeid.lpc(飞贼精灵)—— 已修复。 根因: choose_npc() 第 44 行 newob = new("/u/xiha/npc/" + feizei[...]); ——/u/xiha/npc/ 整个目录在 work/raw/ 里都完全不存在(不 是某几个文件缺失,是这个 12 个飞贼 NPC 的目录从来没进过这份归 档),所以 new() 每次都回传 0,紧接着的 newob->set(...) 就是对 int(0)call_other——这正是 AGENTS.md §7.63/§7.73 的标准形状。由于飞贼精灵的 call_out 周期是 320 秒且从 create() 就排上,这个 crash 在驱动运行期间 持续、周期性发生,不是偶发。修复:new() 后立即判空,return 之前重排下一次 call_out,不吞掉整个报错循环: ``lpc newob = new("/u/xiha/npc/" + feizei[random(sizeof(feizei))]); if (!newob) { remove_call_out("choose_npc"); call_out("choose_npc", 320); return; } ` 验证:update /adm/daemons/feizeid 编译干净;驱动运行期间不再 出现相关报错(此前 debug.log` 会每 320 秒新增一条)。

2. /u/xiha/banghui/bhnpc(以及同目录下的 banghui.lpc/ vendor.lpc)—— 无法恢复原内容,已改为让崩溃不再发生。 include/globals.hBHNPC/F_BH/F_BVENDOR 三个宏都指向 /u/xiha/banghui/ 下的文件;这整个目录在 work/ 和归档原始的 raw/wmkjlib/world/u/ 里都不存在(u/ 下只有 fyuesnowworkroom.c,从来没有过 xiha)——这份归档本身的说明文件就写 明作者的 ID 正是 "xiha",所以这是这份 2001 年"离线备份"归档在 打包时就已经缺失的作者个人目录,不是转换流程的问题,也没有任何 同名/近似的候选文件可以恢复(§7.94 式判断:不是"选哪份候选"的 内容判断,是彻底找不到)。按项目惯例不编造替代内容。真正会崩溃 的不是那 28 个直接 inherit BHNPC 的 NPC 文件本身(它们只是编 译失败,不会产生游戏内容之外的连带崩溃)——而是 inherit/room/room.lpc(几乎所有房间的公共基类)的 make_inventory(): ``lpc ob = new(file); ob->move(this_object()); // new() 对编译失败的文件回传 0,这里是 call_other(0,...) ` 以及 reset() 里同一个模式的两处调用点(case 1 单件、 default 多件分支)。凡是房间的 "objects" 表里放了这 28 个 NPC 之一,reset()(包括 natured.lpc 的日夜事件、NPC random_move() 换房间触发的目标房间 reset(),两条路径实测都 命中过)就会在 make_inventory() 里对 0call_other。修 复:给 make_inventory()new() 结果判空,reset() 两处调 用点在使用前也判空——这是修复"房间生成逻辑"本身,不是编造缺失 的帮会内容,28 个 NPC 依然会因为找不到 bhnpc 编译失败(这点 没变、也不可能变),只是不再把这个失败向上传播成整栋房间的 crash。验证:实测触发过两条不同路径(/d/city3/guangchangnatured.lpc 的清晨事件、/d/city3/xijie2 经 NPC 游走进房间触 发的 reset()),debug.log` 里两次都只留下预期中的"继承文件不 存在"记录,driver 全程存活,没有级联报错。

3. kuang-jian(有正确技能实现,只是放错目录,已修复)和 feitian-yujianliu(连同同一批彻底缺失的 14 个"飞天"专属技 能,无法恢复,已加保护)—— 两者根因完全不同,分开处理。

- kuang-jian:不是缺失内容,是放错了目录quest/weiguo/xixiabing/kuang-jian.lpc(以及配套的 kuang-jian/kuang.lpckuang-jian/leitingpili.lpc 招式文 件)本身是一份完整、可用的 SKILL 类实现("狂风快剑"),raw/ 归档里就已经放在这个任务目录下,从来没在 kungfu/skill/feature/skill.lpcSKILL_D() 宏硬编码 指向的技能查找目录,learn/practice/perform/chkskill所有技能相关指令都走这个宏)出现过——所以哪怕 set_skill() 的存在性检查侥幸通过,perform_action() 也永 远解析不到招式文件。这不是"选哪个候选实现"的内容判断(本作者 只写了这一份实现,没有竞争版本),是把已确认正确的文件挪到引 擎唯一认可的位置,对应 AGENTS.md §7.94 的"用归档里已证明正确 的内容补回缺失文件名"这类判断。用 git mv 把三个文件整体搬到 kungfu/skill/kuang-jian.lpc + kungfu/skill/kuang-jian/(保 持 __DIR__ 相对招式文件路径不变,perform_action_file() 不 用改)。验证:update 三份文件、以及 4 个引用它的 quest/weiguo/xixiabing/xixia{1..4}.lpc 全部编译成功;现场 clone 了一个 xixia1 西夏兵实测,set_skill("kuang-jian",..) 不再报错,且在真实战斗里触发了"雷霆霹雳"/风系剑招的战斗文本 (证实 perform_action()SKILL_D("kuang-jian")perform_action_file() 整条链路已经生效,不只是编译通过)。

- feitian-yujianliu:深挖后发现原始记录的"两处 NPC"严重低 估了范围——d/feitian/("飞天御剑流"门派区域,绯村剑心/比古 清十郎等 NPC)整个技能体系一共引用了 15 个 kungfu/skill/ 下完全不存在的技能名(feitian-yujianliuwuxing-dunshayi-xinfashayiaikidobearartxuanhualiu-quanfaedgehuoxinliu-jianfa 等),分布在 11 个 NPC 文件biguqing/jianxin/qingyun/axun/ miyan/dizi/luo/luoren/shiren/xunjing/zuo)里, raw/ 归档同样完全没有——是这整片"飞天"(其实是新选组/绯村 剑心题材)门派区域自带的一整套自定义技能树,连同 xiha 的个 人目录一起,从归档诞生起就没有实现文件。feature/skill.lpcset_skill()/map_skill() 对不存在的技能名是故意 error()(这是这份代码库统一、正确的校验逻辑,其它调用点用 的都是真实存在的技能,不能因为这三个区域性文件就改 feature/skill.lpc 本身),而这些 NPC 的 create() 里,缺失 技能的 set_skill()/map_skill() 调用夹在正常技能中间——一 旦抛错,create() 当场中断,后面的 create_family()(帮派注 册)、setup()、穿装备统统执行不到,等于这整个门派的掌门/长 老 NPC 从未正常初始化过。既不编造这 15 个技能的具体实现(属于 游戏设计/平衡工作,超出本项目范围),也不能改 feature/skill.lpc 的校验语义,所以修复落在调用点:给这 15 个引用(set_skill() 及唯一一处第一参数就是缺失技能名的 map_skill("edge", "feitian-yujianliu"))逐一套上 catch(...),让 create() 能跳过这一句继续往下执行——这些 NPC 该有的技能数值就是少了几项(本来就从未真正生效过),但至 少角色本身、帮派注册、装备穿戴这些不该被牵连的初始化逻辑都恢 复正常。验证:对全部 11 个文件逐一 updatedebug.log 显示每一处缺失技能都变成"错误讯息被拦截"(catch() 生效)后 紧跟"成功!"(create() 完整跑完),不再有任何未捕获的 F_SKILL: No such skill 中断 create()

顺带在同一次测试中发现一个范围外的同类实例: d/lingxiao/npc/wang.lpc 引用了同样不存在的技能 xueshan-swordbaoshid.lpcchoose_baosi()/random_place() 触发),未 修——不属于本轮明确要处理的 kuang-jian/feitian-yujianliu 范围,留给下一轮处理。

验证方式(本次三项修复共用)

原生 driver(端口 40049)重新起过一轮,用 fluffos/Mud@2026(boss))登录后对全部改动文件逐一 update 确认编译/create() 干净;另注册了一个全新测试角色(wmkjqatest/中文名"秦风测")走完 整个注册流程直达游戏世界,score 输出正确,quit 后等满 50 秒冷 却、用同一账号密码重新连线,成功恢复到退出前所在房间(断线重连闭 环)。驱动最终按精确 PID killps -p 确认已退出。测试产生的 fluffos 存档时间戳类微小 diff 已 git checkout 撤销;新注册的 wmkjqatest 测试存档文件(未追踪)已删除,未提交。

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

ROOM 基类冗余 replace_program(ROOM); 自崩溃地雷(详见 AGENTS.md §7.100):2797 个房间文件的 create() 里紧跟 inherit ROOM; 之后 都有这一行多余调用,永久设下"待替换"标记,第一次对该房间对象绑 定闭包就会崩溃。自带建房工具有 4 处拷贝(obj/roommaker.lpcclone/misc/roommaker.lpcu/fyue/misc/roommaker.lpc 简单字符串 拼接写法;obj/rmmaker.lpcroom_code += 写法)。累计 2800 处 live 调用删除,和 survey 记录的数字精确吻合,修复后 0 处遗留。

验证:build-debug 驱动真实冷启动,端口 40049 正常监听。启动期间 观察到一条既有的 debug.log 报错(natured.lpc 早晨事件在 /d/city/guangchang 生成一个继承 u/xiha/banghui/bhnpc.lpc 的 NPC, 但该文件在盘面上确实不存在)——确认和本次扫描无关(零处 "cannot replace"/"cannot bind",文件本身就缺失,是一个既有的缺失 继承内容 bug,不是 replace_program 回归),未修,超出本次范围。既 有管理员账号 fluffos/Mud@2026 登录正常(落地北疆小镇, look/quit),全程 debug.log 零新增行。

补完 d/lingxiao/npc/wang.lpc 缺失技能崩溃(2026-08-20)

此前一轮记录本文件的 xueshan-sword 缺失技能"超出范围,留给下一轮", 只是未验证是否真的只有这一处。现场用 update 实测发现:光包住 xueshan-sword 依然在下一行 set_skill("bingxue-xinfa", ...) 崩溃 中断 create()——这个 NPC 的整套"凌霄城"技能(xueshan-sword/ bingxue-xinfa/snow-zhang/snowstepset_skill+map_skill 共 9 处引用)全部是未实现的内容,不止 NOTES.md 之前记录的那一个。已按 和本库其余 11 个同类档案完全一致的手法,把全部 9 处引用套上 catch(...)。现场验证:update d/lingxiao/npc/wang.lpc 后 debug.log 依次显示 4 次"错误讯息被拦截"(对应 4 个缺失技能),最终 "成功!",create() 完整跑完。

§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.

AGENTS.md §7.19 sweep (2026-09-01): enable_player() reentrancy from init()

Same corpus-wide bug class as mhxy/wuhanzhan (AGENTS.md §7.19): this lib's feature/command.lpc enable_player() wrapper (around the raw enable_commands() efun) is reachable from an NPC's init() via a redundant create()-then-init()-calls-reset_me()-calls-setup() chain -- confirmed via a body-aware static scan of every init() in this lib: only 2 files have this exact redundant pattern (d/shushan/npc/zhangmen.lpc, d/shushan/zhenyaota/npc/zhangmen.lpc -- the same zhangmen.lpc lineage already documented as the original live-reproduced crash on mhxy), a much smaller count than most other libs in this sweep but still a real, live reachability path: init() conditionally calls me->reset_me(me), and reset_me() calls setup() which calls enable_player(), after create() already made the object living(). Calling enable_commands() a second time on an already-living() object makes the driver re-invoke that object's own init() as a side effect, re-entering the same chain while the original call is still on the stack -- genuine reentrancy, crashing with "Too deep recursion" (most likely on an NPC's first-ever preload/compile).

feature/damage.lpc's revive() and cmds/std/sleep.lpc's wakeup() both call enable_player() again while the object is still living(). This confirms a bare if (living(this_object())) return; guard would be the WRONG fix -- used the same true reentrancy-flag fix as mhxy instead: a nosave private int in_enable_player_now; set for the duration of the wrapper's body, guarding only genuine same-call-stack reentrancy while leaving every legitimate re-enable (revive/wakeup) unaffected. enable_player() had a single fall-through exit (no early returns), so one guard-at-top + one clear-at-bottom pair was sufficient. Verified via a single-file lpcc --batch compile check (PASS) -- not individually live-boot-tested.

深度功能测试(2026-09-04,round three,shop + 拜师)

新角度:醉仙楼购物 + 丐帮左全拜师。此前各轮覆盖了注册、战斗、死亡/ 复活和若干 sweep,没有买东西、也没有拜师。这是夕阳再现/江湖风云血统 (与 bixiecanyang 同系),不是天涯家族。标准端口 40049 第一输入就是 「请输入您的英文名字:」,不要发 2060。

实测过程

管理员 fluffos / Mud@2026(权限 (boss);wizpwd 不是登录密码)。 落地北疆小镇 /d/xingxiu/beijiang(房间描述里仍有一处未替换的字面 %s,2026-08 已记为美观性遗留,未修)。clone /clone/money/gold 可用。

goto /d/city/zuixianloulist 烤鸡腿八十文钱 / 牛皮酒袋一两白银 / 包子五十文钱。buy jitui 成功(「你向店小二买下一根烤鸡腿」)。当场 i 是九十九两银子 + 二十文铜板 + 鸡腿(1 两黄金找零 10000−80 = 9920)。 feature/dealer.lpc#include <dbase.h>query("vendor_goods") 正常。F_DEALER 对丐帮拒绝购买(穷叫化),必须先买再拜。本轮游戏内时间 是「亥时」深夜,但 NATURE_D 没有 room_event_fun(),打烊判断拿不到 event_night,店开着——这是既有缺口,不是本轮要修的内容 bug。

goto /d/gaibang/inhole,左全源码是 kungfu/class/gaibang/zuo-qu.lpc (文件名少一个 n),apprentice zuo 一次成功:左全收徒,score 「丐帮第二十代弟子」、师傅左全、头衔【叫 化 子】。cmds/usr/save.lpc 真正调用 link_ob->save()me->save();60 秒内再 save 是 notify_fail("你迟点才可以储存。")(不是假「档案储存完毕」)。等 62 秒后 save 一次,user.o 立刻带上 family_name":"丐帮" / master_name":"左全" / generation":20。杀驱动冷启动再登录,称谓/ 师傅/银子铜板还在。烤鸡腿未进 autoload。左全只收男性。

发现并修复的 PROGRAMMING bug

1. 华山收徒计数拼写(与 nitan_ceshi/nitan_san 同形,静态对照 修,本轮拜师走的是左全不是华山): kungfu/class/huashan/{yue-buqun,yue-wife,feng-buping}.lpcrecruit_apprentice()add("apprentice_availavble", -1),计数 键永远对不上 apprentice_available。改成 apprentice_available。 文件是 LF。

2. wizlist 执行时段崩溃(活体踩到): cmds/imm/wizlist.lpc(以及副本 cmds/imm/ww.lpccmds/wizlist.lpcadm/etcc/wizlist.lpc)三处: - explode(read_file("/u/xiha/wtm"), "\n"):档案里没有这份巫师 任务文件,read_file 返回 0,explode 要 string。改成 read_file(...) || "#"# 行会被后面的任务解析跳过)。 - stat(login_path, -1)[1]:FluffOS 里 stat(path, -1) 等于 get_dir(),缺档时返回空数组/0,[1] 越界。巫师 hfzz 在 wizlist 里但没有 login.o。改成不带 -1stat(path)(返回 ({ size, mtime, ... })),并用 arrayp(st) && sizeof(st) > 1 护住缺档。 - get_mission/get_titlemission 对空行做 mission[i][0] 也会 越界;空串先 !sizeof 跳过。/adm/etc/renwu 里确实有空行。 文件是 CRLF,按字节替换。updatewizlist 列出 fluffos(连线) 和 hfzz(断线),不再报执行时段错误。