Honghuang World — Fixed Edition (World of Primordial Chaos)

✅ 可玩

洪荒世界(修复版)

xfbhh

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

▶ 开始游玩 · Play Now

洪荒世界(修复版)属于 NT/泥潭(nitan)血统,与本项目收录的 `hhsj`(洪荒世界原版)、`nitan170911` 共享逐字节相同的 master 代码。新角色从"泥潭注册室"开始,需要完成一套完整的"投胎"仪式才算真正踏入这个世界:先选择种族与性别,再挑选性格,最后在"生命之谷"里为膂力、悟性、根骨、身法四项属性分配点数——一切就绪之前,`score` 会一直提示"还没有出生呐"。

English

Part of the "Nitan" (NT) mudlib lineage, sharing a byte-identical master codebase with this collection's hhsj (the original Honghuang World) and nitan170911. New characters begin in the "Nitan Registration Hall" and must complete an elaborate, multi-step "birth" ritual — choosing a race, gender, and temperament, then allocating attribute points in the "Valley of Life" — before truly entering the world.

README

内容亮点

在线试玩

https://mudlibs.fluffos.info/xfbhh/

管理员账号 / Admin account

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

本地运行

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

游戏端口:40190

NOTES · 移植与修复记录

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

NT/nitan/Lonely 血统,master.c 和 hhsj(014-1)以及 nitan170911 逐字节相同。WASM 修复:给 clone/user/user.lpc、inherit/room/room.lpc、adm/daemons/giftd.lpc 应用了 §7.15 的 efun::set/query/delete/addn 修复(这次是按内容逐一修的,不是直接复制档案);修复了 check_legal_name() 里长度界限没减半的部分(2-4 字符,原来还是按字节数校准的 4-8);修复了 efun::message() 对 exc_target=0 的拒绝。登录协议:get_user 用逗号分隔("id,password,ciphertext,email",逗号内部会自动替换成 U+2551),但 get_char 需要字面的 ║ 分隔符("gender║img║nickname")——这是通过直接阅读 logind.lpc 逆向工程得出的。通过 adm/etc/wizlist 把 fluffos/Mud@2026 播种为 (admin)。用真实中文名字(秦风)的完整注册+look/score/quit+管理员 update(针对 clone/user/login.lpc,不是 /obj/login)已全程验证。

深度功能测试(§10.7,本轮)

这轮之前,xfbhh 的记录只到"注册流程能走通"这一层,从来没有真正深入 测试过"生命之谷"投胎仪式之后的内容。这次用真实驱动(native driver) 起服,走了完整流程:注册 → 生命之谷见盘古 → zz(选种族)→ xuan(选 性别)→ choose(选性格)→ washto(洗点分配属性)→ 进入"世界之树"新 手村 → score 查看角色卡 → 移动(west/east 走了新手村三个房间)。

发现并修复的 bug

1. §7.68 死亡/复活软锁,4 处实例d/death/npc/{bai,hei,bgargoyle,wgargoyle}.lpc): death_stage()if (!ob || !present(ob)) return; 把"角色永久离开" 和"角色只是暂时不在场"这两种情况混在一起处理,任何一种都会让复活流 程永久卡死,不重试也不报错。按标准修法拆成两个判断:!ob 才真正放 弃,!present(ob) 则用该文件原有的重试间隔(bai/hei/bgargoyle 是 5 秒,wgargoyle 沿用其自身独有的 10 秒节奏)重新 call_out

2. §7.7 corrupted-dbase 下的 capitalize() 崩溃cmds/std/say.lpc): capitalize(query("id", me))me 的 dbase 被清空(id 变成整数 0 而非字符串)时会直接报错,导致任何人在场时崩溃整个 "say"。修复为 stringp() 判断后再 capitalize,不再假设 id 一定是字符串。

