mirror of
https://github.com/ChuXunYu/OnlineRpg.git
synced 2026-01-31 15:35:46 +00:00
111 lines
7.7 KiB
Markdown
111 lines
7.7 KiB
Markdown
# **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\]**:接收线程收到 log,cout 打印战报。 |