Voice of the Heart: Wind and Cloud IV, Upgraded Edition

✅ 可玩

心声风云四升级版

xsfyssjb

🔑 fluffos(密码见 README) 更新 887e238 2026-09-01 源码 下载 ZIP

▶ 开始游玩 · Play Now

风云Ⅳ(Sumxin 风云)是以古龙小说为背景的 MUD(原站点 sumxin.com/bbs、fy.sumxin.com),地图偏重大漠/西域风情——楼兰、新疆、藏北、流沙等场景齐全,和常见的中原门派地图(华山、武当、少林、丐帮等)并存,突出古龙笔下"大漠孤烟"式的江湖;注册时除了性别,还要选择民族(0-3),呼应这种跨民族的世界观设定;档案里还有一个 `dynamic_npc_quest` 目录,暗示带有动态生成 NPC 任务的机制,而非纯手写的固定任务列表。和这一轮的另一个"风云"手足档案 `wqfy` 是同类 bug 模式,不过底层代码库并不相同;和 `fysjmb`(风云四解密版)才是真正同源代码——`d/dreamland/shanding.lpc` 等文件逐字节相同,此前两份档案都没有互相记录这层关系。

English

Wind and Cloud IV ("Fengyun," by Sumxin), a MUD set in the world of Gu Long's wuxia novels, originally hosted at sumxin.com/bbs and fy.sumxin.com. The map leans hard into Gu Long's desert-frontier jianghu -- Loulan, Xinjiang, Zangbei, and Liusha's shifting-sand borderlands sit alongside the usual central-plains sects (Huashan, Wudang, Shaolin, the Beggars' Sect). Registration adds an ethnicity choice (0-3) on top of gender, echoing that cross-cultural frontier setting, and a dynamic_npc_quest directory hints at procedurally-assigned NPC quests rather than a purely hand-authored quest list. It is a true source sibling of this collection's "Fengyun IV Decrypted Edition" (fysjmb) -- their d/dreamland/ scene files and much of the map are byte-for-byte identical; it happens to share a similar bug pattern with the unrelated codebase behind this collection's "wqfy" but is not otherwise related to it.

README

内容亮点

本次修复的关键 bug

§8.1 GBK 字节区间 is_chinese() bugadm/simul_efun/ chinese.lpcis_chinese() 要求字节数是偶数并检查 str[0] 的 原始字节区间(161-254),在这个驱动按 UTF8 码点索引字符串的情况 下,奇数字数的合法中文名字会被误判为不合法;adm/daemons/ logind.lpc 自己的 check_legal_name() 也有对应的 i%2 奇偶门槛 和字节数长度上限(2-10,原意是提示文字里说的"一到五个中文字")。 已把 is_chinese() 改成逐码点 0x4e00-0x9fff 区间检查, check_legal_name() 改成逐字符检查,长度上限改成字符数 1-5。

管理员账号 / Admin account

这份档案有两个 securityd.lpc 候选(adm/securityd.lpcadm/daemons/securityd.lpc),通过 SECURITY_D 宏确认真正生效的 是 /adm/daemons/securityd(符合 §7.56 的双档案陷阱模式), WIZLIST 确实会在开机时被读取。

警告:对外公开架设前请务必修改此密码。

测试注意事项

性别/民族选择紧跟在 std/char.lpc 首次编译爆发期之后,和 xhcii/xkyxciii 记录过的情况一样会有测试客户端的计时竞态。用 --idle 4 并多送几次"m"/"0"能稳定通过——这纯粹是测试工具的计时问 题,不是 mudlib 本身的缺陷。

本地运行

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

游戏端口:40149

NOTES · 移植与修复记录

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

风云Ⅳ(Sumxin fengyun),一款以古龙小说为题材的 MUD(sumxin.com/bbs、fy.sumxin.com)。和 wqfy(本轮另一个风云系手足档案)血统/bug 模式相同,但是不同的代码库。WASM 修复了经典的 §8.1 GBK 字节区间 is_chinese() bug:adm/simul_efun/chinese.lpc 的 is_chinese() 要求偶数字节对长度,还检查 str[0] 的原始字节区间(161-254),会拒绝合法的奇数字符数 UTF8 中文名字;adm/daemons/logind.lpc 自己的 check_legal_name() 有对应的 i%2 奇偶门槛,以及按字节数算的长度界限(2-10,本意是按用户提示"一到五个中文字"应为 1-5 个字符)。已把 is_chinese() 改成逐码点 0x4e00-0x9fff 区间检查,check_legal_name() 改成逐字符检查,长度界限修正为 1-5。管理员账号播种:fluffos (admin) 加入 adm/etc/wizlist(存在两个 securityd.lpc 候选档案——adm/securityd.lpc 和 adm/daemons/securityd.lpc——已通过 SECURITY_D 宏确认 /adm/daemons/securityd 才是真正生效的那份,符合 §7.56 记载的双档案歧义模式;WIZLIST 真的会在开机时被读取)。注册流程在一次连续的 WASM 客户端会话里完整验证过:GB/BIG5 编码选择→英文 id→y/n 确认创建→中文名字→密码+确认→性别(m/f)→民族选择(0-3)→带着完整角色属性表和可用的 score/look 指令进入游戏世界,全程没有任何意外错误。测试笔记:性别/民族选择正好接在 std/char.lpc 首次编译的大量负荷之后,引发了和 xhcii/xkyxciii 上记载过的同一类测试工具时序竞争——用 --idle 4 补发额外的 'm'/'0' 能可靠绕过;这是客户端时序上的假象,不是 mudlib 本身的缺陷。管理员权限已直接通过 'wizlist' 指令输出确认"目前权限:(admin)",fluffos 出现在最高阶层里。LPC 格式化工具对全部 8238 个档案运行(写入 6459 个,1775 个报错——几乎全部是安全的 TOKEN MISMATCH 安全闸门跳过,针对无法幂等往返的杂乱历史代码,跳过比例明显偏高但无害,因为被跳过的档案完全没有被改动——4 个未改动)。没有 :: 父类呼叫拆分命中,没有 CJK 重新加空格命中,没有 case 标签带尾随注释的候选。唯一一个存在的 map.lpc 档案确认内容完全相同(只是空白差异)。格式化后用同样的完整注册流程重新验证过——干净,管理员权限依然是 (admin)。

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

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

