Reconnect (#46)
* 1 * room:delay and other coroutine * yield in waitForReply * fix stack overflow bug * compress large message when transmiting * delete useless func * reconnect * update doc for reconnect
This commit is contained in:
parent
2ea7acfb7a
commit
a8cd7431ef
|
@ -83,9 +83,9 @@ ___
|
||||||
|
|
||||||
___
|
___
|
||||||
|
|
||||||
## 断线重连(TODO)
|
## 断线重连
|
||||||
|
|
||||||
根据用户名找到掉线的那位玩家,将玩家的状态设置为“在线”,并将房间的状态都发送给他即可。
|
根据用户id找到掉线的那位玩家,将玩家的状态设置为“在线”,并将房间的状态都发送给他即可。
|
||||||
|
|
||||||
但是为了[UI不出错](./ui.md#mainStack),依然需要对重连的玩家走一遍进大厅的流程。
|
但是为了[UI不出错](./ui.md#mainStack),依然需要对重连的玩家走一遍进大厅的流程。
|
||||||
|
|
||||||
|
@ -109,20 +109,30 @@ ___
|
||||||
3. 此外还需要让玩家知道牌堆、弃牌堆、轮数之类的。
|
3. 此外还需要让玩家知道牌堆、弃牌堆、轮数之类的。
|
||||||
4. 玩家的信息就更多了,武将、身份、血量、id...
|
4. 玩家的信息就更多了,武将、身份、血量、id...
|
||||||
|
|
||||||
信息要怎么发呢:
|
所以Lua要在某时候让出一段时间,处理重连等其他内容,可能还会处理一下AI。
|
||||||
|
|
||||||
- 一步一步的告诉重连中的玩家。
|
这种让出时间处理的东西时间要尽可能的短,不要在里面搞个大循环。
|
||||||
- 全部汇总成字符串或者别的什么,然后可以压缩并发送。
|
|
||||||
- 但以上两种都有问题:许多信息保存在Lua中,而Lua的运行是绝对不容其他线程打搅的。
|
|
||||||
- 而且粗略一想,这些东西都应该非常耗时,而如今的线程只有Main线程和各大Room线程。有必要给Room加个子线程专门处理掉线这块的,然后Room该怎么跑继续怎么跑。
|
|
||||||
|
|
||||||
或者换个思路:
|
会阻塞住lua代码的函数有:
|
||||||
|
|
||||||
1. 首先EnterRoom消息,需要**人数**和**操作时长**。
|
- ServerPlayer:waitForReplay()
|
||||||
2. 服务端将这个客户端的*录像信息*发给客户端,客户端满速且不影响UI的播放录像。
|
- Room:delay()
|
||||||
3. 在“播放录像”的过程中,客户端对于正在被收到的消息需进行特殊处理。
|
|
||||||
4. 一个录像文件的体积会非常大。所以服务端所保存的客户端录像应该和真正的录像有差别才行。比如聊天、战报这种数据量大但又无关紧要的东西就不保存。
|
在这里让出主线程,然后调度函数查找目前的请求列表。事实上,整个Room的游戏主流程就是一个协程:
|
||||||
5. 顺便这样也解决了多视角录像的问题,服务端给每个视角都录像就行了。
|
|
||||||
|
```lua
|
||||||
|
-- room.lua:53
|
||||||
|
local co_func = function()
|
||||||
|
self:run()
|
||||||
|
end
|
||||||
|
local co = coroutine.create(co_func)
|
||||||
|
while not self.game_finished do
|
||||||
|
local ret, err_msg = coroutine.resume(co)
|
||||||
|
...
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
如果在游戏流程中调用yield的话,那么这里的resume会返回true,然后可以带有额外的返回值。不过只要返回true就好了,这时候lua就可以做一些简单的任务。而这个简单的任务其实也可以另外写个协程解决。
|
||||||
|
|
||||||
___
|
___
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ function GameLogic:assignRoles()
|
||||||
local p = room.players[i]
|
local p = room.players[i]
|
||||||
p.role = roles[i]
|
p.role = roles[i]
|
||||||
if p.role == "lord" then
|
if p.role == "lord" then
|
||||||
|
p.role_shown = true
|
||||||
room:broadcastProperty(p, "role")
|
room:broadcastProperty(p, "role")
|
||||||
else
|
else
|
||||||
room:notifyProperty(p, p, "role")
|
room:notifyProperty(p, p, "role")
|
||||||
|
@ -168,7 +169,7 @@ function GameLogic:action()
|
||||||
if room.game_finished then break end
|
if room.game_finished then break end
|
||||||
room.current = room.current:getNextAlive()
|
room.current = room.current:getNextAlive()
|
||||||
if checkNoHuman() then
|
if checkNoHuman() then
|
||||||
room:gameOver()
|
room:gameOver("")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -50,17 +50,26 @@ function Room:initialize(_room)
|
||||||
|
|
||||||
self.room.startGame = function(_self)
|
self.room.startGame = function(_self)
|
||||||
Room.initialize(self, _room) -- clear old data
|
Room.initialize(self, _room) -- clear old data
|
||||||
local co_func = function()
|
local main_co = coroutine.create(function()
|
||||||
self:run()
|
self:run()
|
||||||
end
|
end)
|
||||||
local co = coroutine.create(co_func)
|
local request_co = coroutine.create(function()
|
||||||
|
self:requestLoop()
|
||||||
|
end)
|
||||||
while not self.game_finished do
|
while not self.game_finished do
|
||||||
local ret, err_msg = coroutine.resume(co)
|
local ret, err_msg = coroutine.resume(main_co)
|
||||||
|
|
||||||
-- handle error
|
-- handle error
|
||||||
if ret == false then
|
if ret == false then
|
||||||
fk.qCritical(err_msg)
|
fk.qCritical(err_msg)
|
||||||
print(debug.traceback(co))
|
print(debug.traceback(main_co))
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
ret, err_msg = coroutine.resume(request_co)
|
||||||
|
if ret == false then
|
||||||
|
fk.qCritical(err_msg)
|
||||||
|
print(debug.traceback(request_co))
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -383,6 +392,33 @@ function Room:doRaceRequest(command, players, jsonData)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- main loop for the request handling coroutine
|
||||||
|
function Room:requestLoop()
|
||||||
|
while true do
|
||||||
|
local request = self.room:fetchRequest()
|
||||||
|
if request ~= "" then
|
||||||
|
local id, command = table.unpack(request:split(","))
|
||||||
|
id = tonumber(id)
|
||||||
|
if command == "reconnect" then
|
||||||
|
self:getPlayerById(id):reconnect()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- delay function, should only be used in main coroutine
|
||||||
|
---@param ms integer @ millisecond to be delayed
|
||||||
|
function Room:delay(ms)
|
||||||
|
local start = fk.GetMicroSecond()
|
||||||
|
while true do
|
||||||
|
if fk.GetMicroSecond() - start >= ms * 1000 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---@param players ServerPlayer[]
|
---@param players ServerPlayer[]
|
||||||
---@param card_moves CardsMoveStruct[]
|
---@param card_moves CardsMoveStruct[]
|
||||||
---@param forceVisible boolean
|
---@param forceVisible boolean
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
---@field skipped_phases Phase[]
|
---@field skipped_phases Phase[]
|
||||||
---@field phase_state table[]
|
---@field phase_state table[]
|
||||||
---@field phase_index integer
|
---@field phase_index integer
|
||||||
|
---@field role_shown boolean
|
||||||
local ServerPlayer = Player:subclass("ServerPlayer")
|
local ServerPlayer = Player:subclass("ServerPlayer")
|
||||||
|
|
||||||
function ServerPlayer:initialize(_self)
|
function ServerPlayer:initialize(_self)
|
||||||
|
@ -50,18 +51,28 @@ function ServerPlayer:doRequest(command, jsonData, timeout)
|
||||||
self.serverplayer:doRequest(command, jsonData, timeout)
|
self.serverplayer:doRequest(command, jsonData, timeout)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function _waitForReply(player, timeout)
|
||||||
|
local result
|
||||||
|
local start = fk.GetMicroSecond()
|
||||||
|
while true do
|
||||||
|
result = player.serverplayer:waitForReply(0)
|
||||||
|
if result ~= "__notready" then
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
if timeout and (fk.GetMicroSecond() - start) / 1000 >= timeout * 1000 then
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Wait for at most *timeout* seconds for reply from client.
|
--- Wait for at most *timeout* seconds for reply from client.
|
||||||
---
|
---
|
||||||
--- If *timeout* is negative or **nil**, the function will wait forever until get reply.
|
--- If *timeout* is negative or **nil**, the function will wait forever until get reply.
|
||||||
---@param timeout integer @ seconds to wait
|
---@param timeout integer @ seconds to wait
|
||||||
---@return string @ JSON data
|
---@return string @ JSON data
|
||||||
function ServerPlayer:waitForReply(timeout)
|
function ServerPlayer:waitForReply(timeout)
|
||||||
local result = ""
|
local result = _waitForReply(self, timeout)
|
||||||
if timeout == nil then
|
|
||||||
result = self.serverplayer:waitForReply()
|
|
||||||
else
|
|
||||||
result = self.serverplayer:waitForReply(timeout)
|
|
||||||
end
|
|
||||||
self.request_data = ""
|
self.request_data = ""
|
||||||
self.client_reply = result
|
self.client_reply = result
|
||||||
if result == "__cancel" then
|
if result == "__cancel" then
|
||||||
|
@ -72,6 +83,130 @@ function ServerPlayer:waitForReply(timeout)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param player ServerPlayer
|
||||||
|
function ServerPlayer:marshal(player)
|
||||||
|
local room = self.room
|
||||||
|
room:notifyProperty(player, self, "maxHp")
|
||||||
|
room:notifyProperty(player, self, "hp")
|
||||||
|
-- TODO
|
||||||
|
--room:notifyProperty(player, self, "gender")
|
||||||
|
|
||||||
|
if self.kingdom ~= Fk.generals[self.general].kingdom then
|
||||||
|
room:notifyProperty(player, self, "kingdom")
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.dead then
|
||||||
|
room:notifyProperty(player, self, "dead")
|
||||||
|
room:notifyProperty(player, self, "role")
|
||||||
|
else
|
||||||
|
room:notifyProperty(player, self, "seat")
|
||||||
|
room:notifyProperty(player, self, "phase")
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self.faceup then
|
||||||
|
room:notifyProperty(player, self, "faceup")
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.chained then
|
||||||
|
room:notifyProperty(player, self, "chained")
|
||||||
|
end
|
||||||
|
|
||||||
|
local card_moves = {}
|
||||||
|
if #self.player_cards[Player.Hand] ~= 0 then
|
||||||
|
local info = {}
|
||||||
|
for _, i in ipairs(self.player_cards[Player.Hand]) do
|
||||||
|
table.insert(info, { cardId = i, fromArea = Card.DrawPile })
|
||||||
|
end
|
||||||
|
local move = {
|
||||||
|
moveInfo = info,
|
||||||
|
to = self.id,
|
||||||
|
toArea = Card.PlayerHand
|
||||||
|
}
|
||||||
|
table.insert(card_moves, move)
|
||||||
|
end
|
||||||
|
if #self.player_cards[Player.Equip] ~= 0 then
|
||||||
|
local info = {}
|
||||||
|
for _, i in ipairs(self.player_cards[Player.Equip]) do
|
||||||
|
table.insert(info, { cardId = i, fromArea = Card.DrawPile })
|
||||||
|
end
|
||||||
|
local move = {
|
||||||
|
moveInfo = info,
|
||||||
|
to = self.id,
|
||||||
|
toArea = Card.PlayerEquip
|
||||||
|
}
|
||||||
|
table.insert(card_moves, move)
|
||||||
|
end
|
||||||
|
if #self.player_cards[Player.Judge] ~= 0 then
|
||||||
|
local info = {}
|
||||||
|
for _, i in ipairs(self.player_cards[Player.Judge]) do
|
||||||
|
table.insert(info, { cardId = i, fromArea = Card.DrawPile })
|
||||||
|
end
|
||||||
|
local move = {
|
||||||
|
moveInfo = info,
|
||||||
|
to = self.id,
|
||||||
|
toArea = Card.PlayerJudge
|
||||||
|
}
|
||||||
|
table.insert(card_moves, move)
|
||||||
|
end
|
||||||
|
if #card_moves > 0 then
|
||||||
|
room:notifyMoveCards({ player }, card_moves)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: pile, mark
|
||||||
|
|
||||||
|
for _, s in ipairs(self.player_skills) do
|
||||||
|
player:doNotify("AddSkill", json.encode{self.id, s.name})
|
||||||
|
end
|
||||||
|
|
||||||
|
for k, v in pairs(self.cardUsedHistory) do
|
||||||
|
player:doNotify("AddCardUseHistory", json.encode{k, v})
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.role_shown then
|
||||||
|
room:notifyProperty(player, self, "role")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServerPlayer:reconnect()
|
||||||
|
local room = self.room
|
||||||
|
self.serverplayer:setStateString("online")
|
||||||
|
|
||||||
|
self:doNotify("Setup", json.encode{
|
||||||
|
self.id,
|
||||||
|
self.serverplayer:getScreenName(),
|
||||||
|
self.serverplayer:getAvatar(),
|
||||||
|
})
|
||||||
|
self:doNotify("EnterLobby", "")
|
||||||
|
self:doNotify("EnterRoom", json.encode{
|
||||||
|
#room.players, room.timeout,
|
||||||
|
})
|
||||||
|
room:notifyProperty(self, self, "role")
|
||||||
|
|
||||||
|
-- send player data
|
||||||
|
for _, p in ipairs(room:getOtherPlayers(self)) do
|
||||||
|
self:doNotify("AddPlayer", json.encode{
|
||||||
|
p.id,
|
||||||
|
p.serverplayer:getScreenName(),
|
||||||
|
p.serverplayer:getAvatar(),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local player_circle = {}
|
||||||
|
for i = 1, #room.players do
|
||||||
|
table.insert(player_circle, room.players[i].id)
|
||||||
|
end
|
||||||
|
self:doNotify("ArrangeSeats", json.encode(player_circle))
|
||||||
|
|
||||||
|
for _, p in ipairs(room.players) do
|
||||||
|
room:notifyProperty(self, p, "general")
|
||||||
|
p:marshal(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: tell drawPile
|
||||||
|
|
||||||
|
room:broadcastProperty(self, "state")
|
||||||
|
end
|
||||||
|
|
||||||
function ServerPlayer:isAlive()
|
function ServerPlayer:isAlive()
|
||||||
return self.dead == false
|
return self.dead == false
|
||||||
end
|
end
|
||||||
|
|
|
@ -35,8 +35,11 @@ void ClientSocket::connectToHost(const QString &address, ushort port)
|
||||||
void ClientSocket::getMessage()
|
void ClientSocket::getMessage()
|
||||||
{
|
{
|
||||||
while (socket->canReadLine()) {
|
while (socket->canReadLine()) {
|
||||||
char msg[16000]; // buffer
|
auto msg = socket->readLine();
|
||||||
socket->readLine(msg, sizeof(msg));
|
if (msg.startsWith("Compressed")) {
|
||||||
|
msg = msg.sliced(10);
|
||||||
|
msg = qUncompress(QByteArray::fromBase64(msg));
|
||||||
|
}
|
||||||
emit message_got(msg);
|
emit message_got(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +51,12 @@ void ClientSocket::disconnectFromHost()
|
||||||
|
|
||||||
void ClientSocket::send(const QByteArray &msg)
|
void ClientSocket::send(const QByteArray &msg)
|
||||||
{
|
{
|
||||||
|
if (msg.length() >= 1024) {
|
||||||
|
auto comp = qCompress(msg);
|
||||||
|
auto _msg = "Compressed" + comp.toBase64() + "\n";
|
||||||
|
socket->write(_msg);
|
||||||
|
socket->flush();
|
||||||
|
}
|
||||||
socket->write(msg);
|
socket->write(msg);
|
||||||
if (!msg.endsWith("\n"))
|
if (!msg.endsWith("\n"))
|
||||||
socket->write("\n");
|
socket->write("\n");
|
||||||
|
|
|
@ -70,7 +70,7 @@ void Router::request(int type, const QString& command,
|
||||||
expectedReplyId = requestId;
|
expectedReplyId = requestId;
|
||||||
replyTimeout = timeout;
|
replyTimeout = timeout;
|
||||||
requestStartTime = QDateTime::currentDateTime();
|
requestStartTime = QDateTime::currentDateTime();
|
||||||
m_reply = QString();
|
m_reply = "__notready";
|
||||||
replyMutex.unlock();
|
replyMutex.unlock();
|
||||||
|
|
||||||
QJsonArray body;
|
QJsonArray body;
|
||||||
|
@ -126,14 +126,6 @@ void Router::cancelRequest()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Router::waitForReply()
|
|
||||||
{
|
|
||||||
#ifndef Q_OS_WASM
|
|
||||||
replyReadySemaphore.acquire();
|
|
||||||
return m_reply;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Router::waitForReply(int timeout)
|
QString Router::waitForReply(int timeout)
|
||||||
{
|
{
|
||||||
#ifndef Q_OS_WASM
|
#ifndef Q_OS_WASM
|
||||||
|
|
|
@ -43,7 +43,6 @@ public:
|
||||||
void cancelRequest();
|
void cancelRequest();
|
||||||
void abortRequest();
|
void abortRequest();
|
||||||
|
|
||||||
QString waitForReply();
|
|
||||||
QString waitForReply(int timeout);
|
QString waitForReply(int timeout);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -29,9 +29,7 @@ Room::Room(Server* server)
|
||||||
|
|
||||||
Room::~Room()
|
Room::~Room()
|
||||||
{
|
{
|
||||||
// TODO
|
|
||||||
if (isRunning()) {
|
if (isRunning()) {
|
||||||
terminate();
|
|
||||||
wait();
|
wait();
|
||||||
}
|
}
|
||||||
if (L) lua_close(L);
|
if (L) lua_close(L);
|
||||||
|
@ -259,16 +257,6 @@ bool Room::isStarted() const
|
||||||
return gameStarted;
|
return gameStarted;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Room::doRequest(const QList<ServerPlayer *> targets, int timeout)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
void Room::doNotify(const QList<ServerPlayer *> targets, int timeout)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
void Room::doBroadcastNotify(const QList<ServerPlayer *> targets,
|
void Room::doBroadcastNotify(const QList<ServerPlayer *> targets,
|
||||||
const QString& command, const QString& jsonData)
|
const QString& command, const QString& jsonData)
|
||||||
{
|
{
|
||||||
|
@ -302,6 +290,22 @@ void Room::gameOver()
|
||||||
owner = nullptr;
|
owner = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Room::fetchRequest() {
|
||||||
|
request_queue_mutex.lock();
|
||||||
|
QString ret = "";
|
||||||
|
if (!request_queue.isEmpty()) {
|
||||||
|
ret = request_queue.dequeue();
|
||||||
|
}
|
||||||
|
request_queue_mutex.unlock();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::pushRequest(const QString &req) {
|
||||||
|
request_queue_mutex.lock();
|
||||||
|
request_queue.enqueue(req);
|
||||||
|
request_queue_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
void Room::run()
|
void Room::run()
|
||||||
{
|
{
|
||||||
gameStarted = true;
|
gameStarted = true;
|
||||||
|
|
|
@ -40,9 +40,6 @@ public:
|
||||||
bool isStarted() const;
|
bool isStarted() const;
|
||||||
// ====================================}
|
// ====================================}
|
||||||
|
|
||||||
void doRequest(const QList<ServerPlayer *> targets, int timeout);
|
|
||||||
void doNotify(const QList<ServerPlayer *> targets, int timeout);
|
|
||||||
|
|
||||||
void doBroadcastNotify(
|
void doBroadcastNotify(
|
||||||
const QList<ServerPlayer *> targets,
|
const QList<ServerPlayer *> targets,
|
||||||
const QString &command,
|
const QString &command,
|
||||||
|
@ -57,6 +54,9 @@ public:
|
||||||
void roomStart();
|
void roomStart();
|
||||||
LuaFunction startGame;
|
LuaFunction startGame;
|
||||||
|
|
||||||
|
QString fetchRequest();
|
||||||
|
void pushRequest(const QString &req);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void abandoned();
|
void abandoned();
|
||||||
|
|
||||||
|
@ -82,7 +82,8 @@ private:
|
||||||
int timeout;
|
int timeout;
|
||||||
|
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
QMutex lua_mutex;
|
QMutex request_queue_mutex;
|
||||||
|
QQueue<QString> request_queue; // json string
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _ROOM_H
|
#endif // _ROOM_H
|
||||||
|
|
|
@ -240,10 +240,18 @@ void Server::handleNameAndPassword(ClientSocket *client, const QString& name, co
|
||||||
passed = (passwordHash == arr[0].toString());
|
passed = (passwordHash == arr[0].toString());
|
||||||
if (!passed) error_msg = "username or password error";
|
if (!passed) error_msg = "username or password error";
|
||||||
} else {
|
} else {
|
||||||
// TODO: reconnect here
|
auto player = players.value(id);
|
||||||
|
if (player->getState() == Player::Offline) {
|
||||||
|
auto room = player->getRoom();
|
||||||
|
player->setSocket(client);
|
||||||
|
client->disconnect(this);
|
||||||
|
room->pushRequest(QString("%1,reconnect").arg(id));
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
error_msg = "others logged in with this name";
|
error_msg = "others logged in with this name";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error_msg = "invalid user name";
|
error_msg = "invalid user name";
|
||||||
}
|
}
|
||||||
|
@ -289,7 +297,6 @@ void Server::onRoomAbandoned()
|
||||||
updateRoomList();
|
updateRoomList();
|
||||||
//room->deleteLater();
|
//room->deleteLater();
|
||||||
if (room->isRunning()) {
|
if (room->isRunning()) {
|
||||||
room->terminate();
|
|
||||||
room->wait();
|
room->wait();
|
||||||
}
|
}
|
||||||
idle_rooms.push(room);
|
idle_rooms.push(room);
|
||||||
|
@ -306,6 +313,7 @@ void Server::onUserDisconnected()
|
||||||
Room *room = player->getRoom();
|
Room *room = player->getRoom();
|
||||||
if (room->isStarted()) {
|
if (room->isStarted()) {
|
||||||
player->setState(Player::Offline);
|
player->setState(Player::Offline);
|
||||||
|
player->setSocket(nullptr);
|
||||||
// TODO: add a robot
|
// TODO: add a robot
|
||||||
} else {
|
} else {
|
||||||
player->deleteLater();
|
player->deleteLater();
|
||||||
|
|
|
@ -80,20 +80,6 @@ void ServerPlayer::abortRequest()
|
||||||
router->abortRequest();
|
router->abortRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ServerPlayer::waitForReply()
|
|
||||||
{
|
|
||||||
QString ret;
|
|
||||||
Player::State state = getState();
|
|
||||||
if (state != Player::Online) {
|
|
||||||
if (state != Player::Run)
|
|
||||||
QThread::sleep(1);
|
|
||||||
ret = QString("__state=%1").arg(getStateString());
|
|
||||||
} else {
|
|
||||||
ret = router->waitForReply();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ServerPlayer::waitForReply(int timeout)
|
QString ServerPlayer::waitForReply(int timeout)
|
||||||
{
|
{
|
||||||
QString ret;
|
QString ret;
|
||||||
|
|
|
@ -27,7 +27,6 @@ public:
|
||||||
const QString &jsonData, int timeout = -1);
|
const QString &jsonData, int timeout = -1);
|
||||||
void abortRequest();
|
void abortRequest();
|
||||||
QString waitForReply(int timeout);
|
QString waitForReply(int timeout);
|
||||||
QString waitForReply();
|
|
||||||
void doNotify(const QString &command, const QString &jsonData);
|
void doNotify(const QString &command, const QString &jsonData);
|
||||||
|
|
||||||
void prepareForRequest(const QString &command,
|
void prepareForRequest(const QString &command,
|
||||||
|
|
|
@ -42,8 +42,6 @@ public:
|
||||||
bool isStarted() const;
|
bool isStarted() const;
|
||||||
// ====================================}
|
// ====================================}
|
||||||
|
|
||||||
void doRequest(const QList<ServerPlayer *> targets, int timeout);
|
|
||||||
void doNotify(const QList<ServerPlayer *> targets, int timeout);
|
|
||||||
void doBroadcastNotify(
|
void doBroadcastNotify(
|
||||||
const QList<ServerPlayer *> targets,
|
const QList<ServerPlayer *> targets,
|
||||||
const QString &command,
|
const QString &command,
|
||||||
|
@ -53,6 +51,7 @@ public:
|
||||||
void gameOver();
|
void gameOver();
|
||||||
|
|
||||||
LuaFunction startGame;
|
LuaFunction startGame;
|
||||||
|
QString fetchRequest();
|
||||||
};
|
};
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
@ -105,7 +104,6 @@ public:
|
||||||
|
|
||||||
void doRequest(const QString &command,
|
void doRequest(const QString &command,
|
||||||
const QString &json_data, int timeout);
|
const QString &json_data, int timeout);
|
||||||
QString waitForReply();
|
|
||||||
QString waitForReply(int timeout);
|
QString waitForReply(int timeout);
|
||||||
void doNotify(const QString &command, const QString &json_data);
|
void doNotify(const QString &command, const QString &json_data);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue