1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-23 00:28:08 +02:00

Remove connection pointer from CPack

This commit is contained in:
Ivan Savenko
2025-03-01 17:50:52 +00:00
parent 9f713a0914
commit 2fdf40e7a9
13 changed files with 194 additions and 238 deletions

View File

@ -628,6 +628,22 @@ std::string GameResID::entityType()
return "resource"; return "resource";
} }
const std::array<PlayerColor, PlayerColor::PLAYER_LIMIT_I> & PlayerColor::ALL_PLAYERS()
{
static const std::array allPlayers = {
PlayerColor(0),
PlayerColor(1),
PlayerColor(2),
PlayerColor(3),
PlayerColor(4),
PlayerColor(5),
PlayerColor(6),
PlayerColor(7)
};
return allPlayers;
}
const std::array<PrimarySkill, 4> & PrimarySkill::ALL_SKILLS() const std::array<PrimarySkill, 4> & PrimarySkill::ALL_SKILLS()
{ {
static const std::array allSkills = { static const std::array allSkills = {

View File

@ -144,6 +144,8 @@ public:
static const PlayerColor NEUTRAL; //255 static const PlayerColor NEUTRAL; //255
static const PlayerColor PLAYER_LIMIT; //player limit per map static const PlayerColor PLAYER_LIMIT; //player limit per map
static const std::array<PlayerColor, PLAYER_LIMIT_I> & ALL_PLAYERS();
bool isValidPlayer() const; //valid means < PLAYER_LIMIT (especially non-neutral) bool isValidPlayer() const; //valid means < PLAYER_LIMIT (especially non-neutral)
bool isSpectator() const; bool isSpectator() const;

View File

@ -21,10 +21,6 @@ class ICPackVisitor;
struct DLL_LINKAGE CPack : public Serializeable struct DLL_LINKAGE CPack : public Serializeable
{ {
/// Pointer to connection that pack received from
/// Only set & used on server
std::shared_ptr<CConnection> c;
CPack() = default; CPack() = default;
virtual ~CPack() = default; virtual ~CPack() = default;

View File

@ -129,9 +129,9 @@ events::EventBus * CGameHandler::eventBus() const
return serverEventBus.get(); return serverEventBus.get();
} }
CVCMIServer * CGameHandler::gameLobby() const CVCMIServer & CGameHandler::gameLobby() const
{ {
return lobby; return *lobby;
} }
void CGameHandler::levelUpHero(const CGHeroInstance * hero, SecondarySkill skill) void CGameHandler::levelUpHero(const CGHeroInstance * hero, SecondarySkill skill)
@ -421,7 +421,7 @@ void CGameHandler::changeSecSkill(const CGHeroInstance * hero, SecondarySkill wh
void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c) void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
{ {
if(lobby->getState() == EServerState::SHUTDOWN || !gs || !gs->scenarioOps) if(gameLobby().getState() == EServerState::SHUTDOWN || !gs || !gs->scenarioOps)
{ {
assert(0); // game should have shut down before reaching this point! assert(0); // game should have shut down before reaching this point!
return; return;
@ -461,7 +461,7 @@ void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
} }
} }
void CGameHandler::handleReceivedPack(CPackForServer & pack) void CGameHandler::handleReceivedPack(std::shared_ptr<CConnection> connection, CPackForServer & pack)
{ {
//prepare struct informing that action was applied //prepare struct informing that action was applied
auto sendPackageResponse = [&](bool successfullyApplied) auto sendPackageResponse = [&](bool successfullyApplied)
@ -471,7 +471,7 @@ void CGameHandler::handleReceivedPack(CPackForServer & pack)
applied.result = successfullyApplied; applied.result = successfullyApplied;
applied.packType = CTypeList::getInstance().getTypeID(&pack); applied.packType = CTypeList::getInstance().getTypeID(&pack);
applied.requestID = pack.requestID; applied.requestID = pack.requestID;
pack.c->sendPack(applied); connection->sendPack(applied);
}; };
if(isBlockedByQueries(&pack, pack.player)) if(isBlockedByQueries(&pack, pack.player))
@ -483,7 +483,7 @@ void CGameHandler::handleReceivedPack(CPackForServer & pack)
bool result; bool result;
try try
{ {
ApplyGhNetPackVisitor applier(*this); ApplyGhNetPackVisitor applier(*this, connection);
pack.visit(applier); pack.visit(applier);
result = applier.getResult(); result = applier.getResult();
} }
@ -709,9 +709,9 @@ void CGameHandler::start(bool resume)
{ {
LOG_TRACE_PARAMS(logGlobal, "resume=%d", resume); LOG_TRACE_PARAMS(logGlobal, "resume=%d", resume);
for (auto cc : lobby->activeConnections) for (auto cc : gameLobby().activeConnections)
{ {
auto players = lobby->getAllClientPlayers(cc->connectionID); auto players = gameLobby().getAllClientPlayers(cc->connectionID);
std::stringstream sbuffer; std::stringstream sbuffer;
sbuffer << "Connection " << cc->connectionID << " will handle " << players.size() << " player: "; sbuffer << "Connection " << cc->connectionID << " will handle " << players.size() << " player: ";
for (PlayerColor color : players) for (PlayerColor color : players)
@ -1439,7 +1439,7 @@ void CGameHandler::heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)
void CGameHandler::sendToAllClients(CPackForClient & pack) void CGameHandler::sendToAllClients(CPackForClient & pack)
{ {
logNetwork->trace("\tSending to all clients: %s", typeid(pack).name()); logNetwork->trace("\tSending to all clients: %s", typeid(pack).name());
for (auto c : lobby->activeConnections) for (auto c : gameLobby().activeConnections)
c->sendPack(pack); c->sendPack(pack);
} }
@ -1468,64 +1468,62 @@ void CGameHandler::sendAndApply(NewStructures & pack)
checkVictoryLossConditionsForPlayer(getTown(pack.tid)->tempOwner); checkVictoryLossConditionsForPlayer(getTown(pack.tid)->tempOwner);
} }
bool CGameHandler::isPlayerOwns(CPackForServer * pack, ObjectInstanceID id) bool CGameHandler::isPlayerOwns(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack, ObjectInstanceID id)
{ {
return pack->player == getOwner(id) && hasPlayerAt(getOwner(id), pack->c); return pack->player == getOwner(id) && hasPlayerAt(getOwner(id), connection);
} }
void CGameHandler::throwNotAllowedAction(CPackForServer * pack) void CGameHandler::throwNotAllowedAction(const std::shared_ptr<CConnection> & connection)
{ {
if(pack->c) playerMessages->sendSystemMessage(connection, MetaString::createFromTextID("vcmi.server.errors.notAllowed"));
playerMessages->sendSystemMessage(pack->c, MetaString::createFromTextID("vcmi.server.errors.notAllowed"));
logNetwork->error("Player is not allowed to perform this action!"); logNetwork->error("Player is not allowed to perform this action!");
throw ExceptionNotAllowedAction(); throw ExceptionNotAllowedAction();
} }
void CGameHandler::wrongPlayerMessage(CPackForServer * pack, PlayerColor expectedplayer) void CGameHandler::wrongPlayerMessage(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack, PlayerColor expectedplayer)
{ {
auto str = MetaString::createFromTextID("vcmi.server.errors.wrongIdentified"); auto str = MetaString::createFromTextID("vcmi.server.errors.wrongIdentified");
str.appendName(pack->player); str.appendName(pack->player);
str.appendName(expectedplayer); str.appendName(expectedplayer);
logNetwork->error(str.toString()); logNetwork->error(str.toString());
if(pack->c) playerMessages->sendSystemMessage(connection, str);
playerMessages->sendSystemMessage(pack->c, str);
} }
void CGameHandler::throwIfWrongOwner(CPackForServer * pack, ObjectInstanceID id) void CGameHandler::throwIfWrongOwner(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack, ObjectInstanceID id)
{ {
if(!isPlayerOwns(pack, id)) if(!isPlayerOwns(connection, pack, id))
{ {
wrongPlayerMessage(pack, getOwner(id)); wrongPlayerMessage(connection, pack, getOwner(id));
throwNotAllowedAction(pack); throwNotAllowedAction(connection);
} }
} }
void CGameHandler::throwIfPlayerNotActive(CPackForServer * pack) void CGameHandler::throwIfPlayerNotActive(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack)
{ {
if (!turnOrder->isPlayerMakingTurn(pack->player)) if (!turnOrder->isPlayerMakingTurn(pack->player))
throwNotAllowedAction(pack); throwNotAllowedAction(connection);
} }
void CGameHandler::throwIfWrongPlayer(CPackForServer * pack) void CGameHandler::throwIfWrongPlayer(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack)
{ {
throwIfWrongPlayer(pack, pack->player); throwIfWrongPlayer(connection, pack, pack->player);
} }
void CGameHandler::throwIfWrongPlayer(CPackForServer * pack, PlayerColor player) void CGameHandler::throwIfWrongPlayer(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack, PlayerColor player)
{ {
if(!hasPlayerAt(player, pack->c) || pack->player != player) if(!hasPlayerAt(player, connection) || pack->player != player)
{ {
wrongPlayerMessage(pack, player); wrongPlayerMessage(connection, pack, player);
throwNotAllowedAction(pack); throwNotAllowedAction(connection);
} }
} }
void CGameHandler::throwAndComplain(CPackForServer * pack, std::string txt) void CGameHandler::throwAndComplain(const std::shared_ptr<CConnection> & connection, std::string txt)
{ {
complain(txt); complain(txt);
throwNotAllowedAction(pack); throwNotAllowedAction(connection);
} }
void CGameHandler::save(const std::string & filename) void CGameHandler::save(const std::string & filename)
@ -1586,7 +1584,7 @@ bool CGameHandler::load(const std::string & filename)
errorMsg.appendRawString("\n"); errorMsg.appendRawString("\n");
errorMsg.appendRawString(e.whatExcessive()); errorMsg.appendRawString(e.whatExcessive());
} }
lobby->announceMessage(errorMsg); gameLobby().announceMessage(errorMsg);
return false; return false;
} }
catch(const IdentifierResolutionException & e) catch(const IdentifierResolutionException & e)
@ -1595,7 +1593,7 @@ bool CGameHandler::load(const std::string & filename)
MetaString errorMsg; MetaString errorMsg;
errorMsg.appendTextID("vcmi.server.errors.unknownEntity"); errorMsg.appendTextID("vcmi.server.errors.unknownEntity");
errorMsg.replaceRawString(e.identifierName); errorMsg.replaceRawString(e.identifierName);
lobby->announceMessage(errorMsg); gameLobby().announceMessage(errorMsg);
return false; return false;
} }
@ -1605,11 +1603,11 @@ bool CGameHandler::load(const std::string & filename)
auto str = MetaString::createFromTextID("vcmi.broadcast.failedLoadGame"); auto str = MetaString::createFromTextID("vcmi.broadcast.failedLoadGame");
str.appendRawString(": "); str.appendRawString(": ");
str.appendRawString(e.what()); str.appendRawString(e.what());
lobby->announceMessage(str); gameLobby().announceMessage(str);
return false; return false;
} }
gs->preInit(LIBRARY, this); gs->preInit(LIBRARY, this);
gs->updateOnLoad(lobby->si.get()); gs->updateOnLoad(gameLobby().si.get());
return true; return true;
} }
@ -3542,7 +3540,7 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
if(p->human) if(p->human)
{ {
lobby->setState(EServerState::SHUTDOWN); gameLobby().setState(EServerState::SHUTDOWN);
} }
} }
else else

View File

@ -85,7 +85,7 @@ public:
const GameCb * game() const override; const GameCb * game() const override;
vstd::CLoggerBase * logger() const override; vstd::CLoggerBase * logger() const override;
events::EventBus * eventBus() const override; events::EventBus * eventBus() const override;
CVCMIServer * gameLobby() const; CVCMIServer & gameLobby() const;
bool isValidObject(const CGObjectInstance *obj) const; bool isValidObject(const CGObjectInstance *obj) const;
bool isBlockedByQueries(const CPackForServer *pack, PlayerColor player); bool isBlockedByQueries(const CPackForServer *pack, PlayerColor player);
@ -194,7 +194,7 @@ public:
void init(StartInfo *si, Load::ProgressAccumulator & progressTracking); void init(StartInfo *si, Load::ProgressAccumulator & progressTracking);
void handleClientDisconnection(std::shared_ptr<CConnection> c); void handleClientDisconnection(std::shared_ptr<CConnection> c);
void handleReceivedPack(CPackForServer & pack); void handleReceivedPack(std::shared_ptr<CConnection> c, CPackForServer & pack);
bool hasPlayerAt(PlayerColor player, std::shared_ptr<CConnection> c) const; bool hasPlayerAt(PlayerColor player, std::shared_ptr<CConnection> c) const;
bool hasBothPlayersAtSameConnection(PlayerColor left, PlayerColor right) const; bool hasBothPlayersAtSameConnection(PlayerColor left, PlayerColor right) const;
@ -266,19 +266,19 @@ public:
void sendAndApply(SetResources & pack); void sendAndApply(SetResources & pack);
void sendAndApply(NewStructures & pack); void sendAndApply(NewStructures & pack);
void wrongPlayerMessage(CPackForServer * pack, PlayerColor expectedplayer); void wrongPlayerMessage(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack, PlayerColor expectedplayer);
/// Unconditionally throws with "Action not allowed" message /// Unconditionally throws with "Action not allowed" message
[[noreturn]] void throwNotAllowedAction(CPackForServer * pack); [[noreturn]] void throwNotAllowedAction(const std::shared_ptr<CConnection> & connection);
/// Throws if player stated in pack is not making turn right now /// Throws if player stated in pack is not making turn right now
void throwIfPlayerNotActive(CPackForServer * pack); void throwIfPlayerNotActive(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack);
/// Throws if object is not owned by pack sender /// Throws if object is not owned by pack sender
void throwIfWrongOwner(CPackForServer * pack, ObjectInstanceID id); void throwIfWrongOwner(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack, ObjectInstanceID id);
/// Throws if player is not present on connection of this pack /// Throws if player is not present on connection of this pack
void throwIfWrongPlayer(CPackForServer * pack, PlayerColor player); void throwIfWrongPlayer(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack, PlayerColor player);
void throwIfWrongPlayer(CPackForServer * pack); void throwIfWrongPlayer(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack);
[[noreturn]] void throwAndComplain(CPackForServer * pack, std::string txt); [[noreturn]] void throwAndComplain(const std::shared_ptr<CConnection> & connection, std::string txt);
bool isPlayerOwns(CPackForServer * pack, ObjectInstanceID id); bool isPlayerOwns(const std::shared_ptr<CConnection> & connection, const CPackForServer * pack, ObjectInstanceID id);
void start(bool resume); void start(bool resume);
void tick(int millisecondsPassed); void tick(int millisecondsPassed);