深度功能测试(round two,2026-08-27)

第一次完整的 §10.7 连续游玩测试(此前该库从未做过完整 round-two playthrough)。用真实原生 driver(端口 40149)走完了:注册(中文名 "沈牧",id shenmu)→ look/score/i/hp → 移动 → 商店购买 → 帮派拜师 两条路径 → study/learn 技能路径 → fight(安全切磋)/kill(真实战 斗)→ 留言板只读测试 → 两轮断线重连 → 管理员账号验证 → 系统性 grep 排查了任务里列出的全部标准 cross-cutting bug 类别。

发现并修复了 3 个真实 bug:

1. adm/obj/master.lpc::log_error() 把编译 WARNING 当错误播给玩家 看(AGENTS.md §7.103 的确认实例)。 注册后走 look/score/i 立刻触发多条 编译时段错误:...warning: Unused local variable 'x' 字样的原始编译警告文本,直接打印在普通玩家屏幕上(cmds/std/ look.lpc/cmds/usr/inventory.lpc/std/char/master.lpc 首次编译 触发)。修法:if (this_player(1)) efun::write(...) 改成 if (this_player(1) && strsrch(message, "warning:") == -1) efun::write(...)。重启驱动后用同样的 register→look→score→i 流程 复测,干净无警告输出。

2. adm/simul_efun/file.lpc::log_file() 缺少 assure_file() 目录 保护,导致管理员 call 指令对玩家目标彻底失效(AGENTS.md §7.11 的确认实例,和 xyj2006n/xyj2006zzzhx 同一形状同一文件)。 现场复现:用管理员账号 call shenmu->add_money("coin", 5000) 给 测试角色注资时,call.lpc 自己在真正调用目标函数之前先往 /log/nosave/CALL_PLAYER 写审计日志——但 /log/nosave/ 目录从未 存在于本库归档里,write_file() 静默失败并抛出未捕获的执行时段 错误("Wrong permissions...No such file or directory"),导致后面 的 call_other() 根本没有执行——确认了目标角色的物品栏完全没有 变化。这意味着管理员最常用的调试指令 call 对任何玩家目标从来 没有真正生效过。修法:在 log_file() 里实际调用文件里已经写好但 从未被使用的 assure_file(LOG_DIR + file)(因为它在同文件里定义 在 log_file() 之后,加了一行前向声明)。重启后复测:同样的 call 指令干净执行,目标角色物品栏真的发生了变化, /log/nosave/CALL_PLAYER 按需自动创建。

3. adm/daemons/logind.lpc::reconnect() 断线重连时泄漏旧的 link_ob(新增 AGENTS.md §7.155,和 §7.150 的检查目的相同但是不 同的具体形状)。 按任务要求做了两轮"断线(非 quit)→ 等待→重 连"循环,发现 reconnect()userlink_ob 临时变量直接 覆盖成本次新连线对象,却从未 destruct() 掉上一次会话遗留的旧 link_ob——而同一文件里几行之外的"踢掉重复登录"分支 (confirm_relogin()) 是正确处理这个场景的。旧 /obj/login 对象 因为自己的 time_out() 自清理逻辑在 body_ob 被设置后会主动放 弃(if (objectp(query_temp("body_ob"))) return;),所以永远不会 自行销毁,每一次非 quit 的断线重连都会永久泄漏一个对象。本库这份 /obj/login 没有 heart_beat,所以不会像经典 §7.150 那样反复用陈 旧数据覆盖存档,但仍然是一个真实、会无限累积的对象泄漏。修法:在 reconnect() 里补上和 confirm_relogin() 一样的 old_link = user->query_temp("link_ob"); if (old_link && old_link != ob) destruct(old_link);。重启后复测两轮"断线→等待→重连"循环, debug.log 干净无错误,且 find_player()/管理员 call/tell 在两轮重连之后依然能正确找到角色(本库的 set_living_name() 注 册挂在常驻的角色对象本身而不是登录壳对象上,所以 §7.152 描述的 "重连后 find_player 失效" 这条具体症状在本库并不成立——但泄漏对象 本身仍然是一个需要修的真实 bug)。

测试过但确认干净、未改动的部分:

测试角色shenmu(沈牧)在提交前已清理(data/{login,user}/s/ shenmu/ 已删除)。保留的唯一存档账号是管理员种子账号 data/{login,user}/f/fluffos/(id fluffos,密码 Mud@2026(admin) 权限)。