imud (FluffOS Intermud-3 demo)

✅ 可玩

[email protected]

imud

更新 4f9ef99 2026-09-12 源码 下载 ZIP 上游 fluffos/imud

▶ 开始游玩 · Play Now

FluffOS 项目自己的官方演示(源码:<https://github.com/fluffos/imud>,线上地址 <https://imud.fluffos.info>)。这不是一款游戏——没有角色注册、 没有存档、没有房间地图,只是一个从零开始的最小 FluffOS mudlib 范例,用来演示驱动自带的 Intermud-3(跨 MUD 聊天/名录协议)支持。

English

The FluffOS project's own tiny live demo at imud.fluffos.info, not a game: connecting drops you straight into an anonymous session (no login, no registration, no player object/save data, no rooms) with exactly two commands, mudlist (lists the real, live Intermud-3 network via a genuine outbound socket connection to the *i4 router) and update (reload an object by path). Included as a preserved reference example of a minimal from-scratch FluffOS mudlib/I3-client rather than a wuxia game.

README

本馆只保留说明和启动脚本。 work/github.com/fluffos/imud 的 git submodule(.lpc,已按本馆 §9 格式化)。修复请提交到那个仓库,不要在本馆再改一份。克隆本馆时加 --recurse-submodules

内容说明

- mudlist —— 通过真实的 socket 连接到公网上的 Intermud-3 路由器 (*i4, 204.209.44.3:8080),列出当前在线的、真实存在的其他 MUD。 这是本演示唯一有实际内容的功能,连接成功后能看到几十个当前挂在 I3 网络上的真实 MUD(FluffOS/LDMud/CoffeeMud/DGD 等各种驱动)。 - update <path> —— 重新编译/加载指定路径的对象,供演示者热更新代码, 没有任何权限校验(谁连上来都能用)。

重要:会连上真实的公网 Intermud-3 网络

启动这个 lib 会让 secure/imud/imud.c 立即向真实的、目前仍在运行的 Intermud-3 路由器发起出站连接并完成握手——这不是沙盒模拟,是真实的 公网连接,会让本机的公网 IP 短暂出现在真实 I3 网络的 mudlist 里 (显示名固定为 [email protected])。这是原始演示本来就有的行为, 不是本项目引入的 bug,但和语料库里其它所有 lib(纯本地沙盒)不同, 在自动化重复开机测试脚本里对这个 lib 要格外小心——反复重启会反复 向真实第三方服务器发起连接。详见 NOTES.md

在线试玩

本地测试端口如下(原始 config.txt 的 websocket 7878 未启用)。

管理员账号 / Admin account

不适用——这个 lib 没有账号系统,没有登录/注册流程,也没有 wizardp()/ACL 之类的权限分级机制。所有连接者拿到的是同一个匿名会话、 同样的两个命令(含没有任何权限校验的 update),因此不存在需要额外 播种的"管理员账号"。详见 NOTES.md 的 §2.2/§1.5 检查结论。

本地运行

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

游戏端口:40209

NOTES · 移植与修复记录

imud — [email protected]

来源:git clone https://github.com/fluffos/imud(克隆时 HEAD 为 6b232d4 Add WASM pack script + GitHub Pages deploy workflow, 2026-08-24 克隆)。编号 161,端口 40209。状态:done(干净启动, 两个命令均验证可用;这个 lib 本身就没有登录/注册/游戏世界,见下)。

这个 lib 到底是什么

不是游戏。 这是 FluffOS 驱动项目自己在 <https://imud.fluffos.info> 上跑的官方演示,仓库描述就是 "source code for imud.fluffos.info"。整个 work/ 只有 23 个 .lpc/.h 文件(原始 .c),核心逻辑是:

- mudlist:通过 secure/imud/imud.c(一个相当完整的 Intermud-3 协议实现,imud_d.c/Deathblade 1995 年的经典 I3 daemon)向真实的 公网 I3 路由器(*i4, 204.209.44.3:8080)发起 socket 连接,列出 当前挂在 I3 网络上的真实 MUD。这是这个演示唯一有实质内容的功能。 - update <path>destruct()load_object() 指定路径,用于 演示者热更新代码,没有任何权限判断——这是设计如此(单人本地 演示环境),不是要修的 bug。

§2.2 On-sight checklist 结论

按 AGENTS.md §2.2 逐项检查,全部不适用/无发现:

转换(convert_lib.sh)

已经是现代 FluffOS 仓库,直接跑 scripts/convert_lib.sh libs/imud/raw/imud libs/imud/work

config.fluffos

原始 config.txt 只有 external_port_1: websocket 7878,没有普通 telnet 端口——这个项目的 mudclient.py 走原生 telnet,所以改成标准的 port number : 40209(分配端口)而不是 websocket;没有照搬原仓库的 websocket/secure/www 网页客户端配置(那是给 imud.fluffos.info 网站 用的,本项目不需要)。其余数值参数(eval cost、hash table size 等) 沿用其它 lib 的标准模板值,因为原始 config.txt 完全没有配置这些 (是驱动的默认值),不是原样照搬某个"权威"配置。

编译扫查(lpcc_check.sh)

23 个文件,15 PASS / 8 FAIL。8 个失败全部是上面提到的、imud.c 里被注释掉未启用的 I3 扩展协议模块emoteto/file/mail/who/ oob/channel/locate/finger),单独编译时报缺 commands.h/ log.h/socket.h/ports.h/daemons.h/security.h 等本仓库根本没有 的头文件,以及 this_body/find_body/find_user/tell/mud_name/ convert_time/DBBUGIMAIL_D/CHANNEL_D/CMD_OB_TELL/ DIR_I3_FILES 等未定义的函数/全局宏——这些模块显然是从一个更完整的 mudlib 里摘出来的骨架,依赖那个宿主 mudlib 才有的基础设施,从来没有 打算在这个极简演示仓库里独立编译或运行。确认它们不会被任何活跃代码 路径加载grep 全仓库,除自身文件外唯一的引用就是 imud.c 里那些 被注释掉的 inherit 行)——按 AGENTS.md 的 scope 原则,这是上游仓库 自带的、从未启用过的死代码,不是本次转换引入的回归,不修。真正被 inherit/加载的 15 个文件全部 PASS。

