# game-hub **Repository Path**: kimstack/game-hub ## Basic Information - **Project Name**: game-hub - **Description**: No description available - **Primary Language**: Unknown - **License**: AGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-11 - **Last Updated**: 2026-09-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # game-hub · 轻量多人匿名网页游戏大厅 单进程、全内存、零账户体系的网页游戏大厅。为 **2C2G / 3Mbps 小机、同时在线 ≤ 10 人** 的场景优化:首页列出所有已接入的游戏,点击即玩,无需注册登录。 ## 特性 - **免账户**:HttpOnly Cookie 随机 token(`gt`,32 hex)+ IP 区分玩家,首次访问自动发放 - **单进程单端口**:HTTP 静态资源 + `/api/*` + WebSocket 大厅共用一个端口(默认 8080) - **全内存房间**:房间按需创建、空房自动销毁,无需数据库 - **插件化游戏**:每款游戏 = 服务端一个目录 + 客户端一个目录,放入即被自动扫描加载 - **省资源**:唯一运行时依赖是 `ws`;静态资源 gzip 预压缩 + 内存缓存;常驻内存 < 150MB ## 目录结构 ``` game-hub/ ├── server/ │ ├── index.js # 入口:HTTP + 静态资源 + WS 路由 + 游戏注册表 │ ├── lobby.js # 大厅:房间管理 / 匹配 / 限流 / 心跳清理 │ └── games/ │ ├── README.md # 游戏模块契约(写新游戏先读这个) │ ├── echo/ # 示例游戏「回声广场」 │ ├── mahjong/ # 大众麻将(server.js / rules.js / ai.js / board.js) │ └── tank/ # 铁甲战场(server.js / board.js) ├── public/ │ ├── index.html # 首页:游戏列表 │ ├── js/net.js # 公共网络库:new Net(gameId[, roomId]) │ └── games// # 各游戏客户端页面 ├── tools/ # 自测脚本(无头压测 / 端到端 / 规则自测) ├── data/ # 排行榜持久化(board.json / board-tank.json) ├── deploy.sh # Ubuntu 22.04 一键部署(幂等) ├── MAHJONG.md # 麻将规则与番型表 └── TANK.md # 坦克玩法与改造说明 ``` ## 已接入游戏 | 游戏 | id | 说明 | |---|---|---| | 大众麻将 | `mahjong` | 四人计番制麻将,8 番起胡,人机补位、排队顶替、满员围观(可见底牌 + 弹幕),四类排行榜 | | 铁甲战场 | `tank` | 巷子迷宫四向坦克对战,砖墙可打穿,补给型人机掉道具,单局最高分 + 累计击杀榜 | | 回声广场 | `echo` | 示例插件,演示游戏契约的最小实现 | ## 快速开始 本地运行(Node.js ≥ 20): ```bash npm ci npm start # 默认 :8080,PORT=3000 npm start 可改端口 ``` 浏览器打开 `http://localhost:8080`,首页即为游戏列表。 ## 部署(Ubuntu 22.04) ```bash # 把整个 game-hub 目录上传到服务器后: chmod +x deploy.sh ./deploy.sh # 默认端口 8080 PORT=80 ./deploy.sh # 自定义端口 ``` 脚本幂等,重复执行 = 更新代码 + 重启服务。流程:安装 Node 22 → 建低权用户 `gamehub` → 同步代码到 `/opt/game-hub` → `npm ci --omit=dev` → 写 systemd 单元(`Restart=always`、`MemoryMax=512M`)→ ufw 放行 → 健康检查。 常用运维命令: ```bash journalctl -u game-hub -f # 看日志 systemctl restart game-hub # 重启 ``` ## HTTP 接口 | 接口 | 说明 | |---|---| | `GET /api/games` | 游戏列表(动态扫描,含各游戏实时在线人数) | | `GET /api/board?game=` | 排行榜,转发给游戏模块的 `getBoard()`(mahjong / tank 已实现) | | `GET /games//` | 游戏页面(静态目录自动补 `index.html`) | | `WS /ws?game=&room=` | 进入游戏;无 `room` 自动匹配公共房,有 `room` 进私房 | ## 写一款新游戏 只需两个目录,服务启动时自动扫描加载,详见 [`server/games/README.md`](server/games/README.md): 1. **服务端** `server/games//server.js`,导出契约接口: ```js module.exports = { name: '游戏名', desc: '一句话简介', maxPlayers: 8, tickHz: 15, hidden: false, createState() {}, // 房间初始状态 onJoin(state, player, api) {}, // 玩家进房 onMessage(state, player, msg, api) {},// 收到玩家消息(JSON 已解析) onLeave(state, player, api) {}, // 玩家离房 tick(state, dt, api) {} // 逻辑帧 }; ``` 2. **客户端** `public/games//index.html`,用公共库连接: ```js const net = new Net(''); // 私房:new Net('', roomId) net.ready(() => net.send({ t: 'hi' })); net.on(msg => { /* ... */ }); ``` 连上后大厅自动下发 `{ t: 'hello', id, room, players }`。 ## 带宽纪律(3Mbps 小机,写游戏必读) - 快照 ≤ 1.5KB/帧,tick ≤ 15Hz;消息用短键名 JSON(`t`/`x`/`y`) - 客户端输入节流 ≤ 20 次/秒;为 0 / 为默认值的字段不写键名 - 地图、皮肤等静态数据随 welcome 发一次,快照里只发索引 - **实体多的游戏必须按视野裁剪**:客户端上报视口(`vw`/`vh`),服务端用 `player.send()` 逐个下发,不要全量广播(坦克实测:全量 10 人 ~4.5Mbps 会爆带宽,裁剪后 0.55~0.85Mbps) ## 大厅机制 - 每玩家 40 msg/s 令牌桶限流;单条 WS 消息上限 16KB - 30s 心跳断线清理;每游戏最多 20 个房间 - 排行榜按匿名 token 累计,落盘 `data/*.json`(合并写盘,进程退出前强制落盘) ## 自测工具 ```bash node tools/rules-selftest.js # 麻将规则自测 node tools/mahjong-sim.js 10 # 麻将无头模拟 10 局 node tools/e2e-test.js 8100 # 麻将端到端(真实 HTTP + WS) node tools/tank-test.js 10 120 # 坦克无头压测(逻辑 + 带宽 + CPU) node tools/tank-e2e.js 8123 # 坦克端到端 ``` ## 演进路线 HTTPS(Caddy)→ 增量快照 / 二进制协议(带宽紧张时)→ SQLite(数据量起来后替换 JSON 榜单)