Myth of the Three Realms (Test Zone 2)

✅ 可玩

三界神话「测试二区」

sjshv2578bb

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

▶ 开始游玩 · Play Now

"三界神话"系列第三个档案(另见 `sjsh` 宝鸡站原始版、`sjshv150` 紫藤分站),测试二区的内容,和 `sjshv150` 共享同一套"三界神话"世界观——武当、古墓、蜀山、雪山等武侠门派场景与"十二宫""蟠桃""蓬莱""神殿"等神话地名并存,开封城依旧是成规模的解谜任务区;但文件级比对显示与 `sjshv150` 路径相同的档案里也只有约四分之一逐字节一致,两者是共享底层引擎的独立内容快照,而非近乎重复的部署。这份"测试二区"快照独有一片"迷宫"场景(四层以上、约 530 个场景),是这批分站里其它版本都没有的地图内容;`sited.lpc` 本身无条件放行本地回环地址连线,不像 `sjshv150` 需要专门打补丁,本地/WASM 环境下的注册流程也就天然更顺畅。

English

The third build in the "Myth of the Three Realms" series (see also sjsh, the Baoji-station original, and sjshv150, the Wisteria branch) — content for a "Test Zone 2" server. It shares the same wuxia-sect/Chinese-mythology mashup setting as sjshv150 (Wudang, the Ancient Tomb, Shu Mountain, and Snow Mountain sects alongside the Twelve Palaces, the Peach of Immortality, Penglai, and other "Three Realms" mythology locales) and the same substantial Kaifeng puzzle-quest zone, but a file-level comparison shows only about a quarter of shared-path files are byte-identical to sjshv150 — these are genuinely distinct content snapshots sharing a base engine, not near-duplicate deployments. This build's own exclusive content is a large maze area (d/migong/, ~530 files across at least four levels) not present in any sibling build. Its site daemon also allows local loopback connections unconditionally, for a smoother out-of-the-box local registration experience than its sjshv150 sibling.

README

本次修复的关键 bug

和同系档案大部分相同(同源代码),另外还有一个这份档案独有的:

1. §7.60 master.lpclog_error()/standard_trace()CHANNEL_D 尚未加载时呼叫它——两处都补上 find_object(CHANNEL_D) 判断。 2. channeld.lpcdo_channel() 没检查 environment(me) 是否 为空就直接 ->query("no_chat"):一旦上面的 §7.60 修好, CHANNEL_D 真的能加载了,log_error() 广播一条"err"频道消息时 传入的 memaster.lpc 自己的 this_object()——它没有 environment()(永远是 0),触发 *Bad argument 1 to EFUN call_other()。已加上 environment(me) && 判断。 3. §7.61 message() 模拟超越函式缺了 exclude 参数的兜底,和 sjshv150 相同的修法。 4. §7.41 损坏的 emoted.o 存档,同样的 catch(restore()) 修 法。 5. 经典 §8.1 GBK 字节区间 is_chinese():这次分别出现在 adm/daemons/chinesed.lpcCHINESE_D 真正的实现)和 logind.lpccheck_legal_name()(同样的 i%2 字节配对假 设,UTF8 码点索引下对奇数字数的中文名字永远误判)——两处都已修 正。这份档案没有 convertd.lpc(不存在这个文件)。 6. §7.34 logind.lpcget_name() 里有一行遗留的调试 printf("%O\n", ob),会把登录对象内部路径原样打印在中文名字 确认和邮件地址注册提示之间——已删除。

深度功能测试(§10.7,见 NOTES.md)确认了本档案 §7.97(LISTNODES 宏 缺反斜杠导致的死亡死循环)不适用——本档案的 LISTNODES 反斜杠 本来就是对的;也确认了 sjshv150 上发现的 §8.13(WIZ 密码二次登录 死锁)不适用——本档案的 logind.lpc 早就用一个 #define NO_CHECK_WIZPWD 开关规避了这个 bug 形状。完整的死亡→复活循环、留言 板 post/read、管理员写权限(update)均已现场验证通过。

管理员账号 / Admin account

警告:对外公开架设前请务必修改此密码。
测试提示:本档案有一条"新建账号未连续在线满 10 分钟就退出会被
自动删档"的反小号规则,且巫师账号断线(net_dead)超时被设成 1
秒——用巫师账号测试时若要提前结束会话,务必用 quit -lovesjsh
正常退出(绕过 10 分钟限制),不要直接掐断连线,否则账号会被静
默删除(详见 NOTES.md)。

本地运行

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

游戏端口:40125

NOTES · 移植与修复记录

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

