Todo: disable sync (#14)

* lock room lua

* fixme

* add 'id' to lua Player

Co-authored-by: Notify-ctrl <notify-ctrl@qq.com>
This commit is contained in:
Notify-ctrl 2022-04-03 21:43:35 +08:00 committed by GitHub
parent 4c93c897b2
commit 9e09e6e50d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 73 additions and 12 deletions

View File

@ -1,4 +1,5 @@
---@class Player : Object ---@class Player : Object
---@field id integer
---@field hp integer ---@field hp integer
---@field maxHp integer ---@field maxHp integer
---@field kingdom string ---@field kingdom string
@ -31,6 +32,7 @@ Player.NotActive = 8
Player.PhaseNone = 9 Player.PhaseNone = 9
function Player:initialize() function Player:initialize()
self.id = 114514
self.hp = 0 self.hp = 0
self.maxHp = 0 self.maxHp = 0
self.kingdom = "qun" self.kingdom = "qun"

View File

@ -276,7 +276,8 @@ fk.room_callback["PlayerRunned"] = function(jsonData)
local robot = data[2] local robot = data[2]
for _, p in ipairs(RoomInstance.players) do for _, p in ipairs(RoomInstance.players) do
if p:getId() == runner then if p:getId() == runner then
p.serverplayer = RoomInstance:findPlayerById(robot) p.serverplayer = RoomInstance.room:findPlayer(robot)
p.id = p.serverplayer:getId()
end end
end end
end end
@ -291,6 +292,12 @@ fk.room_callback["PlayerStateChanged"] = function(jsonData)
RoomInstance:findPlayerById(id).state = stateString RoomInstance:findPlayerById(id).state = stateString
end end
fk.room_callback["RoomDeleted"] = function(jsonData)
debug.sethook(function ()
error("Room is deleted when running")
end, "l")
end
fk.room_callback["DoLuaScript"] = function(jsonData) fk.room_callback["DoLuaScript"] = function(jsonData)
-- jsonData: [ int uid, string luaScript ] -- jsonData: [ int uid, string luaScript ]
-- warning: only use this in debugging mode. -- warning: only use this in debugging mode.

View File

@ -11,6 +11,7 @@ local ServerPlayer = Player:subclass("ServerPlayer")
function ServerPlayer:initialize(_self) function ServerPlayer:initialize(_self)
Player.initialize(self) Player.initialize(self)
self.serverplayer = _self self.serverplayer = _self
self.id = _self:getId()
self.room = nil self.room = nil
self.next = nil self.next = nil
@ -24,7 +25,7 @@ end
---@return integer ---@return integer
function ServerPlayer:getId() function ServerPlayer:getId()
return self.serverplayer:getId() return self.id
end end
---@param command string ---@param command string

View File

@ -159,7 +159,11 @@ void Router::handlePacket(const QByteArray& rawPacket)
// Add the uid of sender to jsonData // Add the uid of sender to jsonData
QJsonArray arr = QJsonDocument::fromJson(jsonData.toUtf8()).array(); QJsonArray arr = QJsonDocument::fromJson(jsonData.toUtf8()).array();
arr.prepend(player->getId()); arr.prepend(player->getId());
player->getRoom()->callLua(command, QJsonDocument(arr).toJson());
Room *room = player->getRoom();
room->lockLua(__FUNCTION__);
room->callLua(command, QJsonDocument(arr).toJson());
room->unlockLua(__FUNCTION__);
} }
} }
else if (type & TYPE_REQUEST) { else if (type & TYPE_REQUEST) {

View File

@ -39,6 +39,7 @@ public:
int getTimeout() const; int getTimeout() const;
void cancelRequest(); void cancelRequest();
void abortRequest();
QString waitForReply(); QString waitForReply();
QString waitForReply(int timeout); QString waitForReply(int timeout);
@ -49,7 +50,6 @@ signals:
void replyReady(); void replyReady();
protected: protected:
void abortRequest();
void handlePacket(const QByteArray &rawPacket); void handlePacket(const QByteArray &rawPacket);
private: private:

View File

@ -32,10 +32,10 @@ Room::~Room()
{ {
// TODO // TODO
if (isRunning()) { if (isRunning()) {
terminate(); callLua("RoomDeleted", "");
unlockLua(__FUNCTION__);
wait(); wait();
} }
disconnect();
lua_close(L); lua_close(L);
} }
@ -180,6 +180,7 @@ void Room::removePlayer(ServerPlayer *player)
if (gameStarted) { if (gameStarted) {
// TODO: if the player is died.. // TODO: if the player is died..
// create robot first // create robot first
ServerPlayer *robot = new ServerPlayer(this); ServerPlayer *robot = new ServerPlayer(this);
robot->setState(Player::Robot); robot->setState(Player::Robot);
@ -188,6 +189,8 @@ void Room::removePlayer(ServerPlayer *player)
robot->setScreenName(QString("COMP-%1").arg(robot_id)); robot->setScreenName(QString("COMP-%1").arg(robot_id));
robot_id--; robot_id--;
players.append(robot);
// tell lua & clients // tell lua & clients
QJsonArray jsonData; QJsonArray jsonData;
jsonData << player->getId(); jsonData << player->getId();
@ -195,6 +198,10 @@ void Room::removePlayer(ServerPlayer *player)
callLua("PlayerRunned", QJsonDocument(jsonData).toJson()); callLua("PlayerRunned", QJsonDocument(jsonData).toJson());
doBroadcastNotify(getPlayers(), "PlayerRunned", QJsonDocument(jsonData).toJson()); doBroadcastNotify(getPlayers(), "PlayerRunned", QJsonDocument(jsonData).toJson());
runned_players << player->getId(); runned_players << player->getId();
// FIXME: abortRequest here will result crash
// but if dont abort and room is abandoned, the main thread will wait until replyed
// player->abortRequest();
} else { } else {
QJsonArray jsonData; QJsonArray jsonData;
jsonData << player->getId(); jsonData << player->getId();
@ -202,6 +209,8 @@ void Room::removePlayer(ServerPlayer *player)
} }
if (isAbandoned()) { if (isAbandoned()) {
// FIXME: do not delete room here
// create a new thread and delete the room
emit abandoned(); emit abandoned();
} else if (player == owner) { } else if (player == owner) {
setOwner(players.first()); setOwner(players.first());
@ -274,8 +283,28 @@ void Room::gameOver()
} }
} }
void Room::lockLua(const QString &caller)
{
if (!gameStarted) return;
lua_mutex.lock();
#ifdef QT_DEBUG
//qDebug() << caller << "=> room->L is locked.";
#endif
}
void Room::unlockLua(const QString &caller)
{
if (!gameStarted) return;
lua_mutex.unlock();
#ifdef QT_DEBUG
//qDebug() << caller << "=> room->L is unlocked.";
#endif
}
void Room::run() void Room::run()
{ {
gameStarted = true; gameStarted = true;
lockLua(__FUNCTION__);
roomStart(); roomStart();
unlockLua(__FUNCTION__);
} }

