16 KiB
16 KiB
Net-Games API 接口文档
版本: v2.0
更新日期: 2026-04-09
服务端: Flask-SocketIO on port 8900
1. HTTP REST API
1.1 认证相关
GET /api/auth/status - 检查登录状态
响应:
{
"authenticated": true,
"user": {
"id": 1,
"username": "caixianming",
"nickname": "蔡叔叔",
"created_at": "2026-04-01T10:00:00",
"role": "user",
"is_admin": false
}
}
POST /api/auth/login - 用户登录
请求:
{
"username": "caixianming",
"password": "cxm123456"
}
响应:
{
"success": true,
"message": "登录成功",
"user": {
"id": 1,
"username": "caixianming",
"nickname": "蔡叔叔",
"role": "user",
"is_admin": false
}
}
POST /api/auth/register - 用户注册
请求:
{
"username": "newuser",
"password": "password123"
}
响应:
{
"success": true,
"message": "注册成功",
"user": {...}
}
POST /api/auth/logout - 用户登出
响应:
{
"success": true,
"message": "已登出"
}
1.2 用户相关
GET /api/user/profile - 获取个人资料
响应:
{
"success": true,
"user": {
"id": 1,
"username": "caixianming",
"nickname": "蔡叔叔",
"created_at": "2026-04-01T10:00:00"
}
}
PUT /api/user/profile - 更新昵称
请求:
{
"nickname": "新昵称"
}
PUT /api/user/password - 修改密码
请求:
{
"old_password": "旧密码",
"new_password": "新密码"
}
GET /api/user/scores - 获取各游戏积分
响应:
{
"success": true,
"scores": {
"doudizhu": 100,
"chinese_chess": 50
}
}
1.3 房间相关
GET /api/rooms - 获取房间列表
查询参数:
game_type- 游戏类型过滤 (可选)status- 状态过滤: waiting/playing (默认: waiting)
响应:
{
"success": true,
"rooms": [
{
"id": "room_xxx",
"code": "A1B2C3",
"game_type": "doudizhu",
"status": "waiting",
"max_players": 3,
"player_count": 1,
"host_id": "player_xxx",
"created_at": 1234567890,
"players": [...]
}
]
}
GET /api/rooms/<room_code> - 获取房间信息
响应:
{
"success": true,
"room": {
"id": "room_xxx",
"code": "A1B2C3",
"game_type": "doudizhu",
"status": "playing",
"players": [...],
"game": {...}
}
}
1.4 统计相关
GET /api/stats - 获取服务统计(公开)
响应:
{
"success": true,
"stats": {
"total_rooms": 10,
"waiting_rooms": 3,
"playing_rooms": 7,
"total_players": 21
}
}
GET /api/admin/stats - 管理员详细统计
响应:
{
"success": true,
"stats": {
"total_rooms": 10,
"waiting_rooms": 3,
"playing_rooms": 7,
"total_players": 21,
"online_users": 15,
"by_game": {
"doudizhu": {...}
},
"rooms": [...]
}
}
DELETE /api/admin/rooms/<room_code> - 强制关闭房间
响应:
{
"success": true,
"message": "房间 A1B2C3 已关闭"
}
2. Socket.IO 事件
2.1 连接管理
connect - 客户端连接
服务端响应:
{
"event": "connected",
"data": {
"socket_id": "xxx",
"message": "欢迎连接到 Net-Games",
"has_active_game": true,
"room_code": "A1B2C3",
"room_id": "room_xxx"
}
}
disconnect - 客户端断开
- 服务端自动处理,标记玩家为离线
- 30秒后启用AI托管
ping / pong - 心跳
客户端发送:
{
"event": "ping",
"data": {"timestamp": 1234567890}
}
服务端响应:
{
"event": "pong",
"data": {
"timestamp": 1234567890,
"server_time": 1234567890
}
}
2.2 房间管理事件
create_room - 创建房间
客户端发送:
{
"game_type": "doudizhu",
"player_name": "蔡叔叔",
"config": {
"max_players": 3
},
"ai_players": [
{"name": "AI-规则", "ai_type": "rule"},
{"name": "AI-DeepSeek", "ai_type": "deepseek"}
]
}
服务端响应 (创建者):
{
"event": "room_created",
"data": {
"success": true,
"room": {
"id": "room_xxx",
"code": "A1B2C3",
"game_type": "doudizhu",
"status": "waiting",
"max_players": 3,
"player_count": 3,
"host_id": "player_xxx",
"players": [...]
},
"player": {
"id": "player_xxx",
"name": "蔡叔叔",
"seat_number": 0,
"is_ready": false
}
}
}
错误响应:
{
"event": "error",
"data": {
"code": "ALREADY_ONLINE",
"message": "账号 \"蔡叔叔\" 已在游戏中"
}
}
join_room - 加入房间
客户端发送:
{
"room_code": "A1B2C3",
"player_name": "玩家B"
}
服务端响应 (加入者):
{
"event": "room_joined",
"data": {
"success": true,
"room": {...},
"player": {...}
}
}
广播 (其他玩家):
{
"event": "player_joined",
"data": {
"player": {
"id": "player_yyy",
"name": "玩家B",
"seat_number": 1,
"is_ready": false
}
}
}
leave_room - 离开房间
服务端响应 (离开者):
{
"event": "room_left",
"data": {"success": true}
}
广播 (其他玩家):
{
"event": "player_left",
"data": {
"player_id": "player_xxx",
"player_name": "蔡叔叔"
}
}
reconnect_room - 断线重连
客户端发送:
{
"room_code": "A1B2C3",
"player_id": "player_xxx",
"player_name": "蔡叔叔"
}
服务端响应 (重连者):
{
"event": "reconnect_success",
"data": {
"player_id": "player_xxx",
"player": {...},
"room": {...},
"was_ai_controlled": true,
"message": "重连成功,欢迎回到游戏!"
}
}
广播 (其他玩家):
{
"event": "player_reconnected",
"data": {
"player_id": "player_xxx",
"player_name": "蔡叔叔",
"was_ai_controlled": true,
"message": "蔡叔叔 已回到游戏"
}
}
2.3 游戏准备事件
set_ready - 设置准备状态
客户端发送:
{
"ready": true
}
广播 (所有人):
{
"event": "room_updated",
"data": {
"room": {...}
}
}
start_game - 开始游戏(仅房主)
广播 (所有人):
{
"event": "game_started",
"data": {
"room": {
"id": "room_xxx",
"status": "playing",
"game": {
"state": {
"phase": "playing",
"current_turn": "player_xxx",
"data": {
"phase": "calling",
"lord_id": null,
"bottom_cards": [],
"player_cards_count": {"player_xxx": 17, ...}
}
}
}
}
}
}
2.4 游戏操作事件
game_action - 游戏操作
客户端发送:
{
"action": "call",
"data": {"want": true}
}
action 类型:
call- 叫地主 (data:{want: true/false})play- 出牌 (data:{card_ids: [...]})pass- 不出/过 (data:{})toggle_trustee- 切换托管状态
成功广播 (所有人):
{
"event": "state_update",
"data": {
"action": "play",
"player_id": "player_xxx",
"result": {
"success": true,
"message": "出牌成功",
"played_cards": [...],
"card_type": {"type": "pair", "name": "对子"}
},
"game_state": {...}
}
}
失败响应 (仅操作者):
{
"event": "action_failed",
"data": {
"action": "play",
"message": "牌型不合法"
}
}
2.5 游戏结束事件
game_ended - 游戏结束广播
{
"event": "game_ended",
"data": {
"winner": {
"id": "player_xxx",
"player_id": "player_xxx",
"name": "蔡叔叔",
"is_lord": true
},
"winner_id": "player_xxx",
"room": {...},
"scores": {
"player_xxx": {
"name": "蔡叔叔",
"change": 6,
"total": 106,
"is_lord": true,
"is_winner": true,
"is_ai": false
},
"player_yyy": {
"name": "AI-规则",
"change": 0,
"total": 0,
"is_ai": true
}
}
}
}
2.6 托管与超时事件
trustee_changed - 托管状态变更
{
"event": "trustee_changed",
"data": {
"player_id": "player_xxx",
"player_name": "蔡叔叔",
"is_trustee": true,
"message": "蔡叔叔 进入了托管模式"
}
}
player_ai_controlled - 玩家被AI托管
{
"event": "player_ai_controlled",
"data": {
"player_id": "player_xxx",
"player_name": "蔡叔叔",
"reason": "timeout",
"message": "蔡叔叔 超时3次,已启用AI托管"
}
}
player_disconnected - 玩家断开连接
{
"event": "player_disconnected",
"data": {
"player_id": "player_xxx",
"player_name": "蔡叔叔",
"will_ai_control": true
}
}
turn_timeout_auto - 超时自动操作
{
"event": "turn_timeout_auto",
"data": {
"player_id": "player_xxx",
"player_name": "蔡叔叔",
"action": "pass",
"action_name": "不要",
"timeout_count": 1,
"game_state": {...},
"message": "蔡叔叔 超时,自动不要 (1/3)"
}
}
2.7 错误事件
error - 错误通知
{
"event": "error",
"data": {
"code": "NOT_YOUR_TURN",
"message": "不是你的回合"
}
}
常见错误码:
| 错误码 | 说明 |
|---|---|
NOT_IN_ROOM |
不在任何房间中 |
ROOM_NOT_FOUND |
房间不存在 |
ROOM_FULL |
房间已满 |
GAME_NOT_STARTED |
游戏未开始 |
NOT_HOST |
只有房主可以开始游戏 |
NOT_YOUR_TURN |
不是你的回合 |
ALREADY_ONLINE |
已在其他游戏中 |
INVALID_CARDS |
牌型不合法 |
CANNOT_BEAT |
管不起上家的牌 |
AI_PLAYER |
AI玩家不能进行此操作 |
3. 游戏状态结构
3.1 斗地主游戏状态
{
"room_id": "room_xxx",
"game_type": "doudizhu",
"min_players": 3,
"max_players": 3,
"player_count": 3,
"is_started": true,
"is_ended": false,
"state": {
"game_type": "doudizhu",
"room_id": "room_xxx",
"phase": "playing",
"round": 1,
"turn_count": 5,
"current_turn": "player_xxx",
"winner": null,
"player_states": {
"player_xxx": {
"name": "蔡叔叔",
"is_ai": false,
"seat": 0,
"cards": [...],
"card_count": 17
}
},
"data": {
"phase": "playing",
"current_turn": "player_xxx",
"lord_id": "player_xxx",
"bottom_cards": [...],
"desktop_cards": {
"type": "pair",
"value": 5,
"name": "对子"
},
"last_played_id": "player_yyy",
"pass_count": 0,
"player_cards_count": {
"player_xxx": 17,
"player_yyy": 15,
"player_zzz": 16
}
},
"history": [...]
},
"players": {
"player_xxx": {
"id": "player_xxx",
"name": "蔡叔叔",
"type": "human",
"is_ai": false,
"is_connected": true,
"is_ai_controlled": false,
"seat_number": 0,
"is_ready": true,
"role": "landlord"
}
}
}
3.2 玩家视角 (Player View)
客户端通过 player_view 字段只能看到自己的手牌:
{
"my_cards": [
{"id": "card_1", "suit": "spade", "rank": "A", "value": 14},
{"id": "card_2", "suit": "heart", "rank": "K", "value": 13}
],
"my_cards_count": 17
}
4. AI 接口
4.1 AI 适配器基类
class AIAdapter(ABC):
@abstractmethod
async def make_decision(self, game_state: dict,
available_actions: list,
player_context: dict) -> dict:
"""
返回决策结果
{
"action": "play" | "pass" | "call",
"data": {...},
"reasoning": "决策理由"
}
"""
pass
4.2 AI 类型
| AI类型 | 说明 | 适用游戏 |
|---|---|---|
rule |
基于规则的贪心策略 | 斗地主 |
deepseek |
DeepSeek 大模型 | 通用 |
minimax |
Minimax + Alpha-Beta | 象棋 |
4.3 AI 输入格式
{
"game_state": {
"status": "playing",
"current_turn": "ai_player_1",
"phase": "playing",
"desktop_cards": {...},
"player_cards_count": {...}
},
"available_actions": ["play", "pass"],
"player_context": {
"cards": [...],
"is_lord": false,
"teammate_cards": 17
}
}
5. 游戏流程时序图
5.1 创建房间并游戏
┌─────────┐ ┌──────────┐ ┌──────────┐
│ Client │ │ Server │ │ AI │
└────┬────┘ └────┬─────┘ └────┬─────┘
│ │ │
│ create_room │ │
│ ─────────────>│ │
│ │ create room │
│ │ add AI players │
│ room_created │ │
│ <─────────────│ │
│ │ │
│ start_game │ │
│ ─────────────>│ │
│ │ start game │
│ game_started │ │
│ <─────────────│ │
│ │ │
│ state_update │ │
│ <─────────────│ │
│ │ │
│ │ ──────────────>│
│ │ AI decision │
│ │ <──────────────│
│ │ │
│ state_update │ │
│ <─────────────│ (broadcast) │
5.2 断线重连流程
┌─────────┐ ┌──────────┐ ┌──────────┐
│ Client │ │ Server │ │ Room │
└────┬────┘ └────┬─────┘ └────┬─────┘
│ │ │
│ disconnect │ │
│ ────────X │ │
│ │ mark offline │
│ │ start 30s timer│
│ │ │
│ reconnect │ │
│ ─────────────>│ │
│ │ find player │
│ │ ──────────────>│
│ │ <──────────────│
│ │ │
│ reconnect_success │
│ <─────────────│ │
│ │ cancel timer │
│ │ │
│ (30s后如果没有重连) │
│ │ enable AI ctrl │
│ │ │
│ player_ai_controlled │
│ <─────────────│ (broadcast) │
6. 配置说明
6.1 环境变量
| 变量名 | 默认值 | 说明 |
|---|---|---|
NET_GAMES_HOST |
0.0.0.0 |
服务监听地址 |
NET_GAMES_PORT |
8900 |
服务端口 |
NET_GAMES_DEBUG |
true |
调试模式 |
DATABASE_URL |
sqlite:///./netgames.db |
数据库连接 |
DEEPSEEK_API_KEY |
- | DeepSeek API 密钥 |
LOG_LEVEL |
INFO |
日志级别 |
6.2 游戏配置 (config.py)
ROOM_MAX_PLAYERS = {
'doudizhu': 3,
'chinese_chess': 2,
}
ROOM_CODE_LENGTH = 6
ROOM_INACTIVE_TIMEOUT_MINUTES = 30
AI_TIMEOUT_SECONDS = 30
TURN_TIMEOUT_SECONDS = 30 # 回合超时
MAX_TIMEOUT_COUNT = 3 # 最大超时次数
7. 更新日志
| 日期 | 版本 | 变更内容 |
|---|---|---|
| 2026-04-09 | v2.0 | 更新为实际实现版本,添加认证API、托管机制、超时处理 |
| 2026-04-08 | v1.0 | 初始设计文档 |
文档版本: v2.0
最后更新: 2026-04-09