Disable sync (#21)
* fix running from running room * fix: ~serverplayer() * since room player's id won't change anymore, don't use :getId() * we won't access lua from other thread, so drop the mutex * bugfix
This commit is contained in:
parent
5628e67a78
commit
60b9839fd7
|
@ -43,7 +43,11 @@ fk.client_callback["Setup"] = function(jsonData)
|
|||
self:setScreenName(name)
|
||||
self:setAvatar(avatar)
|
||||
Self = ClientPlayer:new(fk.Self)
|
||||
table.insert(ClientInstance.players, Self)
|
||||
end
|
||||
|
||||
fk.client_callback["EnterRoom"] = function(jsonData)
|
||||
ClientInstance.players = {Self}
|
||||
ClientInstance:notifyUI("EnterRoom", jsonData)
|
||||
end
|
||||
|
||||
fk.client_callback["AddPlayer"] = function(jsonData)
|
||||
|
|
|
@ -150,10 +150,22 @@ function GameLogic:action()
|
|||
self:trigger(fk.DrawInitialCards, p, { num = 4 })
|
||||
end
|
||||
|
||||
local function checkNoHuman()
|
||||
for _, p in ipairs(room.players) do
|
||||
if p.serverplayer:getStateString() == "online" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
while true do
|
||||
self:trigger(fk.TurnStart, room.current)
|
||||
if room.game_finished then break end
|
||||
room.current = room.current:getNextAlive()
|
||||
if checkNoHuman() then
|
||||
room:gameOver()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -52,7 +52,6 @@ end
|
|||
function Room:run()
|
||||
for _, p in fk.qlist(self.room:getPlayers()) do
|
||||
local player = ServerPlayer:new(p)
|
||||
player.state = p:getStateString()
|
||||
player.room = self
|
||||
table.insert(self.players, player)
|
||||
end
|
||||
|
@ -74,7 +73,7 @@ end
|
|||
---@param property string
|
||||
function Room:notifyProperty(p, player, property)
|
||||
p:doNotify("PropertyUpdate", json.encode{
|
||||
player:getId(),
|
||||
player.id,
|
||||
property,
|
||||
player[property],
|
||||
})
|
||||
|
@ -134,7 +133,7 @@ function Room:notifyMoveFocus(players, command)
|
|||
|
||||
local ids = {}
|
||||
for _, p in ipairs(players) do
|
||||
table.insert(ids, p:getId())
|
||||
table.insert(ids, p.id)
|
||||
end
|
||||
|
||||
self:doBroadcastNotify("MoveFocus", json.encode{
|
||||
|
@ -165,7 +164,7 @@ function Room:adjustSeats()
|
|||
local player_circle = {}
|
||||
for i = 1, #self.players do
|
||||
self.players[i].seat = i
|
||||
table.insert(player_circle, self.players[i]:getId())
|
||||
table.insert(player_circle, self.players[i].id)
|
||||
end
|
||||
|
||||
self:doBroadcastNotify("ArrangeSeats", json.encode(player_circle))
|
||||
|
@ -233,7 +232,7 @@ function Room:notifyMoveCards(players, card_moves, forceVisible)
|
|||
-- FIXME: move.moveInfo is an array, fix this
|
||||
move.moveVisible = (forceVisible)
|
||||
-- if move is relevant to player, it should be open
|
||||
or ((move.from == p:getId()) or (move.to == p:getId() and move.toArea ~= Card.PlayerSpecial))
|
||||
or ((move.from == p.id) or (move.to == p.id and move.toArea ~= Card.PlayerSpecial))
|
||||
-- cards move from/to equip/judge/discard/processing should be open
|
||||
or move.moveInfo.fromArea == Card.PlayerEquip
|
||||
or move.toArea == Card.PlayerEquip
|
||||
|
@ -364,10 +363,10 @@ function Room:drawCards(player, num, skillName, fromPlace)
|
|||
local topCards = self:getNCards(num, fromPlace)
|
||||
self:moveCards({
|
||||
ids = topCards,
|
||||
to = player:getId(),
|
||||
to = player.id,
|
||||
toArea = Card.PlayerHand,
|
||||
moveReason = fk.ReasonDraw,
|
||||
proposer = player:getId(),
|
||||
proposer = player.id,
|
||||
skillName = skillName,
|
||||
})
|
||||
|
||||
|
@ -394,10 +393,10 @@ function Room:askForDiscard(player, minNum, maxNum, includeEquip, skillName)
|
|||
|
||||
self:moveCards({
|
||||
ids = toDiscard,
|
||||
from = player:getId(),
|
||||
from = player.id,
|
||||
toArea = Card.DiscardPile,
|
||||
moveReason = fk.ReasonDiscard,
|
||||
proposer = player:getId(),
|
||||
proposer = player.id,
|
||||
skillName = skillName
|
||||
})
|
||||
end
|
||||
|
@ -408,7 +407,7 @@ function Room:getPlayerById(id)
|
|||
assert(type(id) == "number")
|
||||
|
||||
for _, p in ipairs(self.players) do
|
||||
if p:getId() == id then
|
||||
if p.id == id then
|
||||
return p
|
||||
end
|
||||
end
|
||||
|
@ -453,7 +452,7 @@ end
|
|||
function Room:getOtherPlayers(player, sortBySeat)
|
||||
local alivePlayers = self:getAlivePlayers(sortBySeat)
|
||||
for _, p in ipairs(alivePlayers) do
|
||||
if p:getId() == player:getId() then
|
||||
if p.id == player.id then
|
||||
table.removeOne(alivePlayers, player)
|
||||
break
|
||||
end
|
||||
|
@ -568,7 +567,7 @@ function Room:changeHp(player, num, reason, skillName, damageStruct)
|
|||
if player.hp < 1 then
|
||||
---@type DyingStruct
|
||||
local dyingStruct = {
|
||||
who = player:getId(),
|
||||
who = player.id,
|
||||
damage = damageStruct,
|
||||
}
|
||||
self:enterDying(dyingStruct)
|
||||
|
@ -624,7 +623,7 @@ function Room:changeMaxHp(player, num)
|
|||
end
|
||||
|
||||
if player.maxHp == 0 then
|
||||
self:killPlayer({ who = player:getId() })
|
||||
self:killPlayer({ who = player.id })
|
||||
end
|
||||
|
||||
self.logic:trigger(fk.MaxHpChanged, player, { num = num })
|
||||
|
@ -718,7 +717,7 @@ function Room:enterDying(dyingStruct)
|
|||
if dyingPlayer.hp < 1 then
|
||||
---@type DeathStruct
|
||||
local deathData = {
|
||||
who = dyingPlayer:getId(),
|
||||
who = dyingPlayer.id,
|
||||
damage = dyingStruct.damage,
|
||||
}
|
||||
self:killPlayer(deathData)
|
||||
|
@ -976,45 +975,6 @@ fk.room_callback["AddRobot"] = function(jsonData)
|
|||
end
|
||||
end
|
||||
|
||||
fk.room_callback["PlayerRunned"] = function(jsonData)
|
||||
-- jsonData: [ int runner_id, int robot_id ]
|
||||
-- note: this function is not called by Router.
|
||||
-- note: when this function is called, the room must be started
|
||||
local data = json.decode(jsonData)
|
||||
local runner = data[1]
|
||||
local robot = data[2]
|
||||
for _, p in ipairs(RoomInstance.players) do
|
||||
if p:getId() == runner then
|
||||
p.serverplayer = RoomInstance.room:findPlayer(robot)
|
||||
p.id = p.serverplayer:getId()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
fk.room_callback["PlayerStateChanged"] = function(jsonData)
|
||||
-- jsonData: [ int uid, string stateString ]
|
||||
-- note: this function is not called by Router.
|
||||
-- note: when this function is called, the room must be started
|
||||
local data = json.decode(jsonData)
|
||||
local id = data[1]
|
||||
local stateString = data[2]
|
||||
RoomInstance:getPlayerById(id).state = stateString
|
||||
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)
|
||||
-- jsonData: [ int uid, string luaScript ]
|
||||
-- warning: only use this in debugging mode.
|
||||
if not DebugMode then return end
|
||||
local data = json.decode(jsonData)
|
||||
assert(load(data[2]))()
|
||||
end
|
||||
|
||||
function CreateRoom(_room)
|
||||
RoomInstance = Room:new(_room)
|
||||
end
|
||||
|
|
|
@ -15,6 +15,7 @@ function ServerPlayer:initialize(_self)
|
|||
Player.initialize(self)
|
||||
self.serverplayer = _self
|
||||
self.id = _self:getId()
|
||||
self.state = _self:getStateString()
|
||||
self.room = nil
|
||||
|
||||
self.next = nil
|
||||
|
@ -27,11 +28,6 @@ function ServerPlayer:initialize(_self)
|
|||
self.phases = {}
|
||||
end
|
||||
|
||||
---@return integer
|
||||
function ServerPlayer:getId()
|
||||
return self.id
|
||||
end
|
||||
|
||||
---@param command string
|
||||
---@param jsonData string
|
||||
function ServerPlayer:doNotify(command, jsonData)
|
||||
|
|
|
@ -33,7 +33,7 @@ GameRule = fk.CreateTriggerSkill{
|
|||
player:addCards(Player.Hand, cardIds)
|
||||
local move_to_notify = {} ---@type CardsMoveStruct
|
||||
move_to_notify.toArea = Card.PlayerHand
|
||||
move_to_notify.to = player:getId()
|
||||
move_to_notify.to = player.id
|
||||
move_to_notify.moveInfo = {}
|
||||
for _, id in ipairs(cardIds) do
|
||||
table.insert(move_to_notify.moveInfo,
|
||||
|
@ -85,14 +85,14 @@ GameRule = fk.CreateTriggerSkill{
|
|||
[Player.Play] = function()
|
||||
while not player.dead do
|
||||
room:notifyMoveFocus(player, "PlayCard")
|
||||
local result = room:doRequest(player, "PlayCard", player:getId())
|
||||
local result = room:doRequest(player, "PlayCard", player.id)
|
||||
if result == "" then break end
|
||||
|
||||
local data = json.decode(result)
|
||||
local card = data.card
|
||||
local targets = data.targets
|
||||
local use = {} ---@type CardUseStruct
|
||||
use.from = player:getId()
|
||||
use.from = player.id
|
||||
use.tos = {}
|
||||
for _, target in ipairs(targets) do
|
||||
table.insert(use.tos, { target })
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Window 2.0
|
||||
import QtQuick.Window 2.15
|
||||
import "Logic.js" as Logic
|
||||
import "Pages"
|
||||
|
||||
|
@ -130,4 +130,8 @@ Window {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
onClosing: {
|
||||
Backend.quitLobby();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,8 @@ QString Player::getStateString() const
|
|||
return QStringLiteral("online");
|
||||
case Trust:
|
||||
return QStringLiteral("trust");
|
||||
case Run:
|
||||
return QStringLiteral("run");
|
||||
case Robot:
|
||||
return QStringLiteral("robot");
|
||||
case Offline:
|
||||
|
@ -77,6 +79,8 @@ void Player::setStateString(const QString &state)
|
|||
setState(Online);
|
||||
else if (state == QStringLiteral("trust"))
|
||||
setState(Trust);
|
||||
else if (state == QStringLiteral("run"))
|
||||
setState(Run);
|
||||
else if (state == QStringLiteral("robot"))
|
||||
setState(Robot);
|
||||
else if (state == QStringLiteral("offline"))
|
||||
|
|
|
@ -10,7 +10,8 @@ public:
|
|||
enum State{
|
||||
Invalid,
|
||||
Online,
|
||||
Trust, // Trust or run
|
||||
Trust,
|
||||
Run,
|
||||
Robot, // only for real robot
|
||||
Offline
|
||||
};
|
||||
|
|
|
@ -161,9 +161,7 @@ void Router::handlePacket(const QByteArray& rawPacket)
|
|||
arr.prepend(player->getId());
|
||||
|
||||
Room *room = player->getRoom();
|
||||
room->lockLua(__FUNCTION__);
|
||||
room->callLua(command, QJsonDocument(arr).toJson());
|
||||
room->unlockLua(__FUNCTION__);
|
||||
}
|
||||
}
|
||||
else if (type & TYPE_REQUEST) {
|
||||
|
|
|
@ -32,8 +32,6 @@ Room::~Room()
|
|||
{
|
||||
// TODO
|
||||
if (isRunning()) {
|
||||
callLua("RoomDeleted", "");
|
||||
unlockLua(__FUNCTION__);
|
||||
wait();
|
||||
}
|
||||
lua_close(L);
|
||||
|
@ -173,44 +171,39 @@ void Room::addRobot(ServerPlayer *player)
|
|||
|
||||
void Room::removePlayer(ServerPlayer *player)
|
||||
{
|
||||
if (!gameStarted) {
|
||||
players.removeOne(player);
|
||||
emit playerRemoved(player);
|
||||
|
||||
if (isLobby()) return;
|
||||
|
||||
if (gameStarted) {
|
||||
// TODO: if the player is died..
|
||||
|
||||
// create robot first
|
||||
ServerPlayer *robot = new ServerPlayer(this);
|
||||
robot->setState(Player::Robot);
|
||||
robot->setId(robot_id);
|
||||
robot->setAvatar(player->getAvatar());
|
||||
robot->setScreenName(QString("COMP-%1").arg(robot_id));
|
||||
robot_id--;
|
||||
|
||||
players.append(robot);
|
||||
|
||||
// tell lua & clients
|
||||
QJsonArray jsonData;
|
||||
jsonData << player->getId();
|
||||
jsonData << robot->getId();
|
||||
callLua("PlayerRunned", QJsonDocument(jsonData).toJson());
|
||||
doBroadcastNotify(getPlayers(), "PlayerRunned", QJsonDocument(jsonData).toJson());
|
||||
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 {
|
||||
QJsonArray jsonData;
|
||||
jsonData << player->getId();
|
||||
doBroadcastNotify(getPlayers(), "RemovePlayer", QJsonDocument(jsonData).toJson());
|
||||
|
||||
if (isLobby()) return;
|
||||
} else {
|
||||
// TODO: if the player is died..
|
||||
|
||||
// change the socket and state to runned player
|
||||
ClientSocket *socket = player->getSocket();
|
||||
player->setState(Player::Run);
|
||||
|
||||
// and then create a new ServerPlayer for the runner
|
||||
ServerPlayer *runner = new ServerPlayer(this);
|
||||
runner->setSocket(socket);
|
||||
connect(runner, &ServerPlayer::disconnected, server, &Server::onUserDisconnected);
|
||||
connect(runner, &Player::stateChanged, server, &Server::onUserStateChanged);
|
||||
runner->setScreenName(player->getScreenName());
|
||||
runner->setAvatar(player->getAvatar());
|
||||
runner->setId(player->getId());
|
||||
|
||||
// finally update Server's player list and clean
|
||||
server->addPlayer(runner);
|
||||
|
||||
emit playerRemoved(runner);
|
||||
runner->abortRequest();
|
||||
}
|
||||
|
||||
if (isAbandoned()) {
|
||||
// FIXME: do not delete room here
|
||||
// create a new thread and delete the room
|
||||
emit abandoned();
|
||||
} else if (player == owner) {
|
||||
setOwner(players.first());
|
||||
|
@ -283,28 +276,8 @@ 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()
|
||||
{
|
||||
gameStarted = true;
|
||||
lockLua(__FUNCTION__);
|
||||
roomStart();
|
||||
unlockLua(__FUNCTION__);
|
||||
}
|
||||
|
|
|
@ -56,9 +56,6 @@ public:
|
|||
void roomStart();
|
||||
LuaFunction startGame;
|
||||
|
||||
void lockLua(const QString &caller);
|
||||
void unlockLua(const QString &caller);
|
||||
|
||||
signals:
|
||||
void abandoned();
|
||||
|
||||
|
|
|
@ -67,6 +67,15 @@ ServerPlayer *Server::findPlayer(int id) const
|
|||
return players.value(id);
|
||||
}
|
||||
|
||||
void Server::addPlayer(ServerPlayer *player)
|
||||
{
|
||||
int id = player->getId();
|
||||
if (players.contains(id))
|
||||
players.remove(id);
|
||||
|
||||
players.insert(id, player);
|
||||
}
|
||||
|
||||
void Server::removePlayer(int id) {
|
||||
players.remove(id);
|
||||
}
|
||||
|
@ -252,10 +261,4 @@ void Server::onUserDisconnected()
|
|||
}
|
||||
|
||||
void Server::onUserStateChanged()
|
||||
{
|
||||
ServerPlayer *player = qobject_cast<ServerPlayer *>(sender());
|
||||
QJsonArray arr;
|
||||
arr << player->getId();
|
||||
arr << player->getStateString();
|
||||
player->getRoom()->callLua("PlayerStateChanged", QJsonDocument(arr).toJson());
|
||||
}
|
||||
{}
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
Room *lobby() const;
|
||||
|
||||
ServerPlayer *findPlayer(int id) const;
|
||||
void addPlayer(ServerPlayer *player);
|
||||
void removePlayer(int id);
|
||||
|
||||
void updateRoomList();
|
||||
|
|
|
@ -21,6 +21,7 @@ ServerPlayer::~ServerPlayer()
|
|||
// now we are in lobby, so quit lobby
|
||||
room->removePlayer(this);
|
||||
}
|
||||
if (server->findPlayer(getId()) == this)
|
||||
server->removePlayer(getId());
|
||||
router->deleteLater();
|
||||
}
|
||||
|
@ -42,6 +43,11 @@ void ServerPlayer::setSocket(ClientSocket *socket)
|
|||
router->setSocket(socket);
|
||||
}
|
||||
|
||||
ClientSocket *ServerPlayer::getSocket() const
|
||||
{
|
||||
return socket;
|
||||
}
|
||||
|
||||
Server *ServerPlayer::getServer() const
|
||||
{
|
||||
return server;
|
||||
|
@ -76,21 +82,20 @@ void ServerPlayer::abortRequest()
|
|||
|
||||
QString ServerPlayer::waitForReply()
|
||||
{
|
||||
room->unlockLua(__FUNCTION__);
|
||||
QString ret;
|
||||
if (getState() != Player::Online) {
|
||||
Player::State state = getState();
|
||||
if (state != Player::Online) {
|
||||
if (state != Player::Run)
|
||||
QThread::sleep(1);
|
||||
ret = "";
|
||||
ret = QString("__state=%1").arg(getStateString());
|
||||
} else {
|
||||
ret = router->waitForReply();
|
||||
}
|
||||
room->lockLua(__FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString ServerPlayer::waitForReply(int timeout)
|
||||
{
|
||||
room->unlockLua(__FUNCTION__);
|
||||
QString ret;
|
||||
if (getState() != Player::Online) {
|
||||
QThread::sleep(1);
|
||||
|
@ -98,7 +103,6 @@ QString ServerPlayer::waitForReply(int timeout)
|
|||
} else {
|
||||
ret = router->waitForReply(timeout);
|
||||
}
|
||||
room->lockLua(__FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ public:
|
|||
~ServerPlayer();
|
||||
|
||||
void setSocket(ClientSocket *socket);
|
||||
ClientSocket *getSocket() const;
|
||||
|
||||
Server *getServer() const;
|
||||
Room *getRoom() const;
|
||||
|
|
|
@ -58,6 +58,7 @@ void QmlBackend::joinServer(QString address)
|
|||
|
||||
void QmlBackend::quitLobby()
|
||||
{
|
||||
if (ClientInstance)
|
||||
delete ClientInstance;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue