服务端热更新功能

当调用upgrade命令后,会创建更加新的roomthread
(!完全没测试过)
This commit is contained in:
notify 2024-04-07 00:35:57 +08:00 committed by GitHub
parent 873d68363c
commit 1a4da186d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 333 additions and 172 deletions

View File

@ -143,14 +143,12 @@ callbacks["UpdateRoomList"] = (jsonData) => {
const current = mainStack.currentItem; // should be lobby const current = mainStack.currentItem; // should be lobby
if (mainStack.depth === 2) { if (mainStack.depth === 2) {
current.roomModel.clear(); current.roomModel.clear();
JSON.parse(jsonData).forEach(function (room) { JSON.parse(jsonData).forEach(room => {
const [roomId, roomName, gameMode, playerNum, capacity, hasPassword,
outdated] = room;
current.roomModel.append({ current.roomModel.append({
roomId: room[0], roomId, roomName, gameMode, playerNum, capacity,
roomName: room[1], hasPassword, outdated,
gameMode: room[2],
playerNum: room[3],
capacity: room[4],
hasPassword: room[5] ? true : false,
}); });
}); });
} }

View File

@ -64,7 +64,13 @@ Item {
Text { Text {
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
Layout.fillWidth: true Layout.fillWidth: true
text: roomName text: {
let ret = roomName;
if (outdated) {
ret = '<font color="grey"><del>' + ret + '</del></font>';
}
return ret;
}
font.pixelSize: 20 font.pixelSize: 20
elide: Label.ElideRight elide: Label.ElideRight
} }
@ -94,7 +100,7 @@ Item {
text: (playerNum < capacity) ? luatr("Enter") : text: (playerNum < capacity) ? luatr("Enter") :
luatr("Observe") luatr("Observe")
enabled: !opTimer.running enabled: !opTimer.running && !outdated
onClicked: { onClicked: {
opTimer.start(); opTimer.start();

View File

@ -318,6 +318,10 @@
<source>room password error</source> <source>room password error</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>room is outdated</source>
<translation></translation>
</message>
<message> <message>
<source>no such room</source> <source>no such room</source>
<translation></translation> <translation></translation>

View File

@ -495,6 +495,7 @@ Fk:loadTranslationTable{
["#ChainStateChange"] = "%from %arg 了武将牌", ["#ChainStateChange"] = "%from %arg 了武将牌",
["#ChainDamage"] = "%from 处于连环状态,将受到传导的伤害", ["#ChainDamage"] = "%from 处于连环状态,将受到传导的伤害",
["#ChangeKingdom"] = "%from 的国籍从 %arg 变成了 %arg2", ["#ChangeKingdom"] = "%from 的国籍从 %arg 变成了 %arg2",
["#RoomOutdated"] = "服务器更新完毕!该房间已过期,将无法再次游玩",
} }
-- card footnote -- card footnote

View File

@ -181,7 +181,7 @@ request_handlers["newroom"] = function(s, id)
s:registerRoom(id) s:registerRoom(id)
end end
request_handlers["reloadpackage"] = function(room, id, reqlist) request_handlers["reloadpackage"] = function(_, _, reqlist)
if not IsConsoleStart() then return end if not IsConsoleStart() then return end
local path = reqlist[3] local path = reqlist[3]
Fk:reloadPackage(path) Fk:reloadPackage(path)

View File

@ -22,6 +22,8 @@ end)
-- 仿照Room接口编写的request协程处理器 -- 仿照Room接口编写的request协程处理器
local requestRoom = setmetatable({ local requestRoom = setmetatable({
id = -1,
runningRooms = runningRooms,
-- minDelayTime 是当没有任何就绪房间时,可以睡眠的时间。 -- minDelayTime 是当没有任何就绪房间时,可以睡眠的时间。
-- 因为这个时间是所有房间预期就绪用时的最小值故称为minDelayTime。 -- 因为这个时间是所有房间预期就绪用时的最小值故称为minDelayTime。
@ -130,6 +132,14 @@ local function mainLoop()
-- 调用RoomThread的trySleep函数开始真正的睡眠。会被wakeUp(c++)唤醒。 -- 调用RoomThread的trySleep函数开始真正的睡眠。会被wakeUp(c++)唤醒。
requestRoom.thread:trySleep(time) requestRoom.thread:trySleep(time)
local runningRoomsCount = -1 -- 必有requestRoom从-1开始算
for _ in pairs(runningRooms) do
runningRoomsCount = runningRoomsCount + 1
if runningRoomsCount > 0 then break end
end
if runningRoomsCount == 0 and requestRoom.thread:isOutdated() then
break
end
-- verbose('[!] Waked up after %f ms...', (os.getms() - cur) / 1000) -- verbose('[!] Waked up after %f ms...', (os.getms() - cur) / 1000)

View File

@ -153,107 +153,6 @@ void Router::abortRequest() {
} }
void Router::handlePacket(const QByteArray &rawPacket) { void Router::handlePacket(const QByteArray &rawPacket) {
#ifndef FK_CLIENT_ONLY
static QMap<QString, void (*)(ServerPlayer *, const QString &)> lobby_actions;
if (lobby_actions.size() <= 0) {
lobby_actions["UpdateAvatar"] = [](ServerPlayer *sender,
const QString &jsonData) {
auto arr = String2Json(jsonData).array();
auto avatar = arr[0].toString();
if (CheckSqlString(avatar)) {
auto sql = QString("UPDATE userinfo SET avatar='%1' WHERE id=%2;")
.arg(avatar)
.arg(sender->getId());
ExecSQL(ServerInstance->getDatabase(), sql);
sender->setAvatar(avatar);
sender->doNotify("UpdateAvatar", avatar);
}
};
lobby_actions["UpdatePassword"] = [](ServerPlayer *sender,
const QString &jsonData) {
auto arr = String2Json(jsonData).array();
auto oldpw = arr[0].toString();
auto newpw = arr[1].toString();
auto sql_find =
QString("SELECT password, salt FROM userinfo WHERE id=%1;")
.arg(sender->getId());
auto passed = false;
auto arr2 = SelectFromDatabase(ServerInstance->getDatabase(), sql_find);
auto result = arr2[0].toObject();
passed = (result["password"].toString() ==
QCryptographicHash::hash(
oldpw.append(result["salt"].toString()).toLatin1(),
QCryptographicHash::Sha256)
.toHex());
if (passed) {
auto sql_update =
QString("UPDATE userinfo SET password='%1' WHERE id=%2;")
.arg(QCryptographicHash::hash(
newpw.append(result["salt"].toString()).toLatin1(),
QCryptographicHash::Sha256)
.toHex())
.arg(sender->getId());
ExecSQL(ServerInstance->getDatabase(), sql_update);
}
sender->doNotify("UpdatePassword", passed ? "1" : "0");
};
lobby_actions["CreateRoom"] = [](ServerPlayer *sender,
const QString &jsonData) {
auto arr = String2Json(jsonData).array();
auto name = arr[0].toString();
auto capacity = arr[1].toInt();
auto timeout = arr[2].toInt();
auto settings =
QJsonDocument(arr[3].toObject()).toJson(QJsonDocument::Compact);
ServerInstance->createRoom(sender, name, capacity, timeout, settings);
};
lobby_actions["EnterRoom"] = [](ServerPlayer *sender,
const QString &jsonData) {
auto arr = String2Json(jsonData).array();
auto roomId = arr[0].toInt();
auto room = ServerInstance->findRoom(roomId);
if (room) {
auto settings = QJsonDocument::fromJson(room->getSettings());
auto password = settings["password"].toString();
if (password.isEmpty() || arr[1].toString() == password) {
room->addPlayer(sender);
} else {
sender->doNotify("ErrorMsg", "room password error");
}
} else {
sender->doNotify("ErrorMsg", "no such room");
}
};
lobby_actions["ObserveRoom"] = [](ServerPlayer *sender,
const QString &jsonData) {
auto arr = String2Json(jsonData).array();
auto roomId = arr[0].toInt();
auto room = ServerInstance->findRoom(roomId);
if (room) {
auto settings = QJsonDocument::fromJson(room->getSettings());
auto password = settings["password"].toString();
if (password.isEmpty() || arr[1].toString() == password) {
room->addObserver(sender);
} else {
sender->doNotify("ErrorMsg", "room password error");
}
} else {
sender->doNotify("ErrorMsg", "no such room");
}
};
lobby_actions["Chat"] = [](ServerPlayer *sender, const QString &jsonData) {
sender->getRoom()->chat(sender, jsonData);
};
lobby_actions["RefreshRoomList"] = [](ServerPlayer *sender,
const QString &jsonData) {
ServerInstance->updateRoomList(sender);
};
}
#endif
QJsonDocument packet = QJsonDocument::fromJson(rawPacket); QJsonDocument packet = QJsonDocument::fromJson(rawPacket);
if (packet.isNull() || !packet.isArray()) if (packet.isNull() || !packet.isArray())
return; return;
@ -278,35 +177,7 @@ void Router::handlePacket(const QByteArray &rawPacket) {
} }
Room *room = player->getRoom(); Room *room = player->getRoom();
if (room->isLobby() && lobby_actions.contains(command)) room->handlePacket(player, command, jsonData);
lobby_actions[command](player, jsonData);
else {
if (command == "QuitRoom") {
room->removePlayer(player);
} else if (command == "AddRobot") {
if (ServerInstance->getConfig("enableBots").toBool()) room->addRobot(player);
} else if (command == "KickPlayer") {
int i = jsonData.toInt();
auto p = room->findPlayer(i);
if (p && !room->isStarted()) {
room->removePlayer(p);
room->addRejectId(i);
QTimer::singleShot(30000, this, [=]() {
room->removeRejectId(i);
});
}
} else if (command == "Ready") {
player->setReady(!player->isReady());
room->doBroadcastNotify(room->getPlayers(), "ReadyChanged",
QString("[%1,%2]").arg(player->getId()).arg(player->isReady()));
} else if (command == "StartGame") {
room->manuallyStart();
} else if (command == "Chat") {
room->chat(player, jsonData);
} else if (command == "PushRequest") {
room->pushRequest(QString("%1,").arg(player->getId()) + jsonData);
}
}
} }
#endif #endif
} else if (type & TYPE_REQUEST) { } else if (type & TYPE_REQUEST) {

View File

@ -22,7 +22,7 @@ Room::Room(RoomThread *m_thread) {
id = server->nextRoomId; id = server->nextRoomId;
server->nextRoomId++; server->nextRoomId++;
this->server = server; this->server = server;
this->m_thread = m_thread; setThread(m_thread);
if (m_thread) { // In case of lobby if (m_thread) { // In case of lobby
m_thread->addRoom(this); m_thread->addRoom(this);
} }
@ -60,7 +60,12 @@ Server *Room::getServer() const { return server; }
RoomThread *Room::getThread() const { return m_thread; } RoomThread *Room::getThread() const { return m_thread; }
void Room::setThread(RoomThread *t) { m_thread = t; } void Room::setThread(RoomThread *t) {
m_thread = t;
if (t != nullptr) {
md5 = t->getMd5();
}
}
int Room::getId() const { return id; } int Room::getId() const { return id; }
@ -366,6 +371,12 @@ int Room::getTimeout() const { return timeout; }
void Room::setTimeout(int timeout) { this->timeout = timeout; } void Room::setTimeout(int timeout) { this->timeout = timeout; }
bool Room::isOutdated() {
bool ret = md5 != server->getMd5();
if (ret) md5 = "";
return ret;
}
bool Room::isStarted() const { return gameStarted; } bool Room::isStarted() const { return gameStarted; }
void Room::doBroadcastNotify(const QList<ServerPlayer *> targets, void Room::doBroadcastNotify(const QList<ServerPlayer *> targets,
@ -616,3 +627,186 @@ void Room::addRejectId(int id) {
void Room::removeRejectId(int id) { void Room::removeRejectId(int id) {
rejected_players.removeOne(id); rejected_players.removeOne(id);
} }
// ------------------------------------------------
static void updateAvatar(ServerPlayer *sender, const QString &jsonData) {
auto arr = String2Json(jsonData).array();
auto avatar = arr[0].toString();
if (CheckSqlString(avatar)) {
auto sql = QString("UPDATE userinfo SET avatar='%1' WHERE id=%2;")
.arg(avatar)
.arg(sender->getId());
ExecSQL(ServerInstance->getDatabase(), sql);
sender->setAvatar(avatar);
sender->doNotify("UpdateAvatar", avatar);
}
}
static void updatePassword(ServerPlayer *sender, const QString &jsonData) {
auto arr = String2Json(jsonData).array();
auto oldpw = arr[0].toString();
auto newpw = arr[1].toString();
auto sql_find =
QString("SELECT password, salt FROM userinfo WHERE id=%1;")
.arg(sender->getId());
auto passed = false;
auto arr2 = SelectFromDatabase(ServerInstance->getDatabase(), sql_find);
auto result = arr2[0].toObject();
passed = (result["password"].toString() ==
QCryptographicHash::hash(
oldpw.append(result["salt"].toString()).toLatin1(),
QCryptographicHash::Sha256)
.toHex());
if (passed) {
auto sql_update =
QString("UPDATE userinfo SET password='%1' WHERE id=%2;")
.arg(QCryptographicHash::hash(
newpw.append(result["salt"].toString()).toLatin1(),
QCryptographicHash::Sha256)
.toHex())
.arg(sender->getId());
ExecSQL(ServerInstance->getDatabase(), sql_update);
}
sender->doNotify("UpdatePassword", passed ? "1" : "0");
}
static void createRoom(ServerPlayer *sender, const QString &jsonData) {
auto arr = String2Json(jsonData).array();
auto name = arr[0].toString();
auto capacity = arr[1].toInt();
auto timeout = arr[2].toInt();
auto settings =
QJsonDocument(arr[3].toObject()).toJson(QJsonDocument::Compact);
ServerInstance->createRoom(sender, name, capacity, timeout, settings);
}
static void enterRoom(ServerPlayer *sender, const QString &jsonData) {
auto arr = String2Json(jsonData).array();
auto roomId = arr[0].toInt();
auto room = ServerInstance->findRoom(roomId);
if (room) {
auto settings = QJsonDocument::fromJson(room->getSettings());
auto password = settings["password"].toString();
if (password.isEmpty() || arr[1].toString() == password) {
if (room->isOutdated()) {
sender->doNotify("ErrorMsg", "room is outdated");
} else {
room->addPlayer(sender);
}
} else {
sender->doNotify("ErrorMsg", "room password error");
}
} else {
sender->doNotify("ErrorMsg", "no such room");
}
}
static void observeRoom(ServerPlayer *sender, const QString &jsonData) {
auto arr = String2Json(jsonData).array();
auto roomId = arr[0].toInt();
auto room = ServerInstance->findRoom(roomId);
if (room) {
auto settings = QJsonDocument::fromJson(room->getSettings());
auto password = settings["password"].toString();
if (password.isEmpty() || arr[1].toString() == password) {
if (room->isOutdated()) {
sender->doNotify("ErrorMsg", "room is outdated");
} else {
room->addObserver(sender);
}
} else {
sender->doNotify("ErrorMsg", "room password error");
}
} else {
sender->doNotify("ErrorMsg", "no such room");
}
}
static void refreshRoomList(ServerPlayer *sender, const QString &) {
ServerInstance->updateRoomList(sender);
};
static void quitRoom(ServerPlayer *player, const QString &) {
auto room = player->getRoom();
room->removePlayer(player);
if (room->isOutdated()) {
player->kicked();
}
}
static void addRobot(ServerPlayer *player, const QString &) {
auto room = player->getRoom();
if (ServerInstance->getConfig("enableBots").toBool())
room->addRobot(player);
}
static void kickPlayer(ServerPlayer *player, const QString &jsonData) {
auto room = player->getRoom();
int i = jsonData.toInt();
auto p = room->findPlayer(i);
if (p && !room->isStarted()) {
room->removePlayer(p);
room->addRejectId(i);
QTimer::singleShot(30000, room, [=]() {
room->removeRejectId(i);
});
}
}
static void ready(ServerPlayer *player, const QString &) {
auto room = player->getRoom();
player->setReady(!player->isReady());
room->doBroadcastNotify(room->getPlayers(), "ReadyChanged",
QString("[%1,%2]").arg(player->getId()).arg(player->isReady()));
}
static void startGame(ServerPlayer *player, const QString &) {
auto room = player->getRoom();
if (room->isOutdated()) {
foreach (auto p, room->getPlayers()) {
p->doNotify("ErrorMsg", "room is outdated");
p->kicked();
}
} else {
room->manuallyStart();
}
}
typedef void (*room_cb)(ServerPlayer *, const QString &);
static const QMap<QString, room_cb> lobby_actions = {
{"UpdateAvatar", updateAvatar},
{"UpdatePassword", updatePassword},
{"CreateRoom", createRoom},
{"EnterRoom", enterRoom},
{"ObserveRoom", observeRoom},
{"RefreshRoomList", refreshRoomList},
};
static const QMap<QString, room_cb> room_actions = {
{"QuitRoom", quitRoom},
{"AddRobot", addRobot},
{"KickPlayer", kickPlayer},
{"Ready", ready},
{"StartGame", startGame},
};
void Room::handlePacket(ServerPlayer *sender, const QString &command,
const QString &jsonData) {
if (command == "Chat") {
chat(sender, jsonData);
return;
} else if (command == "PushRequest") {
if (!isLobby())
pushRequest(QString("%1,").arg(sender->getId()) + jsonData);
}
auto func_table = lobby_actions;
if (!isLobby()) func_table = room_actions;
auto func = func_table[command];
if (func) {
func(sender, jsonData);
}
}

View File

@ -50,6 +50,8 @@ class Room : public QObject {
int getTimeout() const; int getTimeout() const;
void setTimeout(int timeout); void setTimeout(int timeout);
bool isOutdated();
bool isStarted() const; bool isStarted() const;
// ====================================} // ====================================}
@ -65,6 +67,10 @@ class Room : public QObject {
void addRejectId(int id); void addRejectId(int id);
void removeRejectId(int id); void removeRejectId(int id);
// router用
void handlePacket(ServerPlayer *sender, const QString &command,
const QString &jsonData);
signals: signals:
void abandoned(); void abandoned();
@ -90,6 +96,7 @@ class Room : public QObject {
bool m_ready; bool m_ready;
int timeout; int timeout;
QString md5;
void addRunRate(int id, const QString &mode); void addRunRate(int id, const QString &mode);
void updatePlayerGameData(int id, const QString &mode); void updatePlayerGameData(int id, const QString &mode);

View File

@ -3,6 +3,7 @@
#include "roomthread.h" #include "roomthread.h"
#include "server.h" #include "server.h"
#include "util.h" #include "util.h"
#include <lua.h>
#ifndef FK_SERVER_ONLY #ifndef FK_SERVER_ONLY
#include "client.h" #include "client.h"
@ -13,6 +14,7 @@ RoomThread::RoomThread(Server *m_server) {
this->m_server = m_server; this->m_server = m_server;
m_capacity = 100; // TODO: server cfg m_capacity = 100; // TODO: server cfg
terminated = false; terminated = false;
md5 = m_server->getMd5();
L = CreateLuaState(); L = CreateLuaState();
DoLuaScript(L, "lua/freekill.lua"); DoLuaScript(L, "lua/freekill.lua");
@ -26,6 +28,7 @@ RoomThread::~RoomThread() {
wait(); wait();
} }
lua_close(L); lua_close(L);
m_server->removeThread(this);
// foreach (auto room, room_list) { // foreach (auto room, room_list) {
// room->deleteLater(); // room->deleteLater();
// } // }
@ -40,6 +43,8 @@ bool RoomThread::isFull() const {
return m_capacity <= 0; return m_capacity <= 0;
} }
QString RoomThread::getMd5() const { return md5; }
Room *RoomThread::getRoom(int id) const { Room *RoomThread::getRoom(int id) const {
return m_server->findRoom(id); return m_server->findRoom(id);
} }
@ -52,6 +57,10 @@ void RoomThread::addRoom(Room *room) {
void RoomThread::removeRoom(Room *room) { void RoomThread::removeRoom(Room *room) {
room->setThread(nullptr); room->setThread(nullptr);
m_capacity++; m_capacity++;
if (m_capacity == 100 // TODO: server cfg
&& isOutdated()) {
deleteLater();
}
} }
QString RoomThread::fetchRequest() { QString RoomThread::fetchRequest() {
@ -118,3 +127,13 @@ bool RoomThread::isConsoleStart() const {
return false; return false;
#endif #endif
} }
bool RoomThread::isOutdated() {
bool ret = md5 != m_server->getMd5();
if (ret) {
// 让以后每次都outdate
// 不然反复disable/enable的情况下会出乱子
md5 = "";
}
return ret;
}

View File

@ -16,6 +16,7 @@ class RoomThread : public QThread {
Server *getServer() const; Server *getServer() const;
bool isFull() const; bool isFull() const;
QString getMd5() const;
Room *getRoom(int id) const; Room *getRoom(int id) const;
void addRoom(Room *room); void addRoom(Room *room);
void removeRoom(Room *room); void removeRoom(Room *room);
@ -32,6 +33,9 @@ class RoomThread : public QThread {
bool isTerminated() const; bool isTerminated() const;
bool isConsoleStart() const; bool isConsoleStart() const;
bool isOutdated();
protected: protected:
virtual void run(); virtual void run();
@ -39,6 +43,7 @@ class RoomThread : public QThread {
Server *m_server; Server *m_server;
// QList<Room *> room_list; // QList<Room *> room_list;
int m_capacity; int m_capacity;
QString md5;
lua_State *L; lua_State *L;
QMutex request_queue_mutex; QMutex request_queue_mutex;

View File

@ -112,14 +112,14 @@ void Server::createRoom(ServerPlayer *owner, const QString &name, int capacity,
RoomThread *thread = nullptr; RoomThread *thread = nullptr;
foreach (auto t, threads) { foreach (auto t, threads) {
if (!t->isFull()) { if (!t->isFull() && !t->isOutdated()) {
thread = t; thread = t;
break; break;
} }
} }
if (!thread && nextRoomId != 0) { if (!thread && nextRoomId != 0) {
thread = new RoomThread(this); thread = createThread();
threads.append(thread);
} }
if (!idle_rooms.isEmpty()) { if (!idle_rooms.isEmpty()) {
@ -128,6 +128,7 @@ void Server::createRoom(ServerPlayer *owner, const QString &name, int capacity,
nextRoomId++; nextRoomId++;
room->setAbandoned(false); room->setAbandoned(false);
room->setThread(thread); room->setThread(thread);
thread->addRoom(room);
rooms.insert(room->getId(), room); rooms.insert(room->getId(), room);
} else { } else {
room = new Room(thread); room = new Room(thread);
@ -151,6 +152,16 @@ Room *Server::findRoom(int id) const { return rooms.value(id); }
Room *Server::lobby() const { return m_lobby; } Room *Server::lobby() const { return m_lobby; }
RoomThread *Server::createThread() {
RoomThread *thread = new RoomThread(this);
threads.append(thread);
return thread;
}
void Server::removeThread(RoomThread *thread) {
threads.removeOne(thread);
}
ServerPlayer *Server::findPlayer(int id) const { return players.value(id); } ServerPlayer *Server::findPlayer(int id) const { return players.value(id); }
void Server::addPlayer(ServerPlayer *player) { void Server::addPlayer(ServerPlayer *player) {
@ -183,6 +194,7 @@ void Server::updateRoomList(ServerPlayer *teller) {
obj << count; obj << count;
obj << cap; obj << cap;
obj << !password.isEmpty(); obj << !password.isEmpty();
obj << room->isOutdated();
if (count == cap) if (count == cap)
arr << obj; arr << obj;
@ -670,6 +682,30 @@ void Server::endTransaction() {
transaction_mutex.unlock(); transaction_mutex.unlock();
} }
const QString &Server::getMd5() const {
return md5;
}
void Server::refreshMd5() {
md5 = calcFileMD5();
foreach (auto room, rooms) {
if (room->isOutdated()) {
if (!room->isStarted()) {
foreach (auto p, room->getPlayers()) {
p->doNotify("ErrorMsg", "room is outdated");
p->kicked();
}
} else {
room->doBroadcastNotify(room->getPlayers(), "GameLog",
"{\"type\":\"#RoomOutdated\",\"toast\":true}");
}
}
}
foreach (auto p, lobby()->getPlayers()) {
emit p->kicked();
}
}
void Server::readPendingDatagrams() { void Server::readPendingDatagrams() {
while (udpSocket->hasPendingDatagrams()) { while (udpSocket->hasPendingDatagrams()) {
QNetworkDatagram datagram = udpSocket->receiveDatagram(); QNetworkDatagram datagram = udpSocket->receiveDatagram();

View File

@ -31,6 +31,9 @@ public:
Room *findRoom(int id) const; Room *findRoom(int id) const;
Room *lobby() const; Room *lobby() const;
RoomThread *createThread();
void removeThread(RoomThread *thread);
ServerPlayer *findPlayer(int id) const; ServerPlayer *findPlayer(int id) const;
void addPlayer(ServerPlayer *player); void addPlayer(ServerPlayer *player);
void removePlayer(int id); void removePlayer(int id);
@ -50,6 +53,9 @@ public:
void beginTransaction(); void beginTransaction();
void endTransaction(); void endTransaction();
const QString &getMd5() const;
void refreshMd5();
signals: signals:
void roomCreated(Room *room); void roomCreated(Room *room);
void playerAdded(ServerPlayer *player); void playerAdded(ServerPlayer *player);

View File

@ -117,11 +117,13 @@ void Shell::upgradeCommand(QStringList &list) {
auto obj = a.toObject(); auto obj = a.toObject();
Pacman->upgradePack(obj["name"].toString()); Pacman->upgradePack(obj["name"].toString());
} }
ServerInstance->refreshMd5();
return; return;
} }
auto pack = list[0]; auto pack = list[0];
Pacman->upgradePack(pack); Pacman->upgradePack(pack);
ServerInstance->refreshMd5();
} }
void Shell::enableCommand(QStringList &list) { void Shell::enableCommand(QStringList &list) {
@ -132,6 +134,7 @@ void Shell::enableCommand(QStringList &list) {
auto pack = list[0]; auto pack = list[0];
Pacman->enablePack(pack); Pacman->enablePack(pack);
ServerInstance->refreshMd5();
} }
void Shell::disableCommand(QStringList &list) { void Shell::disableCommand(QStringList &list) {
@ -142,6 +145,7 @@ void Shell::disableCommand(QStringList &list) {
auto pack = list[0]; auto pack = list[0];
Pacman->disablePack(pack); Pacman->disablePack(pack);
ServerInstance->refreshMd5();
} }
void Shell::lspkgCommand(QStringList &) { void Shell::lspkgCommand(QStringList &) {
@ -380,33 +384,32 @@ Shell::Shell() {
setObjectName("Shell"); setObjectName("Shell");
signal(SIGINT, sigintHandler); signal(SIGINT, sigintHandler);
static QHash<QString, void (Shell::*)(QStringList &)> handlers; static const QHash<QString, void (Shell::*)(QStringList &)> handlers = {
if (handlers.size() == 0) { {"help", &Shell::helpCommand},
handlers["help"] = &Shell::helpCommand; {"?", &Shell::helpCommand},
handlers["?"] = &Shell::helpCommand; {"lsplayer", &Shell::lspCommand},
handlers["lsplayer"] = &Shell::lspCommand; {"lsroom", &Shell::lsrCommand},
handlers["lsroom"] = &Shell::lsrCommand; {"install", &Shell::installCommand},
handlers["install"] = &Shell::installCommand; {"remove", &Shell::removeCommand},
handlers["remove"] = &Shell::removeCommand; {"upgrade", &Shell::upgradeCommand},
handlers["upgrade"] = &Shell::upgradeCommand; {"u", &Shell::upgradeCommand},
handlers["u"] = &Shell::upgradeCommand; {"lspkg", &Shell::lspkgCommand},
handlers["lspkg"] = &Shell::lspkgCommand; {"enable", &Shell::enableCommand},
handlers["enable"] = &Shell::enableCommand; {"disable", &Shell::disableCommand},
handlers["disable"] = &Shell::disableCommand; {"kick", &Shell::kickCommand},
handlers["kick"] = &Shell::kickCommand; {"msg", &Shell::msgCommand},
handlers["msg"] = &Shell::msgCommand; {"m", &Shell::msgCommand},
handlers["m"] = &Shell::msgCommand; {"ban", &Shell::banCommand},
handlers["ban"] = &Shell::banCommand; {"unban", &Shell::unbanCommand},
handlers["unban"] = &Shell::unbanCommand; {"banip", &Shell::banipCommand},
handlers["banip"] = &Shell::banipCommand; {"unbanip", &Shell::unbanipCommand},
handlers["unbanip"] = &Shell::unbanipCommand; {"banuuid", &Shell::banUuidCommand},
handlers["banuuid"] = &Shell::banUuidCommand; {"unbanuuid", &Shell::unbanUuidCommand},
handlers["unbanuuid"] = &Shell::unbanUuidCommand; {"reloadconf", &Shell::reloadConfCommand},
handlers["reloadconf"] = &Shell::reloadConfCommand; {"r", &Shell::reloadConfCommand},
handlers["r"] = &Shell::reloadConfCommand; {"resetpassword", &Shell::resetPasswordCommand},
handlers["resetpassword"] = &Shell::resetPasswordCommand; {"rp", &Shell::resetPasswordCommand},
handlers["rp"] = &Shell::resetPasswordCommand; };
}
handler_map = handlers; handler_map = handlers;
} }

View File

@ -41,6 +41,7 @@ public:
bool isTerminated() const; bool isTerminated() const;
bool isConsoleStart() const; bool isConsoleStart() const;
bool isOutdated();
}; };
%{ %{