info.html · 介绍 · play.html · 游玩 · llms.txt · 下载与本地运行 · ZIP · GitHub
小雪初晴(游戏内品牌"SnowMud")由 CuteRabbit Studio(JackyBoy)为 CCTX 与 SDXL 社群开发,取材温瑞安武侠小说世界观——有别于本合集常见的金庸/古龙地图模板,药王谷、温家/温寨、龙门等都是温派小说里的真实地标;字节级比对显示,这份档案约 2000 个文件的地图有 99.6% 与姊妹档案 `xxcqii`("小雪初晴II",地图规模更大、多出约 150 个文件)逐字节相同,是同一世界观的一个子集版本而非各自独立开发的续作;两者的管理员账号引导机制也不同:这份档案通过 `securd.lpc` 里硬编码的创始人账号授权,`xxcqii` 则走标准的 `wizlist` 文本文件机制,管理员登录后称号直接显示"【天神】",是这批档案里权限称号最直白的一个。
English
Branded in-game as "SnowMud," developed by CuteRabbit Studio (JackyBoy) for the CCTX and SDXL communities and set in the world of Wen Ruian's wuxia novels -- a setting distinct from the more common Jin Yong/Gu Long map templates elsewhere in this collection, with real landmarks like the Medicine King Valley (药王谷), the Wen family estate (温家/温寨), and Dragon Gate (龙门). A byte-level check confirms this archive's entire ~2,000-file map is a 99.6%-identical subset of sibling xxcqii's larger map -- xxcqii ("Second Snow Clearing") extends this same world with roughly 150 additional files rather than being an independently-built sequel. The two also seed their admin account differently: this archive hardcodes a founder id in securd.lpc rather than reading the standard wizlist file, and shows the highest-ranking title in this batch, "【天神】" (God), directly on login.
README
内容亮点
- 和姊妹档案
xxcqii共享同一套温瑞安世界观地图(药王谷、温家场 景、龙门等),但管理员账号引导机制完全不同:这份档案通过securd.lpc里硬编码的创始人账号(jackyboy)授权,xxcqii则是标准的wizlist文本文件机制。 - 管理员登录后称号直接显示"【天神】",是这批档案里权限称号最直白 的一个。
- 这份档案原始压缩包里完全没有
adm/etc/目录,导致任何一次连 线(不只是 WASM 环境)在英文名字提示之前就会被访客计数器的write_file()静默炸掉,连注册流程都进不去——这是一个真实存在、 会影响原生部署的缺陷,不是测试环境特有的问题(详见下方 bug 修复 说明)。 - 深度功能测试发现 WASM 阶段创建
adm/etc/目录时遗漏了一个文件 (motd),导致每一次注册在幕后仍然静默失败——角色对象正常 创建、存盘,却从未被放进任何房间,look只会看到"灰蒙蒙一片", 没有任何报错。另发现同类连锁 bug(natured.lpc缺失的昼夜数据 表)、§8.9 食物/饮水年龄检查错对象、printf 调试残留、2 处 §7.68 复活软锁,以及一个从未被记录过的 bug:登录对象自身的set()权限保护过严,导致邮箱注册流程生成的新密码从未真正生效(详见 NOTES.md 和 AGENTS.md §7.9/§7.82)。
- 更正(2026-08-05):上面提到的"7.68 复活软锁"修复已经撤销——经重新评估,鬼魂"不在场"时放弃复活流程更可能是有意的游戏设计(多数这类档案里鬼魂本身就无法自行移动,离开是一种游荡机制,回来时 init() 会重新触发流程),不是需要强制重试的 bug;详见 NOTES.md。
本次修复的关键 bug
真正会挡住每一次连线的 bug:这份档案里根本没有 adm/etc/ 这
个目录(连原始压缩包里都没有)。logind.lpc 一连线就会呼叫
write_file(USERS, ...)(访问人次计数器,每次连线都会执行,在英
文名字提示之前),但 write_file() 能自动创建缺失的文件,创
建不了缺失的目录,所以这一步每次都会报"Wrong permissions for
opening file /adm/etc/users for overwrite, No such file or
directory"。这个错误没有被任何地方拦截,驱动就静默把连线直接扔进
了裸的指令提示符——注册流程的 input_to() 根本没被呼叫过,之后
输入什么都是"什么?"(无法识别指令)。这个 bug 在原生开机下也会一
模一样地发生,不只是 WASM 下的问题。已经创建 adm/etc/ 目录,附
带初始化的 users/iduser 计数器文件(都是"0")。
顺带确认(§7.56 双档案陷阱):SECURITY_D 真正指向的是
/adm/daemons/securd,不是那份引用(这份代码库里其实没用到
的)WIZLIST 文本文件的分身档案 securityd.lpc。securd.lpc 通
过 restore_list() 里硬编码的 set("wiz_status/jackyboy",
"(admin)") 来引导管理员账号(和这一轮之前修的 sj 是同一个模
式),已经在旁边加上 set("wiz_status/fluffos", "(admin)")。
管理员账号 / Admin account
- ID:
fluffos - 密码 / Password: 注册时自设(临时密码 + 确认)
- 权限 / Level:
(admin),注册完成时连线横幅已经直接显示"目 前权限:(admin)",人物称号也是最高级的"【天神】"。
警告:对外公开架设前请务必修改此密码。
本地运行
cd libs/xxcq
~/src/fluffos/build-debug/src/driver config.fluffos游戏端口:40135。
NOTES · 移植与修复记录
WASM 修复摘要(迁移自 meta.json 的 group_note)
小雪初晴,游戏内品牌名"SnowMud",CuteRabbit Studio(JackyBoy)为 CCTX 和 SDXL 制作的一款以温瑞安小说为题材的 MUD。WASM 修复了一个真正会卡死游戏的 bug:这份压缩包里任何地方都没有 adm/etc/ 这个目录(连 raw/ 里也确认不存在),导致 logind.lpc 最开头的 write_file(USERS, ...) 呼叫(访客计数器自增,每一次连线、在 id 提示出现之前都会执行)抛出"Wrong permissions for opening file /adm/etc/users for overwrite, No such file or directory"——write_file() 能创建缺失的档案,但创建不了缺失的目录,所以这是每一次连线都会触发的未捕获错误,驱动会静默吞掉它,直接把裸连线丢进一个交互式指令提示符,从未呼叫 input_to() 进入注册流程(之后任何输入都显示成无法识别的"什么?"指令)。这在原生启动下也会一模一样地失败,不只是 WASM 环境的问题。已通过创建 libs/xxcq/work/adm/etc/ 目录并预置 users/iduser 计数器档案(均为 '0')修复。另外通过源码确认(§7.56 双档案歧义提醒)SECURITY_D 实际指向 /adm/daemons/securd,而不是那份引用了(这份代码库里根本没用到的)WIZLIST 文本档案的诱饵档案 .../securityd.lpc——securd.lpc 是通过 restore_list() 里一行硬编码的 set('wiz_status/jackyboy', '(admin)') 呼叫来播种管理员账号的(和本轮之前修过的 sj 那份档案是同一种形态),而不是读取 wizlist 档案;已加上一行同样的 set('wiz_status/fluffos', '(admin)')。注册流程在一次连续的 WASM 客户端会话里完整验证过:GB/BIG5 选择→英文 id→y/n 确认创建→中文名字→临时密码+确认→接受天赋赠礼(y)→性别(m/f)→带着完整角色属性表进入游戏世界,连线横幅里已经直接显示"目前权限:(admin)",还有"【天神】"最高阶层称号,全程没有任何意外错误。LPC 格式化工具对全部 2886 个档案运行(写入 2828 个,28 个报错,30 个未改动)。没有 :: 父类呼叫拆分命中,没有 CJK 重新加空格命中,没有 case 标签带尾随注释的候选。唯一一个存在的 map.lpc 档案确认内容完全相同(只是空白差异)。格式化后用同样的完整注册流程重新验证过——干净,管理员权限依然是 (admin)。
§10.7 深度功能测试(本次新增)
此前只做过一次连续会话内的注册流程验证。本次实际深入游玩后发现:WASM
修复阶段创建 adm/etc/ 目录时遗漏了一个文件,导致每一次注册实际上
仍然会在幕后彻底失败——只是这次失败得比之前更隐蔽,不会中断连接,而
是让角色永远卡在"灰蒙蒙一片、什么也没有"的无环境状态。这是本次会话里
发现的最严重的一类 bug,同时还额外发现了 §8.9、printf 调试残留、2 处
§7.68、以及一个从未被记录过的登录对象权限过严 bug。
修复 1(本次最严重的发现):adm/etc/motd 缺失导致每次注册都静默失败
adm/daemons/logind.lpc 的 enter_world() 里有一行完全没有防护的
write(read_file(MOTD));(MOTD = /adm/etc/motd)。WASM 阶段虽然
创建了 adm/etc/users/iduser,却没注意到还需要一个 motd 文件——
read_file() 对不存在的文件返回 0(不是字符串),write(0) 会让
receive_message() 抛出未捕获的 *Bad argument 1 to receive(),而这
一行恰好出现在同一个函数里、真正把角色 move() 到起始房间那一行代
码之前——所以每一次注册,函数都会在这里意外中断,角色对象已经创建、
已经存盘,但从未被放进任何房间。之后无论连线多少次、输入什么指令,
look 都只会看到"你的四周灰蒙蒙地一片,什么也没有。",没有任何报错
提示玩家,连管理员账号自己第一次注册也是这个下场。这是本档案原始压缩
包里真实存在的缺陷(原生开机下也一样),不是 WASM 沙箱特有的问题;
WASM 阶段已经处理了同类问题的一半(补齐了 adm/etc/ 目录本身),但
遗漏了这个具体文件,掩盖了背后这个真正的代码级 bug。已按 AGENTS.md
§7.9 的标准做法加上 stringp() 判断修复,不再依赖恰好存在这个可选的
欢迎消息文件。
修复 2:adm/daemons/natured.lpc 的同类连锁 bug——缺失的昼夜数据表
同样的根因还影响了另一个完全独立的档案:natured.lpc 的
read_table("/adm/etc/nature/day_phase") 在这份压缩包里同样彻底不存
在,explode(read_file(file), "\n") 在没有防护的情况下崩溃
*Bad argument 1 to explode()——第一次被惰性编译触发的时机恰好是巫师
起始房间自动 look 的时候。加上 stringp() 防护后问题并没有完全解
决:day_phase 变成了空数组,而 init_day_phase()/
update_day_phase()/outdoor_room_description()/outdoor_room_
outcolor() 这四处都假设这个数组至少有一项,sizeof(day_phase)-1 会
变成 -1("Array index must be positive or zero"),取模 %
sizeof(day_phase) 还会除以零——每一个户外房间的 look 都会崩溃。最
终修法是在读取数据表的地方就填入一个最小的兜底单条目("天色如常"),
让下游所有假设"至少一条"的索引/取模运算保持有效,而不是逐个访问点单
独加判断(详见 AGENTS.md §7.9 的追加记录)。
修复 3:§8.9 食物/饮水年龄检查错对象
logind.lpc 的 enter_world():
if (!user->query("food") && !user->query("water") && ob->query("age") == 14)
——ob 是登录对象,ob->query("age") 永远是 undefined,这道门槛永久
为假,每个新角色的食物/饮水会静默永远保持 0。已改成
user->query("age") == 14,实测新角色食物/饮水栏正确显示为满格。
修复 4:printf 调试残留
get_name() 在设置角色中文名字之后紧跟一行
printf("%O\n", ob);,会把登录对象的原始引用(如
/clone/user/login#0)泄露给每一个刚输入完中文名字的新玩家。已删除。
修复 5:两处 §7.68 复活软锁(d/death/npc/{b,w}gargoyle.lpc)
death_stage(object ob, int stage) 原代码
if (!ob || !present(ob)) return; 把"鬼魂对象已经不存在了"和"鬼魂此
刻只是暂时不在这个房间里"混为一谈,一旦判定瞬间鬼魂碰巧不在场就永久
放弃后续引导,把鬼魂永久卡在鬼门关。按标准修法拆开:!ob 才是真正放
弃,!present 改为 5 秒后重试。
修复 6(此前完全没有暴露过的新 bug):登录对象自身的 set() 权限保护过严,导致邮箱注册的密码更新静默失效
clone/user/login.lpc 给自己的 set() 加了 nomask 保护("Protect
login object's data against hackers"):只允许 geteuid(previous_
object()) == ROOT_UID 的调用者写入。但真正核心的邮箱注册流程
inherit/room/regroom.lpc 的 do_register()——不是玩家自造的内容,
是系统本身的注册房间——运行在房间自己的普通域 euid(这里是
"Domain")下,并不是 root,于是它对 linkob->set("password", ...)
和 linkob->set("email", ...) 的调用全部被无声拒绝,只在玩家屏幕上
打印一行 login set is error!Domain(打印之后并不中断,后续代码
照常执行,所以整个注册看起来完全正常:"你是第1个注册的朋友!发送到
...的邮件已经加入发送队列!")。实际效果:系统生成并通过邮件发送给
玩家的新随机密码从未真正生效,玩家的密码一直停留在最初自选的临时密
码上,和"忘记密码请查收邮件"这套流程的承诺完全不符。修复没有直接放
宽 login.lpc 自己的保护(那样会重新打开它自己注释里承认的"漏洞"),
而是给已经拥有 root euid 的 logind.lpc(create() 里
seteuid(getuid()))加了一个小的转发函数 set_login_field(),
regroom.lpc 改成通过这个函数间接写入。已实测确认:修复后同样的注
册流程不再打印任何 login set is error/password seting is fail。
检查、确认不适用的已知 bug 类别
- §7.78 CHARACTER 的 F_* 混入档缺 F_DBASE inherit:
inherit/char/ char.lpc是和 shujian3/hy2002/jh2006 完全相同形状的 ES2 结构,这 几个同宗档案都已经用真实测试排除过这个 bug(裸 set/query 实际写入 了真正的 dbase),本次时间关系未重复验证。
未能完成的部分(诚实记录)
由于地图上能立即找到的敌对 NPC 几乎都被原作者自己注释掉了("objects"
清单整段包在 /* ... */ 里,如 d/bianliang/guandao10.lpc 的
bigwolf),本次深度测试完成了完整的注册→移动→户外场景验证,但没有
找到一个可以快速安全触发的实战/死亡目标,因此没有做成活体的战斗/死
亡/复活验证——bgargoyle.lpc/wgargoyle.lpc 的 §7.68 修复只做到静态
代码审查确认,留给未来 pass 补做。
更正(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 崩溃)
BULLETIN_BOARDinherit+ 多余replace_program()致命形状(AGENTS.md §7.86,post命令崩溃):全档案 20 处命中,已删除多余的replace_program(...)调用(保留inherit),逐文件保留原有行尾格式(CRLF/LF 按文件原样)。本次为跨库 §7.86 扫描修复(触发原因:该 bug 已在 6+ 个互不相关的血统家族独立确认,属于近乎普遍的拷贝粘贴模式),仅做编译检查(驱动干净启动、端口正常监听),未做完整 §10.7 深度游玩测试。
深度功能测试第二轮 / Deep functional test round two (2026-08-15, post driver-upgrade re-test)
驱动于 2026-08-12 升级后的重测。标准检查清单发现并修复五处问题:
1. config.fluffos:maximum evaluation cost 从 700000(已知
风险区间)提升到 5000000。
2. cmds/ang/update.lpc(AGENTS.md §7.106):缺少
environment(me) && 前置防护,补上。
3. adm/simul_efun/file.lpc:log_file() 没有 assure_file()
目录预建保护,补上调用及前向声明;cat() 补上
read_file() || "" 空值防护。
4. adm/obj/master.lpc::log_error()(AGENTS.md §7.10/§7.103):
if (this_player(1)) efun::write(...) 完全没有警告过滤门,任何
编译警告都会原样广播给连线玩家。补上
strsrch(message, "arning:") == -1 判定。
5. clone/user/user.lpc::reconnect()(AGENTS.md §7.108,第十八条
独立确认的血统):adm/daemons/logind.lpc 有同款
exec(old_link, user); 踢掉重复登录写法,reconnect() 缺少
enable_commands()。按 §7.108 记录的写法预防性修复,现场用两个
真实连线复现"保持第一个连线不断开→第二个连线登录→答 y 踢掉旧连
线"验证:score 修复后立即正常显示完整角色档案。
方法论记录(非 bug):既有 fluffos 账号密码未知,改用新账号测试
与本 session 早前在 sj 上遇到的情况一样:已有存档的 fluffos 账
号(第一轮用"临时密码"通过真实注册流程播种,但 NOTES.md 没有记录
具体密码值)用标准密码 Mud@2026 登录失败。管理员授权在
securd.lpc::restore_list() 里是纯代码层硬编码(set("wiz_status/
fluffos", "(admin)")),不依赖密码正确与否。仿照 sj 的处理方
式,新增一行 set("wiz_status/fluffosb", "(admin)"),用全新 id
fluffosb 走真实注册流程验证(密码 Mud@2026),本轮所有测试均
用这个新账号完成。原 fluffos 账号存档原样保留,未触碰。
现场验证摘要
驱动干净启动,fluffosb 走完整注册流程(GB 选择→id→中文名"秦
风"→临时密码→天赋确认→性别)后确认 目前权限:(admin),update
/adm/daemons/logind 成功验证真实写入权限,现场未观察到编译警告
泄漏(确认 log_error 修复生效)。踢掉重复登录重连路径现场验证通过
(见上)。debug.log 全程干净(196 行,无真实错误)。
本轮修改的文件
config.fluffoswork/adm/daemons/securd.lpcwork/adm/obj/master.lpcwork/adm/simul_efun/file.lpcwork/cmds/ang/update.lpc
§7.100 扫描修复(ROOM 基类多余 replace_program())
#define ROOM "/inherit/room/room":删除 792 处多余的、独立成行的
replace_program(ROOM);(保留 inherit ROOM;),与 xxcqii/
xxcqii2 同一血统同一形状(本档案是它们的祖先/同系原始档案)。
clone/misc/roommaker.lpc 同样有两套模板——"造一间空房间"的
heredoc 本来干净,"克隆我所在的房间"命令的字符串拼接模板把同一枚
多余的 replace_program(ROOM); 烤进了每一个新克隆的房间,已同步
修正。已用 build-debug 驱动干净启动验证(0 个新增编译错误,端
口正常监听;启动时的 domain_stats/author_stats 统计文件缺失
警告是预先存在的良性提示);未做完整 §10.7 深度游玩测试。
work/clone/user/user.lpc
§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.
Round three (2026-09-04): shop + 浣花拜师
New angle vs prior rounds. Native build-debug driver, port 40135.
First send is GB/Big5 g. Admin fluffosb/Mud@2026 (秦风, title
【天神】; the older fluffos save still has an unknown password, left
untouched). Lands at 巫师公会.
Shop — 叁合楼 buy jitui paid and received
goto /d/bianliang/sanhelou. 店小二 (d/bianliang/npc/xiaoer2.lpc,
F_DEALER) list shows 烤鸡腿 八十文铜板 (plus 酒袋/包子/酱牛肉).
clone /clone/money/silver (一两) then buy jitui →
你从店小二那里买下了一根烤鸡腿. Inventory: 烤鸡腿 + 二十文铜板
(100 − 80). Relog kept the 20 coins; the food item itself is not
autoload (existing design). No 丐帮 dealer gate in this F_DEALER.
拜师 — 李子木 / 浣花剑派, persisted
goto /d/huanhua/huzu first crashed (below). After the room guard:
虎啸堂 loads 李子木 (li zimu). bai li → 好吧…决定收你为弟子 /
恭喜您成为浣花剑派的第六代弟子. score shows 浣花剑派第六代弟子、
虎组组员 and 你的师父是李子木. Cold-boot relog (same driver still
up, clean quit + login) still shows that title and master. save
printed 档案储存完毕.
The organic 家丁 path (ask jia ding about 拜师 at
d/huanhua/gate.lpc) was not walked: the gate's objects entry
npc/zuyuan_q is a missing file (same content gap as zuyuan_h
below). doording.lpc is a real 家丁 with that inquiry, but is not
the object the gate actually places.
Programming bugs fixed this pass
1. §7.25 make_inventory() on a missing path
(inherit/room/room.lpc). huzu.lpc lists
__DIR__ "npc/zuyuan_h" (file does not exist; zuyuan_q at the
gate is the same gap) then __DIR__ "npc/li". new() returned 0;
0->move() threw *Bad argument 1 to EFUN call_other() and
aborted reset(), so 李子木 never spawned and goto failed.
Guard: if (!objectp(ob)) return 0; plus objectp() before
is_character() in both reset() branches. Live: 虎啸堂 then
showed 李子木 and accepted bai li. Missing zuyuan_* files
left as content gap.
2. do_list() used the whole key array as a mapping index
(feature/dealer.lpc, same shape as xxcqii §7.151).
j = tmp[goods] printed 0件布衣 for the 店小二's worn cloth.
Changed to j = tmp[goods[i]]. After update /feature/dealer +
room refresh, list showed 1件布衣; catalog prices unchanged.