三界神话「测试二区」,5 档案 sjsh 家族集群的第三个;这个变体的 sited.lpc 本来就无条件允许回环连线(没有仅限巫师的闸门),不像 sjshv150。WASM 修复:(1)§7.60 master.lpc log_error()/standard_trace()→CHANNEL_D 编译期崩溃,两处都用 find_object(CHANNEL_D) 守卫。(2)修好(1)之后让 CHANNEL_D 真正加载会暴露出的一个新的、§7.61 相邻的 bug:channeld.lpc 的 do_channel() 无条件呼叫 environment(me)->query("no_chat"),没有检查 environment(me) 是否非空——当 do_channel() 被呼叫在一个没有 environment 的物件上时(比如 master.lpc 自己的 this_object(),经由 log_error() 自己的 CHANNEL_D 广播一个被捕获的 connect() 错误)就会崩溃报"Bad argument 1 to EFUN call_other()"——已加上 environment(me) 真值判断守卫。(3)§7.61 message() simul_efun 包装函式缺少 exclude||({}) 守卫,和 sjshv150 相同。(4)§7.41 类损坏的 emoted.o,同样的 catch(restore()) 修法。(5)§8.1 类的 is_chinese() 字节区间 bug,同时出现在 adm/daemons/chinesed.lpc(CHINESE_D 委托的真正实现)和 logind.lpc 的 check_legal_name() 里的 i%2 奇偶门槛(和 sjshv150 相同的 UTF8 vs GBK 字节配对不匹配)——两处都已修成码点区间/逐字符检查。这份快照里没有 convertd.lpc(档案不存在)。管理员账号播种:fluffos (admin) 加入 adm/etc/wizlist。已验证:完整注册(new→id→管理密码→确认→普通密码→确认→名字→电子邮件→性别)每一步都干净推进,没有任何意外错误;default_trusted_write ACL 已直接核对源码确认授予 (admin) 不受限的"/"访问权限(脚本化测试因为计时/刷屏差异没能捕获到确切的权限显示确认,这是这个家族手足档案里已经记载过的、不阻断的测试工具限制)。LPC 格式化工具对全部 12494 个档案运行;还原了 3 个确认有 CJK 重新加空格损坏的档案(2 个和 sjsh/sjshv150 共享,另加一个重复副本),通过"去空格后比对旧档案"扫描(覆盖 138 个格式化工具触碰过的档案)找到;另外直接比对了两个 map.lpc 档案——干净,只是排版调整。格式化后重新验证过,干净。

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

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

用原生驱动(build-debug/src/driver,端口 40125)通过 scripts/tmux_mud.sh 走完整轮,对照同家族已深挖的 sjsh(宝鸡站)/sjshv150(紫藤分站)NOTES.md 逐条核对候选 bug。

``lpc if (!user->query("wiz_password")) { #ifdef NO_CHECK_WIZPWD write("请登陆后用wizpwd来设定你的巫师密码!\n"); check_ok(user); #else ...destruct(user); ... #endif return; } ` NO_CHECK_WIZPWD 已经定义,所以未设置 WIZ 密码时会打印提醒后正常 check_ok(user) 放行,而不是像 sjshv150 那样直接卡死。用管理员账号 fluffos 实测验证:注册当次会话完全不会走到这段代码(和 sjshv150 的发现一致,只有重连才会碰到);重新连线(用 quit -lovesjsh 正常退出保存后,新开一条连线重连,走完 id + 普通密码流程)后看到"请输入相应的WIZ密码』如果你还没有设定巫师密码,请输入回车继续"提示,直接回车后打印"请登陆后用wizpwd来设定你的巫师密码!",随即正常进入游戏(落地〖巫师会议厅〗,look 显示正常,"系统权限目前是:总管巫师(admin)"),没有任何卡死。结论:这份档案独立于 sjshv150 就已经用一个 #ifdef` 开关规避了这个 bug 形状,§8.13 记录的问题不适用于本档案,无需移植修复。

管理员账号(fluffos/管理密码 Mud@2026/普通密码 Mud@2027)本次通过正常注册流程重新走了一遍——adm/etc/wizlist 里已有 fluffos (admin) 一行(更早的 WASM 阶段播种),但存档目录下当时并没有真正落地的 fluffos.o(说明此前只播种了权限数据,账号从未真正注册过);本次完整走完双密码注册流程后立即显示"系统权限目前是:总管巫师(admin)",update 验证写权限正常。见上文"测试踩坑记录":第一次注册因为用掐断连线的方式测试断线场景,被这份档案自己的反小号删档规则删掉,第二次改用 quit -lovesjsh 正常退出后才成功保留存档——README 已同步更新为具体密码(此前写的是"注册时自设")。

§7.100 跨库扫描修复(ROOM 基类同款 replace_program() 致命形状)

§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): 3 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-08-23)— 补齐前一轮"未覆盖"的三项

用真实驱动(~/src/fluffos/build/src/driver,端口 40125)通过 scripts/tmux_mud.sh 补齐前一轮记录在"未覆盖"里的 buy/拜师/WIZPWD 校验分支三项,同时对照 本 session 在 sjshwzb/sjshwzjqb 两个同家族手足档案上发现的两个真 bug 做移植排查。

结论:本轮补测三项全部通过(buy、拜师、WIZPWD 两个校验分支),两个手足档案上 的已知 bug 都确认不适用于本档案(一个是本档案本来就没有该 bug 症状,一个是文件根本 不存在),额外发现并修复了 d/sea/npc/beast1.lpc 的双重编码损坏 compile-crash bug。

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-setup() (or reset_me() calling setup()) chain -- confirmed live via a static scan of every init() body in this lib: 73 NPC/item files call setup() directly or via reset_me() from init(), after create() already called setup() once (which 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, which re-enters this same chain while the original call is still on the stack -- genuine reentrancy, crashing with "Too deep recursion" (most likely to surface on an NPC's first-ever preload/compile).

same as sanjieshenhua (same lineage): feature/damage.lpc's revive() call is dead/commented, but d/qujing/qujingren/qujingren.lpc's wakeup() calls me->enable_player() on a still-living() disabled object. This confirms a bare if (living(this_object())) return; guard would be the WRONG fix (it would silently break that legitimate re-enable) -- 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/disguise) unaffected. feature/command.lpc's 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.