info.html · 介绍 · play.html · 游玩 · llms.txt · 下载与本地运行 · ZIP · GitHub
《指尖MUD》从嵌套压缩包中提取而来(`zjmud.7z` 内的 `指间mud服务器+手机版客户端.zip`,内部文件夹名为 `hell`),核心系统档案(`master.lpc`/`logind.lpc` 等)为配合自定义手机客户端协议被大幅重写、注册流程和 master 文件哈希都与其他版本不同,但地图内容仍属于本项目"地狱"/Doing 血统六件套家族(与 `hell`、`zjdy2008wzb`、`zjdyaryl`、`zjdywzb`、`zjdyzj` 同源)——逐字节比对显示与 `zjdyzj` 相似度高达 83%,与 `zjdyaryl` 约 79%,与 `zjdy2008wzb` 约 76%,与 `hell`、`zjdywzb` 则更疏远、约 67%,说明这是把同一套门派/城市江湖世界整体搬到一套完全独立开发的手机客户端引擎上,而不是简单的引擎内衍生版本;本作和 [shujian3](../shujian3/) 同属一个手机 App 协议、同一套自定义 `logind.lpc` 血统,但密码学挑战是真正校验的(真实的 `crypt(ZJKEY, ...)` 握手,没有任何万能旁路字符串),是这批档案里手机协议实现最严谨的一个;不过核心系统重写也带来代价——留言板发帖、玩家商店、邮件等旧系统专属功能在重写时没有被移植过来,深度测试确认这些功能在这套引擎里本来就不存在,并非隐藏的 bug。
English
Extracted from a nested archive (zjmud.7z, containing a folder named 'hell'). Its core system files (master.lpc, logind.lpc, and others) were heavily rewritten to support a custom mobile-phone client protocol — different master-file hash, different registration flow — but the map itself belongs to the same six-way 'Hell'/Doing-lineage family as this collection's hell, zjdy2008wzb, zjdyaryl, zjdywzb, and zjdyzj: a byte-level, line-ending-normalized comparison found its /d room tree 83% identical to zjdyzj, 79% to zjdyaryl, 76% to zjdy2008wzb, and 67% to both hell and zjdywzb — the entire sect-and-city world ported onto an independently developed mobile client engine rather than a simple in-engine derivative. It shares the same mobile-app protocol and custom logind.lpc lineage as shujian3, and unlike shujian3 its password field is genuinely cryptographically verified (a real crypt(ZJKEY, ...) challenge with no bypass string) — the most carefully-implemented of this family's mobile protocols. The system rewrite came at a cost: legacy features tied to the old core (bulletin-board posting, player-run shops, mail) were never carried over to the new engine and simply don't exist here.
README
内容亮点
- 地图和"地狱"/Doing 家族(
hell/zjdy2008wzb/zjdywzb)逐字节 相同,说明这份档案是把"地狱"的门派世界搬到了一套完全独立开发的 手机客户端引擎上,而不是简单的引擎内衍生版本。 - 自定义手机 App 协议里的密码学挑战是真实校验的:客户端必须正确计 算
crypt(ZJKEY, str[2..3])才能通过握手,账号密码字段也要求真 实的crypt()密文,和shujian3的"密文字段目前未做真正校验" 形成对比——这是这批档案里安全性设计最认真的一个手机协议实现。 - 地图内容逐字节相同,但核心系统被完全重写这一事实也带来一个副作用: 旧系统专属的功能(留言板
post、玩家可用的商店/买卖/邮件指令)在 重写时没有被移植过来——不是这些子系统里藏着 bug,是它们在这份手机 App 引擎里根本不存在,深度功能测试(§10.7,见 NOTES.md)确认过。
注册流程(手机 App 协议)
1. 连线后驱动打印一次 ver1.0,<str> 握手横幅,input_to("jiance", ...)
等待客户端回应 crypt(ZJKEY, str[2..3])(str 本身是
crypt(ZJKEY, "zj"),一个真实的、需要正确计算的密码学挑战——和
shujian3 不同,这里没有任何万能旁路字符串)。
2. 一次性发送 账号║密码║密文║email——只认字面 ║
分隔符,不会做逗号自动替换;密文字段是真实校验的
crypt(ZJKEY,账号)+crypt(ZJKEY,密码),同样没有旁路。
3. 新账号则紧接着发送 性别║图片║中文昵称,例如 m║img1║指剑。
本次修复的关键 bug
adm/daemons/logind.lpc:crypt(ZJKEY, 0)在这个驱动上不是原版的 确定性 DES-crypt,而是每次都生成一个全新的随机$6$SHA-512 盐值,导致这个客户端挑战/应答握手在数学上永远无法通过(参见 AGENTS.md §7.14,zjdyzj的同类问题)。已改为显式的 旧式 2 字符盐值crypt(ZJKEY, "zj"),恢复确定性。adm/simul_efun/chinese.lpc的is_chinese():沿用旧版 GBK 字节区间判断(str[i]<176||str[i]>=248等),在这个驱动上strlen()按字符计数、str[i]是 Unicode 码点而非原始字节,导致 真实的中文名字永远无法通过检测。已改为码点区间判断 (0x4e00-0x9fff)。clone/user/user.lpc的accept_kill():is_killing(ob)传入了一个物件而is_killing()期望的是字符串 id(AGENTS.md §7.50,这是第三个独立发现同一个 bug 的血统),导致整个玩家身体类 无法编译,注册流程卡死。已改为is_killing(ob->query("id"))。- 三个纯 socket 功能的守护进程在 WASM 下无法编译,按"禁用整个文件 的入口点"的方式清空为 no-op(§7.52):
- adm/daemons/versiond.lpc(~2200 行的版本同步守护进程):
in_server()/connect_server()/send_command()/
send_client_pending_msg()/syn_finish()/in_listen_callback()/
in_write_callback()/in_close_callback()/cmd_close()/
send_pending_msg()/send_result()/clear_syn_info() 内的
socket_close() 分支,共 12 处——这个文件不是"多功能大文件"的
例外情况(is_version_ok()/is_release_server() 等非 socket
函数被 questd.lpc 等广泛调用),但整个文件因为散落各处的
socket_* 调用无法编译,实际上在运行时导致
collect_all_quest_information() 崩溃——之前的记录把这个当作
"非致命错误,保持原样"是不准确的。
- adm/daemons/payd.lpc(HTTP 充值回调服务器)。
- adm/daemons/network/dns_master.lpc(跨服 intermud UDP 层)。
深度功能测试补充修复(2026-08-08,§10.7)
adm/simul_efun/file.lpc的log_file()一直是裸的write_file(), 没有调用同一份文件里紧邻定义的assure_file()(AGENTS.md §7.11); 每一条新连线最先执行的clone/user/login.lpc::logon()就会调用它 写/log/nosave/logon。此前的记录说"创建了缺失的 /log/nosave 目 录"只是治标:那个目录从未被 git 追踪(.gitignore把整个libs/*/work/log/当运行时状态排除),只是恰好还没在某次 checkout 中丢失过。已在log_file()里补上assure_file(LOG_DIR + file);, 并在文件顶部加一行assure_file()前向声明(否则整个simul_efun/master编译失败)——live 验证:临时清空work/log/nosave/后重启驱动,新连线不再卡死,目录被自动重建。efun::message()的 0 值exclude参数问题:核实后确认adm/simul_efun/message.lpc的message()函数体本身就有if (!exclude) exclude = ({});防护,属于彻底根治,不是像zjdywzb/yhwhpublicfi(AGENTS.md §7.88)那样"包装函数漏标varargs、部分调用点参数不足"的破损形状——这份代码从一开始就没 有这个漏洞,此前的 WASM 笔记"已修复"这个说法是准确的。
管理员账号 / Admin account
- id:
fluffos - 密码 / password:
Mud@2026 - 权限 / level:
(admin)
管理员名单存储在纯文本文件 adm/etc/wizlist 里;账号本身通过正常注
册流程创建。
警告:这是一个公开的默认密码,仅供本地/浏览器试玩。正式对外开服前
请务必修改此密码。
本地运行
cd libs/zjmudhell
~/src/fluffos/build-debug/src/driver config.fluffos游戏端口:40204。
NOTES · 移植与修复记录
WASM 修复摘要(迁移自 meta.json 的 group_note)
从 zjmud.7z(指间mud服务器+手机版客户端.zip)里嵌套的一个 zip 中提取,内部文件夹字面命名为 'hell'——和已有的 hell/zjdywzb 世纪家族无关,master 哈希不同。修复了 efun::message() 因 exc_target=0 被拒绝的问题;创建了缺失的 /log/nosave 目录。同样是 shujian3 血统的手机 app 协议和自定义 logind.lpc。需要完整的 WASM 修复:(1)crypt(ZJKEY, 0) 客户端握手的非确定性问题(AGENTS.md §7.14)——已修复为 crypt(ZJKEY, "zj"),和 zjdyzj 一样;和 shujian3 不同,这份档案里 get_user() 中基于 crypt 的密文检查没有被注释掉,也没有逗号到 ║ 的便利替换,所以注册需要字面的 ║ 分隔符和真实的 id/密码密文(crypt(ZJKEY,id)+crypt(ZJKEY,密码));(2)经典的 §8.1 GBK 字节区间 is_chinese() 检查修复成 CJK 码点区间;(3)clone/user/user.lpc 的 accept_kill() 里 is_killing() 物件对字符串参数不匹配(§7.50,这是第三个撞上这个 bug 的血统);(4)按 §7.52 掏空了三个纯 socket 精灵(versiond.lpc——create/in_server/connect_server/send_command 等一共 12 个函式,不像之前那条笔记说的那样"保持原样",因为它实际上在运行时破坏了 questd.lpc 的 collect_all_quest_information();payd.lpc 的 HTTP 支付回呼;adm/daemons/network/dns_master.lpc 的 intermud UDP 层)。管理员(fluffos/Mud@2026)通过真实注册加 adm/etc/wizlist 播种。score 对刚创建的角色正确地被一个'born'标记挡住(游戏设计如此,不是 bug)——改用 look+quit 验证。
深度功能测试(§10.7,2026-08-08)
本次先按 AGENTS.md §11 通读了 zjmudhell 自己的 README("核心系统改写、
地图原样保留"血统关系)以及同一份手机 App 协议血统的 shujian3
README/NOTES.md,逐条对照其已知 bug(§7.68 复活软锁、commandd.lpc
.c 后缀死循环、securityd.lpc valid_read() 误伤等),但不假设
移植——每一条都在 zjmudhell 自己的代码里单独核实。
/log/nosave目录问题:不是"已创建但可能丢失",是代码本身缺失 防护,本次已根治(AGENTS.md §7.11 新增确认实例)。adm/simul_efun/ file.lpc的log_file(string file, string text)一直是裸的write_file(LOG_DIR + file, text),没有调用同一份文件里两个函数之 后就定义的assure_file()(这份代码库里channeld.lpc/examined.lpc/versiond.lpc/securityd.lpc/多个adm/npc/*.lpc/cmds/arch/{punish,restore}.lpc都已经在正确使用这个 helper)。clone/user/login.lpc的logon()——每一条新连线最先执行的函 数,版本握手横幅打印之前——会无条件调用log_file("nosave/logon", ...)。当前work/log/nosave/目录之所 以还在磁盘上,只是因为上一轮 WASM 排查时意外创建过、后续会话一直 没有清空过——它从来没有被 git 追踪(.gitignore把整个libs/*/work/log/当成驱动每次启动都会重建的运行时状态排除掉,和debug.log一个待遇),所以这个隐患一直没有真正暴露。live 复现 确认:把work/log/nosave/临时改名挪走,用未修复的代码重启驱 动、发起一条全新连线——连版本握手横幅ver1.0,...都没有打印出 来,连线直接卡死。修复(在write_file()前加assure_file(LOG_DIR + file);)后,同样的"目录不存在 + 全新驱动 进程"场景下连线正常完成,log/nosave/被自动重新建出来(用ls/git status核实过,时间戳是刚刚,内容只有这次会话自己写 的两个文件)。修复过程踩到和xajhxo(§7.11 原文)完全一样的坑:assure_file()在这份文件里是定义在log_file()之后的,不 加前向声明整个simul_efun/master编译直接失败(No program in object '/adm/single/simul_efun'!,硬启动中止,不是警告)——补一行void assure_file(string file);前向声明后编译恢复干净。已把这个 新确认实例记入 AGENTS.md §7.11(这是继夕阳再现/XYZX 血统家族之后 第二个独立撞上"同一份文件里 log_file() 没调用紧邻的 assure_file()" 这个具体形状的、完全不相关的代码库家族)。
efun::message()的 0 值 exclude 参数问题:确认是彻底根治,不 是"只补了一个症状"。adm/simul_efun/message.lpc的message(mixed arg, string message, mixed target, mixed exclude)本身不是varargs,但函数体第一行就是if (!exclude) exclude = ({}); efun::message(arg, message, target, exclude);——也就是说这个 wrapper 早就把"被驱动静默填成int(0)的缺失第 4 参数"在传给efun::message()之前转换成了空数组,和tell_room()(同一文件里)已有的|| ({})写法是同一个思路,只 是换了个位置实现。这和zjdywzb/yhwhpublicfi(AGENTS.md §7.88) "4 个必填参数、内部调用点只传 3 个"的破损形状不同——zjmudhell这份代码从一开始就没有这个漏洞。live 验证:完整走过"世外桃 源 →east(进入"光明磊落"竹屋,触发陆天抒NPC 对话)→out(进入阎罗殿)"这条注册仪式路径,这条路径上多处message_vision()/message()调用全部正常,没有任何Bad argument 4 to EFUN message()报错。上一轮 WASM 笔记"修复了 efun::message() 因 exc_target=0 被拒绝的问题"这句话本身是准确的 ——本次只是把"为什么准确、准确到什么程度"钉死到具体代码行。
- §7.50/§8.3a:已在此前的跨库扫描中修复过,本次重新核实仍然生效。
clone/user/user.lpc的accept_kill()用的是is_killing(ob->query("id"))(字符串 id,不是物件),feature/ command.lpc的command_hook声明是nomask int command_hook(...)(没有private)。两处都已经是修好之后的形状,角色创建全程没有 卡在这两个已知坑上。
- §7.86(留言板
post崩溃):不适用——这份档案压根没有留言板系 统。全档案搜索BULLETIN_BOARD/BBS_BOARD/inherit.*board/post.lpc均无命中,cmds/目录下也没有任何注册"post"动词的 文件;和hell/zjdywzb等血统家族地图内容逐字节相同、但核心系 统被完全重写这一血统关系一致——留言板属于旧系统的功能,这份手机 App 引擎重写时没有移植过来,不是"已修复",是"从未存在",两者要区 分清楚。
- §7.68(死亡/复活 present() 硬中止软锁):代码形状命中,但按撤回 说明的两个前提条件核实后确认不适用,未做任何修改。
d/death/npc/ {wgargoyle,bgargoyle}.lpc的death_stage()确实是if (!ob || !present(ob, environment())) return;这个撤回前的原 始形状(和shujian3共享同一套gate.lpc/鬼门关血统,shujian3自己的这个修复后来也被撤销了,参见shujian3README 的更正说明, 所以不能拿它当"已验证适用"的先例)。按 §7.68 撤回说明要求的两个前 提条件逐一核实:(1)本档案的feature/move.lpc/feature/ command.lpc里完全没有is_ghost()检查——鬼魂在这份代码里没有 被禁止移动;(2)没有找到任何"强制移动任意玩家、不检查是否是鬼魂" 的脚本 NPC(shujian3/bmxkx2001那种"游导 NPC"角色,全档案搜索is_ghost命中的文件里没有类似的强制move()逻辑)。两个前提都 不成立,说明"鬼魂离场就放弃复活流程,等下次进入房间的init()重新触发"更可能是这份代码里合理的、大多数鬼魂本来就能自行游荡的 设计,不是 bug——按撤回说明的要求,未应用重试式修复。
- 实际死亡机制和
hell/zjdywzb系的鬼门关不完全一样,值得记录:feature/damage.lpc里真正常见的战斗后果是unconcious()(气/精 归零、disable_player()、随机 30-130 秒后call_out("revive", ...)自动苏醒),和真正调用die()/移动进鬼门关的永久死亡是两条不同 的路径——score的死亡记录字段只在真正die()时才会变化。用管 理员账号kill ouyang(欧阳克,/kungfu/class/ouyang/ouyangke, 一个门派级 NPC,明显不是给新手打的)挑起战斗,两回合内被打到"气" 归零、"你的眼前一黑,接著什么也不知道了...."(unconcious()的 标准文本),符合预期;断线重连后如果气/精仍然是负值,logind.lpc的reconnect()(第 364-365 行)会再次调用unconcious()提醒角 色仍在昏迷中——这是有意的一致性检查,不是本次要修的 bug,只是记录 下来供以后遇到类似"重连后又打印一次昏迷提示"时不必重新排查。没有 在这次会话里把角色真正打死(欧阳克显然是刻意放在新手城里、不该被 新手攻击的强力 NPC,按 §7.90 附近"游戏设计/难度,不是 bug"的既有 原则不去动它),因此没有触发真正的鬼门关复活流程;d/death/gate. lpc/wgargoyle.lpc/bgargoyle.lpc已做静态代码审查(见上一条), 未做端到端真人复活的 live 验证。
- §7.90(eval cost 上限):
config.fluffos是这个项目最常见的700000默认值,本次测试没有触发过。完整会话(注册、5+ 个从未 访问过的房间移动、门派 NPC 战斗、断线重连、quit)之后grep -c "cost limit reached" log/debug.log和当次boot*.log都是 0——这份档案目前的内容体量没有顶到默认上限,未做调整。
- 手机 App 协议的实测细节:驱动打印
ver1.0,<str>后需要客户端 回应crypt(ZJKEY, str[2..3])(ZJKEY硬编码在include/zjmud.h里,str本身是固定盐值crypt(ZJKEY, "zj")所以整条握手串在这 个驱动构建上是完全确定性的,可以离线用 Pythoncrypt.crypt()算 出来复用);随后一次性发送账号║密码║密文║email(密文=crypt(ZJKEY,账号)+crypt(ZJKEY,密码),真实校验,没有旁路);新账 号紧接着发送性别║图片║中文昵称。进入游戏后角色创建走的是 "世外桃源(选品质方向)→ 阎罗殿:pianshu <类型>(先天偏属)→wash(忘忧池随机洗四维)→born <地名>(转生出生点)",和shujian3/zjdywzb是同一套仪式骨架,具体房间/NPC 名字不同。管 理员账号fluffos/Mud@2026通过这条真实注册流程创建,目前权限: (admin)立即生效(adm/etc/wizlist里的名单已经生效,账号文件本 身是这次会话新注册出来的,验证密码可用)。
- 确认一次 AGENTS.md §10.2 记录过的 telnet 客户端 CJK 字节损坏问 题,非本档案 bug:通过
scripts/tmux_mud.sh(本地 telnet 进程) 发送kill 李阿婆时,telnet 本地直接掉进了自己的telnet>转义 命令提示符(?Invalid command),从未真正发给驱动;同一条指令换 成scripts/mudclient.py(裸 socket)发送(改用拼音别名kill ouyang,欧阳克的set_name()里注册的别名之一)立即正 常触发战斗。另外这份档案的角色状态栏(012开头的一整行 HP/气/ 食/水状态)大约每秒钟推送一次,属于 §8.3 第 1 条"实时时钟提示符" 的同类情况——用mudclient.py时要用--idle 0.5或更低,tmux_ mud.sh因为是固定等待时长而不是"等到安静",不受这个影响。
- 这份档案没有留言板(见上)、也没有可用玩家指令的商店/买卖/邮件 系统:
cmds/目录下没有mail/buy/list一类的动词文件,feature/dealer.lpc(NPC 商人逻辑)存在但没有任何add_action()暴露给玩家指令——这些功能很可能只通过手机客户端自己的结构化菜单 协议(连线时看到的06b12:...这类按钮提示)触发,raw telnet/ socket 测试触及不到,不代表功能缺失,只是这次测试方法的覆盖边界,
§7.52 追加实例(2026-08-18):adm/daemons/network/messaged.lpc 的 socket_bind() 崩溃
作为 hell 那份档案(AGENTS.md §7.52)发现的同一个 bug 的跨库排查
一环,确认这份档案(和 hell 属于同一个 shujian3/"Doing" 手机
App 血统家族,goto.lpc 也共用完全相同的
MESSAGE_D->find_user(arg) 兜底逻辑)现场复现了完全一致的崩
溃:巫师账号第一次执行 goto(触发 messaged.lpc 首次懒编译)
时,执行时段错误:*Bad argument 2 to socket_bind(); Expected: int
Got: "10".——根因和 hell 完全相同(LOCAL_PORT() 的 (int) 转
型对 get_config() 实际返回的非数字值在运行时不起作用)。这份档
案自己早前的 WASM 修复记录里提到过"按 §7.52 掏空了三个纯 socket
精灵"(versiond.lpc、payd.lpc、dns_master.lpc),但
messaged.lpc(第四个碰 UDP socket 的精灵)当时被漏掉了——和
hell 自己的 versiond.lpc-修过-但-messaged.lpc-漏掉是完全相
同的疏漏模式。修复:startup_udp() 掏空成 return 0,
send_udp() 补上 !socket_id 保护。现场验证:重启全新驱动进
程,goto 干净执行,debug.log 里不再出现任何
socket_bind/Bad argument 记录。
跨库排查结论(截至本次):这个 bug 在 hell/zjmudhell 这两
个同源手机 App 血统档案上都 100% 复现;但在完全不相关的血统
aoxiangtianji(西游记题材)上用同样的方法(call/eval 直接触
发 create())没有复现——get_config(__MUD_PORT__) 在那份档
案上正确返回了数字端口。这说明这不是一个对所有携带这段代码的档案
都必然触发的 bug,可能和具体的血统/配置有关,不能不加验证就对
AGENTS.md §7.52 列出的其余 14 个档案批量套用同一个修复——已经把这
个结论更新回 AGENTS.md §7.52 本身,留给下一轮继续逐个排查。
记录以供以后有更完整客户端模拟能力时补测。
AGENTS.md §7.100 fix (2026-08-19): redundant replace_program(ROOM) landmine
Same corpus-wide bug as the batch-1-6 sweep (ROOM macro
"/inherit/room/room" from include/globals.h). Deleted 2,315 live
standalone replace_program(ROOM); lines under work/ via
fix_710_room.py, plus hand-fixed the room-building tool's
string-builder template (work/clone/misc/roommaker.lpc). 3 real
.lpc files under work/data/ checked — none had the bug pattern.
Remaining matches after the fix are all pre-existing //-commented.
Verified: clean build-debug boot (zero new compile errors, zero
"cannot replace"/"cannot bind" in debug.log; log/ directory didn't
exist for this lib and had to be created before the driver would
boot). Live admin login through this lib's custom 指间MUD
crypt()-challenge protocol (same ZJKEY/handshake as sibling
zjdyzj) as fluffos/Mud@2026 — entered 客店, look/quit both
worked cleanly. Incidental data/{login,user}/f/fluffos.o save drift
from the login test was reverted via git checkout HEAD before
committing.
§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): 5 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.
§10.7 深度功能测试第二轮(2026-08-21):真正的战斗/死亡/复活、商店、拜师
上一轮(2026-08-08)只走完了注册仪式(世外桃源→east→out),从未真正
玩过游戏本体。本轮用管理员账号 fluffos(现场重连,账号早前登记)
补测了战斗死亡复活、商店购买、拜师三项,外加一遍标准检查清单快速核
实。全程用 /home/sunyc/src/fluffos/build-debug/src/driver 加载
config.fluffos,work/log/debug.log 全程零 Error(只有大量正常
的懒编译期 Warning,不是运行时报错)。
- 战斗/死亡/复活:完整走通,未发现新 bug。用管理员
clone /d/guanwai/npc/wolf在/d/guanwai/famu1(伐木场,符合 wolf.lpcinit()里outdoors+/d/guanwai/%*s的自动索敌条件)现场复 制了一只野狼,kill wolf触发真实生死战(不是安全的 spar/fight, 印证了本次会话在其它档案上反复验证过的规律:kill指令对 NPC 目 标没有任何安全闸门)。中途因为默认wimpy阈值触发自动逃跑,wimpy 0关闭后重新交战。追踪了完整的伤害链路:feature/damage.lpc的heart_beat()检查qi<0||jing<0时,如 果living(me)仍为真(角色还没被打晕)就调用unconcious()(设qi/jing精确为 0,disable_player()关闭指令能力,living()随之变假,call_out("revive", ...)排队苏醒);由于kill.lpc对 NPC 目标会双向调用kill_ob()(me->kill_ob(obj)且obj->kill_ob(me)),令野狼真正"想杀死"角色(is_killing生 效),combatd.lpc的脱离战斗判定(第 733 行)要求双方都不is_killing对方才会脱战,所以野狼在角色昏迷后不会停手,继续攻 击把qi打成负值——下一次heart_beat()时living(me)已经是 假,触发真正的die()。现场日志:你的眼前一黑,接著什么也不知 道了....后紧接着你扑在地上挣扎了几下,腿一伸,口中喷出几口鲜 血,死了!,角色被移动到DEATH_ROOM(/d/death/gate.lpc,"鬼 门关"),白无常(d/death/npc/wgargoyle.lpc)的death_stage()五段对话按 5 秒间隔完整播放(是ghost分支),最后reincarnate()+move("/d/city/guangchang")把角色送回泥潭广 场,之后qi/jing随心跳自然恢复。§7.112 死亡阶段重入护栏 现场验证:wgargoyle.lpc/bgargoyle.lpc的death_stage()每 条return路径(不存在/离场、非鬼魂反杀、最终转生)都正确清了death_stage_active临时标记,只有"还在等下一段对话"的中间分支 不清(本来就该保留,等这次call_out链跑完再清),这次是本档案 第一次真正触发这段代码,行为和静态审查时的预期一致,没有发现遗 漏分支。全程debug.log零新增报错。 - 商店购买:确认此前笔记记录的"无可用买卖指令"结论依然成立,不 是本次要修的 bug。
feature/dealer.lpc里do_buy(string arg)函数本身逻辑完整(价格计算、vendor_goods校验、INPUTTXT二次 确认购买数量等都写得很完整),但全档案里没有任何地方真正调用它 ——唯一的调用点是adm/npc/youxun.lpc自己重载后再::do_buy()转发,属于该 NPC 自己内部的特例,不是通用绑定。逐一确认了三层可 能的绑定方式全部缺失:(1)cmds/目录下没有buy.lpc/list.lpc/sell.lpc,也没有对应的.alias文件;(2)feature/command.lpc的command_hook()只通过find_command(verb)精确匹配cmds/里的真实文件,没有"扫描房 间内 NPC 是否认识这个动词"的兜底逻辑;(3)现场对着真实商人 NPC李阿婆(d/city/npc/liapo.lpc,有vendor_goods)连续尝试list/buy 1 苹果/buy apple,全部只得到标准的"什么?"(未知 指令),不是报错,也没有触发任何 debug.log 记录——这正是这份档案 "核心系统改写、商店 UI 从未移植"血统关系的预期行为,没有错误签 名,按项目既定原则不算 bug,维持上一轮"手机客户端菜单协议触及不 到"的结论不变。 - 拜师:完整走通,正确分配门派/称号,未发现新 bug。用管理员
clone /kungfu/class/gaibang/he-bj(丐帮七袋弟子"何不净")现场 复制到角色所在房间,bai he触发真实拜师流程:cmds/skill/ apprentice.lpc(通过cmds/skill/bai.alias绑定到bai动词, 确认过这个绑定机制真实存在)核实双方状态后调用ob->attempt_apprentice(me);he-bj.lpc的permit_recruit()(定义在gaibang.h,判断没有背叛/没有其他门派)和自身的combat_exp > 120000上限检查(新角色combat_exp=0,满足)都 通过,执行command("recruit " + id),recruit_apprentice()正确写入family = { family_name: "丐帮", generation: 20, master_id/master_name: 何不净, title: 七袋弟子 }(师父是七袋, 角色排在第 20 代)。score复核:丐帮第二十代传人、师父:何 不净。,字段全部正确。过程中顺带确认了permit_recruit()/attempt_apprentice()分层设计在这份代码里是完整可用的(不是像d/city/npc/baibian.lpc那个"模仿玩家技能"的对练 NPC那样,虽然 调了create_family()但没有inherit F_MASTER、没有定义attempt_apprentice(),那个是死代码,不适合用来测试拜师——已经 在排查过程中确认,未使用它)。全程debug.log零新增报错。 - 标准检查清单快速核实(本次全部确认已修复/不适用,未发现新问 题):§7.111(
master.lpc的standard_trace()第 230 行error["object"] ? file_name(error["object"]) : "0"已有三元防 护);§7.108(clone/user/user.lpc的reconnect()第一行就是enable_commands());§7.30(feature/skill.lpc5 个 accessor 的mapp(x) ? x : ([])防护逐行核实存在);§7.79(全档案addn(零命中,不适用);§7.100(此前已修复,本次未复查,沿用 之前记录);本次会话额外指定核对的四个"已在其它档案全部关闭"的 corpus-wide 坑,逐一确认代码形状本身不存在,不是漏查而是真的不 适用:adm/daemons/combatd.lpc无bounce相关代码、全档案没有chacha.lpc、adm/daemons/natured.lpc没有if (!userp(ob[i])) destruct(ob[i])这个具体写法、cmds/std/go.lpc没有sizeof(exit[arg])这个具体写法(它用的 是!mapp(exits)/undefinedp(exit[arg])检查,形状不同,不受 影响)。
AGENTS.md §8.3a variant fix (2026-08-27): feature/action.lpc::eval_function() and inherit/item/combined.lpc::destruct_me() wrongly private
Same targeted follow-up as libs/hell (see that lib's NOTES.md entry
of the same date for the full writeup) — libs/revive's own §8.3a
deep-test finding explicitly named zjmudhell as a sibling in the
hell/"Doing" lineage still carrying this bug. Confirmed present here,
byte-identical file layout and content to hell:
feature/action.lpc::start_call_out()'scall_out("eval_function", ...)was blocked by aprivate-declaredeval_function(), inherited into the player body viainherit/char/char.lpc->clone/user/ user.lpc— silently no-ops every delayed-callback effect/sleep/combat mechanism usingstart_call_out().inherit/item/combined.lpc::set_amount(0)'scall_out("destruct_me", 0)was blocked the same way, affecting everyCOMBINED_ITEMdescendant (money, thrown weapons, medicine powders, etc.).
Fix: dropped private from both declarations (function bodies
unchanged), matching the established revive/hell/§8.3a pattern.
Verified live: native build-debug driver, port 40204, using this
lib's custom mobile-app crypt-challenge login protocol (ZJKEY-based
handshake per this lib's own earlier §7.14 fix notes) to log in as the
existing fluffos/Mud@2026 admin account. goto'd to the
sleep_room /d/guanwai/xiuxishi and ran sleep: with the fix in
place, wakeup() fired correctly within its 12 + random(10) second
delay window ("你迷迷糊糊的睁开双眼,爬了起来。"), confirming
start_call_out()/eval_function() actually dispatches post-fix.
(Not independently re-tested with private restored on this lib —
hell's identical before/after test already demonstrated the failure
mode live, and this lib's source was byte-identical before the fix.)
debug.log clean of any 执行时段错误/Bad argument post-fix.
Incidental data/user/f/fluffos.o save drift from the test login
reverted via git checkout before committing.