# tts-like TTS-like tabletop simulator. Rule-engine: [boardgame.io](https://boardgame.io). Desktop shell: [Tauri](https://tauri.app). ## Status 🚧 Early scaffold. 已落地 5 个游戏:DragTest / War / Mill(九子棋)/ Holdem(德州扑克,2-9 人)/ DoubleUp(双升,固定 4 人)。详见 `docs/`。 ## Workspace ``` packages/ engine/ # boardgame.io re-exports + game-authoring helpers + 各游戏定义 ui/ # React UI primitives (, , , , ...) protocol/ # Shared TS types (UI schema, state shapes) server/ # Relay server (wraps boardgame.io master, /api 前缀 + 静态 serve) apps/ web/ # Vite + React SPA (含各游戏 Board 组件 + e2e) desktop/ # Tauri wrapper around apps/web build(待启动) docs/ impl.md # High-level implementation plan ui-primitives.md # UI API design dev-log/ # 按主题切的开发过程记录(做什么 → 问题 → 怎么解决) ``` ## 环境要求 - **Node.js** ≥ 22.12(推荐通过 [nvm](https://github.com/nvm-sh/nvm) 装 22.x) - **pnpm** ≥ 10.16(通过 corepack 启用,见下) - 端口:dev 默认 5173(web)+ 8000(server),生产可合并为单端口 ## 启动整个系统 ### 1. 准备环境(每台机器只需一次) ```sh # 用 nvm 装 Node 22(已装可跳过) nvm install 22 && nvm use 22 # 启用 pnpm(corepack 是 Node 自带的包管理器入口) corepack enable ``` ### 2. 安装依赖 ```sh pnpm install ``` ### 3a. 开发模式(dev,两个进程) ```sh # 终端 1:启动 boardgame.io relay server(:8000) pnpm --filter @tts-like/server dev # 终端 2:启动 vite dev server(:5173) pnpm dev ``` 打开 http://localhost:5173 → 选游戏 → "本地" 单机调试,或 "联机" 创建/加入房间。 vite proxy 自动把 `/api` 和 `/socket.io` 转发到 :8000,同源无 CORS。 ### 3b. 一键 dev(单进程,server 顺带 serve 静态) ```sh pnpm --filter @tts-like/server dev # :8000 # 另一个终端: pnpm --filter @tts-like/web build # 构建到 apps/web/dist # server 检测到 dist 后自动 serve → http://localhost:8000 直接可用(无需 vite) ``` ### 3c. 一键单端口启动(推荐,含双升等全部游戏) 根目录 `start.sh`:以 `PORT=5173` 启动 Koa,单进程同时 serve 前端页面 + `/api` + `/socket.io`,浏览器直连 `:5173`,**无需 Vite 代理**。dist 缺失会自动 build;启动前自动清理 5173/8000 残留。 ```sh ./start.sh # 打开 http://localhost:5173 ``` > 该模式与「统一端口」设计一致:Koa 在 5173 上即完整应用。公网暴露时直接映射 5173 端口即可(如 Cloudflare Tunnel / 反向代理),客户端零配置。详见 `docs/dev-log/14-double-up-game.md`「部署」一节(frp 配置不在本仓库范围内)。 ### 4. 验证(可选) ```sh pnpm -r ts # 全包类型检查 pnpm -r test # 单元测试(engine + server) pnpm test:e2e # Playwright E2E(自动起 server + web) ``` ### 5. 局域网联机 dev 模式 vite 默认监听 `0.0.0.0:5173`,server 的 origins 默认覆盖 LAN 网段(192.168 / 10 / 172.16-31 / 100.x Tailscale)。 其它设备访问 `http://<本机内网IP>:5173/` 即可加入同一房间。 ## 迁移到其它机器 把整个项目目录拷到新机器后,按顺序执行: ```sh # 1. 装 Node 22(nvm 方式) nvm install 22 && nvm use 22 # 2. 启用 pnpm corepack enable # 3. 清掉旧机器的依赖产物(不同 Node 版本 / 不同 OS 架构的 node_modules 不要跨机器拷) rm -rf node_modules packages/*/node_modules apps/*/node_modules # 4. 重装依赖 pnpm install # 5. 验证 pnpm -r ts && pnpm -r test && pnpm test:e2e # 6. 启动 pnpm --filter @tts-like/server dev # 终端 1 pnpm dev # 终端 2 ``` **注意事项:** - **不要跨机器拷 `node_modules`**:原生依赖(如 esbuild / playwright 浏览器二进制)按 OS / 架构编译,跨机器会 ABI 不匹配。新机器重新 `pnpm install`。 - **Playwright 浏览器**:首次跑 e2e 要 `npx playwright install`(下载 Chromium)。 - **房间数据是 InMemory**:server 重启会丢所有进行中的房间(boardgame.io 默认 InMemory)。要持久化需接 DB(v2 规划)。 - **生产部署**:用 `docker compose up --build`(见 `docker-compose.yml`),把 `ALLOWED_ORIGINS` 改成你的真实域名。反代(Nginx/Caddy)终止 TLS 后转发到 :8000。也可用单端口模式:构建后 `PORT=5173 ALLOWED_ORIGINS=https://你的域名 pnpm --filter @tts-like/server start`,直接映射 5173。 - **CORS**:dev 默认覆盖 LAN;生产必须用 `ALLOWED_ORIGINS` 环境变量设具体 origin 列表。 ## 设计参考 - [`docs/impl.md`](./docs/impl.md) — overall architecture and phases - [`docs/ui-primitives.md`](./docs/ui-primitives.md) — UI component API - [`docs/dev-log/README.md`](./docs/dev-log/README.md) — 开发日志索引(做什么 → 问题 → 怎么解决) ## License MIT