3.(本轮最大的发现)新的 §7.78:CHARACTER 的部分 mixin 文件里的裸 set()/query() 调用,即便整个 CHARACTER 对象已经通过 §7.15 修复 拿到了真正的本地 F_DBASE,依然会解析失败。 起因是调试 d/register/npc/pangu.lpcset_name("盘古", ...) 执行完 query("name") 立刻读回 0,玩家看到的"盘古"NPC 显示成武器名 "巨斧",玩家自己的名字在对话里显示成字面的 "0"。

排查过程:feature/name.lpcset_name() 的真正定义处)只 inherit F_NATURE;,完全没有 F_DBASE。LPC 的裸函数调用是按"定义 该函数的文件自己的编译期继承链"解析的,不是按"最终被组合进去的对象 的继承链"——char.lpc 虽然同时 inherit F_DBASE;inherit F_NAME;,但 name.lpc 内部写的裸 set()/query()name.lpc 自己编译时就已经因为找不到本地候选而落到 simul_efun 的共 享兜底 dbase 上了,跟 char.lpc 后来继承了什么完全无关。用最直接的 办法验证:pangu.lpc 自己 create() 里的裸 set("long", ...)(这 个调用是在 pangu.lpc 自己的作用域里写的,pangu.lpc 通过 NPC→CHARACTER 确实有 F_DBASE)事后能正确读回;而 set_name() 内部 的 set("name", ...) 不能——同一个对象、同一个时刻,只是调用发生 的"物理文件"不同,结果就天差地别。

最初想按 §7.15 的老办法给 name.lpc 也加一行 inherit F_DBASE;, 结果直接编译报错:Illegal to redefine 'nomask' function '_query' ——因为 char.lpc 已经通过另一条路径继承了同一个 F_DBASE,这个驱 动不会自动去重同一份文件的多路径继承,反而是硬冲突,会连累 char.lpc 整体编译失败(现象是每次连线登录提示都变得乱七八糟)。

最终修法:把这些 mixin 文件里"自己对自己"的裸调用统一改成 this_object()->set(...)/this_object()->query(...)(call_other), 让调用在运行时动态派发到真正组合出来的那个对象身上,行为上等价于一 次"本该正确解析"的裸调用。受影响的 CHARACTER 组成文件一共 13 个: actionapprenticeattackattributecommandconditiondamageequip_livmessagemoremovenameteam(只有 alias/edit/finance/skill 没有裸调用)。

这个 bug 的严重程度远超 pangu 一个 NPC 的对话乱码:command.lpcenable_player()——每一个新角色登录时 char.lpcsetup() 都会 调它,不是只在这一个 NPC 身上触发——里面的裸 query("id") 读回 0, 直接让 set_living_name() 崩溃(Bad argument 1... Expected: string Got: 0),也就是说修复前任何一个新角色的登录/初始化流程本身就是 崩的,只是驱动的错误处理器把崩溃吞掉了,看起来像是正常继续。 attribute.lpcquery_str()/query_int()/query_con()/ query_dex()/query_per()(战斗/属性读取的核心函数)也是同样的裸 调用模式。

修复后完整重新走了一遍:注册 → zz 1 → xuan 1 → choose 1 → washto 50 50 50 50 → 进入世界之树。score 显示的膂力/悟性/根骨/身 法四项精确等于 washto 分配的 50/50/50/50(修复前这些函数会返回错误 或者共享着别的对象的脏数据),气血/精气/内力/精力等状态条数值也完 全正常(600/600、450/450、2000/2000、1000/1000),全程 debug.log 保持空白。

4.(已记录、本轮未修复)新的 §7.79:裸 addn()/addn_temp() 自 targeting 调用恒定出错,跟 F_DBASE 无关。 addn 这个函数在整个代 码树里从来没有本地定义过,只存在于 simul_efun 的 wizard.lpc(用来兼容一个这个驱动本来没有的原生 efun),任何裸调用 必然是货真价实的 simul_efun 调用;不带显式目标对象的自身增减写法 (如 feature/pill.lpcaddn("food_remaining", -1);)在 simul_efun 调用期间 this_object() 就是 simul_efun 自己,实际改的 是 simul_efun 自己的一次性 dbase,而不是技能真正想加成的角色。用 grep -rPn '(?<!->)\baddn\(|(?<!->)\baddn_temp\(' --include="*.lpc" 扫了一遍,命中约 10150 处、分布在约 3590 个文件,绝大多数在 kungfu/ 技能特效代码里——规模远超一次深挖能处理的范围,本轮只记录 不修复,已经写进 AGENTS.md §7.79,留给以后专门的一轮处理(大概率需 要脚本化批量替换成 this_object()->add(...),而不是手工逐个改)。