View File

@ -49,8 +49,6 @@ public:
void gameOver(); void gameOver();
lua_State *getLuaState() const;
void initLua(); void initLua();
void callLua(const QString &command, const QString &jsonData); void callLua(const QString &command, const QString &jsonData);
LuaFunction callback; LuaFunction callback;
@ -58,6 +56,9 @@ public:
void roomStart(); void roomStart();
LuaFunction startGame; LuaFunction startGame;
void lockLua(const QString &caller);
void unlockLua(const QString &caller);
signals: signals:
void abandoned(); void abandoned();
@ -83,6 +84,7 @@ private:
int timeout; int timeout;
lua_State *L; lua_State *L;
QMutex lua_mutex;
}; };
#endif // _ROOM_H #endif // _ROOM_H

View File

@ -69,22 +69,37 @@ void ServerPlayer::doRequest(const QString& command, const QString& jsonData, in
router->request(type, command, jsonData, timeout); router->request(type, command, jsonData, timeout);
} }
void ServerPlayer::abortRequest()
{
router->abortRequest();
}
QString ServerPlayer::waitForReply() QString ServerPlayer::waitForReply()
{ {
room->unlockLua(__FUNCTION__);
QString ret;
if (getState() != Player::Online) { if (getState() != Player::Online) {
QThread::sleep(1); QThread::sleep(1);
return ""; ret = "";
} else {
ret = router->waitForReply();
} }
return router->waitForReply(); room->lockLua(__FUNCTION__);
return ret;
} }
QString ServerPlayer::waitForReply(int timeout) QString ServerPlayer::waitForReply(int timeout)
{ {
room->unlockLua(__FUNCTION__);
QString ret;
if (getState() != Player::Online) { if (getState() != Player::Online) {
QThread::sleep(1); QThread::sleep(1);
return ""; ret = "";
} else {
ret = router->waitForReply(timeout);
} }
return router->waitForReply(timeout); room->lockLua(__FUNCTION__);
return ret;
} }
void ServerPlayer::doNotify(const QString& command, const QString& jsonData) void ServerPlayer::doNotify(const QString& command, const QString& jsonData)

View File

@ -24,6 +24,7 @@ public:
void doRequest(const QString &command, void doRequest(const QString &command,
const QString &jsonData, int timeout = -1); const QString &jsonData, int timeout = -1);
void abortRequest();
QString waitForReply(int timeout); QString waitForReply(int timeout);
QString waitForReply(); QString waitForReply();
void doNotify(const QString &command, const QString &jsonData); void doNotify(const QString &command, const QString &jsonData);