启动与实测(原生驱动)

cd libs/imud && ~/src/fluffos/build-debug/src/driver config.fluffos: 干净启动,log/debug.log 无 FATAL、无 Fail to load (除上述已知的 死代码模块外)。mudclient.py 连接验证:

⚠️ 重要:启动这个 lib 会发起真实的公网出站连接。 imud.ccreate() 会立即触发 reconnect(),真实 socket 连接到 204.209.44.3:8080(I3 路由器 *i4)并完成握手——不是沙盒模拟,是 真实的第三方服务器。握手完成后我们的实例会短暂出现在真实 I3 网络的 mudlist 里。这是原始演示故意如此设计(整个 lib 的存在意义就是演示这个 协议),不是要修的 bug,但和语料库里其它所有 lib(纯本地、不出网)性质 不同——以后如果对这个 lib 跑自动化重复开机测试(比如 §10.0 那种 long-sit 扫描或轮次性重测 cron),要意识到每次启动都会真的连一次公网 I3 网络,建议:(a) 不要把这个 lib 纳入高频率的自动重启测试队列; (b) 如果需要频繁重启测试,考虑给 reconnect()加一个仅用于本项目 CI/沙盒场景的开关(本次未做——没有被要求修改这个核心演示功能,属于 "design",不是 bug)。

WASM 实测

node scripts/wasm_client.js ~/src/fluffos/build-wasm/src libs/imud --send "" --send "mudlist" --send "quit"(本机默认 PATH 没有 node,用的是 ~/.local/opt/node/bin/node):干净启动,同样没有登录 流程,两个命令都能跑,无 FATAL。唯一的行为差异:secure/imud/socket.c 编译失败——socket_address/socket_writeUndefined function (WASM 构建没有 sockets 包,AGENTS.md §1.3c 记录过的已知策略级差异, 不是本 lib 特有的 bug)。imud.creconnect() 本来就把 clone_object(SOCKET) 包在 catch() 里,所以这个编译失败被优雅捕获, 不影响后续任何东西——router_socket 保持未设置,mudlist 正常执行完, 只是返回 "0 matches out of 0 muds"(空列表,因为拿不到真实 I3 路由器数据)而不是崩溃或挂起。判定 wasm_status: playable——启动、 两个命令、退出全部正常,唯一退化的是 mudlist 的实际内容(这本来就是 WASM 环境天然拿不到公网 socket 的必然结果,无法用 mudlib 侧代码 修复,也符合 §1.3c 里"sockets 包缺失导致的功能整体缺席,按 playable 处理"的既有先例)。

深度功能测试 / Deep functional test(round two, 2026-08-27)

标准 §10.7 round-two checklist(注册→移动→人物信息→战斗→门派/技能→ quit-重连)在这个 lib 上整体不适用——见上面「这个 lib 到底是什么」:没有 账号系统、没有房间地图、没有战斗/技能/门派,connect() 直接丢进匿名 secure/user.c 会话。本轮把同一条原则(不要只读源码就假设能用,实际 连上一个真跑着的驱动,把每一个真实功能都点一遍)适配成这个 lib 实际 拥有的东西:boot 真实原生驱动 → 用真实 socket 客户端把两个命令 (mudlist/update)连同未知命令兜底都跑一遍 → 每次都检查 log/debug.log 以外的运行时错误日志work/log/log/work/log/log_catch, 由 secure/master/error.lpcerror_handler() 写入,不是 log/debug.log——这两套日志此前没有被本 lib 的记录明确区分过,见下)。