未继续测试的部分

时间关系,注册/属性分配/新手村移动验证完之后没有继续找怪打架、逛商 店、拜师门派——上面 §7.78 这个 bug 波及范围极广,判断优先级应该是先 把这个记录清楚、把 CHARACTER 的核心裸调用修完并验证登录/属性不再崩 溃,比继续往后面玩更重要。后续如果有专门针对 xfbhh 的一轮,建议先看 战斗(在新手村外找到怪物,attack.lpc/damage.lpc 这两个刚修的文 件直接决定战斗数值对不对)、然后是死亡/复活(这次 4 个 §7.68 修复 点还没有真正打死过一次角色去验证复活链路本身)。

更正(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-12,round two,新驱动重测)

用新编译的 ~/src/fluffos/build-debug/src/driver(origin/master 最新拉 取,含本项目自己提交并合入的 #1343/#1344 两个 PR,以及同一会话里另外提 交的驱动 PR:把编译诊断严重度标记从小写改回大写 "Warning:"/"Error:", 专门为了兼容本语料库大量老式 MudOS 惯例的 mudlib 代码)重新验证。

to_int() 任务计数器修复

adm/daemons/combatd.lpc/cmds/std/whisper.lpc 里全部 quest_count = ... % 500 已经是 to_int(query(...)) % 500 的修复后形状,无需改动。

新发现并修复:与 hhsj/nt6 逐字节相同的 log_error() 严重度门控缺失

adm/kernel/master/error.lpc——和 hhsj/nt6(同一会话本轮更早修复 过)的对应文件逐字节相同,同一个 bug。修复:只在真正的 error 时才转 发给玩家(debug 频道广播给巫师和 write_file() 落盘均保持不变), 用 "arning:" 大小写无关匹配(AGENTS.md §7.10 案例记录)。

adm/kernel/simul_efun/message.lpcmessage() 包装函式已经带 有 if (!exclude) exclude = ({}); 守卫(虽然没声明 varargs,这个驱 动仍然接受 3 个实参的呼叫),不是本轮的 bug,未改动。

新发现并修复:data/emotion/ 目录缺失导致 emote_d.lpc 存档失败(AGENTS.md §7.11 已有先例)

adm/daemons/emote_d.lpcDATA 常量是 "/data/emotion/emotion" + __SAVE_EXTENSION__,但这份档案从未附带 data/emotion/ 目录,每次表 情指令(emote_d.lpccreate()remove())触发存档都命中 "*Could not open /data/emotion/emotion.o.tmp for a save.",玩家端表现 为"这里发现了臭虫"。修复:mkdir -p data/emotion(含 .gitkeep 占位 以便提交这个空目录)。现场验证:修复前干净注册流程命中这个报 错;修复后同样的注册+欢迎序列流程零报错。

冷启动级联编译撑爆 maximum evaluation cost(AGENTS.md §7.90/§10.8 已有先例)

第一次全新注册在 combatd.lpcsimul_efun.lpcappend_color() 链路上命中一次"Too long evaluation. Execution aborted.",符合已知类 别。验证自愈:驱动"热身"一次注册尝试后,后续全新账号一次性干净 走完注册→欢迎序列(含活动/新闻/邮件提示),全程零报错。

完整游玩测试范围

沿用既有记录的"注册成功进入泥潭注册室,欢迎序列正确显示"作为及格 线。战斗/死亡循环仍未触达(上一轮已经记录过同样的时间预算取舍),留 给下一次专门测试。

本轮结论

驱动升级后 xfbhh 整体状态良好:任务计数器 to_int() 修复确认已生 效;新发现并修复两个真实 bug(与 hhsj/nt6 逐字节相同的 log_error() 严重度门控缺失、data/emotion/ 目录缺失导致的存档失败);message() 包装函式这次不是 bug(已经带有守卫);冷启动 eval-cost 级联验证自 愈。测试账号(qinfengshiyi/qinfengshier/qinfengshisan)存档留在 data/ 下作为佐证,未清理(未跟踪文件,不纳入本次提交)。

AGENTS.md §7.100 修复(2026-08-19)

hhsj 同源的 ROOM 基类冗余 replace_program(ROOM); 自崩溃地雷 (详见 AGENTS.md §7.100):本 lib 4984 个房间文件的 create() 末尾 (紧跟 inherit ROOM;)都有这一行多余调用,第一次对该房间对象绑定 闭包会永久失败。同款地雷也烤进了自带建房工具 clone/misc/roommaker.lpc 的一处字符串拼接代码生成模板。

修复:脚本化删除所有房间文件里独立成行的 replace_program(ROOM);d/huangshan/banshan.lpc 有两处独立调用,均删除),加上 roommaker.lpc 里手动摘除字符串拼接片段。git diff --stat:4985 files changed, 1 insertion(+), 4987 deletions(-),与预期精确吻合。

