Files
OnlineRpg/关键模块与接口.md
ChuXun e287aadd3c 1
2025-10-26 16:37:22 +08:00

5.2 KiB

1. 数据库 Schema (SQLite)

-- 用户表 (Users)
CREATE TABLE IF NOT EXISTS Users (
UserID INTEGER PRIMARY KEY AUTOINCREMENT,
Username TEXT NOT NULL UNIQUE,
PasswordHash TEXT NOT NULL,
CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 角色表 (Characters)
CREATE TABLE IF NOT EXISTS Characters (
CharacterID INTEGER PRIMARY KEY AUTOINCREMENT,
UserID INTEGER NOT NULL,
ClassName TEXT NOT NULL, -- e.g., "Warrior", "Mage"
Level INTEGER NOT NULL DEFAULT 1,
HP INTEGER NOT NULL DEFAULT 100,
MP INTEGER NOT NULL DEFAULT 50,
Attack INTEGER NOT NULL DEFAULT 10,
Speed INTEGER NOT NULL DEFAULT 5,
FOREIGN KEY(UserID) REFERENCES Users(UserID)
);

2. 网络通信协议 (Protocol.h)

使用 | 分隔的文本协议。所有消息以换行符 \n 结束。

2.1. 客户端 -> 服务器 (C2S)

  • 注册: C2S_REG|username|password\n
  • 登录: C2S_LOGIN|username|password\n
  • 大厅聊天: C2S_CHAT|message_content\n
  • 获取列表: C2S_LIST_PLAYERS\n
  • 邀请对战: C2S_INVITE|target_username\n
  • 回应邀请: C2S_INVITE_RSP|inviter_username|accept_or_reject\n (e.g., "accept" / "reject")
  • 战斗行动: C2S_BATTLE_ACTION|skill_name|target_name\n

2.2. 服务器 -> 客户端 (S2C)

  • 通用响应: S2C_RESPONSE|OK|message\n 或 S2C_RESPONSE|ERROR|error_message\n
  • 登录成功: S2C_LOGIN_OK|username|ClassName|Level|HP|MP\n
  • 大厅消息: S2C_MSG|sender_username|message_content\n
  • 玩家列表: S2C_LIST_PLAYERS|user1,user2,user3\n
  • 收到邀请: S2C_INVITE|inviter_username\n
  • 邀请结果: S2C_INVITE_RESULT|target_username|result\n (e.g., "accepted" / "rejected")
  • 战斗开始: S2C_BATTLE_START|opponent_name|opponent_class\n
  • 战斗回合: S2C_BATTLE_TURN|YOUR_TURN\n 或 S2C_BATTLE_TURN|OPPONENT_TURN\n
  • 战斗战报: S2C_BATTLE_LOG|log_message\n
  • 战斗结束: S2C_BATTLE_END|WIN\n 或 S2C_BATTLE_END|LOSE\n

3. 关键类接口定义 (C++ Header 风格)

3.1. Core: HistoryLog.h (模板 + 链表)

#pragma once
#include <vector>

// 必须手写实现链表节点
template <typename T>
struct Node {
T data;
Node<T>* next;
Node(T d) : data(d), next(nullptr) {}
};

// 必须使用手写的 Node<T> 作为底层结构
template <typename T>
class HistoryLog {
private:
Node<T>* head;
int size;

public:
HistoryLog();
~HistoryLog(); // 必须正确释放链表所有节点的内存

void add(T logEntry); // 在链表头部插入  
std::vector\<T\> getAllEntries(); // 遍历链表,返回一个 vector  
int getSize();  

};

3.2. Core: ICharacter.h & ISkill.h (多态)

#pragma once
#include <string>
#include <vector>

class ICharacter; // 前向声明

// 技能基类
class ISkill {
public:
virtual ~ISkill() {}
virtual std::string getName() = 0;
virtual void execute(ICharacter& caster, ICharacter& target) = 0; // 纯虚函数
};

// 角色基类
class ICharacter {
protected:
std::string m_name;
int m_hp;
int m_maxHp;
int m_speed;
std::vector<ISkill*> m_skills; // STL

public:
virtual ~ICharacter(); // 必须是虚析构函数,并清理 m_skills
virtual std::string getName() { return m_name; }
virtual int getHp() { return m_hp; }
virtual bool isAlive() { return m_hp > 0; }
virtual int getSpeed() { return m_speed; }
virtual ISkill* getSkill(const std::string& name);

virtual void takeDamage(int damage) \= 0; // 纯虚函数  
virtual void heal(int amount) \= 0;  

};

// 派生类 (示例)
class Warrior : public ICharacter {
public:
Warrior(std::string name);
virtual void takeDamage(int damage) override; // 重写,实现格挡逻辑
virtual void heal(int amount) override;
};

class Mage : public ICharacter {
public:
Mage(std::string name);
virtual void takeDamage(int damage) override; // 重写,实现法力护盾逻辑
virtual void heal(int amount) override;
};

3.3. Server: ClientHandler.h (网络 + STL + 多线程)

#pragma once
#include <thread>
#include <string>
#include "SocketWrapper.h" // 假设已封装

class GameServer; // 前向声明

class ClientHandler {
public:
// 构造函数,传入 socket 描述符和服务器实例指针
ClientHandler(int socketFd, GameServer* server);
~ClientHandler();

void startHandlerThread(); // 启动 run() 循环  
void stopHandler();        // 停止循环并关闭 socket  
void sendMessage(const std::string& message); // 发送消息给这个客户端

private:
void run(); // 线程主循环 (recv, parse, handle)
void parseCommand(const std::string& command);

int m\_socketFd;  
GameServer\* m\_server; // 用于回调服务器 (e.g., 广播)  
std::thread m\_thread; // STL  
bool m\_isRunning;  
  
// 玩家状态  
std::string m\_username;  
enum class State { Unauthenticated, Lobby, InBattle };  
State m\_state;  

};