Bug found and fixed

secure/imud/imud.lpc:144-146handle_router_read())——检测到非 数组消息后没有 return,继续往下执行 message[0],在真实驱动上 每次启动、每次 I3 socket 建立连接都 100% 必现一次被捕获的运行时 错误。

`` *Value being indexed is zero. Object: /secure/imud/imud at line 148 'read_callback' at /secure/imud/socket#0 at line 94 'CATCH' at /secure/imud/socket#0 at line 94 'handle_router_read' at /secure/imud/imud at line 148 ` 对连接过程完全不可见——mudlist 照常返回真实数据、欢迎语正常、玩家 侧没有任何异常——只有翻这个专门的运行时错误日志才能看到。用今天之前 遗留在 work/log/log_catch` 里的历史记录核实过:2026-08-24 那次首次 转换测试的 4 次启动(22:22/22:23/22:24/22:34)每一次都留了同一条 错误,说明这不是偶发,是从这个 lib 转换进本项目那天起就一直存在、 每次启动必现的问题,只是此前的验证轮次没有检查过这个日志文件。

``lpc if (!arrayp(message)) { debug_message(sprintf("Unknown message: %O", message)); return; } ` message 本来就不是数组时,后面所有依赖 message[0..] 下标访问的 分发逻辑都没有意义,提前返回是唯一合理的行为,不改变任何真实 I3 协议消息(mudlist/startup-reply/error`/未知类型转发错误包)的 处理路径。

debug.log 里一条无害噪音,记录但不修

真实 I3 路由器在握手完成后,会在没有请求的情况下主动推送一条 chanlist-reply 消息(属于 channel 扩展协议,本 lib 的 secure/imud/imud.lpcinheritdaemon_data/reconnect/ mudlist 三个模块,channel 模块本来就被上游仓库自己注释掉,见 「这个 lib 到底是什么」一节)。handle_router_read() 对着这条未知 类型的消息按设计正确地回了一个 "error"/"unk-type" 错误包给路由器, 但真实路由器又回了一句 (<- *i4) not-imp: Unknown command sent to router: error——路由器自己不接受把 "error" 类型的包直接发给它本身 (只接受它转发给别的 mud 的场景)。这是"演示 lib 只启用了三个协议 模块、面对一个真实的、期望更完整协议栈的生产路由器"这一既定设计事实 自然产生的协议噪音,不改变任何行为,两次干净启动(含修复前后)都能 在 log/debug.log 里看到,判定为"design",不修。

结论

本轮修复了一个真实的、每次启动必现的运行时守卫缺失 bug(imud.lpc handle_router_read()return 缺失),修复前对玩家侧完全无感知, 只在专门的运行时错误日志(work/log/log/work/log/log_catch,与 log/debug.log 是不同文件)里可见——这本身也印证了 AGENTS.md §10.7 "quit 的可见输出正常不代表服务端没有静默出错"这条方法论在这个只有两个 命令的极简 demo 上依然成立。除此之外,这个 lib 唯一有实质内容的功能 (mudlist 真实连公网 I3 网络)本轮再次原生实测确认工作正常,update 命令、未知命令兜底、~50 秒空闲期、WASM 构建全部无新发现。

filed upstream as PR #1: <https://github.com/fluffos/imud/pull/1> (2026-08-31,标准 fluffos-org 上游回馈流程,见 project_fluffos_org_upstream_pr_queue.md)——审计了本文件里其余的 转换记录(编码、.c.lpc 重命名、config.fluffos 端口选择、 lpcc 编译扫查的 8 个 FAIL、WASM 实测差异),全部是本仓库自己的集成 工作或上游自带的死代码/环境差异,唯一符合"真实驱动兼容性 bug"标准的 就是这一处 handle_router_read()return 缺失,已在 fork thefallentree/imudfix-handle-router-read-missing-return 分支 里把等价修复应用到上游原始 secure/imud/imud.c(本仓库转换后的路径是 secure/imud/imud.lpc)并提交 PR。

管理员账号

不适用,见 README「管理员账号」小节——没有账号系统,无法播种。

Leftover 678 (2026-09-12) — upstream pin

fluffos/imud PR #1 is the in-tree handle_router_read() missing return. Pin advanced to 3f303add53. Do not high-frequency reboot this lib (live I3).