验证:build-debug 驱动真实冷启动,端口 40190 正常监听, debug.log 全程干净。管理员 fluffos 账号(同 hhsj 的"自连数据 库"登录握手:单行 id,password,x,emailgoto 走访 14 个刚修复的 房间(d/huijiang/d/huanggong/d/luoyang/quest/zhuzao/ d/shenfeng/d/fuzhou/d/xingxiu/d/baihuagu/d/kunlun 等区 域),均正常返回,无 "cannot replace"/"cannot bind" 新增日志行。按 精确 PID 结束驱动;登录产生的两处已跟踪存档增量 (work/data/{login,user}/f/fluffos.o)已 git checkout -- 还原。

AGENTS.md §7.79 修复(2026-08-19)

addn("prop", value)(无第三参数)恒为静默无效果:addn/ addn_temp 只在 adm/kernel/simul_efun/wizard.lpc 有 shim 定义, ob 缺省为 this_object()——但这个 this_object() 是在 simul_efun 内部求值,指向 simul_efun 对象自身,不是真正调用者,于是写入垃圾去 处、静默丢失。3 参及以上调用(显式传 ob)从调用点求值 this_ object(),本就正确,不受影响。

用改造版 argcount.py(括号深度 + 注释/字符串屏蔽的顶层参数计数器) 定位裸 2 参调用,改写为 this_object()->add(...)/this_object()-> add_temp(...)。首轮脚本一度误伤 clone/user/user.lpc——该文件本地 定义了一个(命名笔误,本应叫 add 却写成 addn 的)2 形参覆盖函 数,脚本把这个函数定义行当成了"2 参调用"改写,产出语法错误 (L_ARROW unexpected)。修复脚本加入"定义 vs 调用"通用判别(前一 个词是类型/修饰符关键字 + 右括号后紧跟 {/; → 判定为定义,绝不 改写),并逐文件探测本地覆盖:clone/user/baby.lpc 全 6 个 lib 都 本地覆盖了 addn(未覆盖 addn_temp),clone/user/user.lpc 仅 xfbhh 有上述笔误覆盖——两处的裸 addn(...) 调用经正常 LPC 名字解 析走本地函数,从未真正命中过 simul_efun shim,予以排除;baby.lpc 唯一的 addn_temp(...) 调用未被本地覆盖,正常修复。核实全库无任何 文件 inherit 这两个文件,排除范围无需向外传播。

结果:902 处改写(clone/user/user.lpc 排除 12 处、clone/user/ baby.lpc 排除 8 处但修复其 1 处 addn_temp),git diff --stat: 458 files changed, 902 insertions(+), 902 deletions(-),与工具输出精 确吻合。cmds/adm/rp.lpc/rpp.lpc(已知损坏的旧管理工具,addn 参数解析本就不成立)按调查阶段结论跳过未动。

验证:build-debug 驱动真实冷启动,端口 40190 正常监听,debug. log 全程干净,无新增编译错误。全新账号(qintest779c/角色名"秦 测风")走完注册流程,成功进入泥潭注册室并收到欢迎序列,符合 §10.1 及格线。按精确 PID 结束驱动。

``§7.112`` residual-gap closure (2026-08-20)

Corpus re-scan (grep -rl 'call_out("death_stage"' ... | filter for missing guard) found unguarded init()-scheduled death_stage() call_out chain(s) in d/death/npc/bai.lpc, d/death/npc/hei.lpc that the original two-wave sweep (see AGENTS.md §7.112) missed -- same reconnect-triggered duplicate-chain bug, different filename/lineage. Added the standard query_temp("death_stage_active")/set_temp/delete_temp re-entry guard, adapted per file's own exit points. Compile-verified via lpcc --batch.

§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): 6 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.

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

Lonely GUI:服务端先发 ver1.0,<salt> 和「版本验证成功」,jiance() 把第一行当 get_user。逗号会自动换成 U+2551,所以第一发 fluffos,Mud@2026,x,[email protected] 即可(不必先回 123456789abcd)。管理员 id 不加 _1。巫师落在巫师休息室,未投胎时 score 报「还没有出生呐」。 HP 状态条约 1Hz,脚本 idle 必须 ≤0.45。cloneis_admin() 锁住 (只认 admin_flag==21 / uid luoyun/modaoVERSION_D 发布站判断 已注释)——设计,未改。

投胎:goto /d/register/entry(生命之谷)→ zz 1xuan 1choose 1washto 50 50 50 50(每项 10–200,和必须 200)→ 世界之树。 score:男性人类、光明磊落、膂力/悟性/根骨/身法 50/50/50/50。

拜师:未投胎时在 /d/city/lichunyuan bai kong 已被空空儿收下(丐帮 第二十代)。投胎后 score 仍是【门派】丐帮 / 【师承】空空儿。本 lib 的 feature/dealer.lpc 没有天涯系那种「丐帮拒买」门,不必先买后拜。 华山 yue-buqun/yue-wife/feng-buping 和青城 yurecruit_apprentice 把限额键打成 apprentice_availavblecreate() 写的是 apprentice_available),递减是空操作;已改键名。

