mirror of
https://github.com/ChuXunYu/OnlineRpg.git
synced 2026-01-31 07:01:26 +00:00
2
This commit is contained in:
130
include/client/GameClient.h
Normal file
130
include/client/GameClient.h
Normal file
@@ -0,0 +1,130 @@
|
||||
#pragma once
|
||||
#include "SocketWrapper.h"
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* @brief 游戏客户端
|
||||
*
|
||||
* 技术点:
|
||||
* 1. STL - std::thread (多线程)
|
||||
* 2. 网络编程 - Socket Client
|
||||
*
|
||||
* 设计:
|
||||
* - 主线程: 处理用户输入和发送
|
||||
* - 接收线程: 处理服务器消息接收和显示
|
||||
*/
|
||||
class GameClient {
|
||||
private:
|
||||
std::string m_serverAddress;
|
||||
int m_serverPort;
|
||||
SocketWrapper m_socket;
|
||||
|
||||
std::thread m_recvThread;
|
||||
std::atomic<bool> m_isRunning;
|
||||
std::atomic<bool> m_isConnected;
|
||||
std::atomic<bool> m_isAuthenticated;
|
||||
|
||||
std::string m_username;
|
||||
std::atomic<bool> m_inBattle;
|
||||
std::atomic<bool> m_waitingForTurn;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
GameClient(const std::string& serverAddress, int serverPort);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~GameClient();
|
||||
|
||||
/**
|
||||
* @brief 连接到服务器
|
||||
*/
|
||||
bool connect();
|
||||
|
||||
/**
|
||||
* @brief 断开连接
|
||||
*/
|
||||
void disconnect();
|
||||
|
||||
/**
|
||||
* @brief 运行客户端主循环
|
||||
*/
|
||||
void run();
|
||||
|
||||
/**
|
||||
* @brief 发送消息
|
||||
*/
|
||||
bool sendMessage(const std::string& message);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 接收线程主循环
|
||||
*/
|
||||
void recvLoop();
|
||||
|
||||
/**
|
||||
* @brief 处理服务器消息
|
||||
*/
|
||||
void handleServerMessage(const std::string& message);
|
||||
|
||||
/**
|
||||
* @brief 显示主菜单
|
||||
*/
|
||||
void showMainMenu();
|
||||
|
||||
/**
|
||||
* @brief 显示大厅菜单
|
||||
*/
|
||||
void showLobbyMenu();
|
||||
|
||||
/**
|
||||
* @brief 显示战斗菜单
|
||||
*/
|
||||
void showBattleMenu();
|
||||
|
||||
/**
|
||||
* @brief 处理注册
|
||||
*/
|
||||
void handleRegister();
|
||||
|
||||
/**
|
||||
* @brief 处理登录
|
||||
*/
|
||||
void handleLogin();
|
||||
|
||||
/**
|
||||
* @brief 处理大厅输入
|
||||
*/
|
||||
void handleLobbyInput(const std::string& input);
|
||||
|
||||
/**
|
||||
* @brief 处理战斗输入
|
||||
*/
|
||||
void handleBattleInput(const std::string& input);
|
||||
|
||||
/**
|
||||
* @brief 显示提示符
|
||||
*/
|
||||
void showPrompt();
|
||||
|
||||
/**
|
||||
* @brief 清屏
|
||||
*/
|
||||
void clearScreen();
|
||||
|
||||
/**
|
||||
* @brief 打印分隔线
|
||||
*/
|
||||
void printSeparator();
|
||||
|
||||
/**
|
||||
* @brief 打印标题
|
||||
*/
|
||||
void printTitle(const std::string& title);
|
||||
};
|
||||
171
include/common/Database.h
Normal file
171
include/common/Database.h
Normal file
@@ -0,0 +1,171 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
|
||||
// 前向声明 SQLite 结构
|
||||
struct sqlite3;
|
||||
|
||||
/**
|
||||
* @brief 用户数据结构
|
||||
*/
|
||||
struct UserData {
|
||||
int userId;
|
||||
std::string username;
|
||||
std::string passwordHash;
|
||||
std::string createdAt;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 角色数据结构
|
||||
*/
|
||||
struct CharacterData {
|
||||
int characterId;
|
||||
int userId;
|
||||
std::string className;
|
||||
int level;
|
||||
int hp;
|
||||
int mp;
|
||||
int attack;
|
||||
int speed;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 数据库管理类
|
||||
*
|
||||
* 技术点: 数据库 (Database) - SQLite3
|
||||
* 线程安全: 使用 std::mutex 保护所有数据库操作
|
||||
*/
|
||||
class Database {
|
||||
private:
|
||||
sqlite3* m_db;
|
||||
std::string m_dbPath;
|
||||
mutable std::mutex m_mutex; // 保证线程安全 (STL)
|
||||
bool m_isOpen;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param dbPath 数据库文件路径
|
||||
*/
|
||||
explicit Database(const std::string& dbPath);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~Database();
|
||||
|
||||
// 禁止拷贝
|
||||
Database(const Database&) = delete;
|
||||
Database& operator=(const Database&) = delete;
|
||||
|
||||
/**
|
||||
* @brief 打开数据库连接
|
||||
*/
|
||||
bool open();
|
||||
|
||||
/**
|
||||
* @brief 关闭数据库连接
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* @brief 初始化数据库表结构
|
||||
*/
|
||||
bool initializeTables();
|
||||
|
||||
/**
|
||||
* @brief 检查数据库是否已打开
|
||||
*/
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
|
||||
// ===== 用户相关操作 =====
|
||||
|
||||
/**
|
||||
* @brief 注册新用户
|
||||
* @param username 用户名
|
||||
* @param password 密码 (将被哈希)
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
bool registerUser(const std::string& username, const std::string& password);
|
||||
|
||||
/**
|
||||
* @brief 验证用户登录
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @return bool 是否验证成功
|
||||
*/
|
||||
bool verifyUser(const std::string& username, const std::string& password);
|
||||
|
||||
/**
|
||||
* @brief 检查用户名是否存在
|
||||
*/
|
||||
bool userExists(const std::string& username);
|
||||
|
||||
/**
|
||||
* @brief 获取用户ID
|
||||
*/
|
||||
int getUserId(const std::string& username);
|
||||
|
||||
/**
|
||||
* @brief 获取用户数据
|
||||
*/
|
||||
bool getUserData(const std::string& username, UserData& userData);
|
||||
|
||||
// ===== 角色相关操作 =====
|
||||
|
||||
/**
|
||||
* @brief 创建角色
|
||||
* @param userId 用户ID
|
||||
* @param className 职业名称
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
bool createCharacter(int userId, const std::string& className);
|
||||
|
||||
/**
|
||||
* @brief 获取用户的角色数据
|
||||
*/
|
||||
bool getCharacterData(int userId, CharacterData& charData);
|
||||
|
||||
/**
|
||||
* @brief 更新角色数据
|
||||
*/
|
||||
bool updateCharacter(const CharacterData& charData);
|
||||
|
||||
/**
|
||||
* @brief 检查用户是否有角色
|
||||
*/
|
||||
bool hasCharacter(int userId);
|
||||
|
||||
// ===== 工具函数 =====
|
||||
|
||||
/**
|
||||
* @brief 执行 SQL 语句
|
||||
* @param sql SQL 语句
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
bool executeSql(const std::string& sql);
|
||||
|
||||
/**
|
||||
* @brief 获取最后插入的行 ID
|
||||
*/
|
||||
int getLastInsertId();
|
||||
|
||||
/**
|
||||
* @brief 获取最后的错误信息
|
||||
*/
|
||||
std::string getLastError();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 密码哈希函数 (简单实现)
|
||||
* 注意: 生产环境应使用更安全的哈希算法 (如 bcrypt, argon2)
|
||||
*/
|
||||
std::string hashPassword(const std::string& password);
|
||||
|
||||
/**
|
||||
* @brief 验证密码
|
||||
*/
|
||||
bool verifyPassword(const std::string& password, const std::string& hash);
|
||||
};
|
||||
98
include/common/Protocol.h
Normal file
98
include/common/Protocol.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* @brief 网络通信协议定义
|
||||
*
|
||||
* 协议格式: COMMAND|param1|param2|...\n
|
||||
* 所有消息以换行符 \n 结尾
|
||||
*/
|
||||
|
||||
namespace Protocol {
|
||||
// ===== 协议命令定义 =====
|
||||
|
||||
// === 客户端 -> 服务器 (C2S) ===
|
||||
const std::string C2S_REGISTER = "C2S_REG"; // 注册: C2S_REG|username|password
|
||||
const std::string C2S_LOGIN = "C2S_LOGIN"; // 登录: C2S_LOGIN|username|password
|
||||
const std::string C2S_CHAT = "C2S_CHAT"; // 聊天: C2S_CHAT|message
|
||||
const std::string C2S_LIST_PLAYERS = "C2S_LIST"; // 玩家列表: C2S_LIST
|
||||
const std::string C2S_INVITE = "C2S_INVITE"; // 邀请: C2S_INVITE|target_username
|
||||
const std::string C2S_INVITE_RSP = "C2S_INVITE_RSP"; // 邀请响应: C2S_INVITE_RSP|inviter|accept/reject
|
||||
const std::string C2S_BATTLE_ACTION = "C2S_ACTION"; // 战斗行动: C2S_ACTION|skill_index|target
|
||||
const std::string C2S_LOGOUT = "C2S_LOGOUT"; // 登出: C2S_LOGOUT
|
||||
|
||||
// === 服务器 -> 客户端 (S2C) ===
|
||||
const std::string S2C_RESPONSE = "S2C_RESPONSE"; // 通用响应: S2C_RESPONSE|OK/ERROR|message
|
||||
const std::string S2C_LOGIN_OK = "S2C_LOGIN_OK"; // 登录成功: S2C_LOGIN_OK|username|class|level|hp|mp
|
||||
const std::string S2C_MSG = "S2C_MSG"; // 大厅消息: S2C_MSG|sender|message
|
||||
const std::string S2C_LIST_PLAYERS = "S2C_LIST"; // 玩家列表: S2C_LIST|user1,user2,user3
|
||||
const std::string S2C_INVITE = "S2C_INVITE"; // 收到邀请: S2C_INVITE|inviter_username
|
||||
const std::string S2C_INVITE_RESULT = "S2C_INV_RES"; // 邀请结果: S2C_INV_RES|target|accepted/rejected
|
||||
const std::string S2C_BATTLE_START = "S2C_BAT_START"; // 战斗开始: S2C_BAT_START|opponent|class
|
||||
const std::string S2C_BATTLE_TURN = "S2C_BAT_TURN"; // 回合通知: S2C_BAT_TURN|YOUR_TURN/OPP_TURN
|
||||
const std::string S2C_BATTLE_LOG = "S2C_BAT_LOG"; // 战斗日志: S2C_BAT_LOG|log_message
|
||||
const std::string S2C_BATTLE_END = "S2C_BAT_END"; // 战斗结束: S2C_BAT_END|WIN/LOSE
|
||||
const std::string S2C_SYSTEM = "S2C_SYSTEM"; // 系统消息: S2C_SYSTEM|message
|
||||
|
||||
// ===== 协议工具函数 =====
|
||||
|
||||
/**
|
||||
* @brief 构建协议消息
|
||||
* @param command 命令
|
||||
* @param params 参数列表
|
||||
* @return std::string 完整的协议消息 (包含换行符)
|
||||
*/
|
||||
std::string buildMessage(const std::string& command,
|
||||
const std::vector<std::string>& params = {});
|
||||
|
||||
/**
|
||||
* @brief 解析协议消息
|
||||
* @param message 原始消息
|
||||
* @param command 输出参数: 命令
|
||||
* @param params 输出参数: 参数列表
|
||||
* @return bool 解析是否成功
|
||||
*/
|
||||
bool parseMessage(const std::string& message,
|
||||
std::string& command,
|
||||
std::vector<std::string>& params);
|
||||
|
||||
/**
|
||||
* @brief 构建响应消息
|
||||
*/
|
||||
std::string buildResponse(bool success, const std::string& message);
|
||||
|
||||
/**
|
||||
* @brief 构建登录成功消息
|
||||
*/
|
||||
std::string buildLoginOk(const std::string& username,
|
||||
const std::string& className,
|
||||
int level, int hp, int mp);
|
||||
|
||||
/**
|
||||
* @brief 构建聊天消息
|
||||
*/
|
||||
std::string buildChatMessage(const std::string& sender,
|
||||
const std::string& message);
|
||||
|
||||
/**
|
||||
* @brief 构建玩家列表消息
|
||||
*/
|
||||
std::string buildPlayerList(const std::vector<std::string>& players);
|
||||
|
||||
/**
|
||||
* @brief 构建邀请消息
|
||||
*/
|
||||
std::string buildInvite(const std::string& inviter);
|
||||
|
||||
/**
|
||||
* @brief 构建战斗日志消息
|
||||
*/
|
||||
std::string buildBattleLog(const std::string& logMessage);
|
||||
|
||||
/**
|
||||
* @brief 构建系统消息
|
||||
*/
|
||||
std::string buildSystemMessage(const std::string& message);
|
||||
}
|
||||
139
include/common/SocketWrapper.h
Normal file
139
include/common/SocketWrapper.h
Normal file
@@ -0,0 +1,139 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
typedef SOCKET SocketFd;
|
||||
#define INVALID_SOCKET_FD INVALID_SOCKET
|
||||
#define SOCKET_ERROR_CODE WSAGetLastError()
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
typedef int SocketFd;
|
||||
#define INVALID_SOCKET_FD -1
|
||||
#define SOCKET_ERROR_CODE errno
|
||||
#define closesocket close
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Socket 封装类
|
||||
*
|
||||
* 技术点: 网络编程 (Network Programming) - 原生 Socket API 封装
|
||||
* 跨平台支持: Windows (Winsock) 和 Linux (POSIX Sockets)
|
||||
*/
|
||||
class SocketWrapper {
|
||||
private:
|
||||
SocketFd m_socket;
|
||||
bool m_isValid;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
SocketWrapper();
|
||||
|
||||
/**
|
||||
* @brief 构造函数 (使用现有socket)
|
||||
*/
|
||||
explicit SocketWrapper(SocketFd socket);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~SocketWrapper();
|
||||
|
||||
// 禁止拷贝
|
||||
SocketWrapper(const SocketWrapper&) = delete;
|
||||
SocketWrapper& operator=(const SocketWrapper&) = delete;
|
||||
|
||||
/**
|
||||
* @brief 初始化 Winsock (仅 Windows)
|
||||
*/
|
||||
static bool initializeWinsock();
|
||||
|
||||
/**
|
||||
* @brief 清理 Winsock (仅 Windows)
|
||||
*/
|
||||
static void cleanupWinsock();
|
||||
|
||||
/**
|
||||
* @brief 创建 Socket
|
||||
*/
|
||||
bool create();
|
||||
|
||||
/**
|
||||
* @brief 绑定地址和端口
|
||||
*/
|
||||
bool bind(const std::string& address, int port);
|
||||
|
||||
/**
|
||||
* @brief 监听连接
|
||||
*/
|
||||
bool listen(int backlog = 10);
|
||||
|
||||
/**
|
||||
* @brief 接受客户端连接
|
||||
*/
|
||||
SocketFd accept(std::string& clientAddress, int& clientPort);
|
||||
|
||||
/**
|
||||
* @brief 连接到服务器
|
||||
*/
|
||||
bool connect(const std::string& address, int port);
|
||||
|
||||
/**
|
||||
* @brief 发送数据
|
||||
*/
|
||||
int send(const char* data, int length);
|
||||
|
||||
/**
|
||||
* @brief 发送字符串
|
||||
*/
|
||||
int send(const std::string& message);
|
||||
|
||||
/**
|
||||
* @brief 接收数据
|
||||
*/
|
||||
int recv(char* buffer, int length);
|
||||
|
||||
/**
|
||||
* @brief 接收一行数据 (以 \n 结尾)
|
||||
*/
|
||||
std::string recvLine();
|
||||
|
||||
/**
|
||||
* @brief 设置为非阻塞模式
|
||||
*/
|
||||
bool setNonBlocking(bool nonBlocking);
|
||||
|
||||
/**
|
||||
* @brief 设置 Socket 选项
|
||||
*/
|
||||
bool setReuseAddr(bool reuse);
|
||||
|
||||
/**
|
||||
* @brief 关闭 Socket
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* @brief 检查 Socket 是否有效
|
||||
*/
|
||||
bool isValid() const { return m_isValid; }
|
||||
|
||||
/**
|
||||
* @brief 获取原始 Socket 描述符
|
||||
*/
|
||||
SocketFd getSocket() const { return m_socket; }
|
||||
|
||||
/**
|
||||
* @brief 获取最后的错误信息
|
||||
*/
|
||||
static std::string getLastError();
|
||||
};
|
||||
102
include/core/Characters.h
Normal file
102
include/core/Characters.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
#include "ICharacter.h"
|
||||
|
||||
/**
|
||||
* @brief 战士职业
|
||||
*
|
||||
* 技术点: 多态 (Polymorphism) - 继承和方法重写
|
||||
* 特点: 高生命值、高防御、物理攻击
|
||||
*/
|
||||
class Warrior : public ICharacter {
|
||||
private:
|
||||
int m_rage; // 怒气值 (战士特有资源)
|
||||
int m_maxRage; // 最大怒气值
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param name 角色名称
|
||||
* @param level 等级
|
||||
*/
|
||||
Warrior(const std::string& name, int level = 1);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
virtual ~Warrior() {}
|
||||
|
||||
/**
|
||||
* @brief 受到伤害 (重写) - 战士有格挡机制
|
||||
*/
|
||||
virtual void takeDamage(int damage) override;
|
||||
|
||||
/**
|
||||
* @brief 治疗 (重写)
|
||||
*/
|
||||
virtual void heal(int amount) override;
|
||||
|
||||
/**
|
||||
* @brief 获取怒气值
|
||||
*/
|
||||
int getRage() const { return m_rage; }
|
||||
|
||||
/**
|
||||
* @brief 增加怒气值
|
||||
*/
|
||||
void addRage(int amount);
|
||||
|
||||
/**
|
||||
* @brief 消耗怒气值
|
||||
*/
|
||||
bool consumeRage(int amount);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 法师职业
|
||||
*
|
||||
* 技术点: 多态 (Polymorphism) - 继承和方法重写
|
||||
* 特点: 高魔法值、魔法攻击、低防御
|
||||
*/
|
||||
class Mage : public ICharacter {
|
||||
private:
|
||||
int m_shield; // 法力护盾
|
||||
int m_maxShield; // 最大护盾值
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param name 角色名称
|
||||
* @param level 等级
|
||||
*/
|
||||
Mage(const std::string& name, int level = 1);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
virtual ~Mage() {}
|
||||
|
||||
/**
|
||||
* @brief 受到伤害 (重写) - 法师有法力护盾机制
|
||||
*/
|
||||
virtual void takeDamage(int damage) override;
|
||||
|
||||
/**
|
||||
* @brief 治疗 (重写)
|
||||
*/
|
||||
virtual void heal(int amount) override;
|
||||
|
||||
/**
|
||||
* @brief 获取护盾值
|
||||
*/
|
||||
int getShield() const { return m_shield; }
|
||||
|
||||
/**
|
||||
* @brief 添加护盾
|
||||
*/
|
||||
void addShield(int amount);
|
||||
|
||||
/**
|
||||
* @brief 重置护盾
|
||||
*/
|
||||
void resetShield();
|
||||
};
|
||||
193
include/core/HistoryLog.h
Normal file
193
include/core/HistoryLog.h
Normal file
@@ -0,0 +1,193 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
/**
|
||||
* @brief 链表节点模板类
|
||||
* @tparam T 节点存储的数据类型
|
||||
*
|
||||
* 技术点: 模板 (Template)
|
||||
*/
|
||||
template <typename T>
|
||||
struct Node {
|
||||
T data;
|
||||
Node<T>* next;
|
||||
|
||||
explicit Node(const T& d) : data(d), next(nullptr) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 历史日志记录器 - 使用模板和手写链表实现
|
||||
* @tparam T 日志条目的数据类型
|
||||
*
|
||||
* 技术点:
|
||||
* 1. 模板 (Template) - 泛型编程
|
||||
* 2. 链表 (Linked List) - 手写数据结构
|
||||
*
|
||||
* 用途: 用于记录战斗日志,满足课程要求的"模板+链表"技术点
|
||||
*/
|
||||
template <typename T>
|
||||
class HistoryLog {
|
||||
private:
|
||||
Node<T>* head; // 链表头指针
|
||||
Node<T>* tail; // 链表尾指针 (用于快速追加)
|
||||
int size; // 链表大小
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
HistoryLog() : head(nullptr), tail(nullptr), size(0) {}
|
||||
|
||||
/**
|
||||
* @brief 析构函数 - 必须正确释放所有节点内存
|
||||
*/
|
||||
~HistoryLog() {
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 拷贝构造函数 (深拷贝)
|
||||
*/
|
||||
HistoryLog(const HistoryLog& other) : head(nullptr), tail(nullptr), size(0) {
|
||||
Node<T>* current = other.head;
|
||||
while (current != nullptr) {
|
||||
add(current->data);
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 拷贝赋值运算符
|
||||
*/
|
||||
HistoryLog& operator=(const HistoryLog& other) {
|
||||
if (this != &other) {
|
||||
clear();
|
||||
Node<T>* current = other.head;
|
||||
while (current != nullptr) {
|
||||
add(current->data);
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在链表尾部添加新的日志条目
|
||||
* @param logEntry 日志条目
|
||||
*/
|
||||
void add(const T& logEntry) {
|
||||
Node<T>* newNode = new Node<T>(logEntry);
|
||||
|
||||
if (head == nullptr) {
|
||||
// 空链表
|
||||
head = newNode;
|
||||
tail = newNode;
|
||||
} else {
|
||||
// 追加到尾部
|
||||
tail->next = newNode;
|
||||
tail = newNode;
|
||||
}
|
||||
|
||||
size++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在链表头部插入日志条目
|
||||
* @param logEntry 日志条目
|
||||
*/
|
||||
void addFront(const T& logEntry) {
|
||||
Node<T>* newNode = new Node<T>(logEntry);
|
||||
|
||||
if (head == nullptr) {
|
||||
head = newNode;
|
||||
tail = newNode;
|
||||
} else {
|
||||
newNode->next = head;
|
||||
head = newNode;
|
||||
}
|
||||
|
||||
size++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取所有日志条目
|
||||
* @return std::vector<T> 包含所有日志条目的向量
|
||||
*/
|
||||
std::vector<T> getAllEntries() const {
|
||||
std::vector<T> entries;
|
||||
entries.reserve(size);
|
||||
|
||||
Node<T>* current = head;
|
||||
while (current != nullptr) {
|
||||
entries.push_back(current->data);
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取链表大小
|
||||
* @return int 日志条目数量
|
||||
*/
|
||||
int getSize() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检查链表是否为空
|
||||
* @return bool true 如果为空
|
||||
*/
|
||||
bool isEmpty() const {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 清空所有日志条目
|
||||
*/
|
||||
void clear() {
|
||||
Node<T>* current = head;
|
||||
while (current != nullptr) {
|
||||
Node<T>* temp = current;
|
||||
current = current->next;
|
||||
delete temp;
|
||||
}
|
||||
head = nullptr;
|
||||
tail = nullptr;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取指定索引的日志条目
|
||||
* @param index 索引 (0-based)
|
||||
* @return const T& 日志条目的引用
|
||||
* @throw std::out_of_range 如果索引超出范围
|
||||
*/
|
||||
const T& at(int index) const {
|
||||
if (index < 0 || index >= size) {
|
||||
throw std::out_of_range("Index out of range");
|
||||
}
|
||||
|
||||
Node<T>* current = head;
|
||||
for (int i = 0; i < index; i++) {
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return current->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 打印所有日志 (仅用于调试)
|
||||
*/
|
||||
void print() const {
|
||||
Node<T>* current = head;
|
||||
int index = 0;
|
||||
while (current != nullptr) {
|
||||
// 这里假设 T 支持 << 运算符
|
||||
// std::cout << "[" << index++ << "] " << current->data << std::endl;
|
||||
current = current->next;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
};
|
||||
144
include/core/ICharacter.h
Normal file
144
include/core/ICharacter.h
Normal file
@@ -0,0 +1,144 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
// 前向声明
|
||||
class ICharacter;
|
||||
class ISkill;
|
||||
|
||||
/**
|
||||
* @brief 技能接口 (抽象基类)
|
||||
*
|
||||
* 技术点: 多态 (Polymorphism) - 纯虚函数
|
||||
*/
|
||||
class ISkill {
|
||||
protected:
|
||||
std::string m_name; // 技能名称
|
||||
std::string m_description; // 技能描述
|
||||
int m_manaCost; // 消耗魔法值
|
||||
int m_cooldown; // 冷却时间
|
||||
|
||||
public:
|
||||
virtual ~ISkill() {}
|
||||
|
||||
/**
|
||||
* @brief 执行技能
|
||||
* @param caster 施法者
|
||||
* @param target 目标
|
||||
* @return std::string 战斗日志描述
|
||||
*/
|
||||
virtual std::string execute(ICharacter& caster, ICharacter& target) = 0;
|
||||
|
||||
/**
|
||||
* @brief 获取技能名称
|
||||
*/
|
||||
virtual std::string getName() const { return m_name; }
|
||||
|
||||
/**
|
||||
* @brief 获取技能描述
|
||||
*/
|
||||
virtual std::string getDescription() const { return m_description; }
|
||||
|
||||
/**
|
||||
* @brief 获取魔法消耗
|
||||
*/
|
||||
virtual int getManaCost() const { return m_manaCost; }
|
||||
|
||||
/**
|
||||
* @brief 获取冷却时间
|
||||
*/
|
||||
virtual int getCooldown() const { return m_cooldown; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 角色接口 (抽象基类)
|
||||
*
|
||||
* 技术点: 多态 (Polymorphism) - 纯虚函数、虚析构函数
|
||||
*/
|
||||
class ICharacter {
|
||||
protected:
|
||||
std::string m_name; // 角色名称
|
||||
std::string m_className; // 职业名称
|
||||
int m_level; // 等级
|
||||
int m_hp; // 当前生命值
|
||||
int m_maxHp; // 最大生命值
|
||||
int m_mp; // 当前魔法值
|
||||
int m_maxMp; // 最大魔法值
|
||||
int m_attack; // 攻击力
|
||||
int m_defense; // 防御力
|
||||
int m_speed; // 速度 (决定行动顺序)
|
||||
std::vector<std::shared_ptr<ISkill>> m_skills; // 技能列表 (STL)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 虚析构函数 (必须)
|
||||
*/
|
||||
virtual ~ICharacter() {}
|
||||
|
||||
// === Getters ===
|
||||
virtual std::string getName() const { return m_name; }
|
||||
virtual std::string getClassName() const { return m_className; }
|
||||
virtual int getLevel() const { return m_level; }
|
||||
virtual int getHp() const { return m_hp; }
|
||||
virtual int getMaxHp() const { return m_maxHp; }
|
||||
virtual int getMp() const { return m_mp; }
|
||||
virtual int getMaxMp() const { return m_maxMp; }
|
||||
virtual int getAttack() const { return m_attack; }
|
||||
virtual int getDefense() const { return m_defense; }
|
||||
virtual int getSpeed() const { return m_speed; }
|
||||
|
||||
/**
|
||||
* @brief 检查角色是否存活
|
||||
*/
|
||||
virtual bool isAlive() const { return m_hp > 0; }
|
||||
|
||||
/**
|
||||
* @brief 获取指定名称的技能
|
||||
* @param skillName 技能名称
|
||||
* @return ISkill* 技能指针,如果不存在返回 nullptr
|
||||
*/
|
||||
virtual ISkill* getSkill(const std::string& skillName);
|
||||
|
||||
/**
|
||||
* @brief 获取所有技能
|
||||
*/
|
||||
virtual const std::vector<std::shared_ptr<ISkill>>& getSkills() const {
|
||||
return m_skills;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 受到伤害 (纯虚函数 - 必须在派生类中实现)
|
||||
* @param damage 伤害值
|
||||
*/
|
||||
virtual void takeDamage(int damage) = 0;
|
||||
|
||||
/**
|
||||
* @brief 治疗 (纯虚函数 - 必须在派生类中实现)
|
||||
* @param amount 治疗量
|
||||
*/
|
||||
virtual void heal(int amount) = 0;
|
||||
|
||||
/**
|
||||
* @brief 消耗魔法值
|
||||
* @param amount 消耗量
|
||||
* @return bool 是否成功消耗
|
||||
*/
|
||||
virtual bool consumeMana(int amount);
|
||||
|
||||
/**
|
||||
* @brief 恢复魔法值
|
||||
* @param amount 恢复量
|
||||
*/
|
||||
virtual void restoreMana(int amount);
|
||||
|
||||
/**
|
||||
* @brief 获取角色状态字符串
|
||||
*/
|
||||
virtual std::string getStatus() const;
|
||||
|
||||
/**
|
||||
* @brief 添加技能
|
||||
*/
|
||||
virtual void addSkill(std::shared_ptr<ISkill> skill);
|
||||
};
|
||||
72
include/core/Skills.h
Normal file
72
include/core/Skills.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include "ICharacter.h"
|
||||
#include <random>
|
||||
|
||||
/**
|
||||
* @brief 普通攻击技能
|
||||
*/
|
||||
class NormalAttack : public ISkill {
|
||||
public:
|
||||
NormalAttack();
|
||||
virtual std::string execute(ICharacter& caster, ICharacter& target) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 战士技能: 重击
|
||||
* 造成高额伤害,消耗怒气
|
||||
*/
|
||||
class HeavyStrike : public ISkill {
|
||||
public:
|
||||
HeavyStrike();
|
||||
virtual std::string execute(ICharacter& caster, ICharacter& target) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 战士技能: 防御姿态
|
||||
* 大幅提升防御,回复少量生命
|
||||
*/
|
||||
class DefensiveStance : public ISkill {
|
||||
public:
|
||||
DefensiveStance();
|
||||
virtual std::string execute(ICharacter& caster, ICharacter& target) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 法师技能: 火球术
|
||||
* 造成魔法伤害
|
||||
*/
|
||||
class Fireball : public ISkill {
|
||||
public:
|
||||
Fireball();
|
||||
virtual std::string execute(ICharacter& caster, ICharacter& target) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 法师技能: 冰霜新星
|
||||
* 造成伤害并降低目标速度
|
||||
*/
|
||||
class FrostNova : public ISkill {
|
||||
public:
|
||||
FrostNova();
|
||||
virtual std::string execute(ICharacter& caster, ICharacter& target) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 法师技能: 奥术护盾
|
||||
* 为自己添加法力护盾
|
||||
*/
|
||||
class ArcaneShield : public ISkill {
|
||||
public:
|
||||
ArcaneShield();
|
||||
virtual std::string execute(ICharacter& caster, ICharacter& target) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 治疗术
|
||||
* 恢复生命值
|
||||
*/
|
||||
class Heal : public ISkill {
|
||||
public:
|
||||
Heal();
|
||||
virtual std::string execute(ICharacter& caster, ICharacter& target) override;
|
||||
};
|
||||
134
include/server/BattleRoom.h
Normal file
134
include/server/BattleRoom.h
Normal file
@@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
#include "ICharacter.h"
|
||||
#include "HistoryLog.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
// 前向声明
|
||||
class ClientHandler;
|
||||
|
||||
/**
|
||||
* @brief 战斗房间
|
||||
*
|
||||
* 技术点:
|
||||
* 1. 多态 - ICharacter* 和 ISkill*
|
||||
* 2. 模板+链表 - HistoryLog<string>
|
||||
* 3. STL - std::vector, std::mutex
|
||||
*/
|
||||
class BattleRoom {
|
||||
private:
|
||||
int m_roomId;
|
||||
|
||||
// 战斗双方
|
||||
std::shared_ptr<ClientHandler> m_player1;
|
||||
std::shared_ptr<ClientHandler> m_player2;
|
||||
|
||||
// 角色 (多态)
|
||||
std::shared_ptr<ICharacter> m_char1;
|
||||
std::shared_ptr<ICharacter> m_char2;
|
||||
|
||||
// 战斗日志 (模板+链表)
|
||||
HistoryLog<std::string> m_historyLog;
|
||||
|
||||
// 战斗状态
|
||||
bool m_isRunning;
|
||||
int m_currentTurn; // 0 = player1, 1 = player2
|
||||
int m_turnCount;
|
||||
|
||||
std::mutex m_mutex;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
BattleRoom(int roomId,
|
||||
std::shared_ptr<ClientHandler> player1,
|
||||
std::shared_ptr<ClientHandler> player2,
|
||||
std::shared_ptr<ICharacter> char1,
|
||||
std::shared_ptr<ICharacter> char2);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~BattleRoom();
|
||||
|
||||
/**
|
||||
* @brief 启动战斗
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* @brief 处理玩家行动
|
||||
*/
|
||||
bool handleAction(const std::string& username,
|
||||
int skillIndex,
|
||||
const std::string& targetName);
|
||||
|
||||
/**
|
||||
* @brief 检查战斗是否结束
|
||||
*/
|
||||
bool isFinished() const;
|
||||
|
||||
/**
|
||||
* @brief 获取胜利者
|
||||
*/
|
||||
std::string getWinner() const;
|
||||
|
||||
/**
|
||||
* @brief 获取战斗日志
|
||||
*/
|
||||
std::vector<std::string> getBattleLog() const;
|
||||
|
||||
/**
|
||||
* @brief 获取房间ID
|
||||
*/
|
||||
int getRoomId() const { return m_roomId; }
|
||||
|
||||
/**
|
||||
* @brief 检查是否轮到某玩家
|
||||
*/
|
||||
bool isPlayerTurn(const std::string& username) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 执行一回合
|
||||
*/
|
||||
void executeTurn();
|
||||
|
||||
/**
|
||||
* @brief 广播给双方玩家
|
||||
*/
|
||||
void broadcastToBoth(const std::string& message);
|
||||
|
||||
/**
|
||||
* @brief 发送给玩家1
|
||||
*/
|
||||
void sendToPlayer1(const std::string& message);
|
||||
|
||||
/**
|
||||
* @brief 发送给玩家2
|
||||
*/
|
||||
void sendToPlayer2(const std::string& message);
|
||||
|
||||
/**
|
||||
* @brief 添加战斗日志
|
||||
*/
|
||||
void addLog(const std::string& log);
|
||||
|
||||
/**
|
||||
* @brief 结束战斗
|
||||
*/
|
||||
void endBattle();
|
||||
|
||||
/**
|
||||
* @brief 发送回合通知
|
||||
*/
|
||||
void notifyTurn();
|
||||
|
||||
/**
|
||||
* @brief 发送战斗状态
|
||||
*/
|
||||
void sendBattleStatus();
|
||||
};
|
||||
71
include/server/BattleRoomManager.h
Normal file
71
include/server/BattleRoomManager.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
#include "BattleRoom.h"
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
|
||||
// 前向声明
|
||||
class GameServer;
|
||||
|
||||
/**
|
||||
* @brief 战斗房间管理器
|
||||
*
|
||||
* 技术点: STL - std::map, std::mutex
|
||||
*/
|
||||
class BattleRoomManager {
|
||||
private:
|
||||
GameServer* m_server;
|
||||
std::map<int, std::shared_ptr<BattleRoom>> m_rooms; // STL
|
||||
std::mutex m_mutex; // STL
|
||||
int m_nextRoomId;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
explicit BattleRoomManager(GameServer* server);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~BattleRoomManager();
|
||||
|
||||
/**
|
||||
* @brief 创建战斗房间
|
||||
* @param player1 玩家1用户名
|
||||
* @param player2 玩家2用户名
|
||||
* @return int 房间ID,失败返回 -1
|
||||
*/
|
||||
int createBattle(const std::string& player1, const std::string& player2);
|
||||
|
||||
/**
|
||||
* @brief 获取战斗房间
|
||||
*/
|
||||
std::shared_ptr<BattleRoom> getBattleRoom(int roomId);
|
||||
|
||||
/**
|
||||
* @brief 处理战斗行动
|
||||
*/
|
||||
bool handleBattleAction(int roomId,
|
||||
const std::string& username,
|
||||
int skillIndex,
|
||||
const std::string& targetName);
|
||||
|
||||
/**
|
||||
* @brief 移除战斗房间
|
||||
*/
|
||||
void removeBattleRoom(int roomId);
|
||||
|
||||
/**
|
||||
* @brief 检查玩家是否在战斗中
|
||||
*/
|
||||
bool isPlayerInBattle(const std::string& username);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 创建角色实例
|
||||
*/
|
||||
std::shared_ptr<ICharacter> createCharacter(const std::string& className,
|
||||
const std::string& name,
|
||||
int level = 1);
|
||||
};
|
||||
172
include/server/ClientHandler.h
Normal file
172
include/server/ClientHandler.h
Normal file
@@ -0,0 +1,172 @@
|
||||
#pragma once
|
||||
#include "SocketWrapper.h"
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// 前向声明
|
||||
class GameServer;
|
||||
|
||||
/**
|
||||
* @brief 客户端状态枚举
|
||||
*/
|
||||
enum class ClientState {
|
||||
Unauthenticated, // 未认证
|
||||
Lobby, // 大厅中
|
||||
InBattle // 战斗中
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 客户端处理器
|
||||
*
|
||||
* 技术点:
|
||||
* 1. STL - std::thread (多线程)
|
||||
* 2. 网络编程 - Socket 通信
|
||||
*/
|
||||
class ClientHandler : public std::enable_shared_from_this<ClientHandler> {
|
||||
private:
|
||||
int m_clientId;
|
||||
SocketFd m_socketFd;
|
||||
GameServer* m_server;
|
||||
|
||||
std::thread m_thread;
|
||||
std::atomic<bool> m_isRunning;
|
||||
|
||||
// 客户端状态
|
||||
ClientState m_state;
|
||||
std::string m_username;
|
||||
int m_userId;
|
||||
|
||||
// 战斗相关
|
||||
std::string m_pendingInviter; // 待处理的邀请者
|
||||
int m_battleRoomId; // 所在战斗房间ID
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
ClientHandler(int clientId, SocketFd socketFd, GameServer* server);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~ClientHandler();
|
||||
|
||||
// 禁止拷贝
|
||||
ClientHandler(const ClientHandler&) = delete;
|
||||
ClientHandler& operator=(const ClientHandler&) = delete;
|
||||
|
||||
/**
|
||||
* @brief 启动处理线程
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* @brief 停止处理
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* @brief 发送消息
|
||||
*/
|
||||
bool sendMessage(const std::string& message);
|
||||
|
||||
/**
|
||||
* @brief 获取客户端ID
|
||||
*/
|
||||
int getClientId() const { return m_clientId; }
|
||||
|
||||
/**
|
||||
* @brief 获取用户名
|
||||
*/
|
||||
std::string getUsername() const { return m_username; }
|
||||
|
||||
/**
|
||||
* @brief 获取用户ID
|
||||
*/
|
||||
int getUserId() const { return m_userId; }
|
||||
|
||||
/**
|
||||
* @brief 获取状态
|
||||
*/
|
||||
ClientState getState() const { return m_state; }
|
||||
|
||||
/**
|
||||
* @brief 设置状态
|
||||
*/
|
||||
void setState(ClientState state) { m_state = state; }
|
||||
|
||||
/**
|
||||
* @brief 设置战斗房间ID
|
||||
*/
|
||||
void setBattleRoomId(int roomId) { m_battleRoomId = roomId; }
|
||||
|
||||
/**
|
||||
* @brief 获取战斗房间ID
|
||||
*/
|
||||
int getBattleRoomId() const { return m_battleRoomId; }
|
||||
|
||||
/**
|
||||
* @brief 设置待处理邀请
|
||||
*/
|
||||
void setPendingInviter(const std::string& inviter) { m_pendingInviter = inviter; }
|
||||
|
||||
/**
|
||||
* @brief 获取待处理邀请
|
||||
*/
|
||||
std::string getPendingInviter() const { return m_pendingInviter; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 线程主循环
|
||||
*/
|
||||
void run();
|
||||
|
||||
/**
|
||||
* @brief 处理客户端命令
|
||||
*/
|
||||
void handleCommand(const std::string& command,
|
||||
const std::vector<std::string>& params);
|
||||
|
||||
/**
|
||||
* @brief 处理注册
|
||||
*/
|
||||
void handleRegister(const std::vector<std::string>& params);
|
||||
|
||||
/**
|
||||
* @brief 处理登录
|
||||
*/
|
||||
void handleLogin(const std::vector<std::string>& params);
|
||||
|
||||
/**
|
||||
* @brief 处理聊天
|
||||
*/
|
||||
void handleChat(const std::vector<std::string>& params);
|
||||
|
||||
/**
|
||||
* @brief 处理玩家列表请求
|
||||
*/
|
||||
void handleListPlayers();
|
||||
|
||||
/**
|
||||
* @brief 处理邀请
|
||||
*/
|
||||
void handleInvite(const std::vector<std::string>& params);
|
||||
|
||||
/**
|
||||
* @brief 处理邀请响应
|
||||
*/
|
||||
void handleInviteResponse(const std::vector<std::string>& params);
|
||||
|
||||
/**
|
||||
* @brief 处理战斗行动
|
||||
*/
|
||||
void handleBattleAction(const std::vector<std::string>& params);
|
||||
|
||||
/**
|
||||
* @brief 处理登出
|
||||
*/
|
||||
void handleLogout();
|
||||
};
|
||||
59
include/server/GameLobby.h
Normal file
59
include/server/GameLobby.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
// 前向声明
|
||||
class GameServer;
|
||||
|
||||
/**
|
||||
* @brief 游戏大厅管理类
|
||||
*
|
||||
* 功能:
|
||||
* 1. 管理大厅聊天
|
||||
* 2. 处理玩家列表
|
||||
* 3. 处理对战邀请
|
||||
*/
|
||||
class GameLobby {
|
||||
private:
|
||||
GameServer* m_server;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
explicit GameLobby(GameServer* server);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~GameLobby();
|
||||
|
||||
/**
|
||||
* @brief 广播聊天消息
|
||||
* @param sender 发送者用户名
|
||||
* @param message 消息内容
|
||||
* @param excludeClientId 排除的客户端ID (不发送给自己)
|
||||
*/
|
||||
void broadcastMessage(const std::string& sender,
|
||||
const std::string& message,
|
||||
int excludeClientId = -1);
|
||||
|
||||
/**
|
||||
* @brief 处理对战邀请
|
||||
* @param inviter 邀请者用户名
|
||||
* @param target 被邀请者用户名
|
||||
* @return bool 是否成功发送邀请
|
||||
*/
|
||||
bool handleInvite(const std::string& inviter, const std::string& target);
|
||||
|
||||
/**
|
||||
* @brief 处理邀请响应
|
||||
* @param inviter 邀请者用户名
|
||||
* @param target 被邀请者用户名
|
||||
* @param accept 是否接受
|
||||
* @return bool 是否成功处理
|
||||
*/
|
||||
bool handleInviteResponse(const std::string& inviter,
|
||||
const std::string& target,
|
||||
bool accept);
|
||||
};
|
||||
111
include/server/GameServer.h
Normal file
111
include/server/GameServer.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
#include "SocketWrapper.h"
|
||||
#include "Database.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// 前向声明
|
||||
class ClientHandler;
|
||||
class GameLobby;
|
||||
class BattleRoomManager;
|
||||
|
||||
/**
|
||||
* @brief 游戏服务器主类
|
||||
*
|
||||
* 技术点:
|
||||
* 1. STL - std::map, std::mutex, std::thread
|
||||
* 2. 网络编程 - Socket Server
|
||||
*/
|
||||
class GameServer {
|
||||
private:
|
||||
int m_port;
|
||||
SocketWrapper m_serverSocket;
|
||||
std::shared_ptr<Database> m_database;
|
||||
|
||||
// 客户端管理 (STL)
|
||||
std::map<int, std::shared_ptr<ClientHandler>> m_clients;
|
||||
std::mutex m_clientsMutex;
|
||||
int m_nextClientId;
|
||||
|
||||
// 游戏模块
|
||||
std::shared_ptr<GameLobby> m_lobby;
|
||||
std::shared_ptr<BattleRoomManager> m_battleManager;
|
||||
|
||||
bool m_isRunning;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param port 监听端口
|
||||
* @param dbPath 数据库文件路径
|
||||
*/
|
||||
GameServer(int port, const std::string& dbPath);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~GameServer();
|
||||
|
||||
/**
|
||||
* @brief 启动服务器
|
||||
*/
|
||||
bool start();
|
||||
|
||||
/**
|
||||
* @brief 停止服务器
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* @brief 服务器主循环 (接受连接)
|
||||
*/
|
||||
void run();
|
||||
|
||||
/**
|
||||
* @brief 添加客户端
|
||||
*/
|
||||
int addClient(std::shared_ptr<ClientHandler> client);
|
||||
|
||||
/**
|
||||
* @brief 移除客户端
|
||||
*/
|
||||
void removeClient(int clientId);
|
||||
|
||||
/**
|
||||
* @brief 根据用户名获取客户端
|
||||
*/
|
||||
std::shared_ptr<ClientHandler> getClientByUsername(const std::string& username);
|
||||
|
||||
/**
|
||||
* @brief 获取所有在线玩家列表
|
||||
*/
|
||||
std::vector<std::string> getOnlinePlayers();
|
||||
|
||||
/**
|
||||
* @brief 广播消息给所有在大厅的客户端
|
||||
*/
|
||||
void broadcastToLobby(const std::string& message, int excludeClientId = -1);
|
||||
|
||||
/**
|
||||
* @brief 获取数据库
|
||||
*/
|
||||
std::shared_ptr<Database> getDatabase() { return m_database; }
|
||||
|
||||
/**
|
||||
* @brief 获取大厅
|
||||
*/
|
||||
std::shared_ptr<GameLobby> getLobby() { return m_lobby; }
|
||||
|
||||
/**
|
||||
* @brief 获取战斗管理器
|
||||
*/
|
||||
std::shared_ptr<BattleRoomManager> getBattleManager() { return m_battleManager; }
|
||||
|
||||
/**
|
||||
* @brief 检查服务器是否运行中
|
||||
*/
|
||||
bool isRunning() const { return m_isRunning; }
|
||||
};
|
||||
Reference in New Issue
Block a user