Files
OnlineRpg/系统架构设计.md
ChuXun e287aadd3c 1
2025-10-26 16:37:22 +08:00

111 lines
7.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# **1\. 系统架构图 (C/S 架构)**
\+-------------------------------------------------------------------------+
| \[ 客户端 A (Console) \] |
| \+--------------------+ \+--------------------+ |
| | GameClient | | 主线程 (Input) | |
| | (负责网络通信) | | (发送聊天/指令) | |
| \+--------------------+ \+--------------------+ |
| | SocketWrapper | | 接收线程 (Recv) | |
| | (封装Socket API) | | (打印聊天/战报) | |
| \+--------------------+ \+--------------------+ |
\+-------------^----------------------------------+ |
| (TCP/IP) |
| |
\+-------------v----------------------------------+ |
| \[ 客户端 B (Console) \] |
| (结构同 A) |
\+-------------^----------------------------------+ |
| (TCP/IP) |
| |
\+-------------v-----------------------------------------------------------+
| \[ 服务器 (GameServer Console) \] |
| |
| \+---------------------+ \+-----------------------------------------+ |
| | GameServer (主线程) | | \[ 线程池 / 并发管理 \] | |
| | (Socket, Bind, Listen)| | | |
| | (Loop: Accept) | | \+-----------------+ \+-----------------+ | |
| | | | | ClientHandler A | | ClientHandler B | | |
| | (管理所有 Client) | | | (Thread A) | | (Thread B) | | |
| | (std::map\<fd, Ptr\>)| | \+-----------------+ \+-----------------+ | |
| \+----------^----------+ \+---------^---------------+---------^-----+ |
| | | (Lobby/Battle) | |
| | | | |
| \+----------v----------+ \+---------v---------------+ | |
| | GameLobby (单例) | | BattleRoomManager | | |
| | (std::map\<name, Ptr\>)| | (管理所有战斗房间) | | |
| | (负责聊天/邀请) | | (std::map\<id, Ptr\>) | | |
| \+---------------------+ \+-----------------------+ | |
| | |
| \+-------------------------------v-------+ |
| | \[ 数据库接口 (Database) \] | |
| | (封装 SQLite API) | |
| | (使用 Mutex 保证线程安全) | |
| \+-------------------^-------------------+ |
| | |
\+---------------------------------------------------+---------------------+
|
\+---v---+
| DB |
| (users.db)|
\+-------+
# **2\. 关键组件职责**
1. **GameClient (客户端)**
* 负责连接服务器。
* **必须**使用多线程:一个线程(主线程)负责捕获用户输入 (cin) 并 send另一个线程子线程负责阻塞 recv 并打印服务器消息 (cout)。
* 负责提供控制台的菜单和界面。
2. **GameServer (服务器)**
* 负责监听端口 (listen) 和接受新连接 (accept)。
* 每接受一个新连接,**必须**创建一个 ClientHandler 实例,并在一个**新线程 (std::thread)** 中运行它。
* **必须**使用 std::map (STL) 来存储所有 ClientHandler 的指针或引用,以便管理。
* **必须**使用 std::mutex (STL) 来保护这个 map防止多线程冲突。
3. **ClientHandler (服务器)**
* 在独立的线程中运行,代表一个已连接的客户端。
* 负责该客户端的 recv 循环,解析客户端发来的命令 (使用 Protocol.h)。
* 根据命令,调用 GameLobby (聊天/邀请) 或 BattleRoomManager (战斗) 的功能。
* 负责处理该客户端的异常掉线,并通知 GameServer 将自己从 map 中移除。
4. **GameLobby (服务器)**
* 管理所有处于“大厅”状态的玩家。
* 实现 broadcastMessage() (广播聊天),需要加锁 (std::mutex) 遍历 GameServer 的客户端 map 并发送。
* 实现 handleInvite() (处理邀请逻辑)。
5. **BattleRoom (服务器)**
* 负责处理一场 1v1 战斗。
* 持有**多态**的 ICharacter\* 指针。
* 持有**模板+链表**实现的 HistoryLog\<string\> 实例,用于记录战报。
* 实现 runTurn() 战斗循环逻辑,调用 ISkill 的 execute 方法。
6. **Database (服务器)**
* 封装 SQLite3 的 C API。
* 提供上层易用的接口bool registerUser(user, pass)等。
* **必须**保证是线程安全的(例如,对所有数据库写操作使用一个全局 std::mutex
# **3\. 关键数据流**
## **3.1. 数据流玩家A 发送大厅聊天**
1. **\[Client A\]**:主线程 cin 捕获输入 "Hello"。
2. **\[Client A\]**GameClient 将其打包为 "CHAT|Hello",通过 SocketWrapper::send() 发出。
3. **\[Server\]**ClientHandler A (线程A) 的 recv() 循环收到数据。
4. **\[Server\]**ClientHandler A 解析出是 CHAT 命令。
5. **\[Server\]**ClientHandler A 调用 GameLobby::broadcastMessage("A: Hello")。
6. **\[Server\]**GameLobby **加锁**访问 GameServer 的客户端 map。
7. **\[Server\]**GameLobby 遍历 map对所有**非战斗中**的 ClientHandler (如 B, C, D) 调用 send("MSG|A: Hello")。
8. **\[Client B,C,D\]**:接收线程 (子线程) 的 recv() 收到消息cout 打印 "A: Hello" 到控制台。
## **3.2. 数据流玩家A 攻击 玩家B (战斗中)**
1. **\[Server\]**BattleRoom (线程C) 判定轮到 A 行动。
2. **\[Server\]**BattleRoom 向 ClientHandler A (线程A) 发送 "TURN|YOUR\_TURN"。
3. **\[Client A\]**:接收线程收到 "TURN|YOUR\_TURN"cout 打印 "轮到你行动"。
4. **\[Client A\]**:主线程 cin 捕获输入 "attack B"。
5. **\[Client A\]**GameClient 打包为 "BATTLE|USE\_SKILL|Fireball|B"send() 发出。
6. **\[Server\]**ClientHandler A (线程A) 收到数据,解析后调用 BattleRoom::handleAction("A", "Fireball", "B")。
7. \[Server\]BattleRoom (线程C) 加锁(防止多线程同时修改战斗状态),执行战斗逻辑:
a. ICharacter\* charA \= ...;
b. ISkill\* skill \= charA-\>getSkill("Fireball");
c. skill-\>execute(charA, charB); (多态调用)
d. string log \= "A 对 B 使用了\[火球\]...";
e. m\_historyLog.add(log); (模板+链表调用)
8. **\[Server\]**BattleRoom (线程C) 将战报 log 广播给 ClientHandler A 和 ClientHandler B。
9. **\[Client A, B\]**:接收线程收到 logcout 打印战报。