View File

@ -39,10 +39,13 @@ class CVCMIServerPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
private: private:
CVCMIServer & handler; CVCMIServer & handler;
std::shared_ptr<CGameHandler> gh; std::shared_ptr<CGameHandler> gh;
std::shared_ptr<CConnection> connection;
public: public:
CVCMIServerPackVisitor(CVCMIServer & handler, std::shared_ptr<CGameHandler> gh) CVCMIServerPackVisitor(CVCMIServer & handler, const std::shared_ptr<CGameHandler> & gh, const std::shared_ptr<CConnection> & connection)
:handler(handler), gh(gh) : handler(handler)
, gh(gh)
, connection(connection)
{ {
} }
@ -50,13 +53,13 @@ public:
void visitForLobby(CPackForLobby & packForLobby) override void visitForLobby(CPackForLobby & packForLobby) override
{ {
handler.handleReceivedPack(packForLobby); handler.handleReceivedPack(connection, packForLobby);
} }
void visitForServer(CPackForServer & serverPack) override void visitForServer(CPackForServer & serverPack) override
{ {
if (gh) if (gh)
gh->handleReceivedPack(serverPack); gh->handleReceivedPack(connection, serverPack);
else else
logNetwork->error("Received pack for game server while in lobby!"); logNetwork->error("Received pack for game server while in lobby!");
} }
@ -130,8 +133,7 @@ void CVCMIServer::onPacketReceived(const std::shared_ptr<INetworkConnection> & c
throw std::out_of_range("Unknown connection received in CVCMIServer::findConnection"); throw std::out_of_range("Unknown connection received in CVCMIServer::findConnection");
auto pack = c->retrievePack(message); auto pack = c->retrievePack(message);
pack->c = c; CVCMIServerPackVisitor visitor(*this, this->gh, c);
CVCMIServerPackVisitor visitor(*this, this->gh);
pack->visit(visitor); pack->visit(visitor);
} }
@ -310,20 +312,19 @@ void CVCMIServer::onDisconnected(const std::shared_ptr<INetworkConnection> & con
if (c) if (c)
{ {
LobbyClientDisconnected lcd; LobbyClientDisconnected lcd;
lcd.c = c;
lcd.clientId = c->connectionID; lcd.clientId = c->connectionID;
handleReceivedPack(lcd); handleReceivedPack(c, lcd);
} }
} }
void CVCMIServer::handleReceivedPack(CPackForLobby & pack) void CVCMIServer::handleReceivedPack(std::shared_ptr<CConnection> connection, CPackForLobby & pack)
{ {
ClientPermissionsCheckerNetPackVisitor checker(*this); ClientPermissionsCheckerNetPackVisitor checker(*this, connection);
pack.visit(checker); pack.visit(checker);
if(checker.getResult()) if(checker.getResult())
{ {
ApplyOnServerNetPackVisitor applier(*this); ApplyOnServerNetPackVisitor applier(*this, connection);
pack.visit(applier); pack.visit(applier);
if (applier.getResult()) if (applier.getResult())
announcePack(pack); announcePack(pack);
@ -397,6 +398,7 @@ void CVCMIServer::clientConnected(std::shared_ptr<CConnection> c, std::vector<st
assert(getState() == EServerState::LOBBY); assert(getState() == EServerState::LOBBY);
c->connectionID = currentClientId++; c->connectionID = currentClientId++;
c->uuid = uuid;
if(hostClientId == -1) if(hostClientId == -1)
{ {
@ -445,41 +447,6 @@ void CVCMIServer::clientDisconnected(std::shared_ptr<CConnection> connection)
{ {
gh->handleClientDisconnection(connection); gh->handleClientDisconnection(connection);
} }
// PlayerReinitInterface startAiPack;
// startAiPack.playerConnectionId = PlayerSettings::PLAYER_AI;
//
// for(auto it = playerNames.begin(); it != playerNames.end();)
// {
// if(it->second.connection != c->connectionID)
// {
// ++it;
// continue;
// }
//
// int id = it->first;
// std::string playerLeftMsgText = boost::str(boost::format("%s (pid %d cid %d) left the game") % id % playerNames[id].name % c->connectionID);
// announceTxt(playerLeftMsgText); //send lobby text, it will be ignored for non-lobby clients
// auto * playerSettings = si->getPlayersSettings(id);
// if(!playerSettings)
// {
// ++it;
// continue;
// }
//
// it = playerNames.erase(it);
// setPlayerConnectedId(*playerSettings, PlayerSettings::PLAYER_AI);
//
// if(gh && si && state == EServerState::GAMEPLAY)
// {
// gh->playerMessages->broadcastMessage(playerSettings->color, playerLeftMsgText);
// // gh->connections[playerSettings->color].insert(hostClient);
// startAiPack.players.push_back(playerSettings->color);
// }
// }
//
// if(!startAiPack.players.empty())
// gh->sendAndApply(startAiPack);
} }
void CVCMIServer::reconnectPlayer(int connId) void CVCMIServer::reconnectPlayer(int connId)

View File

@ -102,7 +102,7 @@ public:
void announceMessage(const MetaString & txt); void announceMessage(const MetaString & txt);
void announceMessage(const std::string & txt); void announceMessage(const std::string & txt);
void handleReceivedPack(CPackForLobby & pack); void handleReceivedPack(std::shared_ptr<CConnection> connection, CPackForLobby & pack);
void updateAndPropagateLobbyState(); void updateAndPropagateLobbyState();

View File

@ -14,12 +14,15 @@
class ClientPermissionsCheckerNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) class ClientPermissionsCheckerNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{ {
private: private:
bool result; std::shared_ptr<CConnection> connection;
CVCMIServer & srv; CVCMIServer & srv;
bool result;
public: public:
ClientPermissionsCheckerNetPackVisitor(CVCMIServer & srv) ClientPermissionsCheckerNetPackVisitor(CVCMIServer & srv, const std::shared_ptr<CConnection> & connection)
:srv(srv), result(false) : connection(connection)
, srv(srv)
, result(false)
{ {
} }
@ -49,7 +52,7 @@ private:
public: public:
ApplyOnServerAfterAnnounceNetPackVisitor(CVCMIServer & srv) ApplyOnServerAfterAnnounceNetPackVisitor(CVCMIServer & srv)
:srv(srv) : srv(srv)
{ {
} }
@ -64,12 +67,15 @@ public:
class ApplyOnServerNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) class ApplyOnServerNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{ {
private: private:
bool result; std::shared_ptr<CConnection> connection;
CVCMIServer & srv; CVCMIServer & srv;
bool result;
public: public:
ApplyOnServerNetPackVisitor(CVCMIServer & srv) ApplyOnServerNetPackVisitor(CVCMIServer & srv, const std::shared_ptr<CConnection> & connection)
:srv(srv), result(true) : connection(connection)
, srv(srv)
, result(true)
{ {
} }

View File

@ -28,7 +28,7 @@ void ClientPermissionsCheckerNetPackVisitor::visitForLobby(CPackForLobby & pack)
{ {
if(pack.isForServer()) if(pack.isForServer())
{ {
result = srv.isClientHost(pack.c->connectionID); result = srv.isClientHost(connection->connectionID);
} }
} }
@ -49,12 +49,12 @@ void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientConnected(LobbyClie
void ApplyOnServerNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack) void ApplyOnServerNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack)
{ {
auto compatibleVersion = std::min(pack.version, ESerializationVersion::CURRENT); auto compatibleVersion = std::min(pack.version, ESerializationVersion::CURRENT);
pack.c->setSerializationVersion(compatibleVersion); connection->setSerializationVersion(compatibleVersion);
srv.clientConnected(pack.c, pack.names, pack.uuid, pack.mode); srv.clientConnected(connection, pack.names, pack.uuid, pack.mode);
// Server need to pass some data to newly connected client // Server need to pass some data to newly connected client
pack.clientId = pack.c->connectionID; pack.clientId = connection->connectionID;
pack.mode = srv.si->mode; pack.mode = srv.si->mode;
pack.hostClientId = srv.hostClientId; pack.hostClientId = srv.hostClientId;
pack.version = compatibleVersion; pack.version = compatibleVersion;
@ -64,9 +64,6 @@ void ApplyOnServerNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected
void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack) void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack)
{ {
// FIXME: we need to avoid senting something to client that not yet get answer for LobbyClientConnected
// Until UUID set we only pass LobbyClientConnected to this client
pack.c->uuid = pack.uuid;
srv.updateAndPropagateLobbyState(); srv.updateAndPropagateLobbyState();
// FIXME: what is this??? We do NOT support reconnection into ongoing game - at the very least queries and battles are NOT serialized // FIXME: what is this??? We do NOT support reconnection into ongoing game - at the very least queries and battles are NOT serialized
@ -83,7 +80,7 @@ void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyClientConnected(LobbyCl
void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack) void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack)
{ {
if(pack.clientId != pack.c->connectionID) if(pack.clientId != connection->connectionID)
{ {
result = false; result = false;
return; return;
@ -97,7 +94,7 @@ void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientDisconnected(LobbyC
return; return;
} }
if(pack.c->connectionID != srv.hostClientId) if(connection->connectionID != srv.hostClientId)
{ {
result = false; result = false;
return; return;
@ -109,38 +106,14 @@ void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientDisconnected(LobbyC
void ApplyOnServerNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack) void ApplyOnServerNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack)
{ {
pack.c->getConnection()->close(); connection->getConnection()->close();
srv.clientDisconnected(pack.c); srv.clientDisconnected(connection);
result = true; result = true;
} }
void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack) void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack)
{ {
if(pack.shutdownServer)
{
logNetwork->info("Client requested shutdown, server will close itself...");
srv.setState(EServerState::SHUTDOWN);
return;
}
else if(srv.activeConnections.empty())
{
logNetwork->error("Last connection lost, server will close itself...");
srv.setState(EServerState::SHUTDOWN);
}
else if(pack.c->connectionID == srv.hostClientId)
{
LobbyChangeHost ph;
auto newHost = srv.activeConnections.front();
ph.newHostConnectionId = newHost->connectionID;
srv.announcePack(ph);
}
srv.updateAndPropagateLobbyState(); srv.updateAndPropagateLobbyState();
// if(srv.getState() != EServerState::SHUTDOWN && srv.remoteConnections.count(pack.c))
// {
// srv.remoteConnections -= pack.c;
// srv.connectToRemote();
// }
} }
void ClientPermissionsCheckerNetPackVisitor::visitLobbyChatMessage(LobbyChatMessage & pack) void ClientPermissionsCheckerNetPackVisitor::visitLobbyChatMessage(LobbyChatMessage & pack)
@ -202,12 +175,12 @@ void ApplyOnServerNetPackVisitor::visitLobbySetCampaignBonus(LobbySetCampaignBon
void ClientPermissionsCheckerNetPackVisitor::visitLobbyGuiAction(LobbyGuiAction & pack) void ClientPermissionsCheckerNetPackVisitor::visitLobbyGuiAction(LobbyGuiAction & pack)
{ {
result = srv.isClientHost(pack.c->connectionID); result = srv.isClientHost(connection->connectionID);
} }
void ClientPermissionsCheckerNetPackVisitor::visitLobbyRestartGame(LobbyRestartGame & pack) void ClientPermissionsCheckerNetPackVisitor::visitLobbyRestartGame(LobbyRestartGame & pack)
{ {
result = srv.isClientHost(pack.c->connectionID); result = srv.isClientHost(connection->connectionID);
} }
void ApplyOnServerNetPackVisitor::visitLobbyRestartGame(LobbyRestartGame & pack) void ApplyOnServerNetPackVisitor::visitLobbyRestartGame(LobbyRestartGame & pack)
@ -225,12 +198,12 @@ void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyRestartGame(LobbyRestar
void ClientPermissionsCheckerNetPackVisitor::visitLobbyPrepareStartGame(LobbyPrepareStartGame & pack) void ClientPermissionsCheckerNetPackVisitor::visitLobbyPrepareStartGame(LobbyPrepareStartGame & pack)
{ {
result = srv.isClientHost(pack.c->connectionID); result = srv.isClientHost(connection->connectionID);
} }
void ClientPermissionsCheckerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack) void ClientPermissionsCheckerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack)
{ {
result = srv.isClientHost(pack.c->connectionID); result = srv.isClientHost(connection->connectionID);
} }
void ApplyOnServerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack) void ApplyOnServerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack)
@ -276,7 +249,7 @@ void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyStartGame(LobbyStartGam
void ClientPermissionsCheckerNetPackVisitor::visitLobbyChangeHost(LobbyChangeHost & pack) void ClientPermissionsCheckerNetPackVisitor::visitLobbyChangeHost(LobbyChangeHost & pack)
{ {
result = srv.isClientHost(pack.c->connectionID); result = srv.isClientHost(connection->connectionID);
} }
void ApplyOnServerNetPackVisitor::visitLobbyChangeHost(LobbyChangeHost & pack) void ApplyOnServerNetPackVisitor::visitLobbyChangeHost(LobbyChangeHost & pack)
@ -296,13 +269,13 @@ void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyChangeHost(LobbyChangeH
void ClientPermissionsCheckerNetPackVisitor::visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) void ClientPermissionsCheckerNetPackVisitor::visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack)
{ {
if(srv.isClientHost(pack.c->connectionID)) if(srv.isClientHost(connection->connectionID))
{ {
result = true; result = true;
return; return;
} }
if(vstd::contains(srv.getAllClientPlayers(pack.c->connectionID), pack.color)) if(vstd::contains(srv.getAllClientPlayers(connection->connectionID), pack.color))
{ {
result = true; result = true;
return; return;
@ -439,7 +412,7 @@ void ApplyOnServerNetPackVisitor::visitLobbyPvPAction(LobbyPvPAction & pack)
void ClientPermissionsCheckerNetPackVisitor::visitLobbyDelete(LobbyDelete & pack) void ClientPermissionsCheckerNetPackVisitor::visitLobbyDelete(LobbyDelete & pack)
{ {
result = srv.isClientHost(pack.c->connectionID); result = srv.isClientHost(connection->connectionID);
} }
void ApplyOnServerNetPackVisitor::visitLobbyDelete(LobbyDelete & pack) void ApplyOnServerNetPackVisitor::visitLobbyDelete(LobbyDelete & pack)

View File

@ -46,22 +46,22 @@ void ApplyGhNetPackVisitor::visitGamePause(GamePause & pack)
void ApplyGhNetPackVisitor::visitEndTurn(EndTurn & pack) void ApplyGhNetPackVisitor::visitEndTurn(EndTurn & pack)
{ {
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.turnOrder->onPlayerEndsTurn(pack.player); result = gh.turnOrder->onPlayerEndsTurn(pack.player);
} }
void ApplyGhNetPackVisitor::visitDismissHero(DismissHero & pack) void ApplyGhNetPackVisitor::visitDismissHero(DismissHero & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.hid); gh.throwIfWrongOwner(connection, &pack, pack.hid);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.removeObject(gh.getObj(pack.hid), pack.player); result = gh.removeObject(gh.getObj(pack.hid), pack.player);
} }
void ApplyGhNetPackVisitor::visitMoveHero(MoveHero & pack) void ApplyGhNetPackVisitor::visitMoveHero(MoveHero & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.hid); gh.throwIfWrongOwner(connection, &pack, pack.hid);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
for (auto const & dest : pack.path) for (auto const & dest : pack.path)
{ {
@ -77,96 +77,96 @@ void ApplyGhNetPackVisitor::visitMoveHero(MoveHero & pack)
void ApplyGhNetPackVisitor::visitCastleTeleportHero(CastleTeleportHero & pack) void ApplyGhNetPackVisitor::visitCastleTeleportHero(CastleTeleportHero & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.hid); gh.throwIfWrongOwner(connection, &pack, pack.hid);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.teleportHero(pack.hid, pack.dest, pack.source, pack.player); result = gh.teleportHero(pack.hid, pack.dest, pack.source, pack.player);
} }
void ApplyGhNetPackVisitor::visitArrangeStacks(ArrangeStacks & pack) void ApplyGhNetPackVisitor::visitArrangeStacks(ArrangeStacks & pack)
{ {
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.arrangeStacks(pack.id1, pack.id2, pack.what, pack.p1, pack.p2, pack.val, pack.player); result = gh.arrangeStacks(pack.id1, pack.id2, pack.what, pack.p1, pack.p2, pack.val, pack.player);
} }
void ApplyGhNetPackVisitor::visitBulkMoveArmy(BulkMoveArmy & pack) void ApplyGhNetPackVisitor::visitBulkMoveArmy(BulkMoveArmy & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.srcArmy); gh.throwIfWrongOwner(connection, &pack, pack.srcArmy);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.bulkMoveArmy(pack.srcArmy, pack.destArmy, pack.srcSlot); result = gh.bulkMoveArmy(pack.srcArmy, pack.destArmy, pack.srcSlot);
} }
void ApplyGhNetPackVisitor::visitBulkSplitStack(BulkSplitStack & pack) void ApplyGhNetPackVisitor::visitBulkSplitStack(BulkSplitStack & pack)
{ {
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.bulkSplitStack(pack.src, pack.srcOwner, pack.amount); result = gh.bulkSplitStack(pack.src, pack.srcOwner, pack.amount);
} }
void ApplyGhNetPackVisitor::visitBulkMergeStacks(BulkMergeStacks & pack) void ApplyGhNetPackVisitor::visitBulkMergeStacks(BulkMergeStacks & pack)
{ {
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.bulkMergeStacks(pack.src, pack.srcOwner); result = gh.bulkMergeStacks(pack.src, pack.srcOwner);
} }
void ApplyGhNetPackVisitor::visitBulkSmartSplitStack(BulkSmartSplitStack & pack) void ApplyGhNetPackVisitor::visitBulkSmartSplitStack(BulkSmartSplitStack & pack)
{ {
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.bulkSmartSplitStack(pack.src, pack.srcOwner); result = gh.bulkSmartSplitStack(pack.src, pack.srcOwner);
} }
void ApplyGhNetPackVisitor::visitDisbandCreature(DisbandCreature & pack) void ApplyGhNetPackVisitor::visitDisbandCreature(DisbandCreature & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.id); gh.throwIfWrongOwner(connection, &pack, pack.id);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.disbandCreature(pack.id, pack.pos); result = gh.disbandCreature(pack.id, pack.pos);
} }
void ApplyGhNetPackVisitor::visitBuildStructure(BuildStructure & pack) void ApplyGhNetPackVisitor::visitBuildStructure(BuildStructure & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.tid); gh.throwIfWrongOwner(connection, &pack, pack.tid);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.buildStructure(pack.tid, pack.bid); result = gh.buildStructure(pack.tid, pack.bid);
} }
void ApplyGhNetPackVisitor::visitSpellResearch(SpellResearch & pack) void ApplyGhNetPackVisitor::visitSpellResearch(SpellResearch & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.tid); gh.throwIfWrongOwner(connection, &pack, pack.tid);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.spellResearch(pack.tid, pack.spellAtSlot, pack.accepted); result = gh.spellResearch(pack.tid, pack.spellAtSlot, pack.accepted);
} }
void ApplyGhNetPackVisitor::visitVisitTownBuilding(VisitTownBuilding & pack) void ApplyGhNetPackVisitor::visitVisitTownBuilding(VisitTownBuilding & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.tid); gh.throwIfWrongOwner(connection, &pack, pack.tid);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.visitTownBuilding(pack.tid, pack.bid); result = gh.visitTownBuilding(pack.tid, pack.bid);
} }
void ApplyGhNetPackVisitor::visitRecruitCreatures(RecruitCreatures & pack) void ApplyGhNetPackVisitor::visitRecruitCreatures(RecruitCreatures & pack)
{ {
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
// ownership checks are inside recruitCreatures // ownership checks are inside recruitCreatures
result = gh.recruitCreatures(pack.tid, pack.dst, pack.crid, pack.amount, pack.level, pack.player); result = gh.recruitCreatures(pack.tid, pack.dst, pack.crid, pack.amount, pack.level, pack.player);
} }
void ApplyGhNetPackVisitor::visitUpgradeCreature(UpgradeCreature & pack) void ApplyGhNetPackVisitor::visitUpgradeCreature(UpgradeCreature & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.id); gh.throwIfWrongOwner(connection, &pack, pack.id);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.upgradeCreature(pack.id, pack.pos, pack.cid); result = gh.upgradeCreature(pack.id, pack.pos, pack.cid);
} }
@ -174,9 +174,9 @@ void ApplyGhNetPackVisitor::visitUpgradeCreature(UpgradeCreature & pack)
void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack) void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack)
{ {
const CGTownInstance * town = gh.getTown(pack.tid); const CGTownInstance * town = gh.getTown(pack.tid);
if(!gh.isPlayerOwns(&pack, pack.tid) && !(town->garrisonHero && gh.isPlayerOwns(&pack, town->garrisonHero->id))) if(!gh.isPlayerOwns(connection, &pack, pack.tid) && !(town->garrisonHero && gh.isPlayerOwns(connection, &pack, town->garrisonHero->id)))
gh.throwNotAllowedAction(&pack); //neither town nor garrisoned hero (if present) is ours gh.throwNotAllowedAction(connection); //neither town nor garrisoned hero (if present) is ours
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.garrisonSwap(pack.tid); result = gh.garrisonSwap(pack.tid);
} }
@ -184,8 +184,8 @@ void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack)
void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack) void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack)
{ {
if(gh.getHero(pack.src.artHolder)) if(gh.getHero(pack.src.artHolder))
gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.src.artHolder)); //second hero can be ally gh.throwIfWrongPlayer(connection, &pack, gh.getOwner(pack.src.artHolder)); //second hero can be ally
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.moveArtifact(pack.player, pack.src, pack.dst); result = gh.moveArtifact(pack.player, pack.src, pack.dst);
} }
@ -193,17 +193,17 @@ void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack)
void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack)
{ {
if(gh.getMarket(pack.srcHero) == nullptr) if(gh.getMarket(pack.srcHero) == nullptr)
gh.throwIfWrongOwner(&pack, pack.srcHero); gh.throwIfWrongOwner(connection, &pack, pack.srcHero);
if(pack.swap) if(pack.swap)
gh.throwIfWrongOwner(&pack, pack.dstHero); gh.throwIfWrongOwner(connection, &pack, pack.dstHero);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.bulkMoveArtifacts(pack.player, pack.srcHero, pack.dstHero, pack.swap, pack.equipped, pack.backpack); result = gh.bulkMoveArtifacts(pack.player, pack.srcHero, pack.dstHero, pack.swap, pack.equipped, pack.backpack);
} }
void ApplyGhNetPackVisitor::visitManageBackpackArtifacts(ManageBackpackArtifacts & pack) void ApplyGhNetPackVisitor::visitManageBackpackArtifacts(ManageBackpackArtifacts & pack)
{ {
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
if(gh.getPlayerRelations(pack.player, gh.getOwner(pack.artHolder)) != PlayerRelations::ENEMIES) if(gh.getPlayerRelations(pack.player, gh.getOwner(pack.artHolder)) != PlayerRelations::ENEMIES)
result = gh.manageBackpackArtifacts(pack.player, pack.artHolder, pack.cmd); result = gh.manageBackpackArtifacts(pack.player, pack.artHolder, pack.cmd);
@ -211,7 +211,7 @@ void ApplyGhNetPackVisitor::visitManageBackpackArtifacts(ManageBackpackArtifacts
void ApplyGhNetPackVisitor::visitManageEquippedArtifacts(ManageEquippedArtifacts & pack) void ApplyGhNetPackVisitor::visitManageEquippedArtifacts(ManageEquippedArtifacts & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.artHolder); gh.throwIfWrongOwner(connection, &pack, pack.artHolder);
if(pack.saveCostume) if(pack.saveCostume)
result = gh.saveArtifactsCostume(pack.player, pack.artHolder, pack.costumeIdx); result = gh.saveArtifactsCostume(pack.player, pack.artHolder, pack.costumeIdx);
else else
@ -220,22 +220,22 @@ void ApplyGhNetPackVisitor::visitManageEquippedArtifacts(ManageEquippedArtifacts
void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack) void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.heroID); gh.throwIfWrongOwner(connection, &pack, pack.heroID);
// gh.throwIfPlayerNotActive(&pack); // Might happen when player captures artifacts in battle? // gh.throwIfPlayerNotActive(&pack); // Might happen when player captures artifacts in battle?
result = gh.assembleArtifacts(pack.heroID, pack.artifactSlot, pack.assemble, pack.assembleTo); result = gh.assembleArtifacts(pack.heroID, pack.artifactSlot, pack.assemble, pack.assembleTo);
} }
void ApplyGhNetPackVisitor::visitEraseArtifactByClient(EraseArtifactByClient & pack) void ApplyGhNetPackVisitor::visitEraseArtifactByClient(EraseArtifactByClient & pack)
{ {
gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.al.artHolder)); gh.throwIfWrongPlayer(connection, &pack, gh.getOwner(pack.al.artHolder));
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.eraseArtifactByClient(pack.al); result = gh.eraseArtifactByClient(pack.al);
} }
void ApplyGhNetPackVisitor::visitBuyArtifact(BuyArtifact & pack) void ApplyGhNetPackVisitor::visitBuyArtifact(BuyArtifact & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.hid); gh.throwIfWrongOwner(connection, &pack, pack.hid);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.buyArtifact(pack.hid, pack.aid); result = gh.buyArtifact(pack.hid, pack.aid);
} }
@ -245,14 +245,14 @@ void ApplyGhNetPackVisitor::visitTradeOnMarketplace(TradeOnMarketplace & pack)
const CGHeroInstance * hero = gh.getHero(pack.heroId); const CGHeroInstance * hero = gh.getHero(pack.heroId);
const auto * market = gh.getMarket(pack.marketId); const auto * market = gh.getMarket(pack.marketId);
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
if(!object) if(!object)
gh.throwAndComplain(&pack, "Invalid market object"); gh.throwAndComplain(connection, "Invalid market object");
if(!market) if(!market)
gh.throwAndComplain(&pack, "market is not-a-market! :/"); gh.throwAndComplain(connection, "market is not-a-market! :/");
bool heroCanBeInvalid = false; bool heroCanBeInvalid = false;
@ -261,7 +261,7 @@ void ApplyGhNetPackVisitor::visitTradeOnMarketplace(TradeOnMarketplace & pack)
// For resource exchange we must use our own market or visit neutral market // For resource exchange we must use our own market or visit neutral market
if (object->getOwner().isValidPlayer()) if (object->getOwner().isValidPlayer())
{ {
gh.throwIfWrongOwner(&pack, pack.marketId); gh.throwIfWrongOwner(connection, &pack, pack.marketId);
heroCanBeInvalid = true; heroCanBeInvalid = true;
} }
} }
@ -271,24 +271,24 @@ void ApplyGhNetPackVisitor::visitTradeOnMarketplace(TradeOnMarketplace & pack)
// For skeleton transformer, if hero is null then object must be owned // For skeleton transformer, if hero is null then object must be owned
if (!hero) if (!hero)
{ {
gh.throwIfWrongOwner(&pack, pack.marketId); gh.throwIfWrongOwner(connection, &pack, pack.marketId);
heroCanBeInvalid = true; heroCanBeInvalid = true;
} }
} }
if (!heroCanBeInvalid) if (!heroCanBeInvalid)
{ {
gh.throwIfWrongOwner(&pack, pack.heroId); gh.throwIfWrongOwner(connection, &pack, pack.heroId);
if (!hero) if (!hero)
gh.throwAndComplain(&pack, "Can not trade - no hero!"); gh.throwAndComplain(connection, "Can not trade - no hero!");
// TODO: check that object is actually being visited (e.g. Query exists) // TODO: check that object is actually being visited (e.g. Query exists)
if (!object->visitableAt(hero->visitablePos())) if (!object->visitableAt(hero->visitablePos()))
gh.throwAndComplain(&pack, "Can not trade - object not visited!"); gh.throwAndComplain(connection, "Can not trade - object not visited!");
if (object->getOwner().isValidPlayer() && gh.getPlayerRelations(object->getOwner(), hero->getOwner()) == PlayerRelations::ENEMIES) if (object->getOwner().isValidPlayer() && gh.getPlayerRelations(object->getOwner(), hero->getOwner()) == PlayerRelations::ENEMIES)
gh.throwAndComplain(&pack, "Can not trade - market not owned!"); gh.throwAndComplain(connection, "Can not trade - market not owned!");
} }
result = true; result = true;
@ -344,62 +344,57 @@ void ApplyGhNetPackVisitor::visitTradeOnMarketplace(TradeOnMarketplace & pack)
return; return;
} }
default: default:
gh.throwAndComplain(&pack, "Unknown exchange pack.mode!"); gh.throwAndComplain(connection, "Unknown exchange pack.mode!");
} }
} }
void ApplyGhNetPackVisitor::visitSetFormation(SetFormation & pack) void ApplyGhNetPackVisitor::visitSetFormation(SetFormation & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.hid); gh.throwIfWrongOwner(connection, &pack, pack.hid);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.setFormation(pack.hid, pack.formation); result = gh.setFormation(pack.hid, pack.formation);
} }
void ApplyGhNetPackVisitor::visitHireHero(HireHero & pack) void ApplyGhNetPackVisitor::visitHireHero(HireHero & pack)
{ {
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.heroPool->hireHero(pack.tid, pack.hid, pack.player, pack.nhid); result = gh.heroPool->hireHero(pack.tid, pack.hid, pack.player, pack.nhid);
} }
void ApplyGhNetPackVisitor::visitBuildBoat(BuildBoat & pack) void ApplyGhNetPackVisitor::visitBuildBoat(BuildBoat & pack)
{ {
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
if(gh.getPlayerRelations(gh.getOwner(pack.objid), pack.player) == PlayerRelations::ENEMIES) if(gh.getPlayerRelations(gh.getOwner(pack.objid), pack.player) == PlayerRelations::ENEMIES)
gh.throwAndComplain(&pack, "Can't build boat at enemy shipyard"); gh.throwAndComplain(connection, "Can't build boat at enemy shipyard");
result = gh.buildBoat(pack.objid, pack.player); result = gh.buildBoat(pack.objid, pack.player);
} }
void ApplyGhNetPackVisitor::visitQueryReply(QueryReply & pack) void ApplyGhNetPackVisitor::visitQueryReply(QueryReply & pack)
{ {
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
auto playerToConnection = gh.connections.find(pack.player);
if(playerToConnection == gh.connections.end())
gh.throwAndComplain(&pack, "No such pack.player!");
if(!vstd::contains(playerToConnection->second, pack.c))
gh.throwAndComplain(&pack, "Message came from wrong connection!");
if(pack.qid == QueryID(-1)) if(pack.qid == QueryID(-1))
gh.throwAndComplain(&pack, "Cannot answer the query with pack.id -1!"); gh.throwAndComplain(connection, "Cannot answer the query with pack.id -1!");
result = gh.queryReply(pack.qid, pack.reply, pack.player); result = gh.queryReply(pack.qid, pack.reply, pack.player);
} }
void ApplyGhNetPackVisitor::visitSaveLocalState(SaveLocalState & pack) void ApplyGhNetPackVisitor::visitSaveLocalState(SaveLocalState & pack)
{ {
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
*gh.gameState()->getPlayerState(pack.player)->playerLocalSettings = pack.data; *gh.gameState()->getPlayerState(pack.player)->playerLocalSettings = pack.data;
result = true; result = true;
} }
void ApplyGhNetPackVisitor::visitMakeAction(MakeAction & pack) void ApplyGhNetPackVisitor::visitMakeAction(MakeAction & pack)
{ {
gh.throwIfWrongPlayer(&pack); gh.throwIfWrongPlayer(connection, &pack);
// allowed even if it is not our turn - will be filtered by battle sides // allowed even if it is not our turn - will be filtered by battle sides
result = gh.battles->makePlayerBattleAction(pack.battleID, pack.player, pack.ba); result = gh.battles->makePlayerBattleAction(pack.battleID, pack.player, pack.ba);
@ -407,23 +402,23 @@ void ApplyGhNetPackVisitor::visitMakeAction(MakeAction & pack)
void ApplyGhNetPackVisitor::visitDigWithHero(DigWithHero & pack) void ApplyGhNetPackVisitor::visitDigWithHero(DigWithHero & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.id); gh.throwIfWrongOwner(connection, &pack, pack.id);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
result = gh.dig(gh.getHero(pack.id)); result = gh.dig(gh.getHero(pack.id));
} }
void ApplyGhNetPackVisitor::visitCastAdvSpell(CastAdvSpell & pack) void ApplyGhNetPackVisitor::visitCastAdvSpell(CastAdvSpell & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.hid); gh.throwIfWrongOwner(connection, &pack, pack.hid);
gh.throwIfPlayerNotActive(&pack); gh.throwIfPlayerNotActive(connection, &pack);
if (!pack.sid.hasValue()) if (!pack.sid.hasValue())
gh.throwNotAllowedAction(&pack); gh.throwNotAllowedAction(connection);
const CGHeroInstance * h = gh.getHero(pack.hid); const CGHeroInstance * h = gh.getHero(pack.hid);
if(!h) if(!h)
gh.throwNotAllowedAction(&pack); gh.throwNotAllowedAction(connection);
AdventureSpellCastParameters p; AdventureSpellCastParameters p;
p.caster = h; p.caster = h;
@ -436,7 +431,7 @@ void ApplyGhNetPackVisitor::visitCastAdvSpell(CastAdvSpell & pack)
void ApplyGhNetPackVisitor::visitPlayerMessage(PlayerMessage & pack) void ApplyGhNetPackVisitor::visitPlayerMessage(PlayerMessage & pack)
{ {
if(!pack.player.isSpectator()) // TODO: clearly not a great way to verify permissions if(!pack.player.isSpectator()) // TODO: clearly not a great way to verify permissions
gh.throwIfWrongPlayer(&pack, pack.player); gh.throwIfWrongPlayer(connection, &pack, pack.player);
gh.playerMessages->playerMessage(pack.player, pack.text, pack.currObj); gh.playerMessages->playerMessage(pack.player, pack.text, pack.currObj);
result = true; result = true;

View File

@ -14,12 +14,15 @@
class ApplyGhNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) class ApplyGhNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{ {
private: private:
bool result; std::shared_ptr<CConnection> connection;
CGameHandler & gh; CGameHandler & gh;
bool result;
public: public:
ApplyGhNetPackVisitor(CGameHandler & gh) ApplyGhNetPackVisitor(CGameHandler & gh, const std::shared_ptr<CConnection> & connection)
:gh(gh), result(false) : connection(connection)
, gh(gh)
, result(false)
{ {
} }

View File

@ -66,17 +66,17 @@ void PlayerMessageProcessor::playerMessage(PlayerColor player, const std::string
void PlayerMessageProcessor::commandExit(PlayerColor player, const std::vector<std::string> & words) void PlayerMessageProcessor::commandExit(PlayerColor player, const std::vector<std::string> & words)
{ {
bool isHost = gameHandler->gameLobby()->isPlayerHost(player); bool isHost = gameHandler->gameLobby().isPlayerHost(player);
if(!isHost) if(!isHost)
return; return;
broadcastSystemMessage(MetaString::createFromTextID("vcmi.broadcast.gameTerminated")); broadcastSystemMessage(MetaString::createFromTextID("vcmi.broadcast.gameTerminated"));
gameHandler->gameLobby()->setState(EServerState::SHUTDOWN); gameHandler->gameLobby().setState(EServerState::SHUTDOWN);
} }
void PlayerMessageProcessor::commandKick(PlayerColor player, const std::vector<std::string> & words) void PlayerMessageProcessor::commandKick(PlayerColor player, const std::vector<std::string> & words)
{ {
bool isHost = gameHandler->gameLobby()->isPlayerHost(player); bool isHost = gameHandler->gameLobby().isPlayerHost(player);
if(!isHost) if(!isHost)
return; return;
@ -88,10 +88,10 @@ void PlayerMessageProcessor::commandKick(PlayerColor player, const std::vector<s
playerToKick = PlayerColor(std::stoi(playername)); playerToKick = PlayerColor(std::stoi(playername));
else else
{ {
for(auto & c : gameHandler->connections) for (PlayerColor color : PlayerColor::ALL_PLAYERS())
{ {
if(c.first.toString() == playername) if(color.toString() == playername)
playerToKick = c.first; playerToKick = color;
} }
} }
@ -108,7 +108,7 @@ void PlayerMessageProcessor::commandKick(PlayerColor player, const std::vector<s
void PlayerMessageProcessor::commandSave(PlayerColor player, const std::vector<std::string> & words) void PlayerMessageProcessor::commandSave(PlayerColor player, const std::vector<std::string> & words)
{ {
bool isHost = gameHandler->gameLobby()->isPlayerHost(player); bool isHost = gameHandler->gameLobby().isPlayerHost(player);
if(!isHost) if(!isHost)
return; return;
@ -143,7 +143,7 @@ void PlayerMessageProcessor::commandCheaters(PlayerColor player, const std::vect
void PlayerMessageProcessor::commandStatistic(PlayerColor player, const std::vector<std::string> & words) void PlayerMessageProcessor::commandStatistic(PlayerColor player, const std::vector<std::string> & words)
{ {
bool isHost = gameHandler->gameLobby()->isPlayerHost(player); bool isHost = gameHandler->gameLobby().isPlayerHost(player);
if(!isHost) if(!isHost)
return; return;

View File

@ -260,7 +260,7 @@ void TurnOrderProcessor::doStartNewDay()
if(!activePlayer) if(!activePlayer)
{ {
gameHandler->gameLobby()->setState(EServerState::SHUTDOWN); gameHandler->gameLobby().setState(EServerState::SHUTDOWN);
return; return;
} }