mirror of
https://github.com/LHY0125/Gobang-Game.git
synced 2026-06-29 00:45:55 +08:00
docs: 网络对战功能设计文档
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
# Gobang 网络对战设计文档
|
||||
|
||||
> 状态: 已确认 | 日期: 2026-05-31
|
||||
|
||||
## 目标
|
||||
|
||||
为 Gobang v2.0 实现基于 renet 的 P2P 网络对战,两人通过 IP:端口直连对弈。
|
||||
|
||||
## 架构
|
||||
|
||||
```
|
||||
┌─ React 前端 ───────────────────────────────────────────┐
|
||||
│ OnlineSetup GameView │
|
||||
│ 创建房间/加入房间 连接状态指示 │
|
||||
│ listen("remote-move") │
|
||||
└─────────────────────┬───────────────────────────────────┘
|
||||
│ invoke / listen
|
||||
┌─ Tauri IPC ─────────┼───────────────────────────────────┐
|
||||
│ commands.rs │ │
|
||||
│ host_game(port) │ 对手落子 → │
|
||||
│ join_game(ip,port) │ app.emit("remote-move") │
|
||||
│ send_move(x,y) │ │
|
||||
│ send_undo() │ AppState.network_tx │
|
||||
│ send_resign() │ channel 发送端 │
|
||||
└─────────┬────────────┴──────────────────────────────────┘
|
||||
│ mpsc::channel (NetworkCmd / NetworkEvent)
|
||||
┌─ 网络线程 ──────────────────────────────────────────────┐
|
||||
│ NetworkLoop │
|
||||
│ Server: RenetServer + NetcodeServerTransport │
|
||||
│ Client: RenetClient + NetcodeClientTransport │
|
||||
│ │
|
||||
│ loop { update → recv → process → send_packets } │
|
||||
│ 16ms 帧率,消息通过 channel 与 commands 层通信 │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 通信模型
|
||||
|
||||
renet 内置 Server/Client。主机运行 RenetServer,对手作为 RenetClient 连接。所有消息经主机转发。
|
||||
|
||||
### 消息协议
|
||||
|
||||
网络传输使用 serde JSON + renet ReliableOrdered 通道:
|
||||
|
||||
```rust
|
||||
enum NetMessage {
|
||||
Move { x: usize, y: usize, turn: u32 },
|
||||
Undo { steps: u32 },
|
||||
Resign,
|
||||
}
|
||||
```
|
||||
|
||||
### Channel 接口
|
||||
|
||||
```rust
|
||||
// commands → 网络线程
|
||||
enum NetworkCmd {
|
||||
SendMove { x: usize, y: usize, turn: u32 },
|
||||
SendUndo { steps: u32 },
|
||||
SendResign,
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
// 网络线程 → commands
|
||||
enum NetworkEvent {
|
||||
RemoteMove { x: usize, y: usize },
|
||||
RemoteUndo { steps: u32 },
|
||||
RemoteResign,
|
||||
ClientConnected,
|
||||
ClientDisconnected,
|
||||
Error(String),
|
||||
}
|
||||
```
|
||||
|
||||
## 连接流程
|
||||
|
||||
```
|
||||
主机 (Server) 对手 (Client)
|
||||
host_game(port)
|
||||
绑定 UDP "0.0.0.0:{port}"
|
||||
NetworkLoop::Server 启动
|
||||
返回实际端口
|
||||
emit("waiting") ───────────────────→ 对手 join_game(ip, port)
|
||||
bind UDP "0.0.0.0:0"
|
||||
NetworkLoop::Client 启动
|
||||
connect to server ──→
|
||||
← connected ─────────
|
||||
收到 ClientConnected
|
||||
emit("opponent-joined") ←──────────→ emit("connected")
|
||||
|
||||
游戏开始,黑方(主机)先手正常落子
|
||||
place_piece → NetworkCmd::SendMove ─→ broadcast ─→ client recv
|
||||
NetworkEvent::RemoteMove
|
||||
invoke place_piece
|
||||
```
|
||||
|
||||
## 生命周期
|
||||
|
||||
- 网络线程在 `new_game(Online)` 时 spawn
|
||||
- 游戏结束或 AppState drop 时:发送 Shutdown → 线程退出 → join
|
||||
- 对手断开:主机的 ClientDisconnected event → emit 对手获胜
|
||||
|
||||
## 前端改动
|
||||
|
||||
### OnlineSetup
|
||||
- 创建房间:输入端口号(可选,默认随机),显示"我的地址: IP:端口"
|
||||
- 加入房间:输入"IP:端口",连接
|
||||
|
||||
### GameView — 新增连接状态条
|
||||
- 等待中:显示"等待对手加入... (你的地址: IP:端口)"
|
||||
- 已连接:显示"已连接"
|
||||
- 已断开:显示"对手断开连接" + 对手获胜
|
||||
|
||||
### BoardCanvas — 监听 remote-move
|
||||
```typescript
|
||||
useEffect(() => {
|
||||
const unlisten = listen<{ x: number; y: number }>('remote-move', (event) => {
|
||||
placePiece(event.payload.x, event.payload.y);
|
||||
});
|
||||
return () => { unlisten.then(fn => fn()); };
|
||||
}, []);
|
||||
```
|
||||
|
||||
### GameControls
|
||||
- Online 模式:不显示悔棋(需双方同意,暂不做)
|
||||
- 认输:调用 send_resign
|
||||
|
||||
## AppState 改动
|
||||
|
||||
```rust
|
||||
pub struct AppState {
|
||||
// ... 现有字段 ...
|
||||
pub network_tx: Mutex<Option<Sender<NetworkCmd>>>,
|
||||
}
|
||||
```
|
||||
|
||||
## 依赖
|
||||
|
||||
```toml
|
||||
# core/Cargo.toml & gui/Cargo.toml
|
||||
renet = { version = "0.0.23", features = ["netcode"] }
|
||||
renet_netcode = "0.0.15"
|
||||
serde_json = "1" # 已有
|
||||
```
|
||||
|
||||
## 不做 (YAGNI)
|
||||
|
||||
- Chat 功能(NetMessage 保留类型但无 UI)
|
||||
- NAT 穿透 / 中转服务器
|
||||
- 断线重连
|
||||
- 观战模式
|
||||
- 悔棋双方确认(Online 模式直接禁悔棋)
|
||||
|
||||
## 测试策略
|
||||
|
||||
- Rust 单元测试:NetMessage serde 往返、NetworkCmd/Event channel 通信、NetworkLoop::new 创建
|
||||
- 集成测试:renet 本地 client 模拟(server.new_local_client)
|
||||
- 前端测试:OnlineSetup 组件渲染、状态文本切换
|
||||
- 手动测试:双窗口(host + join localhost)
|
||||
Reference in New Issue
Block a user