
简介这份资源是一款基于 HTML5 技术构建的 MUD 游戏服务器整合了经典武侠小说《笑傲江湖》的江湖世界题材适合 Web 开发初学者、MUD 爱好者以及想要快速架设文字冒险游戏的站长使用。压缩包共 2000 个文件大小约 28.97MB其中以 1687 个 C 语言源文件为主配合 290 个 Markdown 文档、18 个头文件和少量说明文本整体覆盖服务器逻辑、游戏规则、配置参考等多方面内容。资源包已有 333 人浏览学习。从文件构成来看C 源文件主要用于实现游戏命令、战斗系统、物品合成等底层逻辑Markdown 文档则可作为架设与二次开发的参考手册适合对文字 MUD 服务器感兴趣、希望了解传统游戏逻辑与现代 Web 技术结合的开发者。解压后可直接研究入口文件、命令处理模块与数据配置结构便于后续调整江湖地图、角色成长和门派玩法是有一定参考价值的 H5mud 原型项目。1. 服务器端的文字游戏H5mud是什么为什么值得自己架MUDMulti-User Dungeon多用户地牢对老玩家来说是一个时代的符号满屏纯文字的房间描述、方向指令、频道聊天没有画面全靠脑补。H5mud服务器把这个经典玩法搬进了浏览器服务端解压后直接架设客户端不再需要 ZMUD、MUSHclient 这类专用软件打开网页通过 WebSocket 长连接就能玩。对于想怀旧重温文字 RPC 的人、想给朋友搭一个联机文字世界的人或者想拆一套完整 MUD 源码研究服务器逻辑的人这套资源是最低成本的起点——不用等别人开服不用抢账号服务器能通网就能玩。2. 先搞懂服务器架构再动手WebSocket、驱动与 mudlib 怎么分工2.1 MUD 服务器不是一个程序驱动和游戏逻辑是两套东西老派 MUD 的服务器端一直不是单文件程序。1978 年埃塞克斯大学跑出第一个 MUD 时它就已经把网络连接管理和游戏内容定义分开。后来流行的 LPMud、mudOS、DikuMUD 体系里最底层的叫驱动driver负责监听端口、解析用户输入的命令行、调度定时器、管理对象在内存中的生命周期往上一层是 mudlib负责房间、NPC、物品、技能这些具体游戏规则怎么写最上层才是世界数据也就是某个站点自己的地图和任务配置。这份 H5mud 资源之所以能直接架设正是因为它把这三层打包好了驱动跑在服务器上mudlib 提供通用规则世界数据已经填好可供试玩的内容。如果只给你一个空驱动你还需要自己写一整套路西法和区域文件那是另一个量级的工作量。2.2 为什么选 WebSocketMUD 的本质是长连接文本流传统 MUD 走 telnet 的 23 端口玩家输入一条指令服务器回一段文本一来一回之间有严格的时序。浏览器本身不会 telnet于是 H5mud 要解决的核心问题是怎么让网页客户端和服务器保持一条可持续收发文本的长连接。有人会想 HTTP 轮询行不行不行。MUD 里有大量服务器主动推送的场景——房间里的其他玩家说话、NPC 行动、定时刷新的事件这些不能用每隔两秒问一次的方式做延迟和流量都扛不住。WebSocket 一次握手之后双向自由推送文本帧本身就是为 MUD 的命令-回显模型设计的。连接方式连接模型实时性数据形态telnet传统 MUD长连接23 端口好原始 ASCII 文本流HTTP 轮询短连接反复建连差JSON / HTMLWebSocketH5mud长连接一次握手好文本帧 / JSON选 WebSocket 的本质原因是它保留了 telnet 时代的交互时序又把入口从终端换成了浏览器。这也解释了为什么这套资源的服务器端往往有两层一层提供静态网页让玩家打开登录界面另一层是 WebSocket 网关负责把浏览器发来的指令转交给背后的游戏驱动再把驱动生成的文本推回页面。2.3 服务器端文件的大致分工以我拆过这类打包资源的经验解压后核心目录一般长这样目录 / 文件职责server / driver游戏驱动管连接和指令分发lib / mudlib游戏规则层房间、角色、战斗逻辑world / data世界数据与玩家存档web / static浏览器端页面与 WebSocket 客户端脚本config*端口、数据路径、日志级别等配置这里值得多说一句web目录只是门面真正的游戏逻辑全部在服务端。玩家在网页里输入look、north这些指令从浏览器通过 WebSocket 发到服务器由驱动执行后把文本结果推回页面。所以服务器一关网页再漂亮也没用。这也是为什么这类资源最终要落到服务器能稳定跑多久上。2.4 架设之前先确认环境无论是 Linux 服务器还是 Windows先花两分钟确认运行环境。H5mud 的服务器端通常跑在 Node.js 上依赖版本在包内的package.json里写得很清楚我第一次拿到资源时没看 Node 版本直接启动结果驱动报了一堆 API 不存在的错纯属自找的。node -v npm -vv18.17.1 9.6.7第一行确认 Node 大版本第二行确认 npm。如果 Node 版本低于 12某些流控制和 WebSocket 库会直接罢工建议装 Node 16 以上。接着看端口占用情况MUD 服务器最常见的默认端口是 4000网页和 4001WebSocket有些打包版本还会带 23 端口做 telnet 兼容。ss -lntp | grep -E :4000|:4001|:23这条命令在 Linux 上列出监听端口的进程。正常情况下无输出说明端口干净。如果有输出记住 PID后面启动撞了端口再回来杀这一步只是摸底。提示包里的package.json会写清依赖版本第一次启动前务必确保npm install执行过否则会报模块找不到。3. 直接架设解压、改配置、启动、进游戏跑通全流程3.1 解压与目录核对拿到资源包后第一件事不是解压就启动而是先看目录结构确认它是不是完整包。有的版本会把世界数据单独拆出去少了数据文件即便启动成功也是空世界。tar -xzf h5mud-server.tar.gz cd h5mud-server ls -latotal 88 drwxr-xr-x 9 root root 4096 Jul 15 10:22 config drwxr-xr-x 6 root root 4096 Jul 15 10:22 lib drwxr-xr-x 4 root root 4096 Jul 15 10:22 web drwxr-xr-x 3 root root 4096 Jul 15 10:22 world -rw-r--r-- 1 root root 1024 Jul 15 10:22 package.json -rw-r--r-- 1 root root 2048 Jul 15 10:22 server.js如果world目录是空的别往下配了先去把数据文件补齐。server.js是总入口web里放着玩家打开网页时加载的资源world里是地图数据与存档空间。正常包解压出来这几个目录必须同时存在缺任何一个都不能算可直接架设。3.2 配置端口与数据目录我最常被问到的问题之一是能不能换个端口。能参数集中在 config 目录下。以常见的config.json为例核心字段如下{ webPort: 4000, wsPort: 4001, telnetPort: 23, dataDir: ./data, logLevel: info }参数含义注意webPort网页服务端口玩家浏览器访问入口wsPortWebSocket 端口必须能被外部访问防火墙要放行telnetPorttelnet 兼容端口有些包不带看实际版本dataDir玩家存档目录建议改成绝对路径见第 4 章避坑logLevel日志级别debug 模式能看每帧收发内容改完配置后注意一件事dataDir我强烈建议改成绝对路径比如/opt/h5mud/data不要用相对路径。原因是如果你之后用 systemd 或 Docker 管理服务工作目录一变相对路径就把存档写丢了。这个坑我踩过一次角色练到 20 级重启后全没了。3.3 安装依赖并启动依赖是跑起来的前提。Node.js 项目的依赖声明在package.json直接用 npm 安装npm install npm startnpm install会把依赖装到本地的node_modules这一步不能跳过否则启动报找不到ws模块。npm start对应package.json里的scripts.start实际执行的是node server.js。启动后日志会打印监听端口看到类似listening on 4000的输出就说明驱动起来了。ss -lntp | grep -E :4000|:4001招输出里能看到node进程同时监听 4000 和 4001这就说明网页服务和 WebSocket 网关都在跑。如果只有 4000 没有 4001说明 WebSocket 服务启动失败最常见原因是wsPort被占用回头查第 4 章。3.4 浏览器进游戏完整走一遍服务器起来后本机先验证打开浏览器访问http://localhost:4000页面上会看到登录界面。第一次进入直接输入一个玩家名系统会提示创建角色还是登录已有角色。进入游戏后依次输入look这是一个简陋的村庄入口西边是药铺北边是一条通往森林的小路。 向北可以进入森林向西南是集市。能正常回显房间描述说明 WebSocket 这一路通了。再试着走两步north如果服务器返回新的房间描述恭喜地图和移动逻辑都没问题。局域网内的朋友访问时把地址换成服务器的内网 IPhttp://192.168.1.100:4000。这里最容易翻车的是防火墙默认拦截 Node.js 的入站连接后面避坑章细说。3.5 telnet 兼容接入验证部分版本的 H5mud 服务器端会保留传统 telnet 入口端口见配置里的telnetPort。如果这个端口开着可以用终端直接连telnet 192.168.1.100 23连接成功后同样走输入玩家名→创建角色→look的流程。文字 MUD 的老玩家都很吃这一套毕竟能兼容 ZMUD、MUSHclient 这些经典客户端等于把二十年前的生态接回来了。但要注意如果 H5mud 的前端交互用了比较复杂的菜单选择逻辑telnet 文本流未必能完整还原点击行为更多是验证服务器能力用实际玩家大概率还是在浏览器里玩。4. 架设避坑五条血泪经验按现象→原因→解决排查4.1 中文乱码Windows 命令行里全成锟斤拷现象在 Windows Server 上启动后控制台日志全乱码游戏内中文描述也变成一堆替换字符。原因H5mud 源码和世界数据按 UTF-8 存储Windows 默认的 cmd 代码页是 GBKcp936两者编码不匹配文本流到控制台就崩了。解决启动前切换代码页chcp 65001 npm startchcp 65001把控制台代码页切到 UTF-8。如果嫌每次手动输入麻烦写一个start.bat第一行放chcp 65001 nul再npm start。Linux 和 macOS 没有这个问题只有 Windows 需要额外注意。4.2 局域网用户连不上防火墙把 WebSocket 端口挡了现象本机能打开网页局域网其他机器访问http://服务器IP:4000能出页面但进入游戏后始终收不到房间描述页面卡在连接中。原因网页服务4000可能碰巧被防火墙放行但 WebSocket 用的 4001 端口被系统防火墙拦截。浏览器能加载页面是因为 4000 的 HTTP 请求过去了WebSocket 握手走 4001被防火墙静默丢弃。解决放行 WebSocket 端口。Windows 上用管理员执行netsh advfirewall firewall add rule nameH5mud WS dirin actionallow protocolTCP localport4001Linux 上如果用了 firewalldfirewall-cmd --permanent --add-port4001/tcp firewall-cmd --reload加完还要确认云服务商的安全组规则阿里云、腾讯云这些厂商的机器系统防火墙之外还有一层安全组需要去控制台单独放行 TCP 4001。这一步容易漏我见过有人本机跑得好好的服务器一上线就断最后发现是安全组没加。4.3 Nginx 反代导致 WebSocket 握手失败现象服务器前面挂了 Nginx 做反向代理网页能打开但 WebSocket 连接一握手就失败浏览器控制台报 400 Bad Request。原因Nginx 默认不转发Upgrade和Connection请求头WebSocket 握手需要这两个头才能完成协议升级。没有它们Nginx 把请求当普通 HTTP 处理握手必然失败。解决给 WebSocket 对应的 location 加上代理头配置location /ws { proxy_pass http://127.0.0.1:4001; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_read_timeout 3600s; }proxy_http_version 1.1必须配HTTP/1.0 不支持升级协议。proxy_read_timeout建议调到 3600 秒以上MUD 玩家可能在游戏里挂机半天不动超时太短会被 Nginx 断连。4.4 重启后角色数据消失dataDir 用了相对路径现象正常玩了一晚上角色练到好几级重启服务器后登录发现角色不存在world 目录下存档文件也没了。原因配置里dataDir写的是./data工作目录如果在 systemd 服务里被改成了别处相对路径指向的就变成另一个目录存档写到了看不见的地方。解决把dataDir改成绝对路径并在启动前手动建好目录mkdir -p /opt/h5mud/data然后编辑配置{ dataDir: /opt/h5mud/data }改完后重启再登录验证一次角色是否还在。从那以后我拿到任何 MUD 包第一件事就是把所有涉及路径的配置全部改成绝对路径绝不给相对路径留机会。4.5 端口起不来EADDRINUSE 是旧进程没退干净现象执行npm start报Error: listen EADDRINUSE: address already in use :::4001服务起不来。原因上次启动的 node 进程没有正常退出还占着端口。常见于用了CtrlC之后进程没被杀干净或者之前有多个server.js实例在跑。解决找到占用端口的进程并结束lsof -i :4001 kill -9 PIDss -lntp | grep 4001lsof -i :4001拿到 PID 后kill -9。之后重新npm start确认日志输出没有 EADDRINUSE 字样。严谨一点的做法是在启动脚本前加一句检查端口是否占用的断言但我一般直接用pkill -f server.js批量清掉旧实例简单粗暴。5. 进阶黑盒验证 WebSocket 协议、telnet 互通与机器人压测5.1 不打开浏览器用脚本验证服务器活着服务器运维场景下快速确认服务是否正常不能靠人肉开浏览器。写一个最小的 WebSocket 冒烟脚本定时去连服务器能收到响应就认为存活。Python 端用websockets库import asyncio import websockets async def smoke(): uri ws://127.0.0.1:4001 async with websockets.connect(uri) as ws: await ws.send({cmd:look}) frame await asyncio.wait_for(ws.recv(), timeout5) print(frame) asyncio.run(smoke())注意消息格式要对照包内web目录下的 client.js 来定不同版本指令的字段名不一样。有的版本用{cmd:look}有的用{type:command,data:look}。以客户端源码为准不要自己猜。脚本里asyncio.wait_for加 5 秒超时就是为了防服务器假活——连接建立但没响应。之后配 crontab 定时跑这个脚本输出异常就告警比盯日志靠谱。5.2 浏览器与 telnet 双通道共存如果服务器端同时开放了 WebSocket 和 telnet 端口可以做个有意思的验证开一个浏览器窗口再用 telnet 连同一个服务器两边登录不同角色互发say消息确认两个通道走的是同一个游戏世界。这一步能直接检验服务器的事件推送能力——telnet 端说话浏览器端能不能实时收到。正常情况下两边都会立刻刷出频道消息。如果浏览器端延迟明显说明 WebSocket 网关在广播消息时性能有瓶颈检查 4001 端口的连接数是否过高。5.3 机器人刷图验证服务器边界最实用的是用脚本模拟多个玩家连续进出房间验证服务器在并发下的表现。我一般写一个循环建十个 WebSocket 连接每个连接控制角色在地图里移动import asyncio import websockets async def walker(name): uri ws://127.0.0.1:4001 async with websockets.connect(uri) as ws: await ws.send(f{{cmd:login,name:{name}}}) for _ in range(20): await ws.send({cmd:north}) await asyncio.sleep(0.1) async def main(): tasks [walker(fbot{i}) for i in range(10)] await asyncio.gather(*tasks) asyncio.run(main())10 个角色同时跑 20 次移动命令总共 200 步。如果服务器端日志没有报错、内存占用没有持续暴涨基本能说明这台机器带个小团队玩没压力。我的经验是 MUD 这种文本游戏带宽占用极低瓶颈通常在驱动对定时器和对象调度的处理上所以压测时重点观察 CPU 而不是网络。这一步也验证了服务器对批量会话的优雅程度角色全部退出后存档是否完整写入。每次压测完我都会重登一个 bot 角色确认它走到的位置还在防止存档丢帧。那次之后我架设任何带 WebSocket 网关的 MUD 服务都强制先跑一遍冒烟脚本再加机器人压测确认存档落盘才让人进服这套流程替我挡掉了至少三次数据丢失事故。希望帮到你。本文还有配套的精品资源点击获取