商店:醉仙楼 list 只列出店小二身上那件未装备的「布衣」, buy 1 jitui / buy 1 烤鸡腿 都回「你想买什么?」。根因是 feature/dealer.lpc 作为 mixin 没有自己的 F_DBASE,裸 query("vendor_goods") 打到 simul_efun 共享 dbase,init_goods() / do_list 都读不到 NPC 在 create()set 的货表;all_goods 只剩身上的布衣,对不上鸡腿。同文件里其它 1 参自指向 query/query_temp/set_temp/delete_temp 一并改成 this_object()->…(不能给 dealer 加 inherit F_DBASE,会跟 CHARACTER 的 nomask _query 冲突)。旁路文件 feature/dealer1.lpcinit_goods 已经是 this_object()->query("vendor_goods"),但 没有任何 NPC inherit F_DEALER1

钱:武庙二楼 ask gift about 礼物 走节日奖励,当前无节日。 ask gift about 每日礼物 给一条小灵脉 + 500 洪荒点。巫师 gift fluffos 发到 /clone/gift/xiandannew() 失败 (档案不存在),item->move 对 0 做 call_other——管理员指令缺档, 未当玩家商店 bug 修。cmds/usr/sellitem 把售价写入 balanceMONEY_D->player_pay 在身上没带现钱时会扣存款。

重启驱动后现场复核:list 列出烤鸡腿/包子/烤鸭/酒袋/干粮等货表; giveall /clone/money/goldbuy 1 jitui 得到「你从店小二那里买下 了一根烤鸡腿」,身上出现 jitui,找零灵石碎片/灵石。