From 9f5566693123260e06f277d9ffff629e6416e0d7 Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Sun, 12 Feb 2023 09:23:39 +0200 Subject: [PATCH] rework netpacks to avoid double typeinfo --- client/CMakeLists.txt | 2 + client/CServerHandler.cpp | 72 +- client/CServerHandler.h | 7 +- client/Client.cpp | 7 +- client/ClientCommandManager.cpp | 5 +- client/ClientNetPackVisitors.h | 132 +++ client/LobbyClientNetPackVisitors.h | 56 ++ client/NetPacksClient.cpp | 727 ++++++++--------- client/NetPacksLobbyClient.cpp | 114 ++- cmake_modules/VCMI_lib.cmake | 1 + lib/NetPackVisitor.h | 165 ++++ lib/NetPacks.h | 1168 +++++++++++++++------------ lib/NetPacksBase.h | 50 +- lib/NetPacksLib.cpp | 926 ++++++++++++++++++--- lib/NetPacksLobby.h | 127 +-- server/CGameHandler.cpp | 68 +- server/CGameHandler.h | 7 + server/CMakeLists.txt | 2 + server/CVCMIServer.cpp | 57 +- server/LobbyNetPackVisitors.h | 92 +++ server/NetPacksLobbyServer.cpp | 401 +++++---- server/NetPacksServer.cpp | 380 ++++----- server/ServerNetPackVisitors.h | 61 ++ 23 files changed, 3046 insertions(+), 1581 deletions(-) create mode 100644 client/ClientNetPackVisitors.h create mode 100644 client/LobbyClientNetPackVisitors.h create mode 100644 lib/NetPackVisitor.h create mode 100644 server/LobbyNetPackVisitors.h create mode 100644 server/ServerNetPackVisitors.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index a73837eeb..dd0290864 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -212,6 +212,8 @@ set(client_HEADERS CVideoHandler.h Client.h ClientCommandManager.h + ClientNetPackVisitors.h + LobbyClientNetPackVisitors.h resource.h ) diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index e947a0157..bf5b0194e 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -37,7 +37,7 @@ #include "../lib/CConfigHandler.h" #include "../lib/CGeneralTextHandler.h" #include "../lib/CThreadHelper.h" -#include "../lib/NetPacks.h" +#include "../lib/NetPackVisitor.h" #include "../lib/StartInfo.h" #include "../lib/VCMIDirs.h" #include "../lib/mapping/CCampaignHandler.h" @@ -53,6 +53,7 @@ #include #include #include "../lib/serializer/Cast.h" +#include "LobbyClientNetPackVisitors.h" #include @@ -86,15 +87,21 @@ public: bool applyOnLobbyHandler(CServerHandler * handler, void * pack) const override { T * ptr = static_cast(pack); + ApplyOnLobbyHandlerNetPackVisitor visitor(*handler); + logNetwork->trace("\tImmediately apply on lobby: %s", typeList.getTypeInfo(ptr)->name()); - return ptr->applyOnLobbyHandler(handler); + ptr->visit(visitor); + + return visitor.getResult(); } void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler, void * pack) const override { T * ptr = static_cast(pack); + ApplyOnLobbyScreenNetPackVisitor visitor(*handler, lobby); + logNetwork->trace("\tApply on lobby from queue: %s", typeList.getTypeInfo(ptr)->name()); - ptr->applyOnLobbyScreen(lobby, handler); + ptr->visit(visitor); } }; @@ -575,7 +582,7 @@ void CServerHandler::sendStartGame(bool allowOnlyAI) const c->disableStackSendingByID(); } -void CServerHandler::startGameplay(CGameState * gameState) +void CServerHandler::startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameState) { if(CMM) CMM->disable(); @@ -767,6 +774,30 @@ void CServerHandler::debugStartTest(std::string filename, bool save) } } +class ServerHandlerCPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) +{ +private: + CServerHandler & handler; + +public: + ServerHandlerCPackVisitor(CServerHandler & handler) + :handler(handler) + { + } + + virtual bool callTyped() override { return false; } + + virtual void visitForLobby(CPackForLobby & lobbyPack) override + { + handler.visitForLobby(lobbyPack); + } + + virtual void visitForClient(CPackForClient & clientPack) override + { + handler.visitForClient(clientPack); + } +}; + void CServerHandler::threadHandleConnection() { setThreadName("CServerHandler::threadHandleConnection"); @@ -787,20 +818,10 @@ void CServerHandler::threadHandleConnection() // Though currently they'll be delivered and might cause crash. vstd::clear_pointer(pack); } - else if(auto lobbyPack = dynamic_ptr_cast(pack)) + else { - if(applier->getApplier(typeList.getTypeID(pack))->applyOnLobbyHandler(this, pack)) - { - if(!settings["session"]["headless"].Bool()) - { - boost::unique_lock lock(*mx); - packsForLobbyScreen.push_back(lobbyPack); - } - } - } - else if(auto clientPack = dynamic_ptr_cast(pack)) - { - client->handlePack(clientPack); + ServerHandlerCPackVisitor visitor(*this); + pack->visit(visitor); } } } @@ -836,6 +857,23 @@ void CServerHandler::threadHandleConnection() } } +void CServerHandler::visitForLobby(CPackForLobby & lobbyPack) +{ + if(applier->getApplier(typeList.getTypeID(&lobbyPack))->applyOnLobbyHandler(this, &lobbyPack)) + { + if(!settings["session"]["headless"].Bool()) + { + boost::unique_lock lock(*mx); + packsForLobbyScreen.push_back(&lobbyPack); + } + } +} + +void CServerHandler::visitForClient(CPackForClient & clientPack) +{ + client->handlePack(&clientPack); +} + void CServerHandler::threadRunServer() { #if !defined(VCMI_ANDROID) && !defined(VCMI_IOS) diff --git a/client/CServerHandler.h b/client/CServerHandler.h index bdec1c083..59c354415 100644 --- a/client/CServerHandler.h +++ b/client/CServerHandler.h @@ -25,13 +25,13 @@ class CGameState; struct ClientPlayer; struct CPack; struct CPackForLobby; +struct CPackForClient; template class CApplier; VCMI_LIB_NAMESPACE_END class CClient; - class CBaseForLobbyApply; // TODO: Add mutex so we can't set CONNECTION_CANCELLED if client already connected, but thread not setup yet @@ -148,7 +148,7 @@ public: void sendRestartGame() const override; void sendStartGame(bool allowOnlyAI = false) const override; - void startGameplay(CGameState * gameState = nullptr); + void startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameState = nullptr); void endGameplay(bool closeConnection = true, bool restart = false); void startCampaignScenario(std::shared_ptr cs = {}); void showServerError(std::string txt); @@ -159,6 +159,9 @@ public: void debugStartTest(std::string filename, bool save = false); void restoreLastSession(); + + void visitForLobby(CPackForLobby & lobbyPack); + void visitForClient(CPackForClient & clientPack); }; extern CServerHandler * CSH; diff --git a/client/Client.cpp b/client/Client.cpp index 5add9104a..072d4c9e0 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -32,6 +32,7 @@ #include "../lib/serializer/Connection.h" #include "../lib/serializer/CLoadIntegrityValidator.h" #include "../lib/NetPacks.h" +#include "ClientNetPackVisitors.h" #include "../lib/VCMI_Lib.h" #include "../lib/VCMIDirs.h" #include "../lib/mapping/CMap.h" @@ -80,12 +81,14 @@ public: void applyOnClAfter(CClient * cl, void * pack) const override { T * ptr = static_cast(pack); - ptr->applyCl(cl); + ApplyClientNetPackVisitor visitor(*cl, *cl->gameState()); + ptr->visit(visitor); } void applyOnClBefore(CClient * cl, void * pack) const override { T * ptr = static_cast(pack); - ptr->applyFirstCl(cl); + ApplyFirstClientNetPackVisitor visitor(*cl, *cl->gameState()); + ptr->visit(visitor); } }; diff --git a/client/ClientCommandManager.cpp b/client/ClientCommandManager.cpp index 213c9b2de..8f112a5c9 100644 --- a/client/ClientCommandManager.cpp +++ b/client/ClientCommandManager.cpp @@ -18,6 +18,7 @@ #include "CServerHandler.h" #include "gui/CGuiHandler.h" #include "../lib/NetPacks.h" +#include "ClientNetPackVisitors.h" #include "../lib/CConfigHandler.h" #include "../lib/CGameState.h" #include "../lib/CPlayerState.h" @@ -427,7 +428,9 @@ void ClientCommandManager::giveTurn(const PlayerColor &colorIdentifier) YourTurn yt; yt.player = colorIdentifier; yt.daysWithoutCastle = CSH->client->getPlayerState(colorIdentifier)->daysWithoutCastle; - yt.applyCl(CSH->client); + + ApplyClientNetPackVisitor visitor(*CSH->client, *CSH->client->gameState()); + yt.visit(visitor); } void ClientCommandManager::printInfoAboutInterfaceObject(const CIntObject *obj, int level) diff --git a/client/ClientNetPackVisitors.h b/client/ClientNetPackVisitors.h new file mode 100644 index 000000000..72d0a9f2e --- /dev/null +++ b/client/ClientNetPackVisitors.h @@ -0,0 +1,132 @@ +/* + * ClientNetPackVisitors.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include "../lib/NetPackVisitor.h" + +class CClient; + +VCMI_LIB_NAMESPACE_BEGIN + +class CGameState; + +VCMI_LIB_NAMESPACE_END + +class ApplyClientNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) +{ +private: + CClient & cl; + CGameState & gs; + +public: + ApplyClientNetPackVisitor(CClient & cl, CGameState & gs) + :cl(cl), gs(gs) + { + } + + void visitSetResources(SetResources & pack) override; + void visitSetPrimSkill(SetPrimSkill & pack) override; + void visitSetSecSkill(SetSecSkill & pack) override; + void visitHeroVisitCastle(HeroVisitCastle & pack) override; + void visitSetMana(SetMana & pack) override; + void visitSetMovePoints(SetMovePoints & pack) override; + void visitFoWChange(FoWChange & pack) override; + void visitChangeStackCount(ChangeStackCount & pack) override; + void visitSetStackType(SetStackType & pack) override; + void visitEraseStack(EraseStack & pack) override; + void visitSwapStacks(SwapStacks & pack) override; + void visitInsertNewStack(InsertNewStack & pack) override; + void visitRebalanceStacks(RebalanceStacks & pack) override; + void visitBulkRebalanceStacks(BulkRebalanceStacks & pack) override; + void visitBulkSmartRebalanceStacks(BulkSmartRebalanceStacks & pack) override; + void visitPutArtifact(PutArtifact & pack) override; + void visitEraseArtifact(EraseArtifact & pack) override; + void visitMoveArtifact(MoveArtifact & pack) override; + void visitBulkMoveArtifacts(BulkMoveArtifacts & pack) override; + void visitAssembledArtifact(AssembledArtifact & pack) override; + void visitDisassembledArtifact(DisassembledArtifact & pack) override; + void visitHeroVisit(HeroVisit & pack) override; + void visitNewTurn(NewTurn & pack) override; + void visitGiveBonus(GiveBonus & pack) override; + void visitChangeObjPos(ChangeObjPos & pack) override; + void visitPlayerEndsGame(PlayerEndsGame & pack) override; + void visitPlayerReinitInterface(PlayerReinitInterface & pack) override; + void visitRemoveBonus(RemoveBonus & pack) override; + void visitRemoveObject(RemoveObject & pack) override; + void visitTryMoveHero(TryMoveHero & pack) override; + void visitNewStructures(NewStructures & pack) override; + void visitRazeStructures(RazeStructures & pack) override; + void visitSetAvailableCreatures(SetAvailableCreatures & pack) override; + void visitSetHeroesInTown(SetHeroesInTown & pack) override; + void visitHeroRecruited(HeroRecruited & pack) override; + void visitGiveHero(GiveHero & pack) override; + void visitInfoWindow(InfoWindow & pack) override; + void visitSetObjectProperty(SetObjectProperty & pack) override; + void visitHeroLevelUp(HeroLevelUp & pack) override; + void visitCommanderLevelUp(CommanderLevelUp & pack) override; + void visitBlockingDialog(BlockingDialog & pack) override; + void visitGarrisonDialog(GarrisonDialog & pack) override; + void visitExchangeDialog(ExchangeDialog & pack) override; + void visitTeleportDialog(TeleportDialog & pack) override; + void visitMapObjectSelectDialog(MapObjectSelectDialog & pack) override; + void visitBattleStart(BattleStart & pack) override; + void visitBattleNextRound(BattleNextRound & pack) override; + void visitBattleSetActiveStack(BattleSetActiveStack & pack) override; + void visitBattleLogMessage(BattleLogMessage & pack) override; + void visitBattleTriggerEffect(BattleTriggerEffect & pack) override; + void visitBattleAttack(BattleAttack & pack) override; + void visitBattleSpellCast(BattleSpellCast & pack) override; + void visitSetStackEffect(SetStackEffect & pack) override; + void visitStacksInjured(StacksInjured & pack) override; + void visitBattleResultsApplied(BattleResultsApplied & pack) override; + void visitBattleUnitsChanged(BattleUnitsChanged & pack) override; + void visitBattleObstaclesChanged(BattleObstaclesChanged & pack) override; + void visitCatapultAttack(CatapultAttack & pack) override; + void visitEndAction(EndAction & pack) override; + void visitPackageApplied(PackageApplied & pack) override; + void visitSystemMessage(SystemMessage & pack) override; + void visitPlayerBlocked(PlayerBlocked & pack) override; + void visitYourTurn(YourTurn & pack) override; + void visitSaveGameClient(SaveGameClient & pack) override; + void visitPlayerMessageClient(PlayerMessageClient & pack) override; + void visitShowInInfobox(ShowInInfobox & pack) override; + void visitAdvmapSpellCast(AdvmapSpellCast & pack) override; + void visitShowWorldViewEx(ShowWorldViewEx & pack) override; + void visitOpenWindow(OpenWindow & pack) override; + void visitCenterView(CenterView & pack) override; + void visitNewObject(NewObject & pack) override; + void visitSetAvailableArtifacts(SetAvailableArtifacts & pack) override; + void visitEntitiesChanged(EntitiesChanged & pack) override; +}; + +class ApplyFirstClientNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) +{ +private: + CClient & cl; + CGameState & gs; + +public: + ApplyFirstClientNetPackVisitor(CClient & cl, CGameState & gs) + :cl(cl), gs(gs) + { + } + + virtual void visitChangeObjPos(ChangeObjPos & pack) override; + virtual void visitRemoveObject(RemoveObject & pack) override; + virtual void visitTryMoveHero(TryMoveHero & pack) override; + virtual void visitGiveHero(GiveHero & pack) override; + virtual void visitBattleStart(BattleStart & pack) override; + virtual void visitBattleNextRound(BattleNextRound & pack) override; + virtual void visitBattleUpdateGateState(BattleUpdateGateState & pack) override; + virtual void visitBattleResult(BattleResult & pack) override; + virtual void visitBattleStackMoved(BattleStackMoved & pack) override; + virtual void visitBattleAttack(BattleAttack & pack) override; + virtual void visitStartAction(StartAction & pack) override; +}; \ No newline at end of file diff --git a/client/LobbyClientNetPackVisitors.h b/client/LobbyClientNetPackVisitors.h new file mode 100644 index 000000000..9290c8f0e --- /dev/null +++ b/client/LobbyClientNetPackVisitors.h @@ -0,0 +1,56 @@ +/* + * ClientNetPackVisitors.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include "../lib/NetPackVisitor.h" + +class CClient; +class CGameState; + +class ApplyOnLobbyHandlerNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) +{ +private: + CServerHandler & handler; + bool result; + +public: + ApplyOnLobbyHandlerNetPackVisitor(CServerHandler & handler) + :handler(handler), result(true) + { + } + + bool getResult() const { return result; } + + virtual void visitLobbyClientConnected(LobbyClientConnected & pack) override; + virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override; + virtual void visitLobbyEndGame(LobbyEndGame & pack) override; + virtual void visitLobbyStartGame(LobbyStartGame & pack) override; + virtual void visitLobbyUpdateState(LobbyUpdateState & pack) override; +}; + +class ApplyOnLobbyScreenNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) +{ +private: + CServerHandler & handler; + CLobbyScreen * lobby; + +public: + ApplyOnLobbyScreenNetPackVisitor(CServerHandler & handler, CLobbyScreen * lobby) + :handler(handler), lobby(lobby) + { + } + + virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override; + virtual void visitLobbyChatMessage(LobbyChatMessage & pack) override; + virtual void visitLobbyGuiAction(LobbyGuiAction & pack) override; + virtual void visitLobbyStartGame(LobbyStartGame & pack) override; + virtual void visitLobbyUpdateState(LobbyUpdateState & pack) override; + virtual void visitLobbyShowMessage(LobbyShowMessage & pack) override; +}; \ No newline at end of file diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 1565d95bc..014b2a6aa 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -8,7 +8,7 @@ * */ #include "StdInc.h" -#include "../lib/NetPacks.h" +#include "ClientNetPackVisitors.h" #include "Client.h" #include "CPlayerInterface.h" @@ -47,148 +47,138 @@ // This will require rework spectator interface properly though template -bool callOnlyThatInterface(CClient * cl, PlayerColor player, void (T::*ptr)(Args...), Args2 && ...args) +bool callOnlyThatInterface(CClient & cl, PlayerColor player, void (T::*ptr)(Args...), Args2 && ...args) { - if(vstd::contains(cl->playerint, player)) + if(vstd::contains(cl.playerint, player)) { - ((*cl->playerint[player]).*ptr)(std::forward(args)...); + ((*cl.playerint[player]).*ptr)(std::forward(args)...); return true; } return false; } template -bool callInterfaceIfPresent(CClient * cl, PlayerColor player, void (T::*ptr)(Args...), Args2 && ...args) +bool callInterfaceIfPresent(CClient & cl, PlayerColor player, void (T::*ptr)(Args...), Args2 && ...args) { bool called = callOnlyThatInterface(cl, player, ptr, std::forward(args)...); return called; } template -void callOnlyThatBattleInterface(CClient * cl, PlayerColor player, void (T::*ptr)(Args...), Args2 && ...args) +void callOnlyThatBattleInterface(CClient & cl, PlayerColor player, void (T::*ptr)(Args...), Args2 && ...args) { - if(vstd::contains(cl->battleints,player)) - ((*cl->battleints[player]).*ptr)(std::forward(args)...); + if(vstd::contains(cl.battleints,player)) + ((*cl.battleints[player]).*ptr)(std::forward(args)...); - if(cl->additionalBattleInts.count(player)) + if(cl.additionalBattleInts.count(player)) { - for(auto bInt : cl->additionalBattleInts[player]) + for(auto bInt : cl.additionalBattleInts[player]) ((*bInt).*ptr)(std::forward(args)...); } } template -void callBattleInterfaceIfPresent(CClient * cl, PlayerColor player, void (T::*ptr)(Args...), Args2 && ...args) +void callBattleInterfaceIfPresent(CClient & cl, PlayerColor player, void (T::*ptr)(Args...), Args2 && ...args) { callOnlyThatInterface(cl, player, ptr, std::forward(args)...); } //calls all normal interfaces and privileged ones, playerints may be updated when iterating over it, so we need a copy template -void callAllInterfaces(CClient * cl, void (T::*ptr)(Args...), Args2 && ...args) +void callAllInterfaces(CClient & cl, void (T::*ptr)(Args...), Args2 && ...args) { - for(auto pInt : cl->playerint) + for(auto pInt : cl.playerint) ((*pInt.second).*ptr)(std::forward(args)...); } //calls all normal interfaces and privileged ones, playerints may be updated when iterating over it, so we need a copy template -void callBattleInterfaceIfPresentForBothSides(CClient * cl, void (T::*ptr)(Args...), Args2 && ...args) +void callBattleInterfaceIfPresentForBothSides(CClient & cl, void (T::*ptr)(Args...), Args2 && ...args) { - callOnlyThatBattleInterface(cl, cl->gameState()->curB->sides[0].color, ptr, std::forward(args)...); - callOnlyThatBattleInterface(cl, cl->gameState()->curB->sides[1].color, ptr, std::forward(args)...); + callOnlyThatBattleInterface(cl, cl.gameState()->curB->sides[0].color, ptr, std::forward(args)...); + callOnlyThatBattleInterface(cl, cl.gameState()->curB->sides[1].color, ptr, std::forward(args)...); if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool() && LOCPLINT->battleInt) { callOnlyThatBattleInterface(cl, PlayerColor::SPECTATOR, ptr, std::forward(args)...); } } -void SetResources::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitSetResources(SetResources & pack) { //todo: inform on actual resource set transfered - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::receivedResource); + callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::receivedResource); } -void SetPrimSkill::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitSetPrimSkill(SetPrimSkill & pack) { - const CGHeroInstance *h = cl->getHero(id); + const CGHeroInstance * h = cl.getHero(pack.id); if(!h) { - logNetwork->error("Cannot find hero with ID %d", id.getNum()); + logNetwork->error("Cannot find hero with pack.id %d", pack.id.getNum()); return; } - callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroPrimarySkillChanged, h, which, val); + callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroPrimarySkillChanged, h, pack.which, pack.val); } -void SetSecSkill::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitSetSecSkill(SetSecSkill & pack) { - const CGHeroInstance *h = cl->getHero(id); + const CGHeroInstance *h = cl.getHero(pack.id); if(!h) { - logNetwork->error("Cannot find hero with ID %d", id.getNum()); + logNetwork->error("Cannot find hero with pack.id %d", pack.id.getNum()); return; } - callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroSecondarySkillChanged, h, which, val); + callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroSecondarySkillChanged, h, pack.which, pack.val); } -void HeroVisitCastle::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitHeroVisitCastle(HeroVisitCastle & pack) { - const CGHeroInstance *h = cl->getHero(hid); - - if(start()) + const CGHeroInstance *h = cl.getHero(pack.hid); + + if(pack.start()) { - callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroVisitsTown, h, GS(cl)->getTown(tid)); + callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroVisitsTown, h, gs.getTown(pack.tid)); } } -void ChangeSpells::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitSetMana(SetMana & pack) { - //TODO: inform interface? -} - -void SetMana::applyCl(CClient *cl) -{ - const CGHeroInstance *h = cl->getHero(hid); + const CGHeroInstance *h = cl.getHero(pack.hid); callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroManaPointsChanged, h); } -void SetMovePoints::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitSetMovePoints(SetMovePoints & pack) { - const CGHeroInstance *h = cl->getHero(hid); - cl->invalidatePaths(); + const CGHeroInstance *h = cl.getHero(pack.hid); + cl.invalidatePaths(); callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroMovePointsChanged, h); } -void FoWChange::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitFoWChange(FoWChange & pack) { - for(auto &i : cl->playerint) + for(auto &i : cl.playerint) { - if(cl->getPlayerRelations(i.first, player) == PlayerRelations::SAME_PLAYER && waitForDialogs && LOCPLINT == i.second.get()) + if(cl.getPlayerRelations(i.first, pack.player) == PlayerRelations::SAME_PLAYER && pack.waitForDialogs && LOCPLINT == i.second.get()) { LOCPLINT->waitWhileDialog(); } - if(cl->getPlayerRelations(i.first, player) != PlayerRelations::ENEMIES) + if(cl.getPlayerRelations(i.first, pack.player) != PlayerRelations::ENEMIES) { - if(mode) - i.second->tileRevealed(tiles); + if(pack.mode) + i.second->tileRevealed(pack.tiles); else - i.second->tileHidden(tiles); + i.second->tileHidden(pack.tiles); } } - cl->invalidatePaths(); + cl.invalidatePaths(); } -void SetAvailableHeroes::applyCl(CClient *cl) +static void dispatchGarrisonChange(CClient & cl, ObjectInstanceID army1, ObjectInstanceID army2) { - //TODO: inform interface? -} - -static void dispatchGarrisonChange(CClient * cl, ObjectInstanceID army1, ObjectInstanceID army2) -{ - auto obj1 = cl->getObj(army1); + auto obj1 = cl.getObj(army1); if(!obj1) { - logNetwork->error("Cannot find army with ID %d", army1.getNum()); + logNetwork->error("Cannot find army with pack.id %d", army1.getNum()); return; } @@ -196,10 +186,10 @@ static void dispatchGarrisonChange(CClient * cl, ObjectInstanceID army1, ObjectI if(army2 != ObjectInstanceID() && army2 != army1) { - auto obj2 = cl->getObj(army2); + auto obj2 = cl.getObj(army2); if(!obj2) { - logNetwork->error("Cannot find army with ID %d", army2.getNum()); + logNetwork->error("Cannot find army with pack.id %d", army2.getNum()); return; } @@ -208,369 +198,359 @@ static void dispatchGarrisonChange(CClient * cl, ObjectInstanceID army1, ObjectI } } -void ChangeStackCount::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitChangeStackCount(ChangeStackCount & pack) { - dispatchGarrisonChange(cl, army, ObjectInstanceID()); + dispatchGarrisonChange(cl, pack.army, ObjectInstanceID()); } -void SetStackType::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitSetStackType(SetStackType & pack) { - dispatchGarrisonChange(cl, army, ObjectInstanceID()); + dispatchGarrisonChange(cl, pack.army, ObjectInstanceID()); } -void EraseStack::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitEraseStack(EraseStack & pack) { - dispatchGarrisonChange(cl, army, ObjectInstanceID()); + dispatchGarrisonChange(cl, pack.army, ObjectInstanceID()); } -void SwapStacks::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitSwapStacks(SwapStacks & pack) { - dispatchGarrisonChange(cl, srcArmy, dstArmy); + dispatchGarrisonChange(cl, pack.srcArmy, pack.dstArmy); } -void InsertNewStack::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitInsertNewStack(InsertNewStack & pack) { - dispatchGarrisonChange(cl, army, ObjectInstanceID()); + dispatchGarrisonChange(cl, pack.army, ObjectInstanceID()); } -void RebalanceStacks::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitRebalanceStacks(RebalanceStacks & pack) { - dispatchGarrisonChange(cl, srcArmy, dstArmy); + dispatchGarrisonChange(cl, pack.srcArmy, pack.dstArmy); } -void BulkRebalanceStacks::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitBulkRebalanceStacks(BulkRebalanceStacks & pack) { - if(!moves.empty()) + if(!pack.moves.empty()) { - auto destArmy = moves[0].srcArmy == moves[0].dstArmy + auto destArmy = pack.moves[0].srcArmy == pack.moves[0].dstArmy ? ObjectInstanceID() - : moves[0].dstArmy; - dispatchGarrisonChange(cl, moves[0].srcArmy, destArmy); + : pack.moves[0].dstArmy; + dispatchGarrisonChange(cl, pack.moves[0].srcArmy, destArmy); } } -void BulkSmartRebalanceStacks::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitBulkSmartRebalanceStacks(BulkSmartRebalanceStacks & pack) { - if(!moves.empty()) + if(!pack.moves.empty()) { - assert(moves[0].srcArmy == moves[0].dstArmy); - dispatchGarrisonChange(cl, moves[0].srcArmy, ObjectInstanceID()); + assert(pack.moves[0].srcArmy == pack.moves[0].dstArmy); + dispatchGarrisonChange(cl, pack.moves[0].srcArmy, ObjectInstanceID()); } - else if(!changes.empty()) + else if(!pack.changes.empty()) { - dispatchGarrisonChange(cl, changes[0].army, ObjectInstanceID()); + dispatchGarrisonChange(cl, pack.changes[0].army, ObjectInstanceID()); } } -void PutArtifact::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitPutArtifact(PutArtifact & pack) { - callInterfaceIfPresent(cl, al.owningPlayer(), &IGameEventsReceiver::artifactPut, al); + callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::artifactPut, pack.al); } -void EraseArtifact::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitEraseArtifact(EraseArtifact & pack) { - callInterfaceIfPresent(cl, al.owningPlayer(), &IGameEventsReceiver::artifactRemoved, al); + callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::artifactRemoved, pack.al); } -void MoveArtifact::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitMoveArtifact(MoveArtifact & pack) { - auto moveArtifact = [this, cl](PlayerColor player) -> void + auto moveArtifact = [this, &pack](PlayerColor player) -> void { - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::artifactMoved, src, dst); - if(askAssemble) - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::artifactPossibleAssembling, dst); + callInterfaceIfPresent(cl, player, &IGameEventsReceiver::artifactMoved, pack.src, pack.dst); + if(pack.askAssemble) + callInterfaceIfPresent(cl, player, &IGameEventsReceiver::artifactPossibleAssembling, pack.dst); }; - moveArtifact(src.owningPlayer()); - if(src.owningPlayer() != dst.owningPlayer()) - moveArtifact(dst.owningPlayer()); + moveArtifact(pack.src.owningPlayer()); + if(pack.src.owningPlayer() != pack.dst.owningPlayer()) + moveArtifact(pack.dst.owningPlayer()); } -void BulkMoveArtifacts::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack) { - auto applyMove = [this, cl](std::vector & artsPack) -> void + auto applyMove = [this, &pack](std::vector & artsPack) -> void { for(auto & slotToMove : artsPack) { - auto srcLoc = ArtifactLocation(srcArtHolder, slotToMove.srcPos); - auto dstLoc = ArtifactLocation(dstArtHolder, slotToMove.dstPos); + auto srcLoc = ArtifactLocation(pack.srcArtHolder, slotToMove.srcPos); + auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos); callInterfaceIfPresent(cl, srcLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); if(srcLoc.owningPlayer() != dstLoc.owningPlayer()) callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); } }; - applyMove(artsPack0); - if(swap) - applyMove(artsPack1); + applyMove(pack.artsPack0); + if(pack.swap) + applyMove(pack.artsPack1); } -void AssembledArtifact::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitAssembledArtifact(AssembledArtifact & pack) { - callInterfaceIfPresent(cl, al.owningPlayer(), &IGameEventsReceiver::artifactAssembled, al); + callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::artifactAssembled, pack.al); } -void DisassembledArtifact::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitDisassembledArtifact(DisassembledArtifact & pack) { - callInterfaceIfPresent(cl, al.owningPlayer(), &IGameEventsReceiver::artifactDisassembled, al); + callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::artifactDisassembled, pack.al); } -void HeroVisit::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitHeroVisit(HeroVisit & pack) { - auto hero = cl->getHero(heroId); - auto obj = cl->getObj(objId, false); - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::heroVisit, hero, obj, starting); + auto hero = cl.getHero(pack.heroId); + auto obj = cl.getObj(pack.objId, false); + callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::heroVisit, hero, obj, pack.starting); } -void NewTurn::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitNewTurn(NewTurn & pack) { - cl->invalidatePaths(); + cl.invalidatePaths(); } -void GiveBonus::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitGiveBonus(GiveBonus & pack) { - cl->invalidatePaths(); - switch(who) + cl.invalidatePaths(); + switch(pack.who) { - case HERO: + case GiveBonus::HERO: { - const CGHeroInstance *h = GS(cl)->getHero(ObjectInstanceID(id)); + const CGHeroInstance *h = gs.getHero(ObjectInstanceID(pack.id)); callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroBonusChanged, h, *h->getBonusList().back(), true); } break; - case PLAYER: + case GiveBonus::PLAYER: { - const PlayerState *p = GS(cl)->getPlayerState(PlayerColor(id)); - callInterfaceIfPresent(cl, PlayerColor(id), &IGameEventsReceiver::playerBonusChanged, *p->getBonusList().back(), true); + const PlayerState *p = gs.getPlayerState(PlayerColor(pack.id)); + callInterfaceIfPresent(cl, PlayerColor(pack.id), &IGameEventsReceiver::playerBonusChanged, *p->getBonusList().back(), true); } break; } } -void ChangeObjPos::applyFirstCl(CClient *cl) +void ApplyFirstClientNetPackVisitor::visitChangeObjPos(ChangeObjPos & pack) { - CGObjectInstance *obj = GS(cl)->getObjInstance(objid); - if(flags & 1 && CGI->mh) + CGObjectInstance *obj = gs.getObjInstance(pack.objid); + if(pack.flags & 1 && CGI->mh) CGI->mh->hideObject(obj); } -void ChangeObjPos::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitChangeObjPos(ChangeObjPos & pack) { - CGObjectInstance *obj = GS(cl)->getObjInstance(objid); - if(flags & 1 && CGI->mh) + CGObjectInstance *obj = gs.getObjInstance(pack.objid); + if(pack.flags & 1 && CGI->mh) CGI->mh->printObject(obj); - cl->invalidatePaths(); + cl.invalidatePaths(); } -void PlayerEndsGame::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitPlayerEndsGame(PlayerEndsGame & pack) { - callAllInterfaces(cl, &IGameEventsReceiver::gameOver, player, victoryLossCheckResult); + callAllInterfaces(cl, &IGameEventsReceiver::gameOver, pack.player, pack.victoryLossCheckResult); - // In auto testing mode we always close client if red player won or lose - if(!settings["session"]["testmap"].isNull() && player == PlayerColor(0)) + // In auto testing pack.mode we always close client if red pack.player won or lose + if(!settings["session"]["testmap"].isNull() && pack.player == PlayerColor(0)) handleQuit(settings["session"]["spectate"].Bool()); // if spectator is active ask to close client or not } -void PlayerReinitInterface::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitPlayerReinitInterface(PlayerReinitInterface & pack) { - auto initInterfaces = [cl]() + auto initInterfaces = [this]() { - cl->initPlayerInterfaces(); - auto currentPlayer = cl->gameState()->currentPlayer; + cl.initPlayerInterfaces(); + auto currentPlayer = cl.gameState()->currentPlayer; callAllInterfaces(cl, &IGameEventsReceiver::playerStartsTurn, currentPlayer); callOnlyThatInterface(cl, currentPlayer, &CGameInterface::yourTurn); }; - for(auto player : players) + for(auto player : pack.players) { auto & plSettings = CSH->si->getIthPlayersSettings(player); - if(playerConnectionId == PlayerSettings::PLAYER_AI) + if(pack.playerConnectionId == PlayerSettings::PLAYER_AI) { plSettings.connectedPlayerIDs.clear(); - cl->initPlayerEnvironments(); + cl.initPlayerEnvironments(); initInterfaces(); } - else if(playerConnectionId == CSH->c->connectionID) + else if(pack.playerConnectionId == CSH->c->connectionID) { - plSettings.connectedPlayerIDs.insert(playerConnectionId); - cl->playerint.clear(); + plSettings.connectedPlayerIDs.insert(pack.playerConnectionId); + cl.playerint.clear(); initInterfaces(); } } } -void RemoveBonus::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitRemoveBonus(RemoveBonus & pack) { - cl->invalidatePaths(); - switch(who) + cl.invalidatePaths(); + switch(pack.who) { - case HERO: + case RemoveBonus::HERO: { - const CGHeroInstance *h = GS(cl)->getHero(ObjectInstanceID(id)); - callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroBonusChanged, h, bonus, false); + const CGHeroInstance *h = gs.getHero(ObjectInstanceID(pack.id)); + callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroBonusChanged, h, pack.bonus, false); } break; - case PLAYER: + case RemoveBonus::PLAYER: { - //const PlayerState *p = GS(cl)->getPlayerState(id); - callInterfaceIfPresent(cl, PlayerColor(id), &IGameEventsReceiver::playerBonusChanged, bonus, false); + //const PlayerState *p = gs.getPlayerState(pack.id); + callInterfaceIfPresent(cl, PlayerColor(pack.id), &IGameEventsReceiver::playerBonusChanged, pack.bonus, false); } break; } } -void RemoveObject::applyFirstCl(CClient *cl) +void ApplyFirstClientNetPackVisitor::visitRemoveObject(RemoveObject & pack) { - const CGObjectInstance *o = cl->getObj(id); + const CGObjectInstance *o = cl.getObj(pack.id); if(CGI->mh) CGI->mh->hideObject(o, true); //notify interfaces about removal - for(auto i=cl->playerint.begin(); i!=cl->playerint.end(); i++) + for(auto i=cl.playerint.begin(); i!=cl.playerint.end(); i++) { //below line contains little cheat for AI so it will be aware of deletion of enemy heroes that moved or got re-covered by FoW - //TODO: loose requirements as next AI related crashes appear, for example another player collects object that got re-covered by FoW, unsure if AI code workarounds this - if(GS(cl)->isVisible(o, i->first) || (!cl->getPlayerState(i->first)->human && o->ID == Obj::HERO && o->tempOwner != i->first)) + //TODO: loose requirements as next AI related crashes appear, for example another pack.player collects object that got re-covered by FoW, unsure if AI code workarounds this + if(gs.isVisible(o, i->first) || (!cl.getPlayerState(i->first)->human && o->ID == Obj::HERO && o->tempOwner != i->first)) i->second->objectRemoved(o); } } -void RemoveObject::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitRemoveObject(RemoveObject & pack) { - cl->invalidatePaths(); + cl.invalidatePaths(); } -void TryMoveHero::applyFirstCl(CClient *cl) +void ApplyFirstClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack) { - CGHeroInstance *h = GS(cl)->getHero(id); + CGHeroInstance *h = gs.getHero(pack.id); //check if playerint will have the knowledge about movement - if not, directly update maphandler - for(auto i=cl->playerint.begin(); i!=cl->playerint.end(); i++) + for(auto i=cl.playerint.begin(); i!=cl.playerint.end(); i++) { - auto ps = GS(cl)->getPlayerState(i->first); - if(ps && (GS(cl)->isVisible(start - int3(1, 0, 0), i->first) || GS(cl)->isVisible(end - int3(1, 0, 0), i->first))) + auto ps = gs.getPlayerState(i->first); + if(ps && (gs.isVisible(pack.start - int3(1, 0, 0), i->first) || gs.isVisible(pack.end - int3(1, 0, 0), i->first))) { if(ps->human) - humanKnows = true; + pack.humanKnows = true; } } if(!CGI->mh) return; - if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK || !humanKnows) - CGI->mh->hideObject(h, result == EMBARK && humanKnows); + if(pack.result == TryMoveHero::TELEPORTATION || pack.result == TryMoveHero::EMBARK || pack.result == TryMoveHero::DISEMBARK || !pack.humanKnows) + CGI->mh->hideObject(h, pack.result == TryMoveHero::EMBARK && pack.humanKnows); - if(result == DISEMBARK) + if(pack.result == TryMoveHero::DISEMBARK) CGI->mh->printObject(h->boat); } -void TryMoveHero::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack) { - const CGHeroInstance *h = cl->getHero(id); - cl->invalidatePaths(); + const CGHeroInstance *h = cl.getHero(pack.id); + cl.invalidatePaths(); if(CGI->mh) { - if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK) - CGI->mh->printObject(h, result == DISEMBARK); + if(pack.result == TryMoveHero::TELEPORTATION || pack.result == TryMoveHero::EMBARK || pack.result == TryMoveHero::DISEMBARK) + CGI->mh->printObject(h, pack.result == TryMoveHero::DISEMBARK); - if(result == EMBARK) + if(pack.result == TryMoveHero::EMBARK) CGI->mh->hideObject(h->boat); } PlayerColor player = h->tempOwner; - for(auto &i : cl->playerint) - if(cl->getPlayerRelations(i.first, player) != PlayerRelations::ENEMIES) - i.second->tileRevealed(fowRevealed); + for(auto &i : cl.playerint) + if(cl.getPlayerRelations(i.first, player) != PlayerRelations::ENEMIES) + i.second->tileRevealed(pack.fowRevealed); - //notify interfaces about move - auto gs = cl->gameState(); - - for(auto i=cl->playerint.begin(); i!=cl->playerint.end(); i++) + for(auto i=cl.playerint.begin(); i!=cl.playerint.end(); i++) { - if(i->first != PlayerColor::SPECTATOR && gs->checkForStandardLoss(i->first)) // Do not notify vanquished player's interface + if(i->first != PlayerColor::SPECTATOR && gs.checkForStandardLoss(i->first)) // Do not notify vanquished pack.player's interface continue; - if(GS(cl)->isVisible(start - int3(1, 0, 0), i->first) - || GS(cl)->isVisible(end - int3(1, 0, 0), i->first)) + if(gs.isVisible(pack.start - int3(1, 0, 0), i->first) + || gs.isVisible(pack.end - int3(1, 0, 0), i->first)) { - // src and dst of enemy hero move may be not visible => 'verbose' should be false - const bool verbose = cl->getPlayerRelations(i->first, player) != PlayerRelations::ENEMIES; - i->second->heroMoved(*this, verbose); + // pack.src and pack.dst of enemy hero move may be not visible => 'verbose' should be false + const bool verbose = cl.getPlayerRelations(i->first, player) != PlayerRelations::ENEMIES; + i->second->heroMoved(pack, verbose); } } //maphandler didn't get update from playerint, do it now //TODO: restructure nicely - if(!humanKnows && CGI->mh) + if(!pack.humanKnows && CGI->mh) CGI->mh->printObject(h); } -bool TryMoveHero::stopMovement() const +void ApplyClientNetPackVisitor::visitNewStructures(NewStructures & pack) { - return result != SUCCESS && result != EMBARK && result != DISEMBARK && result != TELEPORTATION; -} - -void NewStructures::applyCl(CClient *cl) -{ - CGTownInstance *town = GS(cl)->getTown(tid); - for(const auto & id : bid) + CGTownInstance *town = gs.getTown(pack.tid); + for(const auto & id : pack.bid) { callInterfaceIfPresent(cl, town->tempOwner, &IGameEventsReceiver::buildChanged, town, id, 1); } } -void RazeStructures::applyCl (CClient *cl) +void ApplyClientNetPackVisitor::visitRazeStructures(RazeStructures & pack) { - CGTownInstance *town = GS(cl)->getTown(tid); - for(const auto & id : bid) + CGTownInstance * town = gs.getTown(pack.tid); + for(const auto & id : pack.bid) { callInterfaceIfPresent(cl, town->tempOwner, &IGameEventsReceiver::buildChanged, town, id, 2); } } -void SetAvailableCreatures::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitSetAvailableCreatures(SetAvailableCreatures & pack) { - const CGDwelling *dw = static_cast(cl->getObj(tid)); - - //inform order about the change + const CGDwelling * dw = static_cast(cl.getObj(pack.tid)); PlayerColor p; if(dw->ID == Obj::WAR_MACHINE_FACTORY) //War Machines Factory is not flaggable, it's "owned" by visitor - p = cl->getTile(dw->visitablePos())->visitableObjects.back()->tempOwner; + p = cl.getTile(dw->visitablePos())->visitableObjects.back()->tempOwner; else p = dw->tempOwner; callInterfaceIfPresent(cl, p, &IGameEventsReceiver::availableCreaturesChanged, dw); } -void SetHeroesInTown::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitSetHeroesInTown(SetHeroesInTown & pack) { - CGTownInstance *t = GS(cl)->getTown(tid); - CGHeroInstance *hGarr = GS(cl)->getHero(this->garrison); - CGHeroInstance *hVisit = GS(cl)->getHero(this->visiting); + CGTownInstance * t = gs.getTown(pack.tid); + CGHeroInstance * hGarr = gs.getHero(pack.garrison); + CGHeroInstance * hVisit = gs.getHero(pack.visiting); //inform all players that see this object - for(auto i = cl->playerint.cbegin(); i != cl->playerint.cend(); ++i) + for(auto i = cl.playerint.cbegin(); i != cl.playerint.cend(); ++i) { if(i->first >= PlayerColor::PLAYER_LIMIT) continue; - if(GS(cl)->isVisible(t, i->first) || - (hGarr && GS(cl)->isVisible(hGarr, i->first)) || - (hVisit && GS(cl)->isVisible(hVisit, i->first))) + if(gs.isVisible(t, i->first) || + (hGarr && gs.isVisible(hGarr, i->first)) || + (hVisit && gs.isVisible(hVisit, i->first))) { - cl->playerint[i->first]->heroInGarrisonChange(t); + cl.playerint[i->first]->heroInGarrisonChange(t); } } } -void HeroRecruited::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitHeroRecruited(HeroRecruited & pack) { - CGHeroInstance *h = GS(cl)->map->heroesOnMap.back(); - if(h->subID != hid) + CGHeroInstance *h = gs.map->heroesOnMap.back(); + if(h->subID != pack.hid) { logNetwork->error("Something wrong with hero recruited!"); } @@ -578,7 +558,7 @@ void HeroRecruited::applyCl(CClient *cl) bool needsPrinting = true; if(callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroCreated, h)) { - if(const CGTownInstance *t = GS(cl)->getTown(tid)) + if(const CGTownInstance *t = gs.getTown(pack.tid)) { callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroInGarrisonChange, t); needsPrinting = false; @@ -588,262 +568,257 @@ void HeroRecruited::applyCl(CClient *cl) CGI->mh->printObject(h); } -void GiveHero::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitGiveHero(GiveHero & pack) { - CGHeroInstance *h = GS(cl)->getHero(id); + CGHeroInstance *h = gs.getHero(pack.id); if(CGI->mh) CGI->mh->printObject(h); callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroCreated, h); } -void GiveHero::applyFirstCl(CClient *cl) +void ApplyFirstClientNetPackVisitor::visitGiveHero(GiveHero & pack) { if(CGI->mh) - CGI->mh->hideObject(GS(cl)->getHero(id)); + CGI->mh->hideObject(gs.getHero(pack.id)); } -void InfoWindow::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitInfoWindow(InfoWindow & pack) { std::string str; - text.toString(str); + pack.text.toString(str); - if(!callInterfaceIfPresent(cl, player, &CGameInterface::showInfoDialog, str,components,(soundBase::soundID)soundID)) + if(!callInterfaceIfPresent(cl, pack.player, &CGameInterface::showInfoDialog, str, pack.components,(soundBase::soundID)pack.soundID)) logNetwork->warn("We received InfoWindow for not our player..."); } -void SetObjectProperty::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitSetObjectProperty(SetObjectProperty & pack) { //inform all players that see this object - for(auto it = cl->playerint.cbegin(); it != cl->playerint.cend(); ++it) + for(auto it = cl.playerint.cbegin(); it != cl.playerint.cend(); ++it) { - if(GS(cl)->isVisible(GS(cl)->getObjInstance(id), it->first)) - callInterfaceIfPresent(cl, it->first, &IGameEventsReceiver::objectPropertyChanged, this); + if(gs.isVisible(gs.getObjInstance(pack.id), it->first)) + callInterfaceIfPresent(cl, it->first, &IGameEventsReceiver::objectPropertyChanged, &pack); } } -void HeroLevelUp::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitHeroLevelUp(HeroLevelUp & pack) { - const CGHeroInstance * hero = cl->getHero(heroId); + const CGHeroInstance * hero = cl.getHero(pack.heroId); assert(hero); - callOnlyThatInterface(cl, player, &CGameInterface::heroGotLevel, hero, primskill, skills, queryID); + callOnlyThatInterface(cl, pack.player, &CGameInterface::heroGotLevel, hero, pack.primskill, pack.skills, pack.queryID); } -void CommanderLevelUp::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitCommanderLevelUp(CommanderLevelUp & pack) { - const CGHeroInstance * hero = cl->getHero(heroId); + const CGHeroInstance * hero = cl.getHero(pack.heroId); assert(hero); const CCommanderInstance * commander = hero->commander; assert(commander); assert(commander->armyObj); //is it possible for Commander to exist beyond armed instance? - callOnlyThatInterface(cl, player, &CGameInterface::commanderGotLevel, commander, skills, queryID); + callOnlyThatInterface(cl, pack.player, &CGameInterface::commanderGotLevel, commander, pack.skills, pack.queryID); } -void BlockingDialog::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitBlockingDialog(BlockingDialog & pack) { std::string str; - text.toString(str); + pack.text.toString(str); - if(!callOnlyThatInterface(cl, player, &CGameInterface::showBlockingDialog, str, components, queryID, (soundBase::soundID)soundID, selection(), cancel())) + if(!callOnlyThatInterface(cl, pack.player, &CGameInterface::showBlockingDialog, str, pack.components, pack.queryID, (soundBase::soundID)pack.soundID, pack.selection(), pack.cancel())) logNetwork->warn("We received YesNoDialog for not our player..."); } -void GarrisonDialog::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitGarrisonDialog(GarrisonDialog & pack) { - const CGHeroInstance *h = cl->getHero(hid); - const CArmedInstance *obj = static_cast(cl->getObj(objid)); + const CGHeroInstance *h = cl.getHero(pack.hid); + const CArmedInstance *obj = static_cast(cl.getObj(pack.objid)); - callOnlyThatInterface(cl, h->getOwner(), &CGameInterface::showGarrisonDialog, obj, h, removableUnits, queryID); + callOnlyThatInterface(cl, h->getOwner(), &CGameInterface::showGarrisonDialog, obj, h, pack.removableUnits, pack.queryID); } -void ExchangeDialog::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitExchangeDialog(ExchangeDialog & pack) { - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::heroExchangeStarted, hero1, hero2, queryID); + callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::heroExchangeStarted, pack.hero1, pack.hero2, pack.queryID); } -void TeleportDialog::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitTeleportDialog(TeleportDialog & pack) { - callOnlyThatInterface(cl, player, &CGameInterface::showTeleportDialog, channel, exits, impassable, queryID); + callOnlyThatInterface(cl, pack.player, &CGameInterface::showTeleportDialog, pack.channel, pack.exits, pack.impassable, pack.queryID); } -void MapObjectSelectDialog::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitMapObjectSelectDialog(MapObjectSelectDialog & pack) { - callOnlyThatInterface(cl, player, &CGameInterface::showMapObjectSelectDialog, queryID, icon, title, description, objects); + callOnlyThatInterface(cl, pack.player, &CGameInterface::showMapObjectSelectDialog, pack.queryID, pack.icon, pack.title, pack.description, pack.objects); } -void BattleStart::applyFirstCl(CClient *cl) +void ApplyFirstClientNetPackVisitor::visitBattleStart(BattleStart & pack) { // Cannot use the usual code because curB is not set yet - callOnlyThatBattleInterface(cl, info->sides[0].color, &IBattleEventsReceiver::battleStartBefore, info->sides[0].armyObject, info->sides[1].armyObject, - info->tile, info->sides[0].hero, info->sides[1].hero); - callOnlyThatBattleInterface(cl, info->sides[1].color, &IBattleEventsReceiver::battleStartBefore, info->sides[0].armyObject, info->sides[1].armyObject, - info->tile, info->sides[0].hero, info->sides[1].hero); - callOnlyThatBattleInterface(cl, PlayerColor::SPECTATOR, &IBattleEventsReceiver::battleStartBefore, info->sides[0].armyObject, info->sides[1].armyObject, - info->tile, info->sides[0].hero, info->sides[1].hero); + callOnlyThatBattleInterface(cl, pack.info->sides[0].color, &IBattleEventsReceiver::battleStartBefore, pack.info->sides[0].armyObject, pack.info->sides[1].armyObject, + pack.info->tile, pack.info->sides[0].hero, pack.info->sides[1].hero); + callOnlyThatBattleInterface(cl, pack.info->sides[1].color, &IBattleEventsReceiver::battleStartBefore, pack.info->sides[0].armyObject, pack.info->sides[1].armyObject, + pack.info->tile, pack.info->sides[0].hero, pack.info->sides[1].hero); + callOnlyThatBattleInterface(cl, PlayerColor::SPECTATOR, &IBattleEventsReceiver::battleStartBefore, pack.info->sides[0].armyObject, pack.info->sides[1].armyObject, + pack.info->tile, pack.info->sides[0].hero, pack.info->sides[1].hero); } -void BattleStart::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitBattleStart(BattleStart & pack) { - cl->battleStarted(info); + cl.battleStarted(pack.info); } -void BattleNextRound::applyFirstCl(CClient *cl) +void ApplyFirstClientNetPackVisitor::visitBattleNextRound(BattleNextRound & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleNewRoundFirst, round); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleNewRoundFirst, pack.round); } -void BattleNextRound::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitBattleNextRound(BattleNextRound & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleNewRound, round); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleNewRound, pack.round); } -void BattleSetActiveStack::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitBattleSetActiveStack(BattleSetActiveStack & pack) { - if(!askPlayerInterface) + if(!pack.askPlayerInterface) return; - const CStack *activated = GS(cl)->curB->battleGetStackByID(stack); - PlayerColor playerToCall; //player that will move activated stack + const CStack *activated = gs.curB->battleGetStackByID(pack.stack); + PlayerColor playerToCall; //pack.player that will move activated stack if (activated->hasBonusOfType(Bonus::HYPNOTIZED)) { - playerToCall = (GS(cl)->curB->sides[0].color == activated->owner - ? GS(cl)->curB->sides[1].color - : GS(cl)->curB->sides[0].color); + playerToCall = (gs.curB->sides[0].color == activated->owner + ? gs.curB->sides[1].color + : gs.curB->sides[0].color); } else { playerToCall = activated->owner; } - cl->startPlayerBattleAction(playerToCall); + cl.startPlayerBattleAction(playerToCall); } -void BattleLogMessage::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitBattleLogMessage(BattleLogMessage & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleLogMessage, lines); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleLogMessage, pack.lines); } -void BattleTriggerEffect::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitBattleTriggerEffect(BattleTriggerEffect & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleTriggerEffect, *this); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleTriggerEffect, pack); } -void BattleUpdateGateState::applyFirstCl(CClient * cl) +void ApplyFirstClientNetPackVisitor::visitBattleUpdateGateState(BattleUpdateGateState & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleGateStateChanged, state); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleGateStateChanged, pack.state); } -void BattleResult::applyFirstCl(CClient *cl) +void ApplyFirstClientNetPackVisitor::visitBattleResult(BattleResult & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleEnd, this); - cl->battleFinished(); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleEnd, &pack); + cl.battleFinished(); } -void BattleStackMoved::applyFirstCl(CClient *cl) +void ApplyFirstClientNetPackVisitor::visitBattleStackMoved(BattleStackMoved & pack) { - const CStack * movedStack = GS(cl)->curB->battleGetStackByID(stack); - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStackMoved, movedStack, tilesToMove, distance, teleporting); + const CStack * movedStack = gs.curB->battleGetStackByID(pack.stack); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStackMoved, movedStack, pack.tilesToMove, pack.distance, pack.teleporting); } -void BattleAttack::applyFirstCl(CClient *cl) +void ApplyFirstClientNetPackVisitor::visitBattleAttack(BattleAttack & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleAttack, this); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleAttack, &pack); } -void BattleAttack::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitBattleAttack(BattleAttack & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksAttacked, bsa, shot()); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksAttacked, pack.bsa, pack.shot()); } -void StartAction::applyFirstCl(CClient *cl) +void ApplyFirstClientNetPackVisitor::visitStartAction(StartAction & pack) { - cl->curbaction = boost::make_optional(ba); - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::actionStarted, ba); + cl.curbaction = boost::make_optional(pack.ba); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::actionStarted, pack.ba); } -void BattleSpellCast::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitBattleSpellCast(BattleSpellCast & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleSpellCast, this); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleSpellCast, &pack); } -void SetStackEffect::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitSetStackEffect(SetStackEffect & pack) { //informing about effects - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksEffectsSet, *this); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksEffectsSet, pack); } -void StacksInjured::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitStacksInjured(StacksInjured & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksAttacked, stacks, false); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksAttacked, pack.stacks, false); } -void BattleResultsApplied::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitBattleResultsApplied(BattleResultsApplied & pack) { - callInterfaceIfPresent(cl, player1, &IGameEventsReceiver::battleResultsApplied); - callInterfaceIfPresent(cl, player2, &IGameEventsReceiver::battleResultsApplied); + callInterfaceIfPresent(cl, pack.player1, &IGameEventsReceiver::battleResultsApplied); + callInterfaceIfPresent(cl, pack.player2, &IGameEventsReceiver::battleResultsApplied); callInterfaceIfPresent(cl, PlayerColor::SPECTATOR, &IGameEventsReceiver::battleResultsApplied); } -void BattleUnitsChanged::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitBattleUnitsChanged(BattleUnitsChanged & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleUnitsChanged, changedStacks); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleUnitsChanged, pack.changedStacks); } -void BattleObstaclesChanged::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitBattleObstaclesChanged(BattleObstaclesChanged & pack) { //inform interfaces about removed obstacles - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleObstaclesChanged, changes); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleObstaclesChanged, pack.changes); } -void CatapultAttack::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitCatapultAttack(CatapultAttack & pack) { //inform interfaces about catapult attack - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleCatapultAttacked, *this); + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleCatapultAttacked, pack); } -CGameState* CPackForClient::GS(CClient *cl) +void ApplyClientNetPackVisitor::visitEndAction(EndAction & pack) { - return cl->gs; + callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::actionFinished, *cl.curbaction); + cl.curbaction.reset(); } -void EndAction::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitPackageApplied(PackageApplied & pack) { - callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::actionFinished, *cl->curbaction); - cl->curbaction.reset(); -} - -void PackageApplied::applyCl(CClient *cl) -{ - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::requestRealized, this); - if(!CClient::waitingRequest.tryRemovingElement(requestID)) + callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::requestRealized, &pack); + if(!CClient::waitingRequest.tryRemovingElement(pack.requestID)) logNetwork->warn("Surprising server message! PackageApplied for unknown requestID!"); } -void SystemMessage::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitSystemMessage(SystemMessage & pack) { std::ostringstream str; - str << "System message: " << text; + str << "System message: " << pack.text; logNetwork->error(str.str()); // usually used to receive error messages from server if(LOCPLINT && !settings["session"]["hideSystemMessages"].Bool()) LOCPLINT->cingconsole->print(str.str()); } -void PlayerBlocked::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitPlayerBlocked(PlayerBlocked & pack) { - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::playerBlocked, reason, startOrEnd == BLOCKADE_STARTED); + callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::playerBlocked, pack.reason, pack.startOrEnd == PlayerBlocked::BLOCKADE_STARTED); } -void YourTurn::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitYourTurn(YourTurn & pack) { - logNetwork->debug("Server gives turn to %s", player.getStr()); + logNetwork->debug("Server gives turn to %s", pack.player.getStr()); - callAllInterfaces(cl, &IGameEventsReceiver::playerStartsTurn, player); - callOnlyThatInterface(cl, player, &CGameInterface::yourTurn); + callAllInterfaces(cl, &IGameEventsReceiver::playerStartsTurn, pack.player); + callOnlyThatInterface(cl, pack.player, &CGameInterface::yourTurn); } -void SaveGameClient::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitSaveGameClient(SaveGameClient & pack) { - const auto stem = FileInfo::GetPathStem(fname); + const auto stem = FileInfo::GetPathStem(pack.fname); if(!CResourceHandler::get("local")->createResource(stem.to_string() + ".vcgm1")) { logNetwork->error("Failed to create resource %s", stem.to_string() + ".vcgm1"); @@ -853,8 +828,8 @@ void SaveGameClient::applyCl(CClient *cl) try { CSaveFile save(*CResourceHandler::get()->getResourceName(ResourceID(stem.to_string(), EResType::CLIENT_SAVEGAME))); - cl->saveCommonState(save); - save << *cl; + cl.saveCommonState(save); + save << cl; } catch(std::exception &e) { @@ -862,140 +837,140 @@ void SaveGameClient::applyCl(CClient *cl) } } -void PlayerMessageClient::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitPlayerMessageClient(PlayerMessageClient & pack) { - logNetwork->debug("Player %s sends a message: %s", player.getStr(), text); + logNetwork->debug("pack.player %s sends a message: %s", pack.player.getStr(), pack.text); std::ostringstream str; - if(player.isSpectator()) - str << "Spectator: " << text; + if(pack.player.isSpectator()) + str << "Spectator: " << pack.text; else - str << cl->getPlayerState(player)->nodeName() <<": " << text; + str << cl.getPlayerState(pack.player)->nodeName() <<": " << pack.text; if(LOCPLINT) LOCPLINT->cingconsole->print(str.str()); } -void ShowInInfobox::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitShowInInfobox(ShowInInfobox & pack) { - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::showComp, c, text.toString()); + callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::showComp, pack.c, pack.text.toString()); } -void AdvmapSpellCast::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitAdvmapSpellCast(AdvmapSpellCast & pack) { - cl->invalidatePaths(); - auto caster = cl->getHero(casterID); + cl.invalidatePaths(); + auto caster = cl.getHero(pack.casterID); if(caster) //consider notifying other interfaces that see hero? - callInterfaceIfPresent(cl, caster->getOwner(), &IGameEventsReceiver::advmapSpellCast, caster, spellID); + callInterfaceIfPresent(cl, caster->getOwner(), &IGameEventsReceiver::advmapSpellCast, caster, pack.spellID); else logNetwork->error("Invalid hero instance"); } -void ShowWorldViewEx::applyCl(CClient * cl) +void ApplyClientNetPackVisitor::visitShowWorldViewEx(ShowWorldViewEx & pack) { - callOnlyThatInterface(cl, player, &CGameInterface::showWorldViewEx, objectPositions); + callOnlyThatInterface(cl, pack.player, &CGameInterface::showWorldViewEx, pack.objectPositions); } -void OpenWindow::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack) { - switch(window) + switch(pack.window) { - case RECRUITMENT_FIRST: - case RECRUITMENT_ALL: + case OpenWindow::RECRUITMENT_FIRST: + case OpenWindow::RECRUITMENT_ALL: { - const CGDwelling *dw = dynamic_cast(cl->getObj(ObjectInstanceID(id1))); - const CArmedInstance *dst = dynamic_cast(cl->getObj(ObjectInstanceID(id2))); - callInterfaceIfPresent(cl, dst->tempOwner, &IGameEventsReceiver::showRecruitmentDialog, dw, dst, window == RECRUITMENT_FIRST ? 0 : -1); + const CGDwelling *dw = dynamic_cast(cl.getObj(ObjectInstanceID(pack.id1))); + const CArmedInstance *dst = dynamic_cast(cl.getObj(ObjectInstanceID(pack.id2))); + callInterfaceIfPresent(cl, dst->tempOwner, &IGameEventsReceiver::showRecruitmentDialog, dw, dst, pack.window == OpenWindow::RECRUITMENT_FIRST ? 0 : -1); } break; - case SHIPYARD_WINDOW: + case OpenWindow::SHIPYARD_WINDOW: { - const IShipyard *sy = IShipyard::castFrom(cl->getObj(ObjectInstanceID(id1))); + const IShipyard *sy = IShipyard::castFrom(cl.getObj(ObjectInstanceID(pack.id1))); callInterfaceIfPresent(cl, sy->o->tempOwner, &IGameEventsReceiver::showShipyardDialog, sy); } break; - case THIEVES_GUILD: + case OpenWindow::THIEVES_GUILD: { //displays Thieves' Guild window (when hero enters Den of Thieves) - const CGObjectInstance *obj = cl->getObj(ObjectInstanceID(id2)); - callInterfaceIfPresent(cl, PlayerColor(id1), &IGameEventsReceiver::showThievesGuildWindow, obj); + const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.id2)); + callInterfaceIfPresent(cl, PlayerColor(pack.id1), &IGameEventsReceiver::showThievesGuildWindow, obj); } break; - case UNIVERSITY_WINDOW: + case OpenWindow::UNIVERSITY_WINDOW: { //displays University window (when hero enters University on adventure map) - const IMarket *market = IMarket::castFrom(cl->getObj(ObjectInstanceID(id1))); - const CGHeroInstance *hero = cl->getHero(ObjectInstanceID(id2)); + const IMarket *market = IMarket::castFrom(cl.getObj(ObjectInstanceID(pack.id1))); + const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.id2)); callInterfaceIfPresent(cl, hero->tempOwner, &IGameEventsReceiver::showUniversityWindow, market, hero); } break; - case MARKET_WINDOW: + case OpenWindow::MARKET_WINDOW: { //displays Thieves' Guild window (when hero enters Den of Thieves) - const CGObjectInstance *obj = cl->getObj(ObjectInstanceID(id1)); - const CGHeroInstance *hero = cl->getHero(ObjectInstanceID(id2)); + const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.id1)); + const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.id2)); const IMarket *market = IMarket::castFrom(obj); - callInterfaceIfPresent(cl, cl->getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showMarketWindow, market, hero); + callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showMarketWindow, market, hero); } break; - case HILL_FORT_WINDOW: + case OpenWindow::HILL_FORT_WINDOW: { //displays Hill fort window - const CGObjectInstance *obj = cl->getObj(ObjectInstanceID(id1)); - const CGHeroInstance *hero = cl->getHero(ObjectInstanceID(id2)); - callInterfaceIfPresent(cl, cl->getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showHillFortWindow, obj, hero); + const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.id1)); + const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.id2)); + callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showHillFortWindow, obj, hero); } break; - case PUZZLE_MAP: + case OpenWindow::PUZZLE_MAP: { - callInterfaceIfPresent(cl, PlayerColor(id1), &IGameEventsReceiver::showPuzzleMap); + callInterfaceIfPresent(cl, PlayerColor(pack.id1), &IGameEventsReceiver::showPuzzleMap); } break; - case TAVERN_WINDOW: - const CGObjectInstance *obj1 = cl->getObj(ObjectInstanceID(id1)), - *obj2 = cl->getObj(ObjectInstanceID(id2)); + case OpenWindow::TAVERN_WINDOW: + const CGObjectInstance *obj1 = cl.getObj(ObjectInstanceID(pack.id1)), + *obj2 = cl.getObj(ObjectInstanceID(pack.id2)); callInterfaceIfPresent(cl, obj1->tempOwner, &IGameEventsReceiver::showTavernWindow, obj2); break; } } -void CenterView::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitCenterView(CenterView & pack) { - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::centerView, pos, focusTime); + callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::centerView, pack.pos, pack.focusTime); } -void NewObject::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitNewObject(NewObject & pack) { - cl->invalidatePaths(); + cl.invalidatePaths(); - const CGObjectInstance *obj = cl->getObj(id); + const CGObjectInstance *obj = cl.getObj(pack.id); if(CGI->mh) CGI->mh->printObject(obj, true); - for(auto i=cl->playerint.begin(); i!=cl->playerint.end(); i++) + for(auto i=cl.playerint.begin(); i!=cl.playerint.end(); i++) { - if(GS(cl)->isVisible(obj, i->first)) + if(gs.isVisible(obj, i->first)) i->second->newObject(obj); } } -void SetAvailableArtifacts::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitSetAvailableArtifacts(SetAvailableArtifacts & pack) { - if(id < 0) //artifact merchants globally + if(pack.id < 0) //artifact merchants globally { callAllInterfaces(cl, &IGameEventsReceiver::availableArtifactsChanged, nullptr); } else { - const CGBlackMarket *bm = dynamic_cast(cl->getObj(ObjectInstanceID(id))); + const CGBlackMarket *bm = dynamic_cast(cl.getObj(ObjectInstanceID(pack.id))); assert(bm); - callInterfaceIfPresent(cl, cl->getTile(bm->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::availableArtifactsChanged, bm); + callInterfaceIfPresent(cl, cl.getTile(bm->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::availableArtifactsChanged, bm); } } -void EntitiesChanged::applyCl(CClient *cl) +void ApplyClientNetPackVisitor::visitEntitiesChanged(EntitiesChanged & pack) { - cl->invalidatePaths(); + cl.invalidatePaths(); } diff --git a/client/NetPacksLobbyClient.cpp b/client/NetPacksLobbyClient.cpp index b9459b6f6..4dbd33cb2 100644 --- a/client/NetPacksLobbyClient.cpp +++ b/client/NetPacksLobbyClient.cpp @@ -9,6 +9,7 @@ */ #include "StdInc.h" +#include "LobbyClientNetPackVisitors.h" #include "lobby/CSelectionBase.h" #include "lobby/CLobbyScreen.h" @@ -28,123 +29,120 @@ #include "../lib/NetPacksLobby.h" #include "../lib/serializer/Connection.h" -bool LobbyClientConnected::applyOnLobbyHandler(CServerHandler * handler) +void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack) { + result = false; + // Check if it's LobbyClientConnected for our client - if(uuid == handler->c->uuid) + if(pack.uuid == handler.c->uuid) { - handler->c->connectionID = clientId; + handler.c->connectionID = pack.clientId; if(!settings["session"]["headless"].Bool()) - GH.pushIntT(static_cast(handler->screenType)); - handler->state = EClientState::LOBBY; - return true; + GH.pushIntT(static_cast(handler.screenType)); + handler.state = EClientState::LOBBY; } - return false; } -void LobbyClientConnected::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) +void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack) { + if(pack.clientId != pack.c->connectionID) + { + result = false; + return; + } + + handler.stopServerConnection(); } -bool LobbyClientDisconnected::applyOnLobbyHandler(CServerHandler * handler) -{ - if(clientId != c->connectionID) - return false; - - handler->stopServerConnection(); - return true; -} - -void LobbyClientDisconnected::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) +void ApplyOnLobbyScreenNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack) { if(GH.listInt.size()) GH.popInts(1); } -void LobbyChatMessage::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) +void ApplyOnLobbyScreenNetPackVisitor::visitLobbyChatMessage(LobbyChatMessage & pack) { if(lobby && lobby->card) { - lobby->card->chat->addNewMessage(playerName + ": " + message); + lobby->card->chat->addNewMessage(pack.playerName + ": " + pack.message); lobby->card->setChat(true); if(lobby->buttonChat) lobby->buttonChat->addTextOverlay(CGI->generaltexth->allTexts[531], FONT_SMALL); } } -void LobbyGuiAction::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) +void ApplyOnLobbyScreenNetPackVisitor::visitLobbyGuiAction(LobbyGuiAction & pack) { - if(!lobby || !handler->isGuest()) + if(!lobby || !handler.isGuest()) return; - switch(action) + switch(pack.action) { - case NO_TAB: + case LobbyGuiAction::NO_TAB: lobby->toggleTab(lobby->curTab); break; - case OPEN_OPTIONS: + case LobbyGuiAction::OPEN_OPTIONS: lobby->toggleTab(lobby->tabOpt); break; - case OPEN_SCENARIO_LIST: + case LobbyGuiAction::OPEN_SCENARIO_LIST: lobby->toggleTab(lobby->tabSel); break; - case OPEN_RANDOM_MAP_OPTIONS: + case LobbyGuiAction::OPEN_RANDOM_MAP_OPTIONS: lobby->toggleTab(lobby->tabRand); break; } } -bool LobbyEndGame::applyOnLobbyHandler(CServerHandler * handler) +void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack) { - if(handler->state == EClientState::GAMEPLAY) + if(handler.state == EClientState::GAMEPLAY) { - handler->endGameplay(closeConnection, restart); + handler.endGameplay(pack.closeConnection, pack.restart); } - if(restart) - handler->sendStartGame(); - - return true; + if(pack.restart) + handler.sendStartGame(); } -bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler) +void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack) { - if(clientId != -1 && clientId != handler->c->connectionID) - return false; - - handler->state = EClientState::STARTING; - if(handler->si->mode != StartInfo::LOAD_GAME || clientId == handler->c->connectionID) + if(pack.clientId != -1 && pack.clientId != handler.c->connectionID) { - auto modeBackup = handler->si->mode; - handler->si = initializedStartInfo; - handler->si->mode = modeBackup; + result = false; + return; + } + + handler.state = EClientState::STARTING; + if(handler.si->mode != StartInfo::LOAD_GAME || pack.clientId == handler.c->connectionID) + { + auto modeBackup = handler.si->mode; + handler.si = pack.initializedStartInfo; + handler.si->mode = modeBackup; } if(settings["session"]["headless"].Bool()) - handler->startGameplay(initializedGameState); - return true; + handler.startGameplay(pack.initializedGameState); } -void LobbyStartGame::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) +void ApplyOnLobbyScreenNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack) { - if(clientId != -1 && clientId != handler->c->connectionID) + if(pack.clientId != -1 && pack.clientId != handler.c->connectionID) return; - GH.pushIntT(std::bind(&CServerHandler::startGameplay, handler, initializedGameState)); + GH.pushIntT(std::bind(&CServerHandler::startGameplay, &handler, pack.initializedGameState)); } -bool LobbyUpdateState::applyOnLobbyHandler(CServerHandler * handler) +void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyUpdateState(LobbyUpdateState & pack) { - hostChanged = state.hostClientId != handler->hostClientId; - static_cast(*handler) = state; - return true; + pack.hostChanged = pack.state.hostClientId != handler.hostClientId; + static_cast(handler) = pack.state; } -void LobbyUpdateState::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) +void ApplyOnLobbyScreenNetPackVisitor::visitLobbyUpdateState(LobbyUpdateState & pack) { if(!lobby) //stub: ignore message for game mode return; - if(!lobby->bonusSel && handler->si->campState && handler->state == EClientState::LOBBY_CAMPAIGN) + if(!lobby->bonusSel && handler.si->campState && handler.state == EClientState::LOBBY_CAMPAIGN) { lobby->bonusSel = std::make_shared(); GH.pushInt(lobby->bonusSel); @@ -155,15 +153,15 @@ void LobbyUpdateState::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * else lobby->updateAfterStateChange(); - if(hostChanged) - lobby->toggleMode(handler->isHost()); + if(pack.hostChanged) + lobby->toggleMode(handler.isHost()); } -void LobbyShowMessage::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) +void ApplyOnLobbyScreenNetPackVisitor::visitLobbyShowMessage(LobbyShowMessage & pack) { if(!lobby) //stub: ignore message for game mode return; lobby->buttonStart->block(false); - handler->showServerError(message); + handler.showServerError(pack.message); } diff --git a/cmake_modules/VCMI_lib.cmake b/cmake_modules/VCMI_lib.cmake index d9306edab..37fb945f1 100644 --- a/cmake_modules/VCMI_lib.cmake +++ b/cmake_modules/VCMI_lib.cmake @@ -439,6 +439,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ${MAIN_LIB_DIR}/NetPacksBase.h ${MAIN_LIB_DIR}/NetPacks.h ${MAIN_LIB_DIR}/NetPacksLobby.h + ${MAIN_LIB_DIR}/NetPackVisitor.h ${MAIN_LIB_DIR}/ObstacleHandler.h ${MAIN_LIB_DIR}/PathfinderUtil.h ${MAIN_LIB_DIR}/Point.h diff --git a/lib/NetPackVisitor.h b/lib/NetPackVisitor.h new file mode 100644 index 000000000..642b90c5a --- /dev/null +++ b/lib/NetPackVisitor.h @@ -0,0 +1,165 @@ +/* + * CServerHandler.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include "NetPacks.h" +#include "NetPacksLobby.h" + +VCMI_LIB_NAMESPACE_BEGIN + +class ICPackVisitor +{ +public: + virtual bool callTyped() { return true; } + + virtual void visitForLobby(CPackForLobby & pack) {} + virtual void visitForServer(CPackForServer & pack) {} + virtual void visitForClient(CPackForClient & pack) {} + virtual void visitPackageApplied(PackageApplied & pack) {} + virtual void visitSystemMessage(SystemMessage & pack) {} + virtual void visitPlayerBlocked(PlayerBlocked & pack) {} + virtual void visitPlayerCheated(PlayerCheated & pack) {} + virtual void visitYourTurn(YourTurn & pack) {} + virtual void visitEntitiesChanged(EntitiesChanged & pack) {} + virtual void visitSetResources(SetResources & pack) {} + virtual void visitSetPrimSkill(SetPrimSkill & pack) {} + virtual void visitSetSecSkill(SetSecSkill & pack) {} + virtual void visitHeroVisitCastle(HeroVisitCastle & pack) {} + virtual void visitChangeSpells(ChangeSpells & pack) {} + virtual void visitSetMana(SetMana & pack) {} + virtual void visitSetMovePoints(SetMovePoints & pack) {} + virtual void visitFoWChange(FoWChange & pack) {} + virtual void visitSetAvailableHeroes(SetAvailableHeroes & pack) {} + virtual void visitGiveBonus(GiveBonus & pack) {} + virtual void visitChangeObjPos(ChangeObjPos & pack) {} + virtual void visitPlayerEndsGame(PlayerEndsGame & pack) {} + virtual void visitPlayerReinitInterface(PlayerReinitInterface & pack) {} + virtual void visitRemoveBonus(RemoveBonus & pack) {} + virtual void visitSetCommanderProperty(SetCommanderProperty & pack) {} + virtual void visitAddQuest(AddQuest & pack) {} + virtual void visitUpdateArtHandlerLists(UpdateArtHandlerLists & pack) {} + virtual void visitUpdateMapEvents(UpdateMapEvents & pack) {} + virtual void visitUpdateCastleEvents(UpdateCastleEvents & pack) {} + virtual void visitChangeFormation(ChangeFormation & pack) {} + virtual void visitRemoveObject(RemoveObject & pack) {} + virtual void visitTryMoveHero(TryMoveHero & pack) {} + virtual void visitNewStructures(NewStructures & pack) {} + virtual void visitRazeStructures(RazeStructures & pack) {} + virtual void visitSetAvailableCreatures(SetAvailableCreatures & pack) {} + virtual void visitSetHeroesInTown(SetHeroesInTown & pack) {} + virtual void visitHeroRecruited(HeroRecruited & pack) {} + virtual void visitGiveHero(GiveHero & pack) {} + virtual void visitCatapultAttack(CatapultAttack & pack) {} + virtual void visitOpenWindow(OpenWindow & pack) {} + virtual void visitNewObject(NewObject & pack) {} + virtual void visitSetAvailableArtifacts(SetAvailableArtifacts & pack) {} + virtual void visitNewArtifact(NewArtifact & pack) {} + virtual void visitChangeStackCount(ChangeStackCount & pack) {} + virtual void visitSetStackType(SetStackType & pack) {} + virtual void visitEraseStack(EraseStack & pack) {} + virtual void visitSwapStacks(SwapStacks & pack) {} + virtual void visitInsertNewStack(InsertNewStack & pack) {} + virtual void visitRebalanceStacks(RebalanceStacks & pack) {} + virtual void visitBulkRebalanceStacks(BulkRebalanceStacks & pack) {} + virtual void visitBulkSmartRebalanceStacks(BulkSmartRebalanceStacks & pack) {} + virtual void visitPutArtifact(PutArtifact & pack) {} + virtual void visitEraseArtifact(EraseArtifact & pack) {} + virtual void visitMoveArtifact(MoveArtifact & pack) {} + virtual void visitBulkMoveArtifacts(BulkMoveArtifacts & pack) {} + virtual void visitAssembledArtifact(AssembledArtifact & pack) {} + virtual void visitDisassembledArtifact(DisassembledArtifact & pack) {} + virtual void visitHeroVisit(HeroVisit & pack) {} + virtual void visitNewTurn(NewTurn & pack) {} + virtual void visitInfoWindow(InfoWindow & pack) {} + virtual void visitSetObjectProperty(SetObjectProperty & pack) {} + virtual void visitChangeObjectVisitors(ChangeObjectVisitors & pack) {} + virtual void visitPrepareHeroLevelUp(PrepareHeroLevelUp & pack) {} + virtual void visitHeroLevelUp(HeroLevelUp & pack) {} + virtual void visitCommanderLevelUp(CommanderLevelUp & pack) {} + virtual void visitBlockingDialog(BlockingDialog & pack) {} + virtual void visitGarrisonDialog(GarrisonDialog & pack) {} + virtual void visitExchangeDialog(ExchangeDialog & pack) {} + virtual void visitTeleportDialog(TeleportDialog & pack) {} + virtual void visitMapObjectSelectDialog(MapObjectSelectDialog & pack) {} + virtual void visitBattleStart(BattleStart & pack) {} + virtual void visitBattleNextRound(BattleNextRound & pack) {} + virtual void visitBattleSetActiveStack(BattleSetActiveStack & pack) {} + virtual void visitBattleResult(BattleResult & pack) {} + virtual void visitBattleLogMessage(BattleLogMessage & pack) {} + virtual void visitBattleStackMoved(BattleStackMoved & pack) {} + virtual void visitBattleUnitsChanged(BattleUnitsChanged & pack) {} + virtual void visitBattleAttack(BattleAttack & pack) {} + virtual void visitStartAction(StartAction & pack) {} + virtual void visitEndAction(EndAction & pack) {} + virtual void visitBattleSpellCast(BattleSpellCast & pack) {} + virtual void visitSetStackEffect(SetStackEffect & pack) {} + virtual void visitStacksInjured(StacksInjured & pack) {} + virtual void visitBattleResultsApplied(BattleResultsApplied & pack) {} + virtual void visitBattleObstaclesChanged(BattleObstaclesChanged & pack) {} + virtual void visitBattleSetStackProperty(BattleSetStackProperty & pack) {} + virtual void visitBattleTriggerEffect(BattleTriggerEffect & pack) {} + virtual void visitBattleUpdateGateState(BattleUpdateGateState & pack) {} + virtual void visitShowInInfobox(ShowInInfobox & pack) {} + virtual void visitAdvmapSpellCast(AdvmapSpellCast & pack) {} + virtual void visitShowWorldViewEx(ShowWorldViewEx & pack) {} + virtual void visitEndTurn(EndTurn & pack) {} + virtual void visitDismissHero(DismissHero & pack) {} + virtual void visitMoveHero(MoveHero & pack) {} + virtual void visitCastleTeleportHero(CastleTeleportHero & pack) {} + virtual void visitArrangeStacks(ArrangeStacks & pack) {} + virtual void visitBulkMoveArmy(BulkMoveArmy & pack) {} + virtual void visitBulkSplitStack(BulkSplitStack & pack) {} + virtual void visitBulkMergeStacks(BulkMergeStacks & pack) {} + virtual void visitBulkSmartSplitStack(BulkSmartSplitStack & pack) {} + virtual void visitDisbandCreature(DisbandCreature & pack) {} + virtual void visitBuildStructure(BuildStructure & pack) {} + virtual void visitRazeStructure(RazeStructure & pack) {} + virtual void visitRecruitCreatures(RecruitCreatures & pack) {} + virtual void visitUpgradeCreature(UpgradeCreature & pack) {} + virtual void visitGarrisonHeroSwap(GarrisonHeroSwap & pack) {} + virtual void visitExchangeArtifacts(ExchangeArtifacts & pack) {} + virtual void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) {} + virtual void visitAssembleArtifacts(AssembleArtifacts & pack) {} + virtual void visitBuyArtifact(BuyArtifact & pack) {} + virtual void visitTradeOnMarketplace(TradeOnMarketplace & pack) {} + virtual void visitSetFormation(SetFormation & pack) {} + virtual void visitHireHero(HireHero & pack) {} + virtual void visitBuildBoat(BuildBoat & pack) {} + virtual void visitQueryReply(QueryReply & pack) {} + virtual void visitMakeAction(MakeAction & pack) {} + virtual void visitMakeCustomAction(MakeCustomAction & pack) {} + virtual void visitDigWithHero(DigWithHero & pack) {} + virtual void visitCastAdvSpell(CastAdvSpell & pack) {} + virtual void visitSaveGame(SaveGame & pack) {} + virtual void visitSaveGameClient(SaveGameClient & pack) {} + virtual void visitPlayerMessage(PlayerMessage & pack) {} + virtual void visitPlayerMessageClient(PlayerMessageClient & pack) {} + virtual void visitCenterView(CenterView & pack) {} + virtual void visitLobbyClientConnected(LobbyClientConnected & pack) {} + virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) {} + virtual void visitLobbyChatMessage(LobbyChatMessage & pack) {} + virtual void visitLobbyGuiAction(LobbyGuiAction & pack) {} + virtual void visitLobbyEndGame(LobbyEndGame & pack) {} + virtual void visitLobbyStartGame(LobbyStartGame & pack) {} + virtual void visitLobbyChangeHost(LobbyChangeHost & pack) {} + virtual void visitLobbyUpdateState(LobbyUpdateState & pack) {} + virtual void visitLobbySetMap(LobbySetMap & pack) {} + virtual void visitLobbySetCampaign(LobbySetCampaign & pack) {} + virtual void visitLobbySetCampaignMap(LobbySetCampaignMap & pack) {} + virtual void visitLobbySetCampaignBonus(LobbySetCampaignBonus & pack) {} + virtual void visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) {} + virtual void visitLobbySetPlayer(LobbySetPlayer & pack) {} + virtual void visitLobbySetTurnTime(LobbySetTurnTime & pack) {} + virtual void visitLobbySetDifficulty(LobbySetDifficulty & pack) {} + virtual void visitLobbyForceSetPlayer(LobbyForceSetPlayer & pack) {} + virtual void visitLobbyShowMessage(LobbyShowMessage & pack) {} +}; + +VCMI_LIB_NAMESPACE_END \ No newline at end of file diff --git a/lib/NetPacks.h b/lib/NetPacks.h index bc3b21b3a..24decd24f 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -36,7 +36,7 @@ struct ArtSlotInfo; struct QuestInfo; class IBattleState; -struct Query : public CPackForClient +struct DLL_LINKAGE Query : public CPackForClient { QueryID queryID; // equals to -1 if it is not an actual query (and should not be answered) }; @@ -53,8 +53,8 @@ struct StackLocation { } - DLL_LINKAGE const CStackInstance *getStack(); - template void serialize(Handler &h, const int version) + DLL_LINKAGE const CStackInstance * getStack(); + template void serialize(Handler & h, const int version) { h & army; h & slot; @@ -62,23 +62,21 @@ struct StackLocation }; /***********************************************************************************************************/ - - -struct PackageApplied : public CPackForClient +struct DLL_LINKAGE PackageApplied : public CPackForClient { PackageApplied() = default; PackageApplied(ui8 Result) : result(Result) { } - void applyCl(CClient *cl); + virtual void visitTyped(ICPackVisitor & visitor) override; ui8 result = 0; //0 - something went wrong, request hasn't been realized; 1 - OK ui32 packType = 0; //type id of applied package ui32 requestID = 0; //an ID given by client to the request that was applied PlayerColor player; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & result; h & packType; @@ -87,27 +85,26 @@ struct PackageApplied : public CPackForClient } }; -struct SystemMessage : public CPackForClient +struct DLL_LINKAGE SystemMessage : public CPackForClient { SystemMessage(std::string Text) : text(std::move(Text)) { } SystemMessage() = default; - void applyCl(CClient *cl); + + virtual void visitTyped(ICPackVisitor & visitor) override; std::string text; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & text; } }; -struct PlayerBlocked : public CPackForClient +struct DLL_LINKAGE PlayerBlocked : public CPackForClient { - void applyCl(CClient *cl); - enum EReason { UPCOMING_BATTLE, ONGOING_MOVEMENT }; enum EMode { BLOCKADE_STARTED, BLOCKADE_ENDED }; @@ -115,7 +112,9 @@ struct PlayerBlocked : public CPackForClient EMode startOrEnd = BLOCKADE_STARTED; PlayerColor player; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & reason; h & startOrEnd; @@ -123,15 +122,17 @@ struct PlayerBlocked : public CPackForClient } }; -struct PlayerCheated : public CPackForClient +struct DLL_LINKAGE PlayerCheated : public CPackForClient { - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; PlayerColor player; bool losingCheatCode = false; bool winningCheatCode = false; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & player; h & losingCheatCode; @@ -139,44 +140,47 @@ struct PlayerCheated : public CPackForClient } }; -struct YourTurn : public CPackForClient +struct DLL_LINKAGE YourTurn : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; PlayerColor player; boost::optional daysWithoutCastle; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & player; h & daysWithoutCastle; } }; -struct EntitiesChanged: public CPackForClient +struct DLL_LINKAGE EntitiesChanged : public CPackForClient { std::vector changes; - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState * gs); + void applyGs(CGameState * gs); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & changes; } }; -struct SetResources : public CPackForClient +struct DLL_LINKAGE SetResources : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; + + virtual void visitTyped(ICPackVisitor & visitor) override; bool abs = true; //false - changes by value; 1 - sets to value PlayerColor player; TResources res; //res[resid] => res amount - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & abs; h & player; @@ -184,17 +188,18 @@ struct SetResources : public CPackForClient } }; -struct SetPrimSkill : public CPackForClient +struct DLL_LINKAGE SetPrimSkill : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; + + virtual void visitTyped(ICPackVisitor & visitor) override; ui8 abs = 0; //0 - changes by value; 1 - sets to value ObjectInstanceID id; PrimarySkill::PrimarySkill which = PrimarySkill::ATTACK; si64 val = 0; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & abs; h & id; @@ -203,17 +208,18 @@ struct SetPrimSkill : public CPackForClient } }; -struct SetSecSkill : public CPackForClient +struct DLL_LINKAGE SetSecSkill : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; + + virtual void visitTyped(ICPackVisitor & visitor) override; ui8 abs = 0; //0 - changes by value; 1 - sets to value ObjectInstanceID id; SecondarySkill which; ui16 val = 0; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & abs; h & id; @@ -222,10 +228,11 @@ struct SetSecSkill : public CPackForClient } }; -struct HeroVisitCastle : public CPackForClient +struct DLL_LINKAGE HeroVisitCastle : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; + + virtual void visitTyped(ICPackVisitor & visitor) override; ui8 flags = 0; //1 - start ObjectInstanceID tid, hid; @@ -235,7 +242,7 @@ struct HeroVisitCastle : public CPackForClient return flags & 1; } - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & flags; h & tid; @@ -243,16 +250,17 @@ struct HeroVisitCastle : public CPackForClient } }; -struct ChangeSpells : public CPackForClient +struct DLL_LINKAGE ChangeSpells : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); + + virtual void visitTyped(ICPackVisitor & visitor) override; ui8 learn = 1; //1 - gives spell, 0 - takes ObjectInstanceID hid; std::set spells; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & learn; h & hid; @@ -260,16 +268,17 @@ struct ChangeSpells : public CPackForClient } }; -struct SetMana : public CPackForClient +struct DLL_LINKAGE SetMana : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; + + virtual void visitTyped(ICPackVisitor & visitor) override; ObjectInstanceID hid; si32 val = 0; bool absolute = true; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & val; h & hid; @@ -277,16 +286,17 @@ struct SetMana : public CPackForClient } }; -struct SetMovePoints : public CPackForClient +struct DLL_LINKAGE SetMovePoints : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; ObjectInstanceID hid; si32 val = 0; bool absolute = true; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & val; h & hid; @@ -294,16 +304,18 @@ struct SetMovePoints : public CPackForClient } }; -struct FoWChange : public CPackForClient +struct DLL_LINKAGE FoWChange : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); std::unordered_set tiles; PlayerColor player; ui8 mode = 0; //mode==0 - hide, mode==1 - reveal bool waitForDialogs = false; - template void serialize(Handler &h, const int version) + + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & tiles; h & player; @@ -312,20 +324,22 @@ struct FoWChange : public CPackForClient } }; -struct SetAvailableHeroes : public CPackForClient +struct DLL_LINKAGE SetAvailableHeroes : public CPackForClient { SetAvailableHeroes() { for(auto & i : army) i.clear(); } - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); PlayerColor player; si32 hid[GameConstants::AVAILABLE_HEROES_PER_PLAYER]; //-1 if no hero CSimpleArmy army[GameConstants::AVAILABLE_HEROES_PER_PLAYER]; - template void serialize(Handler &h, const int version) + + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & player; h & hid; @@ -333,42 +347,43 @@ struct SetAvailableHeroes : public CPackForClient } }; -struct GiveBonus : public CPackForClient +struct DLL_LINKAGE GiveBonus : public CPackForClient { GiveBonus(ui8 Who = 0) - : who(Who) { } - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); - enum {HERO, PLAYER, TOWN}; + void applyGs(CGameState * gs); + + enum { HERO, PLAYER, TOWN }; ui8 who = 0; //who receives bonus, uses enum above si32 id = 0; //hero. town or player id - whoever receives it Bonus bonus; MetaString bdescr; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & bonus; h & id; h & bdescr; h & who; - assert( id != -1); + assert(id != -1); } }; -struct ChangeObjPos : public CPackForClient +struct DLL_LINKAGE ChangeObjPos : public CPackForClient { - void applyFirstCl(CClient *cl); - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); ObjectInstanceID objid; int3 nPos; ui8 flags = 0; //bit flags: 1 - redraw - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & objid; h & nPos; @@ -376,47 +391,47 @@ struct ChangeObjPos : public CPackForClient } }; -struct PlayerEndsGame : public CPackForClient +struct DLL_LINKAGE PlayerEndsGame : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; PlayerColor player; EVictoryLossCheckResult victoryLossCheckResult; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & player; h & victoryLossCheckResult; } }; -struct PlayerReinitInterface : public CPackForClient +struct DLL_LINKAGE PlayerReinitInterface : public CPackForClient { - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState *gs); - + void applyGs(CGameState * gs); + std::vector players; ui8 playerConnectionId; //PLAYER_AI for AI player - - template void serialize(Handler &h, const int version) + + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & players; h & playerConnectionId; } }; -struct RemoveBonus : public CPackForClient +struct DLL_LINKAGE RemoveBonus : public CPackForClient { RemoveBonus(ui8 Who = 0) - : who(Who) { } - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); - enum {HERO, PLAYER, TOWN}; + enum { HERO, PLAYER, TOWN }; ui8 who; //who receives bonus, uses enum above ui32 whoID = 0; //hero, town or player id - whoever loses bonus @@ -427,7 +442,9 @@ struct RemoveBonus : public CPackForClient //used locally: copy of removed bonus Bonus bonus; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & source; h & id; @@ -436,12 +453,11 @@ struct RemoveBonus : public CPackForClient } }; -struct SetCommanderProperty : public CPackForClient +struct DLL_LINKAGE SetCommanderProperty : public CPackForClient { - enum ECommanderProperty {ALIVE, BONUS, SECONDARY_SKILL, EXPERIENCE, SPECIAL_SKILL}; + enum ECommanderProperty { ALIVE, BONUS, SECONDARY_SKILL, EXPERIENCE, SPECIAL_SKILL }; - void applyCl(CClient *cl){} - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); ObjectInstanceID heroid; @@ -450,7 +466,9 @@ struct SetCommanderProperty : public CPackForClient si32 additionalInfo = 0; //for secondary skills choice Bonus accumulatedBonus; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & heroid; h & which; @@ -460,27 +478,30 @@ struct SetCommanderProperty : public CPackForClient } }; -struct AddQuest : public CPackForClient +struct DLL_LINKAGE AddQuest : public CPackForClient { - void applyCl(CClient *cl){} - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; PlayerColor player; QuestInfo quest; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & player; h & quest; } }; -struct UpdateArtHandlerLists : public CPackForClient +struct DLL_LINKAGE UpdateArtHandlerLists : public CPackForClient { - std::vector treasures, minors, majors, relics; + std::vector treasures, minors, majors, relics; - DLL_LINKAGE void applyGs(CGameState * gs) const; - template void serialize(Handler &h, const int version) + void applyGs(CGameState * gs) const; + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & treasures; h & minors; @@ -489,68 +510,71 @@ struct UpdateArtHandlerLists : public CPackForClient } }; -struct UpdateMapEvents : public CPackForClient +struct DLL_LINKAGE UpdateMapEvents : public CPackForClient { - std::list events; - DLL_LINKAGE void applyGs(CGameState * gs) const; - template void serialize(Handler &h, const int version) + + void applyGs(CGameState * gs) const; + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & events; } }; -struct UpdateCastleEvents : public CPackForClient +struct DLL_LINKAGE UpdateCastleEvents : public CPackForClient { - ObjectInstanceID town; std::list events; - DLL_LINKAGE void applyGs(CGameState * gs) const; - template void serialize(Handler &h, const int version) + void applyGs(CGameState * gs) const; + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & town; h & events; } }; -struct ChangeFormation : public CPackForClient +struct DLL_LINKAGE ChangeFormation : public CPackForClient { - ObjectInstanceID hid; ui8 formation = 0; - DLL_LINKAGE void applyGs(CGameState * gs) const; - template void serialize(Handler &h, const int version) + void applyGs(CGameState * gs) const; + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & hid; h & formation; } }; -struct RemoveObject : public CPackForClient +struct DLL_LINKAGE RemoveObject : public CPackForClient { RemoveObject() = default; RemoveObject(const ObjectInstanceID & ID) : id(ID) - {} - void applyFirstCl(CClient *cl); - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + { + } + + void applyGs(CGameState * gs); + virtual void visitTyped(ICPackVisitor & visitor) override; ObjectInstanceID id; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & id; } }; -struct TryMoveHero : public CPackForClient +struct DLL_LINKAGE TryMoveHero : public CPackForClient { - void applyFirstCl(CClient *cl); - void applyCl(CClient *cl); - void applyGs(CGameState *gs); + void applyGs(CGameState * gs); enum EResult { @@ -572,9 +596,14 @@ struct TryMoveHero : public CPackForClient bool humanKnows = false; //used locally during applying to client - bool stopMovement() const; + virtual void visitTyped(ICPackVisitor & visitor) override; - template void serialize(Handler &h, const int version) + bool stopMovement() const + { + return result != SUCCESS && result != EMBARK && result != DISEMBARK && result != TELEPORTATION; + } + + template void serialize(Handler & h, const int version) { h & id; h & result; @@ -586,16 +615,17 @@ struct TryMoveHero : public CPackForClient } }; -struct NewStructures : public CPackForClient +struct DLL_LINKAGE NewStructures : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); ObjectInstanceID tid; std::set bid; si16 builded = 0; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & tid; h & bid; @@ -603,16 +633,17 @@ struct NewStructures : public CPackForClient } }; -struct RazeStructures : public CPackForClient +struct DLL_LINKAGE RazeStructures : public CPackForClient { - void applyCl (CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); ObjectInstanceID tid; std::set bid; si16 destroyed = 0; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & tid; h & bid; @@ -620,29 +651,31 @@ struct RazeStructures : public CPackForClient } }; -struct SetAvailableCreatures : public CPackForClient +struct DLL_LINKAGE SetAvailableCreatures : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; ObjectInstanceID tid; std::vector > > creatures; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & tid; h & creatures; } }; -struct SetHeroesInTown : public CPackForClient +struct DLL_LINKAGE SetHeroesInTown : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; ObjectInstanceID tid, visiting, garrison; //id of town, visiting hero, hero in garrison - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & tid; h & visiting; @@ -650,17 +683,18 @@ struct SetHeroesInTown : public CPackForClient } }; -struct HeroRecruited : public CPackForClient +struct DLL_LINKAGE HeroRecruited : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; si32 hid = -1; //subID of hero ObjectInstanceID tid; int3 tile; PlayerColor player; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & hid; h & tid; @@ -669,33 +703,36 @@ struct HeroRecruited : public CPackForClient } }; -struct GiveHero : public CPackForClient +struct DLL_LINKAGE GiveHero : public CPackForClient { - void applyFirstCl(CClient *cl); - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; ObjectInstanceID id; //object id PlayerColor player; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & id; h & player; } }; -struct OpenWindow : public CPackForClient +struct DLL_LINKAGE OpenWindow : public CPackForClient { - void applyCl(CClient *cl); - - enum EWindow {EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL, SHIPYARD_WINDOW, THIEVES_GUILD, - UNIVERSITY_WINDOW, HILL_FORT_WINDOW, MARKET_WINDOW, PUZZLE_MAP, TAVERN_WINDOW}; + enum EWindow + { + EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL, SHIPYARD_WINDOW, THIEVES_GUILD, + UNIVERSITY_WINDOW, HILL_FORT_WINDOW, MARKET_WINDOW, PUZZLE_MAP, TAVERN_WINDOW + }; ui8 window; si32 id1 = -1; si32 id2 = -1; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & window; h & id1; @@ -703,10 +740,9 @@ struct OpenWindow : public CPackForClient } }; -struct NewObject : public CPackForClient +struct DLL_LINKAGE NewObject : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); Obj ID; ui32 subID = 0; @@ -714,7 +750,9 @@ struct NewObject : public CPackForClient ObjectInstanceID id; //used locally, filled during applyGs - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & ID; h & subID; @@ -722,46 +760,50 @@ struct NewObject : public CPackForClient } }; -struct SetAvailableArtifacts : public CPackForClient +struct DLL_LINKAGE SetAvailableArtifacts : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; si32 id = 0; //two variants: id < 0: set artifact pool for Artifact Merchants in towns; id >= 0: set pool for adv. map Black Market (id is the id of Black Market instance then) std::vector arts; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & id; h & arts; } }; -struct NewArtifact : public CPackForClient +struct DLL_LINKAGE NewArtifact : public CPackForClient { - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); ConstTransitivePtr art; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & art; } }; -struct CGarrisonOperationPack : CPackForClient +struct DLL_LINKAGE CGarrisonOperationPack : CPackForClient { }; -struct ChangeStackCount : CGarrisonOperationPack +struct DLL_LINKAGE ChangeStackCount : CGarrisonOperationPack { ObjectInstanceID army; SlotID slot; TQuantity count; bool absoluteValue; //if not -> count will be added (or subtracted if negative) - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState * gs); + void applyGs(CGameState * gs); + + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -772,16 +814,17 @@ struct ChangeStackCount : CGarrisonOperationPack } }; -struct SetStackType : CGarrisonOperationPack +struct DLL_LINKAGE SetStackType : CGarrisonOperationPack { ObjectInstanceID army; SlotID slot; CreatureID type; - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & army; h & slot; @@ -789,30 +832,30 @@ struct SetStackType : CGarrisonOperationPack } }; -struct EraseStack : CGarrisonOperationPack +struct DLL_LINKAGE EraseStack : CGarrisonOperationPack { ObjectInstanceID army; SlotID slot; - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); + virtual void visitTyped(ICPackVisitor & visitor) override; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & army; h & slot; } }; -struct SwapStacks : CGarrisonOperationPack +struct DLL_LINKAGE SwapStacks : CGarrisonOperationPack { ObjectInstanceID srcArmy; ObjectInstanceID dstArmy; SlotID srcSlot; SlotID dstSlot; - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState * gs); + void applyGs(CGameState * gs); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -823,15 +866,15 @@ struct SwapStacks : CGarrisonOperationPack } }; -struct InsertNewStack : CGarrisonOperationPack +struct DLL_LINKAGE InsertNewStack : CGarrisonOperationPack { ObjectInstanceID army; SlotID slot; CreatureID type; TQuantity count = 0; - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState * gs); + void applyGs(CGameState * gs); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -843,7 +886,7 @@ struct InsertNewStack : CGarrisonOperationPack }; ///moves creatures from src stack to dst slot, may be used for merging/splittint/moving stacks -struct RebalanceStacks : CGarrisonOperationPack +struct DLL_LINKAGE RebalanceStacks : CGarrisonOperationPack { ObjectInstanceID srcArmy; ObjectInstanceID dstArmy; @@ -852,10 +895,10 @@ struct RebalanceStacks : CGarrisonOperationPack TQuantity count; - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs); + void applyGs(CGameState * gs); + virtual void visitTyped(ICPackVisitor & visitor) override; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & srcArmy; h & dstArmy; @@ -865,29 +908,29 @@ struct RebalanceStacks : CGarrisonOperationPack } }; -struct BulkRebalanceStacks : CGarrisonOperationPack +struct DLL_LINKAGE BulkRebalanceStacks : CGarrisonOperationPack { std::vector moves; - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState * gs); + void applyGs(CGameState * gs); + virtual void visitTyped(ICPackVisitor & visitor) override; - template + template void serialize(Handler & h, const int version) { h & moves; } }; -struct BulkSmartRebalanceStacks : CGarrisonOperationPack +struct DLL_LINKAGE BulkSmartRebalanceStacks : CGarrisonOperationPack { std::vector moves; std::vector changes; - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState * gs); + void applyGs(CGameState * gs); + virtual void visitTyped(ICPackVisitor & visitor) override; - template + template void serialize(Handler & h, const int version) { h & moves; @@ -897,11 +940,11 @@ struct BulkSmartRebalanceStacks : CGarrisonOperationPack struct GetEngagedHeroIds : boost::static_visitor> { - boost::optional operator()(const ConstTransitivePtr &h) const + boost::optional operator()(const ConstTransitivePtr & h) const { return h->id; } - boost::optional operator()(const ConstTransitivePtr &s) const + boost::optional operator()(const ConstTransitivePtr & s) const { if(s->armyObj && s->armyObj->ID == Obj::HERO) return s->armyObj->id; @@ -909,49 +952,50 @@ struct GetEngagedHeroIds : boost::static_visitor art; - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); + virtual void visitTyped(ICPackVisitor & visitor) override; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & al; h & art; } }; -struct EraseArtifact : CArtifactOperationPack +struct DLL_LINKAGE EraseArtifact : CArtifactOperationPack { ArtifactLocation al; - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); + virtual void visitTyped(ICPackVisitor & visitor) override; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & al; } }; -struct MoveArtifact : CArtifactOperationPack +struct DLL_LINKAGE MoveArtifact : CArtifactOperationPack { MoveArtifact() = default; MoveArtifact(ArtifactLocation * src, ArtifactLocation * dst, bool askAssemble = true) : src(*src), dst(*dst), askAssemble(askAssemble) - {} + { + } ArtifactLocation src, dst; bool askAssemble = true; - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -961,7 +1005,7 @@ struct MoveArtifact : CArtifactOperationPack } }; -struct BulkMoveArtifacts : CArtifactOperationPack +struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack { struct LinkedSlots { @@ -985,7 +1029,9 @@ struct BulkMoveArtifacts : CArtifactOperationPack TArtHolder dstArtHolder; BulkMoveArtifacts() - : swap(false) {} + : swap(false) + { + } BulkMoveArtifacts(TArtHolder srcArtHolder, TArtHolder dstArtHolder, bool swap) : srcArtHolder(std::move(std::move(srcArtHolder))) , dstArtHolder(std::move(std::move(dstArtHolder))) @@ -993,14 +1039,16 @@ struct BulkMoveArtifacts : CArtifactOperationPack { } - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState * gs); + void applyGs(CGameState * gs); std::vector artsPack0; std::vector artsPack1; bool swap; CArtifactSet * getSrcHolderArtSet(); CArtifactSet * getDstHolderArtSet(); + + virtual void visitTyped(ICPackVisitor & visitor) override; + template void serialize(Handler & h, const int version) { h & artsPack0; @@ -1011,35 +1059,37 @@ struct BulkMoveArtifacts : CArtifactOperationPack } }; -struct AssembledArtifact : CArtifactOperationPack +struct DLL_LINKAGE AssembledArtifact : CArtifactOperationPack { ArtifactLocation al; //where assembly will be put - CArtifact *builtArt; + CArtifact * builtArt; - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & al; h & builtArt; } }; -struct DisassembledArtifact : CArtifactOperationPack +struct DLL_LINKAGE DisassembledArtifact : CArtifactOperationPack { ArtifactLocation al; - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & al; } }; -struct HeroVisit : public CPackForClient +struct DLL_LINKAGE HeroVisit : public CPackForClient { PlayerColor player; ObjectInstanceID heroId; @@ -1047,8 +1097,9 @@ struct HeroVisit : public CPackForClient bool starting; //false -> ending - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState * gs); + void applyGs(CGameState * gs); + + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -1059,24 +1110,25 @@ struct HeroVisit : public CPackForClient } }; -struct NewTurn : public CPackForClient +struct DLL_LINKAGE NewTurn : public CPackForClient { - enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, DEITYOFFIRE, PLAGUE, NO_ACTION}; + enum weekType { NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, DEITYOFFIRE, PLAGUE, NO_ACTION }; - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + void applyGs(CGameState * gs); + + virtual void visitTyped(ICPackVisitor & visitor) override; struct Hero { ObjectInstanceID id; ui32 move, mana; //id is a general serial id - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & id; h & move; h & mana; } - bool operator<(const Hero&h)const{return id < h.id;} + bool operator<(const Hero & h)const { return id < h.id; } }; std::set heroes; //updates movement and mana points @@ -1088,7 +1140,7 @@ struct NewTurn : public CPackForClient NewTurn() = default; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & heroes; h & cres; @@ -1099,16 +1151,16 @@ struct NewTurn : public CPackForClient } }; -struct InfoWindow : public CPackForClient //103 - displays simple info window +struct DLL_LINKAGE InfoWindow : public CPackForClient //103 - displays simple info window { - void applyCl(CClient *cl); - MetaString text; std::vector components; PlayerColor player; ui16 soundID = 0; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & text; h & components; @@ -1120,7 +1172,9 @@ struct InfoWindow : public CPackForClient //103 - displays simple info window namespace ObjProperty { - enum {OWNER = 1, BLOCKVIS = 2, PRIMARY_STACK_COUNT = 3, VISITORS = 4, VISITED = 5, ID = 6, AVAILABLE_CREATURE = 7, SUBID = 8, + enum + { + OWNER = 1, BLOCKVIS = 2, PRIMARY_STACK_COUNT = 3, VISITORS = 4, VISITED = 5, ID = 6, AVAILABLE_CREATURE = 7, SUBID = 8, MONSTER_COUNT = 10, MONSTER_POWER = 11, MONSTER_EXP = 12, MONSTER_RESTORE_TYPE = 13, MONSTER_REFUSED_JOIN, //town-specific @@ -1135,11 +1189,9 @@ namespace ObjProperty }; } -struct SetObjectProperty : public CPackForClient +struct DLL_LINKAGE SetObjectProperty : public CPackForClient { - DLL_LINKAGE void applyGs(CGameState * gs) const; - void applyCl(CClient *cl); - + void applyGs(CGameState * gs) const; ObjectInstanceID id; ui8 what = 0; // see ObjProperty enum ui32 val = 0; @@ -1148,9 +1200,12 @@ struct SetObjectProperty : public CPackForClient : id(ID) , what(What) , val(Val) - {} + { + } - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & id; h & what; @@ -1158,7 +1213,7 @@ struct SetObjectProperty : public CPackForClient } }; -struct ChangeObjectVisitors : public CPackForClient +struct DLL_LINKAGE ChangeObjectVisitors : public CPackForClient { enum VisitMode { @@ -1171,7 +1226,9 @@ struct ChangeObjectVisitors : public CPackForClient ObjectInstanceID object; ObjectInstanceID hero; // note: hero owner will be also marked as "visited" this object - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; + + virtual void visitTyped(ICPackVisitor & visitor) override; ChangeObjectVisitors() = default; @@ -1179,9 +1236,10 @@ struct ChangeObjectVisitors : public CPackForClient : mode(mode) , object(object) , hero(heroID) - {} + { + } - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & object; h & hero; @@ -1189,22 +1247,24 @@ struct ChangeObjectVisitors : public CPackForClient } }; -struct PrepareHeroLevelUp : public CPackForClient +struct DLL_LINKAGE PrepareHeroLevelUp : public CPackForClient { ObjectInstanceID heroId; /// Do not serialize, used by server only std::vector skills; - DLL_LINKAGE void applyGs(CGameState * gs); + void applyGs(CGameState * gs); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & heroId; } }; -struct HeroLevelUp : public Query +struct DLL_LINKAGE HeroLevelUp : public Query { PlayerColor player; ObjectInstanceID heroId; @@ -1212,8 +1272,9 @@ struct HeroLevelUp : public Query PrimarySkill::PrimarySkill primskill = PrimarySkill::ATTACK; std::vector skills; - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; + + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -1225,15 +1286,16 @@ struct HeroLevelUp : public Query } }; -struct CommanderLevelUp : public Query +struct DLL_LINKAGE CommanderLevelUp : public Query { PlayerColor player; ObjectInstanceID heroId; std::vector skills; //0-5 - secondary skills, val-100 - special skill - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; + + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -1247,12 +1309,9 @@ struct CommanderLevelUp : public Query //A dialog that requires making decision by player - it may contain components to choose between or has yes/no options //Client responds with QueryReply, where answer: 0 - cancel pressed, choice doesn't matter; 1/2/... - first/second/... component selected and OK pressed //Until sending reply player won't be allowed to take any actions -struct BlockingDialog : public Query +struct DLL_LINKAGE BlockingDialog : public Query { - enum {ALLOW_CANCEL = 1, SELECTION = 2}; - - void applyCl(CClient *cl); - + enum { ALLOW_CANCEL = 1, SELECTION = 2 }; MetaString text; std::vector components; PlayerColor player; @@ -1275,7 +1334,9 @@ struct BlockingDialog : public Query } BlockingDialog() = default; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & queryID; h & text; @@ -1286,13 +1347,14 @@ struct BlockingDialog : public Query } }; -struct GarrisonDialog : public Query +struct DLL_LINKAGE GarrisonDialog : public Query { - void applyCl(CClient *cl); ObjectInstanceID objid, hid; bool removableUnits = false; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & queryID; h & objid; @@ -1301,16 +1363,16 @@ struct GarrisonDialog : public Query } }; -struct ExchangeDialog : public Query +struct DLL_LINKAGE ExchangeDialog : public Query { - void applyCl(CClient *cl); - PlayerColor player; ObjectInstanceID hero1; ObjectInstanceID hero2; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & queryID; h & player; @@ -1319,23 +1381,23 @@ struct ExchangeDialog : public Query } }; -struct TeleportDialog : public Query +struct DLL_LINKAGE TeleportDialog : public Query { TeleportDialog() = default; TeleportDialog(const PlayerColor & Player, const TeleportChannelID & Channel) : player(Player) , channel(Channel) - {} - - void applyCl(CClient *cl); - + { + } PlayerColor player; TeleportChannelID channel; TTeleportExitsList exits; bool impassable = false; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & queryID; h & player; @@ -1345,7 +1407,7 @@ struct TeleportDialog : public Query } }; -struct MapObjectSelectDialog : public Query +struct DLL_LINKAGE MapObjectSelectDialog : public Query { PlayerColor player; Component icon; @@ -1353,7 +1415,7 @@ struct MapObjectSelectDialog : public Query MetaString description; std::vector objects; - void applyCl(CClient * cl); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -1367,62 +1429,65 @@ struct MapObjectSelectDialog : public Query }; class BattleInfo; -struct BattleStart : public CPackForClient +struct DLL_LINKAGE BattleStart : public CPackForClient { - void applyFirstCl(CClient *cl); - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; BattleInfo * info = nullptr; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & info; } }; -struct BattleNextRound : public CPackForClient +struct DLL_LINKAGE BattleNextRound : public CPackForClient { - void applyFirstCl(CClient *cl); - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; si32 round = 0; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & round; } }; -struct BattleSetActiveStack : public CPackForClient +struct DLL_LINKAGE BattleSetActiveStack : public CPackForClient { - void applyCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; ui32 stack = 0; ui8 askPlayerInterface = true; - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & stack; h & askPlayerInterface; } }; -struct BattleResult : public CPackForClient +struct DLL_LINKAGE BattleResult : public CPackForClient { - enum EResult {NORMAL = 0, ESCAPE = 1, SURRENDER = 2}; + enum EResult { NORMAL = 0, ESCAPE = 1, SURRENDER = 2 }; - void applyFirstCl(CClient *cl); - void applyGs(CGameState *gs); + void applyFirstCl(CClient * cl); + void applyGs(CGameState * gs); EResult result = NORMAL; ui8 winner = 2; //0 - attacker, 1 - defender, [2 - draw (should be possible?)] - std::map casualties[2]; //first => casualties of attackers - map crid => number + std::map casualties[2]; //first => casualties of attackers - map crid => number TExpType exp[2] = {0, 0}; //exp for attacker and defender std::set artifacts; //artifacts taken from loser to winner - currently unused - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & result; h & winner; @@ -1433,13 +1498,14 @@ struct BattleResult : public CPackForClient } }; -struct BattleLogMessage : public CPackForClient +struct DLL_LINKAGE BattleLogMessage : public CPackForClient { std::vector lines; - void applyCl(CClient * cl); - DLL_LINKAGE void applyGs(CGameState * gs); - DLL_LINKAGE void applyBattle(IBattleState * battleState); + void applyGs(CGameState * gs); + void applyBattle(IBattleState * battleState); + + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -1447,16 +1513,19 @@ struct BattleLogMessage : public CPackForClient } }; -struct BattleStackMoved : public CPackForClient +struct DLL_LINKAGE BattleStackMoved : public CPackForClient { ui32 stack = 0; std::vector tilesToMove; int distance = 0; bool teleporting = false; - void applyFirstCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); - DLL_LINKAGE void applyBattle(IBattleState * battleState); - template void serialize(Handler &h, const int version) + + void applyGs(CGameState * gs); + void applyBattle(IBattleState * battleState); + + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & stack; h & tilesToMove; @@ -1465,14 +1534,15 @@ struct BattleStackMoved : public CPackForClient } }; -struct BattleUnitsChanged : public CPackForClient +struct DLL_LINKAGE BattleUnitsChanged : public CPackForClient { - DLL_LINKAGE void applyGs(CGameState *gs); - DLL_LINKAGE void applyBattle(IBattleState * battleState); - void applyCl(CClient *cl); + void applyGs(CGameState * gs); + void applyBattle(IBattleState * battleState); std::vector changedStacks; + virtual void visitTyped(ICPackVisitor & visitor) override; + template void serialize(Handler & h, const int version) { h & changedStacks; @@ -1481,14 +1551,14 @@ struct BattleUnitsChanged : public CPackForClient struct BattleStackAttacked { - DLL_LINKAGE void applyGs(CGameState *gs); + DLL_LINKAGE void applyGs(CGameState * gs); DLL_LINKAGE void applyBattle(IBattleState * battleState); ui32 stackAttacked = 0, attackerID = 0; ui32 killedAmount = 0; int64_t damageAmount = 0; UnitChanges newState; - enum EFlags {KILLED = 1, SECONDARY = 2, REBIRTH = 4, CLONE_KILLED = 8, SPELL_EFFECT = 16, FIRE_SHIELD = 32, }; + enum EFlags { KILLED = 1, SECONDARY = 2, REBIRTH = 4, CLONE_KILLED = 8, SPELL_EFFECT = 16, FIRE_SHIELD = 32, }; ui32 flags = 0; //uses EFlags (above) SpellID spellID = SpellID::NONE; //only if flag SPELL_EFFECT is set @@ -1517,7 +1587,8 @@ struct BattleStackAttacked { return flags & FIRE_SHIELD; } - template void serialize(Handler &h, const int version) + + template void serialize(Handler & h, const int version) { h & stackAttacked; h & attackerID; @@ -1527,24 +1598,21 @@ struct BattleStackAttacked h & damageAmount; h & spellID; } - bool operator<(const BattleStackAttacked &b) const + bool operator<(const BattleStackAttacked & b) const { return stackAttacked < b.stackAttacked; } }; -struct BattleAttack : public CPackForClient +struct DLL_LINKAGE BattleAttack : public CPackForClient { - void applyFirstCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); - void applyCl(CClient *cl); - + void applyGs(CGameState * gs); BattleUnitsChanged attackerChanges; std::vector bsa; ui32 stackAttacking = 0; ui32 flags = 0; //uses Eflags (below) - enum EFlags{SHOT = 1, COUNTER = 2, LUCKY = 4, UNLUCKY = 8, BALLISTA_DOUBLE_DMG = 16, DEATH_BLOW = 32, SPELL_LIKE = 64, LIFE_DRAIN = 128}; + enum EFlags { SHOT = 1, COUNTER = 2, LUCKY = 4, UNLUCKY = 8, BALLISTA_DOUBLE_DMG = 16, DEATH_BLOW = 32, SPELL_LIKE = 64, LIFE_DRAIN = 128 }; BattleHex tile; SpellID spellID = SpellID::NONE; //for SPELL_LIKE @@ -1581,7 +1649,10 @@ struct BattleAttack : public CPackForClient { return flags & LIFE_DRAIN; } - template void serialize(Handler &h, const int version) + + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & bsa; h & stackAttacking; @@ -1592,36 +1663,38 @@ struct BattleAttack : public CPackForClient } }; -struct StartAction : public CPackForClient +struct DLL_LINKAGE StartAction : public CPackForClient { StartAction() = default; StartAction(BattleAction act) : ba(std::move(act)) - {} - void applyFirstCl(CClient *cl); - DLL_LINKAGE void applyGs(CGameState *gs); + { + } + void applyFirstCl(CClient * cl); + void applyGs(CGameState * gs); BattleAction ba; - template void serialize(Handler &h, const int version) + + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & ba; } }; -struct EndAction : public CPackForClient +struct DLL_LINKAGE EndAction : public CPackForClient { - void applyCl(CClient *cl); + virtual void visitTyped(ICPackVisitor & visitor) override; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { } }; -struct BattleSpellCast : public CPackForClient +struct DLL_LINKAGE BattleSpellCast : public CPackForClient { - DLL_LINKAGE void applyGs(CGameState * gs) const; - void applyCl(CClient *cl); - + void applyGs(CGameState * gs) const; bool activeCast = true; ui8 side = 0; //which hero did cast spell: 0 - attacker, 1 - defender SpellID spellID; //id of spell @@ -1633,7 +1706,9 @@ struct BattleSpellCast : public CPackForClient si32 casterStack = -1; // -1 if not cated by creature, >=0 caster stack ID bool castByHero = true; //if true - spell has been cast by hero, otherwise by a creature - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & side; h & spellID; @@ -1648,16 +1723,16 @@ struct BattleSpellCast : public CPackForClient } }; -struct SetStackEffect : public CPackForClient +struct DLL_LINKAGE SetStackEffect : public CPackForClient { - DLL_LINKAGE void applyGs(CGameState * gs); - DLL_LINKAGE void applyBattle(IBattleState * battleState); - void applyCl(CClient * cl); - + void applyGs(CGameState * gs); + void applyBattle(IBattleState * battleState); std::vector>> toAdd; std::vector>> toUpdate; std::vector>> toRemove; + virtual void visitTyped(ICPackVisitor & visitor) override; + template void serialize(Handler & h, const int version) { h & toAdd; @@ -1666,48 +1741,49 @@ struct SetStackEffect : public CPackForClient } }; -struct StacksInjured : public CPackForClient +struct DLL_LINKAGE StacksInjured : public CPackForClient { - DLL_LINKAGE void applyGs(CGameState * gs); - DLL_LINKAGE void applyBattle(IBattleState * battleState); - - void applyCl(CClient * cl); + void applyGs(CGameState * gs); + void applyBattle(IBattleState * battleState); std::vector stacks; + virtual void visitTyped(ICPackVisitor & visitor) override; + template void serialize(Handler & h, const int version) { h & stacks; } }; -struct BattleResultsApplied : public CPackForClient +struct DLL_LINKAGE BattleResultsApplied : public CPackForClient { PlayerColor player1, player2; + virtual void visitTyped(ICPackVisitor & visitor) override; - void applyCl(CClient *cl); - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & player1; h & player2; } }; -struct BattleObstaclesChanged : public CPackForClient +struct DLL_LINKAGE BattleObstaclesChanged : public CPackForClient { - DLL_LINKAGE void applyGs(CGameState * gs); - DLL_LINKAGE void applyBattle(IBattleState * battleState); - void applyCl(CClient * cl); + void applyGs(CGameState * gs); + void applyBattle(IBattleState * battleState); std::vector changes; + virtual void visitTyped(ICPackVisitor & visitor) override; + template void serialize(Handler & h, const int version) { h & changes; } }; -struct ELF_VISIBILITY CatapultAttack : public CPackForClient +struct DLL_LINKAGE CatapultAttack : public CPackForClient { struct AttackInfo { @@ -1723,160 +1799,175 @@ struct ELF_VISIBILITY CatapultAttack : public CPackForClient } }; - DLL_LINKAGE CatapultAttack(); - DLL_LINKAGE ~CatapultAttack() override; + CatapultAttack(); + ~CatapultAttack() override; - DLL_LINKAGE void applyGs(CGameState * gs); - DLL_LINKAGE void applyBattle(IBattleState * battleState); - void applyCl(CClient * cl); + void applyGs(CGameState * gs); + void applyBattle(IBattleState * battleState); std::vector< AttackInfo > attackedParts; int attacker = -1; //if -1, then a spell caused this - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & attackedParts; h & attacker; } }; -struct BattleSetStackProperty : public CPackForClient +struct DLL_LINKAGE BattleSetStackProperty : public CPackForClient { - enum BattleStackProperty {CASTS, ENCHANTER_COUNTER, UNBIND, CLONED, HAS_CLONE}; + enum BattleStackProperty { CASTS, ENCHANTER_COUNTER, UNBIND, CLONED, HAS_CLONE }; - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; int stackID = 0; BattleStackProperty which = CASTS; int val = 0; int absolute = 0; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & stackID; h & which; h & val; h & absolute; } + +protected: + virtual void visitTyped(ICPackVisitor & visitor) override; }; ///activated at the beginning of turn -struct BattleTriggerEffect : public CPackForClient +struct DLL_LINKAGE BattleTriggerEffect : public CPackForClient { - DLL_LINKAGE void applyGs(CGameState * gs) const; //effect - void applyCl(CClient *cl); //play animations & stuff + void applyGs(CGameState * gs) const; //effect int stackID = 0; int effect = 0; //use corresponding Bonus type int val = 0; int additionalInfo = 0; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & stackID; h & effect; h & val; h & additionalInfo; } + +protected: + virtual void visitTyped(ICPackVisitor & visitor) override; }; -struct BattleUpdateGateState : public CPackForClient +struct DLL_LINKAGE BattleUpdateGateState : public CPackForClient { - void applyFirstCl(CClient *cl); - - DLL_LINKAGE void applyGs(CGameState * gs) const; + void applyGs(CGameState * gs) const; EGateState state = EGateState::NONE; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & state; } + +protected: + virtual void visitTyped(ICPackVisitor & visitor) override; }; -struct ShowInInfobox : public CPackForClient +struct DLL_LINKAGE ShowInInfobox : public CPackForClient { PlayerColor player; Component c; MetaString text; - - void applyCl(CClient *cl); - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & player; h & c; h & text; } + +protected: + virtual void visitTyped(ICPackVisitor & visitor) override; }; -struct AdvmapSpellCast : public CPackForClient +struct DLL_LINKAGE AdvmapSpellCast : public CPackForClient { ObjectInstanceID casterID; SpellID spellID; - - void applyCl(CClient *cl); - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & casterID; h & spellID; } + +protected: + virtual void visitTyped(ICPackVisitor & visitor) override; }; -struct ShowWorldViewEx : public CPackForClient +struct DLL_LINKAGE ShowWorldViewEx : public CPackForClient { PlayerColor player; std::vector objectPositions; - void applyCl(CClient *cl); - - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & player; h & objectPositions; } + +protected: + virtual void visitTyped(ICPackVisitor & visitor) override; }; /***********************************************************************************************************/ -struct EndTurn : public CPackForServer +struct DLL_LINKAGE EndTurn : public CPackForServer { - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); } }; -struct DismissHero : public CPackForServer +struct DLL_LINKAGE DismissHero : public CPackForServer { DismissHero() = default; DismissHero(const ObjectInstanceID & HID) : hid(HID) - {} + { + } ObjectInstanceID hid; - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & hid; } }; -struct MoveHero : public CPackForServer +struct DLL_LINKAGE MoveHero : public CPackForServer { MoveHero() = default; MoveHero(const int3 & Dest, const ObjectInstanceID & HID, bool Transit) : dest(Dest) , hid(HID) , transit(Transit) - {} + { + } int3 dest; ObjectInstanceID hid; bool transit = false; - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & dest; @@ -1885,20 +1976,22 @@ struct MoveHero : public CPackForServer } }; -struct CastleTeleportHero : public CPackForServer +struct DLL_LINKAGE CastleTeleportHero : public CPackForServer { CastleTeleportHero() = default; CastleTeleportHero(const ObjectInstanceID & HID, const ObjectInstanceID & Dest, ui8 Source) : dest(Dest) , hid(HID) , source(Source) - {} + { + } ObjectInstanceID dest; ObjectInstanceID hid; si8 source = 0; //who give teleporting, 1=castle gate - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & dest; @@ -1906,7 +1999,7 @@ struct CastleTeleportHero : public CPackForServer } }; -struct ArrangeStacks : public CPackForServer +struct DLL_LINKAGE ArrangeStacks : public CPackForServer { ArrangeStacks() = default; ArrangeStacks(ui8 W, const SlotID & P1, const SlotID & P2, const ObjectInstanceID & ID1, const ObjectInstanceID & ID2, si32 VAL) @@ -1916,14 +2009,17 @@ struct ArrangeStacks : public CPackForServer , id1(ID1) , id2(ID2) , val(VAL) - {} + { + } ui8 what = 0; //1 - swap; 2 - merge; 3 - split SlotID p1, p2; //positions of first and second stack ObjectInstanceID id1, id2; //ids of objects with garrison si32 val = 0; - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & what; @@ -1935,7 +2031,7 @@ struct ArrangeStacks : public CPackForServer } }; -struct BulkMoveArmy : public CPackForServer +struct DLL_LINKAGE BulkMoveArmy : public CPackForServer { SlotID srcSlot; ObjectInstanceID srcArmy; @@ -1947,21 +2043,22 @@ struct BulkMoveArmy : public CPackForServer : srcArmy(srcArmy) , destArmy(destArmy) , srcSlot(srcSlot) - {} + { + } - bool applyGh(CGameHandler * gh); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { - h & static_cast(*this); + h & static_cast(*this); h & srcSlot; h & srcArmy; h & destArmy; } }; -struct BulkSplitStack : public CPackForServer +struct DLL_LINKAGE BulkSplitStack : public CPackForServer { SlotID src; ObjectInstanceID srcOwner; @@ -1973,21 +2070,22 @@ struct BulkSplitStack : public CPackForServer : src(src) , srcOwner(srcOwner) , amount(howMany) - {} + { + } - bool applyGh(CGameHandler * gh); + virtual void visitTyped(ICPackVisitor & visitor) override; - template + template void serialize(Handler & h, const int version) { - h & static_cast(*this); + h & static_cast(*this); h & src; h & srcOwner; h & amount; } }; -struct BulkMergeStacks : public CPackForServer +struct DLL_LINKAGE BulkMergeStacks : public CPackForServer { SlotID src; ObjectInstanceID srcOwner; @@ -1997,20 +2095,21 @@ struct BulkMergeStacks : public CPackForServer BulkMergeStacks(const ObjectInstanceID & srcOwner, const SlotID & src) : src(src) , srcOwner(srcOwner) - {} + { + } - bool applyGh(CGameHandler * gh); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { - h & static_cast(*this); + h & static_cast(*this); h & src; h & srcOwner; } }; -struct BulkSmartSplitStack : public CPackForServer +struct DLL_LINKAGE BulkSmartSplitStack : public CPackForServer { SlotID src; ObjectInstanceID srcOwner; @@ -2020,31 +2119,34 @@ struct BulkSmartSplitStack : public CPackForServer BulkSmartSplitStack(const ObjectInstanceID & srcOwner, const SlotID & src) : src(src) , srcOwner(srcOwner) - {} + { + } - bool applyGh(CGameHandler * gh); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { - h & static_cast(*this); + h & static_cast(*this); h & src; h & srcOwner; } }; -struct DisbandCreature : public CPackForServer +struct DLL_LINKAGE DisbandCreature : public CPackForServer { DisbandCreature() = default; DisbandCreature(const SlotID & Pos, const ObjectInstanceID & ID) : pos(Pos) , id(ID) - {} + { + } SlotID pos; //stack pos ObjectInstanceID id; //object id - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & pos; @@ -2052,18 +2154,20 @@ struct DisbandCreature : public CPackForServer } }; -struct BuildStructure : public CPackForServer +struct DLL_LINKAGE BuildStructure : public CPackForServer { BuildStructure() = default; BuildStructure(const ObjectInstanceID & TID, const BuildingID & BID) : tid(TID) , bid(BID) - {} + { + } ObjectInstanceID tid; //town id BuildingID bid; //structure id - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & tid; @@ -2071,12 +2175,12 @@ struct BuildStructure : public CPackForServer } }; -struct RazeStructure : public BuildStructure +struct DLL_LINKAGE RazeStructure : public BuildStructure { - bool applyGh(CGameHandler *gh); + virtual void visitTyped(ICPackVisitor & visitor) override; }; -struct RecruitCreatures : public CPackForServer +struct DLL_LINKAGE RecruitCreatures : public CPackForServer { RecruitCreatures() = default; RecruitCreatures(const ObjectInstanceID & TID, const ObjectInstanceID & DST, const CreatureID & CRID, si32 Amount, si32 Level) @@ -2085,14 +2189,17 @@ struct RecruitCreatures : public CPackForServer , crid(CRID) , amount(Amount) , level(Level) - {} + { + } ObjectInstanceID tid; //dwelling id, or town ObjectInstanceID dst; //destination ID, e.g. hero CreatureID crid; ui32 amount = 0; //creature amount si32 level = 0; //dwelling level to buy from, -1 if any - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & tid; @@ -2103,20 +2210,22 @@ struct RecruitCreatures : public CPackForServer } }; -struct UpgradeCreature : public CPackForServer +struct DLL_LINKAGE UpgradeCreature : public CPackForServer { UpgradeCreature() = default; UpgradeCreature(const SlotID & Pos, const ObjectInstanceID & ID, const CreatureID & CRID) : pos(Pos) , id(ID) , cid(CRID) - {} + { + } SlotID pos; //stack pos ObjectInstanceID id; //object id CreatureID cid; //id of type to which we want make upgrade - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & pos; @@ -2125,27 +2234,31 @@ struct UpgradeCreature : public CPackForServer } }; -struct GarrisonHeroSwap : public CPackForServer +struct DLL_LINKAGE GarrisonHeroSwap : public CPackForServer { GarrisonHeroSwap() = default; GarrisonHeroSwap(const ObjectInstanceID & TID) : tid(TID) - {} + { + } ObjectInstanceID tid; - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & tid; } }; -struct ExchangeArtifacts : public CPackForServer +struct DLL_LINKAGE ExchangeArtifacts : public CPackForServer { ArtifactLocation src, dst; - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & src; @@ -2153,7 +2266,7 @@ struct ExchangeArtifacts : public CPackForServer } }; -struct BulkExchangeArtifacts : public CPackForServer +struct DLL_LINKAGE BulkExchangeArtifacts : public CPackForServer { ObjectInstanceID srcHero; ObjectInstanceID dstHero; @@ -2167,17 +2280,18 @@ struct BulkExchangeArtifacts : public CPackForServer { } - bool applyGh(CGameHandler * gh); + virtual void visitTyped(ICPackVisitor & visitor) override; + template void serialize(Handler & h, const int version) { - h & static_cast(*this); + h & static_cast(*this); h & srcHero; h & dstHero; h & swap; } }; -struct AssembleArtifacts : public CPackForServer +struct DLL_LINKAGE AssembleArtifacts : public CPackForServer { AssembleArtifacts() = default; AssembleArtifacts(const ObjectInstanceID & _heroID, const ArtifactPosition & _artifactSlot, bool _assemble, const ArtifactID & _assembleTo) @@ -2185,14 +2299,16 @@ struct AssembleArtifacts : public CPackForServer , artifactSlot(_artifactSlot) , assemble(_assemble) , assembleTo(_assembleTo) - {} + { + } ObjectInstanceID heroID; ArtifactPosition artifactSlot; bool assemble = false; // True to assemble artifact, false to disassemble. ArtifactID assembleTo; // Artifact to assemble into. - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & heroID; @@ -2202,18 +2318,20 @@ struct AssembleArtifacts : public CPackForServer } }; -struct BuyArtifact : public CPackForServer +struct DLL_LINKAGE BuyArtifact : public CPackForServer { BuyArtifact() = default; BuyArtifact(const ObjectInstanceID & HID, const ArtifactID & AID) : hid(HID) , aid(AID) - {} + { + } ObjectInstanceID hid; ArtifactID aid; - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & hid; @@ -2221,7 +2339,7 @@ struct BuyArtifact : public CPackForServer } }; -struct TradeOnMarketplace : public CPackForServer +struct DLL_LINKAGE TradeOnMarketplace : public CPackForServer { ObjectInstanceID marketId; ObjectInstanceID heroId; @@ -2230,8 +2348,9 @@ struct TradeOnMarketplace : public CPackForServer std::vector r1, r2; //mode 0: r1 - sold resource, r2 - bought res (exception: when sacrificing art r1 is art id [todo: make r2 preferred slot?] std::vector val; //units of sold resource - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & marketId; @@ -2243,19 +2362,21 @@ struct TradeOnMarketplace : public CPackForServer } }; -struct SetFormation : public CPackForServer +struct DLL_LINKAGE SetFormation : public CPackForServer { SetFormation() = default; ; SetFormation(const ObjectInstanceID & HID, ui8 Formation) : hid(HID) , formation(Formation) - {} + { + } ObjectInstanceID hid; ui8 formation = 0; - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & hid; @@ -2263,19 +2384,21 @@ struct SetFormation : public CPackForServer } }; -struct HireHero : public CPackForServer +struct DLL_LINKAGE HireHero : public CPackForServer { HireHero() = default; HireHero(si32 HID, const ObjectInstanceID & TID) : hid(HID) , tid(TID) - {} + { + } si32 hid = 0; //available hero serial ObjectInstanceID tid; //town (tavern) id PlayerColor player; - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & hid; @@ -2284,31 +2407,34 @@ struct HireHero : public CPackForServer } }; -struct BuildBoat : public CPackForServer +struct DLL_LINKAGE BuildBoat : public CPackForServer { ObjectInstanceID objid; //where player wants to buy a boat - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & objid; } }; -struct QueryReply : public CPackForServer +struct DLL_LINKAGE QueryReply : public CPackForServer { QueryReply() = default; QueryReply(const QueryID & QID, const JsonNode & Reply) : qid(QID) , reply(Reply) - {} + { + } QueryID qid; PlayerColor player; JsonNode reply; - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & qid; @@ -2317,58 +2443,64 @@ struct QueryReply : public CPackForServer } }; -struct MakeAction : public CPackForServer +struct DLL_LINKAGE MakeAction : public CPackForServer { MakeAction() = default; MakeAction(BattleAction BA) : ba(std::move(BA)) - {} + { + } BattleAction ba; - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & ba; } }; -struct MakeCustomAction : public CPackForServer +struct DLL_LINKAGE MakeCustomAction : public CPackForServer { MakeCustomAction() = default; MakeCustomAction(BattleAction BA) : ba(std::move(BA)) - {} + { + } BattleAction ba; - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & ba; } }; -struct DigWithHero : public CPackForServer +struct DLL_LINKAGE DigWithHero : public CPackForServer { ObjectInstanceID id; //digging hero id - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & id; } }; -struct CastAdvSpell : public CPackForServer +struct DLL_LINKAGE CastAdvSpell : public CPackForServer { ObjectInstanceID hid; //hero id SpellID sid; //spell id int3 pos; //selected tile (not always used) - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & hid; @@ -2379,17 +2511,20 @@ struct CastAdvSpell : public CPackForServer /***********************************************************************************************************/ -struct SaveGame : public CPackForServer +struct DLL_LINKAGE SaveGame : public CPackForServer { SaveGame() = default; SaveGame(std::string Fname) : fname(std::move(Fname)) - {} + { + } std::string fname; - void applyGs(CGameState *gs){} - bool applyGh(CGameHandler *gh); - template void serialize(Handler &h, const int version) + void applyGs(CGameState * gs) {}; + + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & fname; @@ -2397,35 +2532,39 @@ struct SaveGame : public CPackForServer }; // TODO: Eventually we should re-merge both SaveGame and PlayerMessage -struct SaveGameClient : public CPackForClient +struct DLL_LINKAGE SaveGameClient : public CPackForClient { SaveGameClient() = default; SaveGameClient(std::string Fname) : fname(std::move(Fname)) - {} + { + } std::string fname; + virtual void visitTyped(ICPackVisitor & visitor) override; - void applyCl(CClient *cl); - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & fname; } }; -struct PlayerMessage : public CPackForServer +struct DLL_LINKAGE PlayerMessage : public CPackForServer { PlayerMessage() = default; PlayerMessage(std::string Text, const ObjectInstanceID & obj) : text(std::move(Text)) , currObj(obj) - {} - void applyGs(CGameState *gs){} - bool applyGh(CGameHandler *gh); + { + } + + void applyGs(CGameState * gs) {}; + + virtual void visitTyped(ICPackVisitor & visitor) override; std::string text; ObjectInstanceID currObj; // optional parameter that specifies current object. For cheats :) - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & static_cast(*this); h & text; @@ -2433,34 +2572,35 @@ struct PlayerMessage : public CPackForServer } }; -struct PlayerMessageClient : public CPackForClient +struct DLL_LINKAGE PlayerMessageClient : public CPackForClient { PlayerMessageClient() = default; PlayerMessageClient(const PlayerColor & Player, std::string Text) : player(Player) , text(std::move(Text)) - {} - void applyCl(CClient *cl); + { + } + virtual void visitTyped(ICPackVisitor & visitor) override; PlayerColor player; std::string text; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & player; h & text; } }; -struct CenterView : public CPackForClient +struct DLL_LINKAGE CenterView : public CPackForClient { - void applyCl(CClient *cl); - PlayerColor player; int3 pos; ui32 focusTime = 0; //ms - template void serialize(Handler &h, const int version) + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) { h & pos; h & player; diff --git a/lib/NetPacksBase.h b/lib/NetPacksBase.h index 8159fb6c4..16b322c3e 100644 --- a/lib/NetPacksBase.h +++ b/lib/NetPacksBase.h @@ -17,6 +17,9 @@ class CClient; class CGameHandler; +class CLobbyScreen; +class CServerHandler; +class CVCMIServer; VCMI_LIB_NAMESPACE_BEGIN @@ -30,6 +33,8 @@ class CArtifactSet; class CBonusSystemNode; struct ArtSlotInfo; +class ICPackVisitor; + struct DLL_LINKAGE CPack { std::shared_ptr c; // Pointer to connection that pack received from @@ -45,27 +50,31 @@ struct DLL_LINKAGE CPack void applyGs(CGameState * gs) {} + + void visit(ICPackVisitor & cpackVisitor); + +protected: + /// + /// For basic types of netpacks hierarchy like CPackForClient. Called first. + /// + virtual void visitBasic(ICPackVisitor & cpackVisitor); + + /// + /// For leaf types of netpacks hierarchy. Called after visitBasic. + /// + virtual void visitTyped(ICPackVisitor & cpackVisitor); }; -struct CPackForClient : public CPack +struct DLL_LINKAGE CPackForClient : public CPack { - CGameState* GS(CClient *cl); - void applyFirstCl(CClient *cl)//called before applying to gs - {} - void applyCl(CClient *cl)//called after applying to gs - {} +protected: + virtual void visitBasic(ICPackVisitor & cpackVisitor) override; }; -struct CPackForServer : public CPack +struct DLL_LINKAGE CPackForServer : public CPack { mutable PlayerColor player = PlayerColor::NEUTRAL; mutable si32 requestID; - CGameState * GS(CGameHandler * gh); - bool applyGh(CGameHandler *gh) //called after applying to gs - { - logGlobal->error("Should not happen... applying plain CPackForServer"); - return false; - } template void serialize(Handler &h, const int version) { @@ -74,14 +83,15 @@ struct CPackForServer : public CPack } protected: - void throwNotAllowedAction(); - void throwOnWrongOwner(CGameHandler * gh, ObjectInstanceID id); - void throwOnWrongPlayer(CGameHandler * gh, PlayerColor player); - void throwAndComplain(CGameHandler * gh, std::string txt); - bool isPlayerOwns(CGameHandler * gh, ObjectInstanceID id); + virtual void visitBasic(ICPackVisitor & cpackVisitor) override; +}; -private: - void wrongPlayerMessage(CGameHandler * gh, PlayerColor expectedplayer); +struct DLL_LINKAGE CPackForLobby : public CPack +{ + virtual bool isForServer() const; + +protected: + virtual void visitBasic(ICPackVisitor & cpackVisitor) override; }; struct DLL_LINKAGE MetaString diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index c29013c4b..3a262982f 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "NetPacks.h" - +#include "NetPackVisitor.h" #include "CGeneralTextHandler.h" #include "mapObjects/CObjectClassesHandler.h" #include "CArtHandler.h" @@ -31,7 +31,736 @@ VCMI_LIB_NAMESPACE_BEGIN -DLL_LINKAGE void SetResources::applyGs(CGameState * gs) const +void CPack::visit(ICPackVisitor & visitor) +{ + visitBasic(visitor); + + // visitBasic may destroy this and in such cases we do not want to call visitTyped + if(visitor.callTyped()) + { + visitTyped(visitor); + } +} + +void CPack::visitBasic(ICPackVisitor & visitor) +{ +} + +void CPack::visitTyped(ICPackVisitor & visitor) +{ +} + +void CPackForClient::visitBasic(ICPackVisitor & visitor) +{ + visitor.visitForClient(*this); +} + +void CPackForServer::visitBasic(ICPackVisitor & visitor) +{ + visitor.visitForServer(*this); +} + +void CPackForLobby::visitBasic(ICPackVisitor & visitor) +{ + visitor.visitForLobby(*this); +} + +bool CPackForLobby::isForServer() const +{ + return false; +} + +bool CLobbyPackToServer::isForServer() const +{ + return true; +} + +void PackageApplied::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitPackageApplied(*this); +} + +void SystemMessage::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSystemMessage(*this); +} + +void PlayerBlocked::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitPlayerBlocked(*this); +} + +void PlayerCheated::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitPlayerCheated(*this); +} + +void YourTurn::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitYourTurn(*this); +} + +void EntitiesChanged::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitEntitiesChanged(*this); +} + +void SetResources::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetResources(*this); +} + +void SetPrimSkill::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetPrimSkill(*this); +} + +void SetSecSkill::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetSecSkill(*this); +} + +void HeroVisitCastle::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitHeroVisitCastle(*this); +} + +void ChangeSpells::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitChangeSpells(*this); +} + +void SetMana::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetMana(*this); +} + +void SetMovePoints::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetMovePoints(*this); +} + +void FoWChange::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitFoWChange(*this); +} + +void SetAvailableHeroes::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetAvailableHeroes(*this); +} + +void GiveBonus::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitGiveBonus(*this); +} + +void ChangeObjPos::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitChangeObjPos(*this); +} + +void PlayerEndsGame::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitPlayerEndsGame(*this); +} + +void PlayerReinitInterface::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitPlayerReinitInterface(*this); +} + +void RemoveBonus::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitRemoveBonus(*this); +} + +void SetCommanderProperty::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetCommanderProperty(*this); +} + +void AddQuest::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitAddQuest(*this); +} + +void UpdateArtHandlerLists::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitUpdateArtHandlerLists(*this); +} + +void UpdateMapEvents::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitUpdateMapEvents(*this); +} + +void UpdateCastleEvents::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitUpdateCastleEvents(*this); +} + +void ChangeFormation::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitChangeFormation(*this); +} + +void RemoveObject::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitRemoveObject(*this); +} + +void TryMoveHero::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitTryMoveHero(*this); +} + +void NewStructures::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitNewStructures(*this); +} + +void RazeStructures::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitRazeStructures(*this); +} + +void SetAvailableCreatures::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetAvailableCreatures(*this); +} + +void SetHeroesInTown::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetHeroesInTown(*this); +} + +void HeroRecruited::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitHeroRecruited(*this); +} + +void GiveHero::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitGiveHero(*this); +} + +void OpenWindow::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitOpenWindow(*this); +} + +void NewObject::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitNewObject(*this); +} + +void SetAvailableArtifacts::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetAvailableArtifacts(*this); +} + +void NewArtifact::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitNewArtifact(*this); +} + +void ChangeStackCount::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitChangeStackCount(*this); +} + +void SetStackType::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetStackType(*this); +} + +void EraseStack::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitEraseStack(*this); +} + +void SwapStacks::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSwapStacks(*this); +} + +void InsertNewStack::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitInsertNewStack(*this); +} + +void RebalanceStacks::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitRebalanceStacks(*this); +} + +void BulkRebalanceStacks::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBulkRebalanceStacks(*this); +} + +void BulkSmartRebalanceStacks::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBulkSmartRebalanceStacks(*this); +} + +void PutArtifact::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitPutArtifact(*this); +} + +void EraseArtifact::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitEraseArtifact(*this); +} + +void MoveArtifact::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitMoveArtifact(*this); +} + +void BulkMoveArtifacts::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBulkMoveArtifacts(*this); +} + +void AssembledArtifact::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitAssembledArtifact(*this); +} + +void DisassembledArtifact::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitDisassembledArtifact(*this); +} + +void HeroVisit::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitHeroVisit(*this); +} + +void NewTurn::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitNewTurn(*this); +} + +void InfoWindow::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitInfoWindow(*this); +} + +void SetObjectProperty::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetObjectProperty(*this); +} + +void ChangeObjectVisitors::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitChangeObjectVisitors(*this); +} + +void PrepareHeroLevelUp::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitPrepareHeroLevelUp(*this); +} + +void HeroLevelUp::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitHeroLevelUp(*this); +} + +void CommanderLevelUp::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitCommanderLevelUp(*this); +} + +void BlockingDialog::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBlockingDialog(*this); +} + +void GarrisonDialog::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitGarrisonDialog(*this); +} + +void ExchangeDialog::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitExchangeDialog(*this); +} + +void TeleportDialog::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitTeleportDialog(*this); +} + +void MapObjectSelectDialog::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitMapObjectSelectDialog(*this); +} + +void BattleStart::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleStart(*this); +} + +void BattleNextRound::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleNextRound(*this); +} + +void BattleSetActiveStack::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleSetActiveStack(*this); +} + +void BattleResult::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleResult(*this); +} + +void BattleLogMessage::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleLogMessage(*this); +} + +void BattleStackMoved::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleStackMoved(*this); +} + +void BattleUnitsChanged::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleUnitsChanged(*this); +} + +void BattleAttack::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleAttack(*this); +} + +void StartAction::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitStartAction(*this); +} + +void EndAction::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitEndAction(*this); +} + +void BattleSpellCast::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleSpellCast(*this); +} + +void SetStackEffect::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetStackEffect(*this); +} + +void StacksInjured::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitStacksInjured(*this); +} + +void BattleResultsApplied::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleResultsApplied(*this); +} + +void BattleObstaclesChanged::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleObstaclesChanged(*this); +} + +void BattleSetStackProperty::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleSetStackProperty(*this); +} + +void BattleTriggerEffect::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleTriggerEffect(*this); +} + +void BattleUpdateGateState::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBattleUpdateGateState(*this); +} + +void ShowInInfobox::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitShowInInfobox(*this); +} + +void AdvmapSpellCast::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitAdvmapSpellCast(*this); +} + +void ShowWorldViewEx::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitShowWorldViewEx(*this); +} + +void EndTurn::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitEndTurn(*this); +} + +void DismissHero::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitDismissHero(*this); +} + +void MoveHero::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitMoveHero(*this); +} + +void CastleTeleportHero::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitCastleTeleportHero(*this); +} + +void ArrangeStacks::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitArrangeStacks(*this); +} + +void BulkMoveArmy::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBulkMoveArmy(*this); +} + +void BulkSplitStack::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBulkSplitStack(*this); +} + +void BulkMergeStacks::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBulkMergeStacks(*this); +} + +void BulkSmartSplitStack::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBulkSmartSplitStack(*this); +} + +void DisbandCreature::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitDisbandCreature(*this); +} + +void BuildStructure::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBuildStructure(*this); +} + +void RazeStructure::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitRazeStructure(*this); +} + +void RecruitCreatures::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitRecruitCreatures(*this); +} + +void UpgradeCreature::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitUpgradeCreature(*this); +} + +void GarrisonHeroSwap::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitGarrisonHeroSwap(*this); +} + +void ExchangeArtifacts::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitExchangeArtifacts(*this); +} + +void BulkExchangeArtifacts::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBulkExchangeArtifacts(*this); +} + +void AssembleArtifacts::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitAssembleArtifacts(*this); +} + +void BuyArtifact::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBuyArtifact(*this); +} + +void TradeOnMarketplace::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitTradeOnMarketplace(*this); +} + +void SetFormation::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSetFormation(*this); +} + +void HireHero::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitHireHero(*this); +} + +void BuildBoat::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitBuildBoat(*this); +} + +void QueryReply::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitQueryReply(*this); +} + +void MakeAction::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitMakeAction(*this); +} + +void MakeCustomAction::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitMakeCustomAction(*this); +} + +void DigWithHero::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitDigWithHero(*this); +} + +void CastAdvSpell::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitCastAdvSpell(*this); +} + +void SaveGame::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSaveGame(*this); +} + +void SaveGameClient::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitSaveGameClient(*this); +} + +void PlayerMessage::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitPlayerMessage(*this); +} + +void PlayerMessageClient::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitPlayerMessageClient(*this); +} + +void CenterView::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitCenterView(*this); +} + +void LobbyClientConnected::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbyClientConnected(*this); +} + +void LobbyClientDisconnected::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbyClientDisconnected(*this); +} + +void LobbyChatMessage::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbyChatMessage(*this); +} + +void LobbyGuiAction::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbyGuiAction(*this); +} + +void LobbyEndGame::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbyEndGame(*this); +} + +void LobbyStartGame::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbyStartGame(*this); +} + +void LobbyChangeHost::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbyChangeHost(*this); +} + +void LobbyUpdateState::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbyUpdateState(*this); +} + +void LobbySetMap::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbySetMap(*this); +} + +void LobbySetCampaign::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbySetCampaign(*this); +} + +void LobbySetCampaignMap::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbySetCampaignMap(*this); +} + +void LobbySetCampaignBonus::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbySetCampaignBonus(*this); +} + +void LobbyChangePlayerOption::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbyChangePlayerOption(*this); +} + +void LobbySetPlayer::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbySetPlayer(*this); +} + +void LobbySetTurnTime::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbySetTurnTime(*this); +} + +void LobbySetDifficulty::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbySetDifficulty(*this); +} + +void LobbyForceSetPlayer::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbyForceSetPlayer(*this); +} + +void LobbyShowMessage::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitLobbyShowMessage(*this); +} + +void SetResources::applyGs(CGameState * gs) const { assert(player < PlayerColor::PLAYER_LIMIT); if(abs) @@ -45,20 +774,20 @@ DLL_LINKAGE void SetResources::applyGs(CGameState * gs) const gs->getPlayerState(player)->resources.positive(); } -DLL_LINKAGE void SetPrimSkill::applyGs(CGameState * gs) const +void SetPrimSkill::applyGs(CGameState * gs) const { CGHeroInstance * hero = gs->getHero(id); assert(hero); hero->setPrimarySkill(which, val, abs); } -DLL_LINKAGE void SetSecSkill::applyGs(CGameState * gs) const +void SetSecSkill::applyGs(CGameState * gs) const { CGHeroInstance *hero = gs->getHero(id); hero->setSecSkillLevel(which, val, abs); } -DLL_LINKAGE void SetCommanderProperty::applyGs(CGameState *gs) +void SetCommanderProperty::applyGs(CGameState *gs) { CCommanderInstance * commander = gs->getHero(heroid)->commander; assert (commander); @@ -87,7 +816,7 @@ DLL_LINKAGE void SetCommanderProperty::applyGs(CGameState *gs) } } -DLL_LINKAGE void AddQuest::applyGs(CGameState * gs) const +void AddQuest::applyGs(CGameState * gs) const { assert (vstd::contains(gs->players, player)); auto * vec = &gs->players[player].quests; @@ -97,7 +826,7 @@ DLL_LINKAGE void AddQuest::applyGs(CGameState * gs) const logNetwork->warn("Warning! Attempt to add duplicated quest"); } -DLL_LINKAGE void UpdateArtHandlerLists::applyGs(CGameState * gs) const +void UpdateArtHandlerLists::applyGs(CGameState * gs) const { VLC->arth->minors = minors; VLC->arth->majors = majors; @@ -105,23 +834,23 @@ DLL_LINKAGE void UpdateArtHandlerLists::applyGs(CGameState * gs) const VLC->arth->relics = relics; } -DLL_LINKAGE void UpdateMapEvents::applyGs(CGameState * gs) const +void UpdateMapEvents::applyGs(CGameState * gs) const { gs->map->events = events; } -DLL_LINKAGE void UpdateCastleEvents::applyGs(CGameState * gs) const +void UpdateCastleEvents::applyGs(CGameState * gs) const { auto * t = gs->getTown(town); t->events = events; } -DLL_LINKAGE void ChangeFormation::applyGs(CGameState * gs) const +void ChangeFormation::applyGs(CGameState * gs) const { gs->getHero(hid)->setFormation(formation); } -DLL_LINKAGE void HeroVisitCastle::applyGs(CGameState * gs) const +void HeroVisitCastle::applyGs(CGameState * gs) const { CGHeroInstance *h = gs->getHero(hid); CGTownInstance *t = gs->getTown(tid); @@ -135,7 +864,7 @@ DLL_LINKAGE void HeroVisitCastle::applyGs(CGameState * gs) const t->setVisitingHero(nullptr); } -DLL_LINKAGE void ChangeSpells::applyGs(CGameState *gs) +void ChangeSpells::applyGs(CGameState *gs) { CGHeroInstance *hero = gs->getHero(hid); @@ -147,7 +876,7 @@ DLL_LINKAGE void ChangeSpells::applyGs(CGameState *gs) hero->removeSpellFromSpellbook(sid); } -DLL_LINKAGE void SetMana::applyGs(CGameState * gs) const +void SetMana::applyGs(CGameState * gs) const { CGHeroInstance * hero = gs->getHero(hid); @@ -161,7 +890,7 @@ DLL_LINKAGE void SetMana::applyGs(CGameState * gs) const vstd::amax(hero->mana, 0); //not less than 0 } -DLL_LINKAGE void SetMovePoints::applyGs(CGameState * gs) const +void SetMovePoints::applyGs(CGameState * gs) const { CGHeroInstance *hero = gs->getHero(hid); @@ -175,7 +904,7 @@ DLL_LINKAGE void SetMovePoints::applyGs(CGameState * gs) const vstd::amax(hero->movement, 0); //not less than 0 } -DLL_LINKAGE void FoWChange::applyGs(CGameState *gs) +void FoWChange::applyGs(CGameState *gs) { TeamState * team = gs->getPlayerTeam(player); auto fogOfWarMap = team->fogOfWarMap; @@ -206,7 +935,7 @@ DLL_LINKAGE void FoWChange::applyGs(CGameState *gs) } } -DLL_LINKAGE void SetAvailableHeroes::applyGs(CGameState *gs) +void SetAvailableHeroes::applyGs(CGameState *gs) { PlayerState *p = gs->getPlayerState(player); p->availableHeroes.clear(); @@ -220,7 +949,7 @@ DLL_LINKAGE void SetAvailableHeroes::applyGs(CGameState *gs) } } -DLL_LINKAGE void GiveBonus::applyGs(CGameState *gs) +void GiveBonus::applyGs(CGameState *gs) { CBonusSystemNode *cbsn = nullptr; switch(who) @@ -271,7 +1000,7 @@ DLL_LINKAGE void GiveBonus::applyGs(CGameState *gs) boost::replace_first(descr, "%s", std::to_string(std::abs(bonus.val))); } -DLL_LINKAGE void ChangeObjPos::applyGs(CGameState *gs) +void ChangeObjPos::applyGs(CGameState *gs) { CGObjectInstance *obj = gs->getObjInstance(objid); if(!obj) @@ -284,7 +1013,7 @@ DLL_LINKAGE void ChangeObjPos::applyGs(CGameState *gs) gs->map->addBlockVisTiles(obj); } -DLL_LINKAGE void ChangeObjectVisitors::applyGs(CGameState * gs) const +void ChangeObjectVisitors::applyGs(CGameState * gs) const { switch (mode) { case VISITOR_ADD: @@ -321,7 +1050,7 @@ DLL_LINKAGE void ChangeObjectVisitors::applyGs(CGameState * gs) const } } -DLL_LINKAGE void PlayerEndsGame::applyGs(CGameState * gs) const +void PlayerEndsGame::applyGs(CGameState * gs) const { PlayerState *p = gs->getPlayerState(player); if(victoryLossCheckResult.victory()) @@ -363,7 +1092,7 @@ DLL_LINKAGE void PlayerEndsGame::applyGs(CGameState * gs) const } } -DLL_LINKAGE void PlayerReinitInterface::applyGs(CGameState *gs) +void PlayerReinitInterface::applyGs(CGameState *gs) { if(!gs || !gs->scenarioOps) return; @@ -376,7 +1105,7 @@ DLL_LINKAGE void PlayerReinitInterface::applyGs(CGameState *gs) } } -DLL_LINKAGE void RemoveBonus::applyGs(CGameState *gs) +void RemoveBonus::applyGs(CGameState *gs) { CBonusSystemNode * node = nullptr; if (who == HERO) @@ -397,7 +1126,7 @@ DLL_LINKAGE void RemoveBonus::applyGs(CGameState *gs) } } -DLL_LINKAGE void RemoveObject::applyGs(CGameState *gs) +void RemoveObject::applyGs(CGameState *gs) { CGObjectInstance *obj = gs->getObjInstance(id); @@ -581,7 +1310,7 @@ void TryMoveHero::applyGs(CGameState *gs) (*fogOfWarMap)[t.z][t.x][t.y] = 1; } -DLL_LINKAGE void NewStructures::applyGs(CGameState *gs) +void NewStructures::applyGs(CGameState *gs) { CGTownInstance *t = gs->getTown(tid); @@ -605,7 +1334,7 @@ DLL_LINKAGE void NewStructures::applyGs(CGameState *gs) t->recreateBuildingsBonuses(); } -DLL_LINKAGE void RazeStructures::applyGs(CGameState *gs) +void RazeStructures::applyGs(CGameState *gs) { CGTownInstance *t = gs->getTown(tid); for(const auto & id : bid) @@ -618,14 +1347,14 @@ DLL_LINKAGE void RazeStructures::applyGs(CGameState *gs) t->recreateBuildingsBonuses(); } -DLL_LINKAGE void SetAvailableCreatures::applyGs(CGameState * gs) const +void SetAvailableCreatures::applyGs(CGameState * gs) const { auto * dw = dynamic_cast(gs->getObjInstance(tid)); assert(dw); dw->creatures = creatures; } -DLL_LINKAGE void SetHeroesInTown::applyGs(CGameState * gs) const +void SetHeroesInTown::applyGs(CGameState * gs) const { CGTownInstance *t = gs->getTown(tid); @@ -654,7 +1383,7 @@ DLL_LINKAGE void SetHeroesInTown::applyGs(CGameState * gs) const } } -DLL_LINKAGE void HeroRecruited::applyGs(CGameState * gs) const +void HeroRecruited::applyGs(CGameState * gs) const { assert(vstd::contains(gs->hpool.heroesPool, hid)); CGHeroInstance *h = gs->hpool.heroesPool[hid]; @@ -695,7 +1424,7 @@ DLL_LINKAGE void HeroRecruited::applyGs(CGameState * gs) const } } -DLL_LINKAGE void GiveHero::applyGs(CGameState * gs) const +void GiveHero::applyGs(CGameState * gs) const { CGHeroInstance *h = gs->getHero(id); @@ -717,7 +1446,7 @@ DLL_LINKAGE void GiveHero::applyGs(CGameState * gs) const h->inTownGarrison = false; } -DLL_LINKAGE void NewObject::applyGs(CGameState *gs) +void NewObject::applyGs(CGameState *gs) { TerrainId terrainType = ETerrainId::NONE; @@ -776,7 +1505,7 @@ DLL_LINKAGE void NewObject::applyGs(CGameState *gs) logGlobal->debug("Added object id=%d; address=%x; name=%s", id, (intptr_t)o, o->getObjectName()); } -DLL_LINKAGE void NewArtifact::applyGs(CGameState *gs) +void NewArtifact::applyGs(CGameState *gs) { assert(!vstd::contains(gs->map->artInstances, art)); gs->map->addNewArtifactInstance(art); @@ -787,7 +1516,7 @@ DLL_LINKAGE void NewArtifact::applyGs(CGameState *gs) cart->createConstituents(); } -DLL_LINKAGE const CStackInstance * StackLocation::getStack() +const CStackInstance * StackLocation::getStack() { if(!army->hasStackAtSlot(slot)) { @@ -819,35 +1548,35 @@ struct GetBase : boost::static_visitor }; -DLL_LINKAGE void ArtifactLocation::removeArtifact() +void ArtifactLocation::removeArtifact() { CArtifactInstance *a = getArt(); assert(a); a->removeFrom(*this); } -DLL_LINKAGE const CArmedInstance * ArtifactLocation::relatedObj() const +const CArmedInstance * ArtifactLocation::relatedObj() const { return boost::apply_visitor(ObjectRetriever(), artHolder); } -DLL_LINKAGE PlayerColor ArtifactLocation::owningPlayer() const +PlayerColor ArtifactLocation::owningPlayer() const { const auto * obj = relatedObj(); return obj ? obj->tempOwner : PlayerColor::NEUTRAL; } -DLL_LINKAGE CArtifactSet *ArtifactLocation::getHolderArtSet() +CArtifactSet *ArtifactLocation::getHolderArtSet() { return boost::apply_visitor(GetBase(), artHolder); } -DLL_LINKAGE CBonusSystemNode *ArtifactLocation::getHolderNode() +CBonusSystemNode *ArtifactLocation::getHolderNode() { return boost::apply_visitor(GetBase(), artHolder); } -DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const +const CArtifactInstance *ArtifactLocation::getArt() const { const auto * s = getSlot(); if(s) @@ -856,30 +1585,30 @@ DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const return nullptr; } -DLL_LINKAGE const CArtifactSet * ArtifactLocation::getHolderArtSet() const +const CArtifactSet * ArtifactLocation::getHolderArtSet() const { auto * t = const_cast(this); return t->getHolderArtSet(); } -DLL_LINKAGE const CBonusSystemNode * ArtifactLocation::getHolderNode() const +const CBonusSystemNode * ArtifactLocation::getHolderNode() const { auto * t = const_cast(this); return t->getHolderNode(); } -DLL_LINKAGE CArtifactInstance *ArtifactLocation::getArt() +CArtifactInstance *ArtifactLocation::getArt() { const ArtifactLocation *t = this; return const_cast(t->getArt()); } -DLL_LINKAGE const ArtSlotInfo *ArtifactLocation::getSlot() const +const ArtSlotInfo *ArtifactLocation::getSlot() const { return getHolderArtSet()->getSlot(slot); } -DLL_LINKAGE void ChangeStackCount::applyGs(CGameState * gs) +void ChangeStackCount::applyGs(CGameState * gs) { auto * srcObj = gs->getArmyInstance(army); if(!srcObj) @@ -891,7 +1620,7 @@ DLL_LINKAGE void ChangeStackCount::applyGs(CGameState * gs) srcObj->changeStackCount(slot, count); } -DLL_LINKAGE void SetStackType::applyGs(CGameState * gs) +void SetStackType::applyGs(CGameState * gs) { auto * srcObj = gs->getArmyInstance(army); if(!srcObj) @@ -900,7 +1629,7 @@ DLL_LINKAGE void SetStackType::applyGs(CGameState * gs) srcObj->setStackType(slot, type); } -DLL_LINKAGE void EraseStack::applyGs(CGameState * gs) +void EraseStack::applyGs(CGameState * gs) { auto * srcObj = gs->getArmyInstance(army); if(!srcObj) @@ -909,7 +1638,7 @@ DLL_LINKAGE void EraseStack::applyGs(CGameState * gs) srcObj->eraseStack(slot); } -DLL_LINKAGE void SwapStacks::applyGs(CGameState * gs) +void SwapStacks::applyGs(CGameState * gs) { auto * srcObj = gs->getArmyInstance(srcArmy); if(!srcObj) @@ -926,7 +1655,7 @@ DLL_LINKAGE void SwapStacks::applyGs(CGameState * gs) dstObj->putStack(dstSlot, s1); } -DLL_LINKAGE void InsertNewStack::applyGs(CGameState *gs) +void InsertNewStack::applyGs(CGameState *gs) { if(auto * obj = gs->getArmyInstance(army)) obj->putStack(slot, new CStackInstance(type, count)); @@ -934,7 +1663,7 @@ DLL_LINKAGE void InsertNewStack::applyGs(CGameState *gs) logNetwork->error("[CRITICAL] InsertNewStack: invalid army object %d, possible game state corruption.", army.getNum()); } -DLL_LINKAGE void RebalanceStacks::applyGs(CGameState * gs) +void RebalanceStacks::applyGs(CGameState * gs) { auto * srcObj = gs->getArmyInstance(srcArmy); if(!srcObj) @@ -1033,13 +1762,13 @@ DLL_LINKAGE void RebalanceStacks::applyGs(CGameState * gs) CBonusSystemNode::treeHasChanged(); } -DLL_LINKAGE void BulkRebalanceStacks::applyGs(CGameState * gs) +void BulkRebalanceStacks::applyGs(CGameState * gs) { for(auto & move : moves) move.applyGs(gs); } -DLL_LINKAGE void BulkSmartRebalanceStacks::applyGs(CGameState * gs) +void BulkSmartRebalanceStacks::applyGs(CGameState * gs) { for(auto & move : moves) move.applyGs(gs); @@ -1048,14 +1777,14 @@ DLL_LINKAGE void BulkSmartRebalanceStacks::applyGs(CGameState * gs) change.applyGs(gs); } -DLL_LINKAGE void PutArtifact::applyGs(CGameState *gs) +void PutArtifact::applyGs(CGameState *gs) { assert(art->canBePutAt(al)); art->putAt(al); //al.hero->putArtifact(al.slot, art); } -DLL_LINKAGE void EraseArtifact::applyGs(CGameState *gs) +void EraseArtifact::applyGs(CGameState *gs) { const auto * slot = al.getSlot(); if(slot->locked) @@ -1066,7 +1795,7 @@ DLL_LINKAGE void EraseArtifact::applyGs(CGameState *gs) auto * aset = al.getHolderArtSet(); #ifndef NDEBUG bool found = false; - #endif + #endif for(auto& p : aset->artifactsWorn) { auto art = p.second.artifact; @@ -1075,7 +1804,7 @@ DLL_LINKAGE void EraseArtifact::applyGs(CGameState *gs) dis.al.slot = aset->getArtPos(art); #ifndef NDEBUG found = true; - #endif + #endif break; } } @@ -1090,7 +1819,7 @@ DLL_LINKAGE void EraseArtifact::applyGs(CGameState *gs) al.removeArtifact(); } -DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs) +void MoveArtifact::applyGs(CGameState * gs) { CArtifactInstance * art = src.getArt(); if(!ArtifactUtils::isSlotBackpack(dst.slot)) @@ -1099,7 +1828,7 @@ DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs) art->move(src, dst); } -DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) +void BulkMoveArtifacts::applyGs(CGameState * gs) { enum class EBulkArtsOp { @@ -1169,7 +1898,7 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) } } -DLL_LINKAGE void AssembledArtifact::applyGs(CGameState *gs) +void AssembledArtifact::applyGs(CGameState *gs) { CArtifactSet * artSet = al.getHolderArtSet(); const CArtifactInstance *transformedArt = al.getArt(); @@ -1210,7 +1939,7 @@ DLL_LINKAGE void AssembledArtifact::applyGs(CGameState *gs) combinedArt->putAt(al); } -DLL_LINKAGE void DisassembledArtifact::applyGs(CGameState *gs) +void DisassembledArtifact::applyGs(CGameState *gs) { auto * disassembled = dynamic_cast(al.getArt()); assert(disassembled); @@ -1228,11 +1957,11 @@ DLL_LINKAGE void DisassembledArtifact::applyGs(CGameState *gs) gs->map->eraseArtifactInstance(disassembled); } -DLL_LINKAGE void HeroVisit::applyGs(CGameState *gs) +void HeroVisit::applyGs(CGameState *gs) { } -DLL_LINKAGE void SetAvailableArtifacts::applyGs(CGameState * gs) const +void SetAvailableArtifacts::applyGs(CGameState * gs) const { if(id >= 0) { @@ -1251,7 +1980,7 @@ DLL_LINKAGE void SetAvailableArtifacts::applyGs(CGameState * gs) const } } -DLL_LINKAGE void NewTurn::applyGs(CGameState *gs) +void NewTurn::applyGs(CGameState *gs) { gs->day = day; @@ -1321,7 +2050,7 @@ DLL_LINKAGE void NewTurn::applyGs(CGameState *gs) } } -DLL_LINKAGE void SetObjectProperty::applyGs(CGameState * gs) const +void SetObjectProperty::applyGs(CGameState * gs) const { CGObjectInstance *obj = gs->getObjInstance(id); if(!obj) @@ -1361,7 +2090,7 @@ DLL_LINKAGE void SetObjectProperty::applyGs(CGameState * gs) const } } -DLL_LINKAGE void PrepareHeroLevelUp::applyGs(CGameState * gs) +void PrepareHeroLevelUp::applyGs(CGameState * gs) { auto * hero = gs->getHero(heroId); assert(hero); @@ -1378,14 +2107,14 @@ DLL_LINKAGE void PrepareHeroLevelUp::applyGs(CGameState * gs) } } -DLL_LINKAGE void HeroLevelUp::applyGs(CGameState * gs) const +void HeroLevelUp::applyGs(CGameState * gs) const { auto * hero = gs->getHero(heroId); assert(hero); hero->levelUp(skills); } -DLL_LINKAGE void CommanderLevelUp::applyGs(CGameState * gs) const +void CommanderLevelUp::applyGs(CGameState * gs) const { auto * hero = gs->getHero(heroId); assert(hero); @@ -1394,23 +2123,23 @@ DLL_LINKAGE void CommanderLevelUp::applyGs(CGameState * gs) const commander->levelUp(); } -DLL_LINKAGE void BattleStart::applyGs(CGameState * gs) const +void BattleStart::applyGs(CGameState * gs) const { gs->curB = info; gs->curB->localInit(); } -DLL_LINKAGE void BattleNextRound::applyGs(CGameState * gs) const +void BattleNextRound::applyGs(CGameState * gs) const { gs->curB->nextRound(round); } -DLL_LINKAGE void BattleSetActiveStack::applyGs(CGameState * gs) const +void BattleSetActiveStack::applyGs(CGameState * gs) const { gs->curB->nextTurn(stack); } -DLL_LINKAGE void BattleTriggerEffect::applyGs(CGameState * gs) const +void BattleTriggerEffect::applyGs(CGameState * gs) const { CStack * st = gs->curB->getStack(stackID); assert(st); @@ -1448,7 +2177,7 @@ DLL_LINKAGE void BattleTriggerEffect::applyGs(CGameState * gs) const } } -DLL_LINKAGE void BattleUpdateGateState::applyGs(CGameState * gs) const +void BattleUpdateGateState::applyGs(CGameState * gs) const { if(gs->curB) gs->curB->si.gateState = state; @@ -1490,37 +2219,37 @@ void BattleResult::applyGs(CGameState *gs) gs->curB.dellNull(); } -DLL_LINKAGE void BattleLogMessage::applyGs(CGameState *gs) +void BattleLogMessage::applyGs(CGameState *gs) { //nothing } -DLL_LINKAGE void BattleLogMessage::applyBattle(IBattleState * battleState) +void BattleLogMessage::applyBattle(IBattleState * battleState) { //nothing } -DLL_LINKAGE void BattleStackMoved::applyGs(CGameState *gs) +void BattleStackMoved::applyGs(CGameState *gs) { applyBattle(gs->curB); } -DLL_LINKAGE void BattleStackMoved::applyBattle(IBattleState * battleState) +void BattleStackMoved::applyBattle(IBattleState * battleState) { battleState->moveUnit(stack, tilesToMove.back()); } -DLL_LINKAGE void BattleStackAttacked::applyGs(CGameState * gs) +void BattleStackAttacked::applyGs(CGameState * gs) { applyBattle(gs->curB); } -DLL_LINKAGE void BattleStackAttacked::applyBattle(IBattleState * battleState) +void BattleStackAttacked::applyBattle(IBattleState * battleState) { battleState->setUnitState(newState.id, newState.data, newState.healthDelta); } -DLL_LINKAGE void BattleAttack::applyGs(CGameState * gs) +void BattleAttack::applyGs(CGameState * gs) { CStack * attacker = gs->curB->getStack(stackAttacking); assert(attacker); @@ -1533,7 +2262,7 @@ DLL_LINKAGE void BattleAttack::applyGs(CGameState * gs) attacker->removeBonusesRecursive(Bonus::UntilAttack); } -DLL_LINKAGE void StartAction::applyGs(CGameState *gs) +void StartAction::applyGs(CGameState *gs) { CStack *st = gs->curB->getStack(ba.stackNumber); @@ -1581,7 +2310,7 @@ DLL_LINKAGE void StartAction::applyGs(CGameState *gs) } } -DLL_LINKAGE void BattleSpellCast::applyGs(CGameState * gs) const +void BattleSpellCast::applyGs(CGameState * gs) const { assert(gs->curB); @@ -1594,12 +2323,12 @@ DLL_LINKAGE void BattleSpellCast::applyGs(CGameState * gs) const } } -DLL_LINKAGE void SetStackEffect::applyGs(CGameState *gs) +void SetStackEffect::applyGs(CGameState *gs) { applyBattle(gs->curB); } -DLL_LINKAGE void SetStackEffect::applyBattle(IBattleState * battleState) +void SetStackEffect::applyBattle(IBattleState * battleState) { for(const auto & stackData : toRemove) battleState->removeUnitBonus(stackData.first, stackData.second); @@ -1612,23 +2341,23 @@ DLL_LINKAGE void SetStackEffect::applyBattle(IBattleState * battleState) } -DLL_LINKAGE void StacksInjured::applyGs(CGameState *gs) +void StacksInjured::applyGs(CGameState *gs) { applyBattle(gs->curB); } -DLL_LINKAGE void StacksInjured::applyBattle(IBattleState * battleState) +void StacksInjured::applyBattle(IBattleState * battleState) { for(BattleStackAttacked stackAttacked : stacks) stackAttacked.applyBattle(battleState); } -DLL_LINKAGE void BattleUnitsChanged::applyGs(CGameState *gs) +void BattleUnitsChanged::applyGs(CGameState *gs) { applyBattle(gs->curB); } -DLL_LINKAGE void BattleUnitsChanged::applyBattle(IBattleState * battleState) +void BattleUnitsChanged::applyBattle(IBattleState * battleState) { for(auto & elem : changedStacks) { @@ -1653,13 +2382,13 @@ DLL_LINKAGE void BattleUnitsChanged::applyBattle(IBattleState * battleState) } } -DLL_LINKAGE void BattleObstaclesChanged::applyGs(CGameState * gs) +void BattleObstaclesChanged::applyGs(CGameState * gs) { if(gs->curB) applyBattle(gs->curB); } -DLL_LINKAGE void BattleObstaclesChanged::applyBattle(IBattleState * battleState) +void BattleObstaclesChanged::applyBattle(IBattleState * battleState) { for(const auto & change : changes) { @@ -1682,17 +2411,22 @@ DLL_LINKAGE void BattleObstaclesChanged::applyBattle(IBattleState * battleState) } } -DLL_LINKAGE CatapultAttack::CatapultAttack() = default; +CatapultAttack::CatapultAttack() = default; -DLL_LINKAGE CatapultAttack::~CatapultAttack() = default; +CatapultAttack::~CatapultAttack() = default; -DLL_LINKAGE void CatapultAttack::applyGs(CGameState * gs) +void CatapultAttack::applyGs(CGameState * gs) { if(gs->curB) applyBattle(gs->curB); } -DLL_LINKAGE void CatapultAttack::applyBattle(IBattleState * battleState) +void CatapultAttack::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitCatapultAttack(*this); +} + +void CatapultAttack::applyBattle(IBattleState * battleState) { const auto * town = battleState->getDefendedTown(); if(!town) @@ -1708,7 +2442,7 @@ DLL_LINKAGE void CatapultAttack::applyBattle(IBattleState * battleState) } } -DLL_LINKAGE void BattleSetStackProperty::applyGs(CGameState * gs) const +void BattleSetStackProperty::applyGs(CGameState * gs) const { CStack * stack = gs->curB->getStack(stackID); switch(which) @@ -1749,7 +2483,7 @@ DLL_LINKAGE void BattleSetStackProperty::applyGs(CGameState * gs) const } } -DLL_LINKAGE void PlayerCheated::applyGs(CGameState * gs) const +void PlayerCheated::applyGs(CGameState * gs) const { if(!player.isValidPlayer()) return; @@ -1758,7 +2492,7 @@ DLL_LINKAGE void PlayerCheated::applyGs(CGameState * gs) const gs->getPlayerState(player)->enteredWinningCheatCode = winningCheatCode; } -DLL_LINKAGE void YourTurn::applyGs(CGameState * gs) const +void YourTurn::applyGs(CGameState * gs) const { gs->currentPlayer = player; @@ -1766,14 +2500,14 @@ DLL_LINKAGE void YourTurn::applyGs(CGameState * gs) const playerState.daysWithoutCastle = daysWithoutCastle; } -DLL_LINKAGE Component::Component(const CStackBasicDescriptor & stack) +Component::Component(const CStackBasicDescriptor & stack) : id(CREATURE) , subtype(stack.type->idNumber) , val(stack.count) { } -DLL_LINKAGE void EntitiesChanged::applyGs(CGameState * gs) +void EntitiesChanged::applyGs(CGameState * gs) { for(const auto & change : changes) gs->updateEntity(change.metatype, change.entityIndex, change.data); diff --git a/lib/NetPacksLobby.h b/lib/NetPacksLobby.h index b41dfe97a..143984769 100644 --- a/lib/NetPacksLobby.h +++ b/lib/NetPacksLobby.h @@ -13,7 +13,6 @@ #include "StartInfo.h" -class CLobbyScreen; class CServerHandler; class CVCMIServer; @@ -25,40 +24,16 @@ struct StartInfo; class CMapGenOptions; struct ClientPlayer; -struct CPackForLobby : public CPack +struct DLL_LINKAGE CLobbyPackToPropagate : public CPackForLobby { - bool checkClientPermissions(CVCMIServer * srv) const - { - return false; - } - - bool applyOnServer(CVCMIServer * srv) - { - return true; - } - - void applyOnServerAfterAnnounce(CVCMIServer * srv) {} - - bool applyOnLobbyHandler(CServerHandler * handler) - { - return true; - } - - void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) {} }; -struct CLobbyPackToPropagate : public CPackForLobby +struct DLL_LINKAGE CLobbyPackToServer : public CPackForLobby { - + virtual bool isForServer() const override; }; -struct CLobbyPackToServer : public CPackForLobby -{ - bool checkClientPermissions(CVCMIServer * srv) const; - void applyOnServerAfterAnnounce(CVCMIServer * srv); -}; - -struct LobbyClientConnected : public CLobbyPackToPropagate +struct DLL_LINKAGE LobbyClientConnected : public CLobbyPackToPropagate { // Set by client before sending pack to server std::string uuid; @@ -68,11 +43,7 @@ struct LobbyClientConnected : public CLobbyPackToPropagate int clientId = -1; int hostClientId = -1; - bool checkClientPermissions(CVCMIServer * srv) const; - bool applyOnLobbyHandler(CServerHandler * handler); - void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler); - bool applyOnServer(CVCMIServer * srv); - void applyOnServerAfterAnnounce(CVCMIServer * srv); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -85,16 +56,13 @@ struct LobbyClientConnected : public CLobbyPackToPropagate } }; -struct LobbyClientDisconnected : public CLobbyPackToPropagate +struct DLL_LINKAGE LobbyClientDisconnected : public CLobbyPackToPropagate { int clientId; bool shutdownServer = false; - bool checkClientPermissions(CVCMIServer * srv) const; - bool applyOnServer(CVCMIServer * srv); - void applyOnServerAfterAnnounce(CVCMIServer * srv); - bool applyOnLobbyHandler(CServerHandler * handler); - void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler); + + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -103,12 +71,11 @@ struct LobbyClientDisconnected : public CLobbyPackToPropagate } }; -struct LobbyChatMessage : public CLobbyPackToPropagate +struct DLL_LINKAGE LobbyChatMessage : public CLobbyPackToPropagate { std::string playerName, message; - bool checkClientPermissions(CVCMIServer * srv) const; - void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -117,14 +84,14 @@ struct LobbyChatMessage : public CLobbyPackToPropagate } }; -struct LobbyGuiAction : public CLobbyPackToPropagate +struct DLL_LINKAGE LobbyGuiAction : public CLobbyPackToPropagate { enum EAction : ui8 { NONE, NO_TAB, OPEN_OPTIONS, OPEN_SCENARIO_LIST, OPEN_RANDOM_MAP_OPTIONS } action = NONE; - bool checkClientPermissions(CVCMIServer * srv) const; - void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler); + + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -132,14 +99,11 @@ struct LobbyGuiAction : public CLobbyPackToPropagate } }; -struct LobbyEndGame : public CLobbyPackToPropagate +struct DLL_LINKAGE LobbyEndGame : public CLobbyPackToPropagate { bool closeConnection = false, restart = false; - bool checkClientPermissions(CVCMIServer * srv) const; - bool applyOnServer(CVCMIServer * srv); - void applyOnServerAfterAnnounce(CVCMIServer * srv); - bool applyOnLobbyHandler(CServerHandler * handler); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -148,18 +112,14 @@ struct LobbyEndGame : public CLobbyPackToPropagate } }; -struct LobbyStartGame : public CLobbyPackToPropagate +struct DLL_LINKAGE LobbyStartGame : public CLobbyPackToPropagate { // Set by server std::shared_ptr initializedStartInfo = nullptr; CGameState * initializedGameState = nullptr; int clientId = -1; //-1 means to all clients - bool checkClientPermissions(CVCMIServer * srv) const; - bool applyOnServer(CVCMIServer * srv); - void applyOnServerAfterAnnounce(CVCMIServer * srv); - bool applyOnLobbyHandler(CServerHandler * handler); - void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -172,13 +132,11 @@ struct LobbyStartGame : public CLobbyPackToPropagate } }; -struct LobbyChangeHost : public CLobbyPackToPropagate +struct DLL_LINKAGE LobbyChangeHost : public CLobbyPackToPropagate { int newHostConnectionId = -1; - bool checkClientPermissions(CVCMIServer * srv) const; - bool applyOnServer(CVCMIServer * srv); - bool applyOnServerAfterAnnounce(CVCMIServer * srv); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -186,13 +144,12 @@ struct LobbyChangeHost : public CLobbyPackToPropagate } }; -struct LobbyUpdateState : public CLobbyPackToPropagate +struct DLL_LINKAGE LobbyUpdateState : public CLobbyPackToPropagate { LobbyState state; bool hostChanged = false; // Used on client-side only - bool applyOnLobbyHandler(CServerHandler * handler); - void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -200,13 +157,14 @@ struct LobbyUpdateState : public CLobbyPackToPropagate } }; -struct LobbySetMap : public CLobbyPackToServer +struct DLL_LINKAGE LobbySetMap : public CLobbyPackToServer { std::shared_ptr mapInfo; std::shared_ptr mapGenOpts; LobbySetMap() : mapInfo(nullptr), mapGenOpts(nullptr) {} - bool applyOnServer(CVCMIServer * srv); + + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -215,11 +173,11 @@ struct LobbySetMap : public CLobbyPackToServer } }; -struct LobbySetCampaign : public CLobbyPackToServer +struct DLL_LINKAGE LobbySetCampaign : public CLobbyPackToServer { std::shared_ptr ourCampaign; - bool applyOnServer(CVCMIServer * srv); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -227,11 +185,11 @@ struct LobbySetCampaign : public CLobbyPackToServer } }; -struct LobbySetCampaignMap : public CLobbyPackToServer +struct DLL_LINKAGE LobbySetCampaignMap : public CLobbyPackToServer { int mapId = -1; - bool applyOnServer(CVCMIServer * srv); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -239,11 +197,11 @@ struct LobbySetCampaignMap : public CLobbyPackToServer } }; -struct LobbySetCampaignBonus : public CLobbyPackToServer +struct DLL_LINKAGE LobbySetCampaignBonus : public CLobbyPackToServer { int bonusId = -1; - bool applyOnServer(CVCMIServer * srv); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -251,15 +209,14 @@ struct LobbySetCampaignBonus : public CLobbyPackToServer } }; -struct LobbyChangePlayerOption : public CLobbyPackToServer +struct DLL_LINKAGE LobbyChangePlayerOption : public CLobbyPackToServer { enum EWhat : ui8 {UNKNOWN, TOWN, HERO, BONUS}; ui8 what = UNKNOWN; si8 direction = 0; //-1 or +1 PlayerColor color = PlayerColor::CANNOT_DETERMINE; - bool checkClientPermissions(CVCMIServer * srv) const; - bool applyOnServer(CVCMIServer * srv); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -269,11 +226,11 @@ struct LobbyChangePlayerOption : public CLobbyPackToServer } }; -struct LobbySetPlayer : public CLobbyPackToServer +struct DLL_LINKAGE LobbySetPlayer : public CLobbyPackToServer { PlayerColor clickedColor = PlayerColor::CANNOT_DETERMINE; - bool applyOnServer(CVCMIServer * srv); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -281,11 +238,11 @@ struct LobbySetPlayer : public CLobbyPackToServer } }; -struct LobbySetTurnTime : public CLobbyPackToServer +struct DLL_LINKAGE LobbySetTurnTime : public CLobbyPackToServer { ui8 turnTime = 0; - bool applyOnServer(CVCMIServer * srv); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -293,11 +250,11 @@ struct LobbySetTurnTime : public CLobbyPackToServer } }; -struct LobbySetDifficulty : public CLobbyPackToServer +struct DLL_LINKAGE LobbySetDifficulty : public CLobbyPackToServer { ui8 difficulty = 0; - bool applyOnServer(CVCMIServer * srv); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { @@ -305,12 +262,12 @@ struct LobbySetDifficulty : public CLobbyPackToServer } }; -struct LobbyForceSetPlayer : public CLobbyPackToServer +struct DLL_LINKAGE LobbyForceSetPlayer : public CLobbyPackToServer { ui8 targetConnectedPlayer = -1; PlayerColor targetPlayerColor = PlayerColor::CANNOT_DETERMINE; - bool applyOnServer(CVCMIServer * srv); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { @@ -319,11 +276,11 @@ struct LobbyForceSetPlayer : public CLobbyPackToServer } }; -struct LobbyShowMessage : public CLobbyPackToPropagate +struct DLL_LINKAGE LobbyShowMessage : public CLobbyPackToPropagate { std::string message; - void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler); + virtual void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler & h, const int version) { diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index ab77d339c..9daa9ccde 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -30,7 +30,7 @@ #include "../lib/CStack.h" #include "../lib/battle/BattleInfo.h" #include "../lib/CondSh.h" -#include "../lib/NetPacks.h" +#include "ServerNetPackVisitors.h" #include "../lib/VCMI_Lib.h" #include "../lib/mapping/CMap.h" #include "../lib/mapping/CMapService.h" @@ -196,7 +196,7 @@ template class CApplyOnGH; class CBaseForGHApply { public: - virtual bool applyOnGH(CGameHandler * gh, void * pack) const =0; + virtual bool applyOnGH(CGameHandler * gh, CGameState * gs, void * pack) const =0; virtual ~CBaseForGHApply(){} template static CBaseForGHApply *getApplier(const U * t=nullptr) { @@ -207,12 +207,16 @@ public: template class CApplyOnGH : public CBaseForGHApply { public: - bool applyOnGH(CGameHandler * gh, void * pack) const override + bool applyOnGH(CGameHandler * gh, CGameState * gs, void * pack) const override { T *ptr = static_cast(pack); try { - return ptr->applyGh(gh); + ApplyGhNetPackVisitor applier(*gh, *gs); + + ptr->visit(applier); + + return applier.getResult(); } catch(ExceptionNotAllowedAction & e) { @@ -230,7 +234,7 @@ template <> class CApplyOnGH : public CBaseForGHApply { public: - bool applyOnGH(CGameHandler * gh, void * pack) const override + bool applyOnGH(CGameHandler * gh, CGameState * gs, void * pack) const override { logGlobal->error("Cannot apply on GH plain CPack!"); assert(0); @@ -1358,7 +1362,7 @@ void CGameHandler::handleReceivedPack(CPackForServer * pack) } else if(apply) { - const bool result = apply->applyOnGH(this, pack); + const bool result = apply->applyOnGH(this, this->gs, pack); if(result) logGlobal->trace("Message %s successfully applied!", typeid(*pack).name()); else @@ -2933,6 +2937,58 @@ void CGameHandler::sendAndApply(NewStructures * pack) checkVictoryLossConditionsForPlayer(getTown(pack->tid)->tempOwner); } +bool CGameHandler::isPlayerOwns(CPackForServer * pack, ObjectInstanceID id) +{ + return getPlayerAt(pack->c) == getOwner(id); +} + +void CGameHandler::throwNotAllowedAction(CPackForServer * pack) +{ + if(pack->c) + { + SystemMessage temp_message("You are not allowed to perform this action!"); + pack->c->sendPack(&temp_message); + } + logNetwork->error("Player is not allowed to perform this action!"); + throw ExceptionNotAllowedAction(); +} + +void CGameHandler::wrongPlayerMessage(CPackForServer * pack, PlayerColor expectedplayer) +{ + std::ostringstream oss; + oss << "You were identified as player " << getPlayerAt(pack->c) << " while expecting " << expectedplayer; + logNetwork->error(oss.str()); + if(pack->c) + { + SystemMessage temp_message(oss.str()); + pack->c->sendPack(&temp_message); + } +} + +void CGameHandler::throwOnWrongOwner(CPackForServer * pack, ObjectInstanceID id) +{ + if(!isPlayerOwns(pack, id)) + { + wrongPlayerMessage(pack, getOwner(id)); + throwNotAllowedAction(pack); + } +} + +void CGameHandler::throwOnWrongPlayer(CPackForServer * pack, PlayerColor player) +{ + if(!hasPlayerAt(player, pack->c) && player != getPlayerAt(pack->c)) + { + wrongPlayerMessage(pack, player); + throwNotAllowedAction(pack); + } +} + +void CGameHandler::throwAndComplain(CPackForServer * pack, std::string txt) +{ + complain(txt); + throwNotAllowedAction(pack); +} + void CGameHandler::save(const std::string & filename) { logGlobal->info("Saving to %s", filename); diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 5d9800e49..8b970dcc3 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -303,6 +303,13 @@ public: void sendAndApply(SetResources * pack); void sendAndApply(NewStructures * pack); + void wrongPlayerMessage(CPackForServer * pack, PlayerColor expectedplayer); + void throwNotAllowedAction(CPackForServer * pack); + void throwOnWrongOwner(CPackForServer * pack, ObjectInstanceID id); + void throwOnWrongPlayer(CPackForServer * pack, PlayerColor player); + void throwAndComplain(CPackForServer * pack, std::string txt); + bool isPlayerOwns(CPackForServer * pack, ObjectInstanceID id); + struct FinishingBattleHelper { FinishingBattleHelper(); diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 0677f1e8c..56379c69a 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -14,6 +14,8 @@ set(server_HEADERS CGameHandler.h CQuery.h CVCMIServer.h + LobbyNetPackVisitors.h + ServerNetPackVisitors.h ) assign_source_group(${server_SRCS} ${server_HEADERS}) diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 426ab0392..9382c69bc 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -27,6 +27,8 @@ #include "../lib/StartInfo.h" #include "../lib/mapping/CMap.h" #include "../lib/rmg/CMapGenOptions.h" +#include "../lib/NetPackVisitor.h" +#include "LobbyNetPackVisitors.h" #ifdef VCMI_ANDROID #include #include @@ -81,10 +83,17 @@ public: bool applyOnServerBefore(CVCMIServer * srv, void * pack) const override { T * ptr = static_cast(pack); - if(ptr->checkClientPermissions(srv)) + ClientPermissionsCheckerNetPackVisitor checker(*srv); + ptr->visit(checker); + + if(checker.getResult()) { boost::unique_lock stateLock(srv->stateMutex); - return ptr->applyOnServer(srv); + ApplyOnServerNetPackVisitor applier(*srv); + + ptr->visit(applier); + + return applier.getResult(); } else return false; @@ -93,7 +102,8 @@ public: void applyOnServerAfter(CVCMIServer * srv, void * pack) const override { T * ptr = static_cast(pack); - ptr->applyOnServerAfterAnnounce(srv); + ApplyOnServerAfterAnnounceNetPackVisitor applier(*srv); + ptr->visit(applier); } }; @@ -363,6 +373,35 @@ void CVCMIServer::connectionAccepted(const boost::system::error_code & ec) startAsyncAccept(); } +class CVCMIServerPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) +{ +private: + CVCMIServer & handler; + CGameHandler & gh; + +public: + CVCMIServerPackVisitor(CVCMIServer & handler, CGameHandler & gh) + :handler(handler), gh(gh) + { + } + + virtual bool callTyped() override { return false; } + + virtual void visitForLobby(CPackForLobby & packForLobby) override + { + handler.handleReceivedPack(std::unique_ptr(&packForLobby)); + } + + virtual void visitForServer(CPackForServer & serverPack) override + { + gh.handleReceivedPack(&serverPack); + } + + virtual void visitForClient(CPackForClient & clientPack) override + { + } +}; + void CVCMIServer::threadHandleClient(std::shared_ptr c) { setThreadName("CVCMIServer::handleConnection"); @@ -394,15 +433,9 @@ void CVCMIServer::threadHandleClient(std::shared_ptr c) } break; } - - if(auto lobbyPack = dynamic_ptr_cast(pack)) - { - handleReceivedPack(std::unique_ptr(lobbyPack)); - } - else if(auto serverPack = dynamic_ptr_cast(pack)) - { - gh->handleReceivedPack(serverPack); - } + + CVCMIServerPackVisitor visitor(*this, *this->gh); + pack->visit(visitor); } #ifndef _MSC_VER } diff --git a/server/LobbyNetPackVisitors.h b/server/LobbyNetPackVisitors.h new file mode 100644 index 000000000..251f1efcb --- /dev/null +++ b/server/LobbyNetPackVisitors.h @@ -0,0 +1,92 @@ +/* + * LobbyNetPackVisitors.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include "../lib/NetPackVisitor.h" + +class ClientPermissionsCheckerNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) +{ +private: + bool result; + CVCMIServer & srv; + +public: + ClientPermissionsCheckerNetPackVisitor(CVCMIServer & srv) + :srv(srv), result(false) + { + } + + bool getResult() const + { + return result; + } + + virtual void visitForLobby(CPackForLobby & pack) override; + virtual void visitLobbyClientConnected(LobbyClientConnected & pack) override; + virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override; + virtual void visitLobbyEndGame(LobbyEndGame & pack) override; + virtual void visitLobbyStartGame(LobbyStartGame & pack) override; + virtual void visitLobbyChangeHost(LobbyChangeHost & pack) override; + virtual void visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) override; + virtual void visitLobbyChatMessage(LobbyChatMessage & pack) override; + virtual void visitLobbyGuiAction(LobbyGuiAction & pack) override; +}; + +class ApplyOnServerAfterAnnounceNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) +{ +private: + CVCMIServer & srv; + +public: + ApplyOnServerAfterAnnounceNetPackVisitor(CVCMIServer & srv) + :srv(srv) + { + } + + virtual void visitForLobby(CPackForLobby & pack) override; + virtual void visitLobbyClientConnected(LobbyClientConnected & pack) override; + virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override; + virtual void visitLobbyEndGame(LobbyEndGame & pack) override; + virtual void visitLobbyStartGame(LobbyStartGame & pack) override; + virtual void visitLobbyChangeHost(LobbyChangeHost & pack) override; +}; + +class ApplyOnServerNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) +{ +private: + bool result; + CVCMIServer & srv; + +public: + ApplyOnServerNetPackVisitor(CVCMIServer & srv) + :srv(srv), result(true) + { + } + + bool getResult() const + { + return result; + } + + virtual void visitLobbyClientConnected(LobbyClientConnected & pack) override; + virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override; + virtual void visitLobbySetMap(LobbySetMap & pack) override; + virtual void visitLobbySetCampaign(LobbySetCampaign & pack) override; + virtual void visitLobbySetCampaignMap(LobbySetCampaignMap & pack) override; + virtual void visitLobbySetCampaignBonus(LobbySetCampaignBonus & pack) override; + virtual void visitLobbyEndGame(LobbyEndGame & pack) override; + virtual void visitLobbyStartGame(LobbyStartGame & pack) override; + virtual void visitLobbyChangeHost(LobbyChangeHost & pack) override; + virtual void visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) override; + virtual void visitLobbySetPlayer(LobbySetPlayer & pack) override; + virtual void visitLobbySetTurnTime(LobbySetTurnTime & pack) override; + virtual void visitLobbySetDifficulty(LobbySetDifficulty & pack) override; + virtual void visitLobbyForceSetPlayer(LobbyForceSetPlayer & pack) override; +}; \ No newline at end of file diff --git a/server/NetPacksLobbyServer.cpp b/server/NetPacksLobbyServer.cpp index d86685f49..a4a85c900 100644 --- a/server/NetPacksLobbyServer.cpp +++ b/server/NetPacksLobbyServer.cpp @@ -8,6 +8,7 @@ * */ #include "StdInc.h" +#include "LobbyNetPackVisitors.h" #include "CVCMIServer.h" #include "CGameHandler.h" @@ -21,328 +22,378 @@ #include "../lib/mapping/CMapService.h" #include "../lib/mapping/CMapInfo.h" -bool CLobbyPackToServer::checkClientPermissions(CVCMIServer * srv) const +void ClientPermissionsCheckerNetPackVisitor::visitForLobby(CPackForLobby & pack) { - return srv->isClientHost(c->connectionID); + if(pack.isForServer()) + { + result = srv.isClientHost(pack.c->connectionID); + } } -void CLobbyPackToServer::applyOnServerAfterAnnounce(CVCMIServer * srv) +void ApplyOnServerAfterAnnounceNetPackVisitor::visitForLobby(CPackForLobby & pack) { // Propogate options after every CLobbyPackToServer - srv->updateAndPropagateLobbyState(); + if(pack.isForServer()) + { + srv.updateAndPropagateLobbyState(); + } } -bool LobbyClientConnected::checkClientPermissions(CVCMIServer * srv) const +void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack) { - if(srv->gh) + if(srv.gh) { - for(auto & connection : srv->hangingConnections) + for(auto & connection : srv.hangingConnections) { - if(connection->uuid == uuid) + if(connection->uuid == pack.uuid) { - return true; + { + result = true; + return; + } } } } - if(srv->state == EServerState::LOBBY) - return true; + if(srv.state == EServerState::LOBBY) + { + result = true; + return; + } //disconnect immediately and ignore this client - srv->connections.erase(c); - if(c && c->isOpen()) + srv.connections.erase(pack.c); + if(pack.c && pack.c->isOpen()) { - c->close(); - c->connected = false; + pack.c->close(); + pack.c->connected = false; + } + { + result = false; + return; } - return false; } -bool LobbyClientConnected::applyOnServer(CVCMIServer * srv) +void ApplyOnServerNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack) { - if(srv->gh) + if(srv.gh) { - for(auto & connection : srv->hangingConnections) + for(auto & connection : srv.hangingConnections) { - if(connection->uuid == uuid) + if(connection->uuid == pack.uuid) { logNetwork->info("Reconnection player"); - c->connectionID = connection->connectionID; - for(auto & playerConnection : srv->gh->connections) + pack.c->connectionID = connection->connectionID; + for(auto & playerConnection : srv.gh->connections) { for(auto & existingConnection : playerConnection.second) { if(existingConnection == connection) { playerConnection.second.erase(existingConnection); - playerConnection.second.insert(c); + playerConnection.second.insert(pack.c); break; } } } - srv->hangingConnections.erase(connection); + srv.hangingConnections.erase(connection); break; } } } - srv->clientConnected(c, names, uuid, mode); + srv.clientConnected(pack.c, pack.names, pack.uuid, pack.mode); // Server need to pass some data to newly connected client - clientId = c->connectionID; - mode = srv->si->mode; - hostClientId = srv->hostClientId; - return true; + pack.clientId = pack.c->connectionID; + pack.mode = srv.si->mode; + pack.hostClientId = srv.hostClientId; + + result = true; } -void LobbyClientConnected::applyOnServerAfterAnnounce(CVCMIServer * srv) +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 - c->uuid = uuid; - srv->updateAndPropagateLobbyState(); - if(srv->state == EServerState::GAMEPLAY) + pack.c->uuid = pack.uuid; + srv.updateAndPropagateLobbyState(); + if(srv.state == EServerState::GAMEPLAY) { //immediately start game std::unique_ptr startGameForReconnectedPlayer(new LobbyStartGame); - startGameForReconnectedPlayer->initializedStartInfo = srv->si; - startGameForReconnectedPlayer->initializedGameState = srv->gh->gameState(); - startGameForReconnectedPlayer->clientId = c->connectionID; - srv->addToAnnounceQueue(std::move(startGameForReconnectedPlayer)); + startGameForReconnectedPlayer->initializedStartInfo = srv.si; + startGameForReconnectedPlayer->initializedGameState = srv.gh->gameState(); + startGameForReconnectedPlayer->clientId = pack.c->connectionID; + srv.addToAnnounceQueue(std::move(startGameForReconnectedPlayer)); } } -bool LobbyClientDisconnected::checkClientPermissions(CVCMIServer * srv) const +void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack) { - if(clientId != c->connectionID) - return false; - - if(shutdownServer) + if(pack.clientId != pack.c->connectionID) { - if(!srv->cmdLineOptions.count("run-by-client")) - return false; - - if(c->uuid != srv->cmdLineOptions["uuid"].as()) - return false; - } - - return true; -} - -bool LobbyClientDisconnected::applyOnServer(CVCMIServer * srv) -{ - srv->clientDisconnected(c); - c->close(); - c->connected = false; - return true; -} - -void LobbyClientDisconnected::applyOnServerAfterAnnounce(CVCMIServer * srv) -{ - if(c && c->isOpen()) - { - boost::unique_lock lock(*c->mutexWrite); - c->close(); - c->connected = false; - } - - if(shutdownServer) - { - logNetwork->info("Client requested shutdown, server will close itself..."); - srv->state = EServerState::SHUTDOWN; + result = false; return; } - else if(srv->connections.empty()) + + if(pack.shutdownServer) + { + if(!srv.cmdLineOptions.count("run-by-client")) + { + result = false; + return; + } + + if(pack.c->uuid != srv.cmdLineOptions["uuid"].as()) + { + result = false; + return; + } + } + + result = true; +} + +void ApplyOnServerNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack) +{ + srv.clientDisconnected(pack.c); + pack.c->close(); + pack.c->connected = false; + + result = true; +} + +void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack) +{ + if(pack.c && pack.c->isOpen()) + { + boost::unique_lock lock(*pack.c->mutexWrite); + pack.c->close(); + pack.c->connected = false; + } + + if(pack.shutdownServer) + { + logNetwork->info("Client requested shutdown, server will close itself..."); + srv.state = EServerState::SHUTDOWN; + return; + } + else if(srv.connections.empty()) { logNetwork->error("Last connection lost, server will close itself..."); - srv->state = EServerState::SHUTDOWN; + srv.state = EServerState::SHUTDOWN; } - else if(c == srv->hostClient) + else if(pack.c == srv.hostClient) { auto ph = std::make_unique(); - auto newHost = *RandomGeneratorUtil::nextItem(srv->connections, CRandomGenerator::getDefault()); + auto newHost = *RandomGeneratorUtil::nextItem(srv.connections, CRandomGenerator::getDefault()); ph->newHostConnectionId = newHost->connectionID; - srv->addToAnnounceQueue(std::move(ph)); + srv.addToAnnounceQueue(std::move(ph)); } - srv->updateAndPropagateLobbyState(); + srv.updateAndPropagateLobbyState(); } -bool LobbyChatMessage::checkClientPermissions(CVCMIServer * srv) const +void ClientPermissionsCheckerNetPackVisitor::visitLobbyChatMessage(LobbyChatMessage & pack) { - return true; + result = true; } -bool LobbySetMap::applyOnServer(CVCMIServer * srv) +void ApplyOnServerNetPackVisitor::visitLobbySetMap(LobbySetMap & pack) { - if(srv->state != EServerState::LOBBY) - return false; - - srv->updateStartInfoOnMapChange(mapInfo, mapGenOpts); - return true; -} - -bool LobbySetCampaign::applyOnServer(CVCMIServer * srv) -{ - srv->si->mapname = ourCampaign->camp->header.filename; - srv->si->mode = StartInfo::CAMPAIGN; - srv->si->campState = ourCampaign; - srv->si->turnTime = 0; - bool isCurrentMapConquerable = ourCampaign->currentMap && ourCampaign->camp->conquerable(*ourCampaign->currentMap); - for(int i = 0; i < ourCampaign->camp->scenarios.size(); i++) + if(srv.state != EServerState::LOBBY) { - if(ourCampaign->camp->conquerable(i)) + result = false; + return; + } + + srv.updateStartInfoOnMapChange(pack.mapInfo, pack.mapGenOpts); + + result = true; +} + +void ApplyOnServerNetPackVisitor::visitLobbySetCampaign(LobbySetCampaign & pack) +{ + srv.si->mapname = pack.ourCampaign->camp->header.filename; + srv.si->mode = StartInfo::CAMPAIGN; + srv.si->campState = pack.ourCampaign; + srv.si->turnTime = 0; + bool isCurrentMapConquerable = pack.ourCampaign->currentMap && pack.ourCampaign->camp->conquerable(*pack.ourCampaign->currentMap); + for(int i = 0; i < pack.ourCampaign->camp->scenarios.size(); i++) + { + if(pack.ourCampaign->camp->conquerable(i)) { - if(!isCurrentMapConquerable || (isCurrentMapConquerable && i == *ourCampaign->currentMap)) + if(!isCurrentMapConquerable || (isCurrentMapConquerable && i == *pack.ourCampaign->currentMap)) { - srv->setCampaignMap(i); + srv.setCampaignMap(i); } } } - return true; + + result = true; } -bool LobbySetCampaignMap::applyOnServer(CVCMIServer * srv) +void ApplyOnServerNetPackVisitor::visitLobbySetCampaignMap(LobbySetCampaignMap & pack) { - srv->setCampaignMap(mapId); - return true; + srv.setCampaignMap(pack.mapId); + + result = true; } -bool LobbySetCampaignBonus::applyOnServer(CVCMIServer * srv) +void ApplyOnServerNetPackVisitor::visitLobbySetCampaignBonus(LobbySetCampaignBonus & pack) { - srv->setCampaignBonus(bonusId); - return true; + srv.setCampaignBonus(pack.bonusId); + + result = true; } -bool LobbyGuiAction::checkClientPermissions(CVCMIServer * srv) const +void ClientPermissionsCheckerNetPackVisitor::visitLobbyGuiAction(LobbyGuiAction & pack) { - return srv->isClientHost(c->connectionID); + result = srv.isClientHost(pack.c->connectionID); } -bool LobbyEndGame::checkClientPermissions(CVCMIServer * srv) const +void ClientPermissionsCheckerNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack) { - return srv->isClientHost(c->connectionID); + result = srv.isClientHost(pack.c->connectionID); } -bool LobbyEndGame::applyOnServer(CVCMIServer * srv) +void ApplyOnServerNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack) { - srv->prepareToRestart(); - return true; + srv.prepareToRestart(); + + result = true; } -void LobbyEndGame::applyOnServerAfterAnnounce(CVCMIServer * srv) +void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack) { - boost::unique_lock stateLock(srv->stateMutex); - for(auto & c : srv->connections) + boost::unique_lock stateLock(srv.stateMutex); + for(auto & c : srv.connections) { c->enterLobbyConnectionMode(); c->disableStackSendingByID(); } } -bool LobbyStartGame::checkClientPermissions(CVCMIServer * srv) const +void ClientPermissionsCheckerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack) { - return srv->isClientHost(c->connectionID); + result = srv.isClientHost(pack.c->connectionID); } -bool LobbyStartGame::applyOnServer(CVCMIServer * srv) +void ApplyOnServerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack) { try { - srv->verifyStateBeforeStart(true); + srv.verifyStateBeforeStart(true); } catch(...) { - return false; + result = false; + return; } // Server will prepare gamestate and we announce StartInfo to clients - if(!srv->prepareToStartGame()) - return false; + if(!srv.prepareToStartGame()) + { + result = false; + return; + } - initializedStartInfo = std::make_shared(*srv->gh->getStartInfo(true)); - initializedGameState = srv->gh->gameState(); + pack.initializedStartInfo = std::make_shared(*srv.gh->getStartInfo(true)); + pack.initializedGameState = srv.gh->gameState(); - return true; + result = true; } -void LobbyStartGame::applyOnServerAfterAnnounce(CVCMIServer * srv) +void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack) { - if(clientId == -1) //do not restart game for single client only - srv->startGameImmidiately(); + if(pack.clientId == -1) //do not restart game for single client only + srv.startGameImmidiately(); else { - for(auto & c : srv->connections) + for(auto & c : srv.connections) { - if(c->connectionID == clientId) + if(c->connectionID == pack.clientId) { - c->enterGameplayConnectionMode(srv->gh->gameState()); - srv->reconnectPlayer(clientId); + c->enterGameplayConnectionMode(srv.gh->gameState()); + srv.reconnectPlayer(pack.clientId); } } } } -bool LobbyChangeHost::checkClientPermissions(CVCMIServer * srv) const +void ClientPermissionsCheckerNetPackVisitor::visitLobbyChangeHost(LobbyChangeHost & pack) { - return srv->isClientHost(c->connectionID); + result = srv.isClientHost(pack.c->connectionID); } -bool LobbyChangeHost::applyOnServer(CVCMIServer * srv) +void ApplyOnServerNetPackVisitor::visitLobbyChangeHost(LobbyChangeHost & pack) { - return true; + result = true; } -bool LobbyChangeHost::applyOnServerAfterAnnounce(CVCMIServer * srv) +void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyChangeHost(LobbyChangeHost & pack) { - return srv->passHost(newHostConnectionId); -} - -bool LobbyChangePlayerOption::checkClientPermissions(CVCMIServer * srv) const -{ - if(srv->isClientHost(c->connectionID)) - return true; - - if(vstd::contains(srv->getAllClientPlayers(c->connectionID), color)) - return true; - - return false; -} - -bool LobbyChangePlayerOption::applyOnServer(CVCMIServer * srv) -{ - switch(what) + auto result = srv.passHost(pack.newHostConnectionId); + + if(!result) { - case TOWN: - srv->optionNextCastle(color, direction); + logGlobal->error("passHost returned false. What does it mean?"); + } +} + +void ClientPermissionsCheckerNetPackVisitor::visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) +{ + if(srv.isClientHost(pack.c->connectionID)) + { + result = true; + return; + } + + if(vstd::contains(srv.getAllClientPlayers(pack.c->connectionID), pack.color)) + { + result = true; + return; + } + + result = false; +} + +void ApplyOnServerNetPackVisitor::visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) +{ + switch(pack.what) + { + case LobbyChangePlayerOption::TOWN: + srv.optionNextCastle(pack.color, pack.direction); break; - case HERO: - srv->optionNextHero(color, direction); + case LobbyChangePlayerOption::HERO: + srv.optionNextHero(pack.color, pack.direction); break; - case BONUS: - srv->optionNextBonus(color, direction); + case LobbyChangePlayerOption::BONUS: + srv.optionNextBonus(pack.color, pack.direction); break; } - return true; + + result = true; } -bool LobbySetPlayer::applyOnServer(CVCMIServer * srv) +void ApplyOnServerNetPackVisitor::visitLobbySetPlayer(LobbySetPlayer & pack) { - srv->setPlayer(clickedColor); - return true; + srv.setPlayer(pack.clickedColor); + result = true; } -bool LobbySetTurnTime::applyOnServer(CVCMIServer * srv) +void ApplyOnServerNetPackVisitor::visitLobbySetTurnTime(LobbySetTurnTime & pack) { - srv->si->turnTime = turnTime; - return true; + srv.si->turnTime = pack.turnTime; + result = true; } -bool LobbySetDifficulty::applyOnServer(CVCMIServer * srv) +void ApplyOnServerNetPackVisitor::visitLobbySetDifficulty(LobbySetDifficulty & pack) { - srv->si->difficulty = vstd::abetween(difficulty, 0, 4); - return true; + srv.si->difficulty = vstd::abetween(pack.difficulty, 0, 4); + result = true; } -bool LobbyForceSetPlayer::applyOnServer(CVCMIServer * srv) +void ApplyOnServerNetPackVisitor::visitLobbyForceSetPlayer(LobbyForceSetPlayer & pack) { - srv->si->playerInfos[targetPlayerColor].connectedPlayerIDs.insert(targetConnectedPlayer); - return true; + srv.si->playerInfos[pack.targetPlayerColor].connectedPlayerIDs.insert(pack.targetConnectedPlayer); + result = true; } diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index 889fccab9..9f195bd4b 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -8,7 +8,7 @@ * */ #include "StdInc.h" -#include "../lib/NetPacks.h" +#include "ServerNetPackVisitors.h" #include "CGameHandler.h" #include "../lib/IGameCallback.h" @@ -22,384 +22,330 @@ #include "../lib/spells/ISpellMechanics.h" #include "../lib/serializer/Cast.h" -bool CPackForServer::isPlayerOwns(CGameHandler * gh, ObjectInstanceID id) +void ApplyGhNetPackVisitor::visitSaveGame(SaveGame & pack) { - return gh->getPlayerAt(c) == gh->getOwner(id); + gh.save(pack.fname); + logGlobal->info("Game has been saved as %s", pack.fname); + result = true; } -void CPackForServer::throwNotAllowedAction() +void ApplyGhNetPackVisitor::visitEndTurn(EndTurn & pack) { - if(c) + PlayerColor currentPlayer = gs.currentPlayer; + if(pack.player != currentPlayer) { - SystemMessage temp_message("You are not allowed to perform this action!"); - c->sendPack(&temp_message); - } - logNetwork->error("Player is not allowed to perform this action!"); - throw ExceptionNotAllowedAction(); -} + if(gh.getPlayerStatus(pack.player) == EPlayerStatus::INGAME) + gh.throwAndComplain(&pack, "pack.player attempted to end turn for another pack.player!"); -void CPackForServer::wrongPlayerMessage(CGameHandler * gh, PlayerColor expectedplayer) -{ - std::ostringstream oss; - oss << "You were identified as player " << gh->getPlayerAt(c) << " while expecting " << expectedplayer; - logNetwork->error(oss.str()); - if(c) - { - SystemMessage temp_message(oss.str()); - c->sendPack(&temp_message); - } -} + logGlobal->debug("pack.player attempted to end turn after game over. Ignoring this request."); -void CPackForServer::throwOnWrongOwner(CGameHandler * gh, ObjectInstanceID id) -{ - if(!isPlayerOwns(gh, id)) - { - wrongPlayerMessage(gh, gh->getOwner(id)); - throwNotAllowedAction(); - } -} - -void CPackForServer::throwOnWrongPlayer(CGameHandler * gh, PlayerColor player) -{ - if(!gh->hasPlayerAt(player, c) && player != gh->getPlayerAt(c)) - { - wrongPlayerMessage(gh, player); - throwNotAllowedAction(); - } -} - -void CPackForServer::throwAndComplain(CGameHandler * gh, std::string txt) -{ - gh->complain(txt); - throwNotAllowedAction(); -} - - -CGameState * CPackForServer::GS(CGameHandler * gh) -{ - return gh->gs; -} - -bool SaveGame::applyGh(CGameHandler * gh) -{ - gh->save(fname); - logGlobal->info("Game has been saved as %s", fname); - return true; -} - -bool EndTurn::applyGh(CGameHandler * gh) -{ - PlayerColor currentPlayer = GS(gh)->currentPlayer; - if(player != currentPlayer) - { - if(gh->getPlayerStatus(player) == EPlayerStatus::INGAME) - throwAndComplain(gh, "Player attempted to end turn for another player!"); - - logGlobal->debug("Player attempted to end turn after game over. Ignoring this request."); - - return true; + result = true; + return; } - throwOnWrongPlayer(gh, player); - if(gh->queries.topQuery(player)) - throwAndComplain(gh, "Cannot end turn before resolving queries!"); + gh.throwOnWrongPlayer(&pack, pack.player); + if(gh.queries.topQuery(pack.player)) + gh.throwAndComplain(&pack, "Cannot end turn before resolving queries!"); - gh->states.setFlag(GS(gh)->currentPlayer, &PlayerStatus::makingTurn, false); - return true; + gh.states.setFlag(gs.currentPlayer, &PlayerStatus::makingTurn, false); + result = true; } -bool DismissHero::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitDismissHero(DismissHero & pack) { - throwOnWrongOwner(gh, hid); - return gh->removeObject(gh->getObj(hid)); + gh.throwOnWrongOwner(&pack, pack.hid); + result = gh.removeObject(gh.getObj(pack.hid)); } -bool MoveHero::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitMoveHero(MoveHero & pack) { - throwOnWrongOwner(gh, hid); - return gh->moveHero(hid, dest, 0, transit, gh->getPlayerAt(c)); + gh.throwOnWrongOwner(&pack, pack.hid); + result = gh.moveHero(pack.hid, pack.dest, 0, pack.transit, gh.getPlayerAt(pack.c)); } -bool CastleTeleportHero::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitCastleTeleportHero(CastleTeleportHero & pack) { - throwOnWrongOwner(gh, hid); + gh.throwOnWrongOwner(&pack, pack.hid); - return gh->teleportHero(hid, dest, source, gh->getPlayerAt(c)); + result = gh.teleportHero(pack.hid, pack.dest, pack.source, gh.getPlayerAt(pack.c)); } -bool ArrangeStacks::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitArrangeStacks(ArrangeStacks & pack) { //checks for owning in the gh func - return gh->arrangeStacks(id1, id2, what, p1, p2, val, gh->getPlayerAt(c)); + result = gh.arrangeStacks(pack.id1, pack.id2, pack.what, pack.p1, pack.p2, pack.val, gh.getPlayerAt(pack.c)); } -bool BulkMoveArmy::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitBulkMoveArmy(BulkMoveArmy & pack) { - return gh->bulkMoveArmy(srcArmy, destArmy, srcSlot); + result = gh.bulkMoveArmy(pack.srcArmy, pack.destArmy, pack.srcSlot); } -bool BulkSplitStack::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitBulkSplitStack(BulkSplitStack & pack) { - return gh->bulkSplitStack(src, srcOwner, amount); + result = gh.bulkSplitStack(pack.src, pack.srcOwner, pack.amount); } -bool BulkMergeStacks::applyGh(CGameHandler* gh) +void ApplyGhNetPackVisitor::visitBulkMergeStacks(BulkMergeStacks & pack) { - return gh->bulkMergeStacks(src, srcOwner); + result = gh.bulkMergeStacks(pack.src, pack.srcOwner); } -bool BulkSmartSplitStack::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitBulkSmartSplitStack(BulkSmartSplitStack & pack) { - return gh->bulkSmartSplitStack(src, srcOwner); + result = gh.bulkSmartSplitStack(pack.src, pack.srcOwner); } -bool DisbandCreature::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitDisbandCreature(DisbandCreature & pack) { - throwOnWrongOwner(gh, id); - return gh->disbandCreature(id, pos); + gh.throwOnWrongOwner(&pack, pack.id); + result = gh.disbandCreature(pack.id, pack.pos); } -bool BuildStructure::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitBuildStructure(BuildStructure & pack) { - throwOnWrongOwner(gh, tid); - return gh->buildStructure(tid, bid); + gh.throwOnWrongOwner(&pack, pack.tid); + result = gh.buildStructure(pack.tid, pack.bid); } -bool RecruitCreatures::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitRecruitCreatures(RecruitCreatures & pack) { - return gh->recruitCreatures(tid, dst, crid, amount, level); + result = gh.recruitCreatures(pack.tid, pack.dst, pack.crid, pack.amount, pack.level); } -bool UpgradeCreature::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitUpgradeCreature(UpgradeCreature & pack) { - throwOnWrongOwner(gh, id); - return gh->upgradeCreature(id, pos, cid); + gh.throwOnWrongOwner(&pack, pack.id); + result = gh.upgradeCreature(pack.id, pack.pos, pack.cid); } -bool GarrisonHeroSwap::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack) { - const CGTownInstance * town = gh->getTown(tid); - if(!isPlayerOwns(gh, tid) && !(town->garrisonHero && isPlayerOwns(gh, town->garrisonHero->id))) - throwNotAllowedAction(); //neither town nor garrisoned hero (if present) is ours - return gh->garrisonSwap(tid); + const CGTownInstance * town = gh.getTown(pack.tid); + if(!gh.isPlayerOwns(&pack, pack.tid) && !(town->garrisonHero && gh.isPlayerOwns(&pack, town->garrisonHero->id))) + gh.throwNotAllowedAction(&pack); //neither town nor garrisoned hero (if present) is ours + result = gh.garrisonSwap(pack.tid); } -bool ExchangeArtifacts::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack) { - throwOnWrongPlayer(gh, src.owningPlayer()); //second hero can be ally - return gh->moveArtifact(src, dst); + gh.throwOnWrongPlayer(&pack, pack.src.owningPlayer()); //second hero can be ally + result = gh.moveArtifact(pack.src, pack.dst); } -bool BulkExchangeArtifacts::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) { - const CGHeroInstance * pSrcHero = gh->getHero(srcHero); - throwOnWrongPlayer(gh, pSrcHero->getOwner()); - return gh->bulkMoveArtifacts(srcHero, dstHero, swap); + const CGHeroInstance * pSrcHero = gh.getHero(pack.srcHero); + gh.throwOnWrongPlayer(&pack, pSrcHero->getOwner()); + result = gh.bulkMoveArtifacts(pack.srcHero, pack.dstHero, pack.swap); } -bool AssembleArtifacts::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack) { - throwOnWrongOwner(gh, heroID); - return gh->assembleArtifacts(heroID, artifactSlot, assemble, assembleTo); + gh.throwOnWrongOwner(&pack, pack.heroID); + result = gh.assembleArtifacts(pack.heroID, pack.artifactSlot, pack.assemble, pack.assembleTo); } -bool BuyArtifact::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitBuyArtifact(BuyArtifact & pack) { - throwOnWrongOwner(gh, hid); - return gh->buyArtifact(hid, aid); + gh.throwOnWrongOwner(&pack, pack.hid); + result = gh.buyArtifact(pack.hid, pack.aid); } -bool TradeOnMarketplace::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitTradeOnMarketplace(TradeOnMarketplace & pack) { - const CGObjectInstance * market = gh->getObj(marketId); + const CGObjectInstance * market = gh.getObj(pack.marketId); if(!market) - throwAndComplain(gh, "Invalid market object"); - const CGHeroInstance * hero = gh->getHero(heroId); + gh.throwAndComplain(&pack, "Invalid market object"); + const CGHeroInstance * hero = gh.getHero(pack.heroId); //market must be owned or visited const IMarket * m = IMarket::castFrom(market); if(!m) - throwAndComplain(gh, "market is not-a-market! :/"); + gh.throwAndComplain(&pack, "market is not-a-market! :/"); PlayerColor player = market->tempOwner; if(player >= PlayerColor::PLAYER_LIMIT) - player = gh->getTile(market->visitablePos())->visitableObjects.back()->tempOwner; + player = gh.getTile(market->visitablePos())->visitableObjects.back()->tempOwner; if(player >= PlayerColor::PLAYER_LIMIT) - throwAndComplain(gh, "No player can use this market!"); + gh.throwAndComplain(&pack, "No player can use this market!"); - bool allyTownSkillTrade = (mode == EMarketMode::RESOURCE_SKILL && gh->getPlayerRelations(player, hero->tempOwner) == PlayerRelations::ALLIES); + bool allyTownSkillTrade = (pack.mode == EMarketMode::RESOURCE_SKILL && gh.getPlayerRelations(player, hero->tempOwner) == PlayerRelations::ALLIES); if(hero && (!(player == hero->tempOwner || allyTownSkillTrade) || hero->visitablePos() != market->visitablePos())) - throwAndComplain(gh, "This hero can't use this marketplace!"); + gh.throwAndComplain(&pack, "This hero can't use this marketplace!"); if(!allyTownSkillTrade) - throwOnWrongPlayer(gh, player); + gh.throwOnWrongPlayer(&pack, player); - bool result = true; + result = true; - switch(mode) + switch(pack.mode) { case EMarketMode::RESOURCE_RESOURCE: - for(int i = 0; i < r1.size(); ++i) - result &= gh->tradeResources(m, val[i], player, r1[i], r2[i]); + for(int i = 0; i < pack.r1.size(); ++i) + result &= gh.tradeResources(m, pack.val[i], player, pack.r1[i], pack.r2[i]); break; case EMarketMode::RESOURCE_PLAYER: - for(int i = 0; i < r1.size(); ++i) - result &= gh->sendResources(val[i], player, static_cast(r1[i]), PlayerColor(r2[i])); + for(int i = 0; i < pack.r1.size(); ++i) + result &= gh.sendResources(pack.val[i], player, static_cast(pack.r1[i]), PlayerColor(pack.r2[i])); break; case EMarketMode::CREATURE_RESOURCE: - for(int i = 0; i < r1.size(); ++i) - result &= gh->sellCreatures(val[i], m, hero, SlotID(r1[i]), static_cast(r2[i])); + for(int i = 0; i < pack.r1.size(); ++i) + result &= gh.sellCreatures(pack.val[i], m, hero, SlotID(pack.r1[i]), static_cast(pack.r2[i])); break; case EMarketMode::RESOURCE_ARTIFACT: - for(int i = 0; i < r1.size(); ++i) - result &= gh->buyArtifact(m, hero, static_cast(r1[i]), ArtifactID(r2[i])); + for(int i = 0; i < pack.r1.size(); ++i) + result &= gh.buyArtifact(m, hero, static_cast(pack.r1[i]), ArtifactID(pack.r2[i])); break; case EMarketMode::ARTIFACT_RESOURCE: - for(int i = 0; i < r1.size(); ++i) - result &= gh->sellArtifact(m, hero, ArtifactInstanceID(r1[i]), static_cast(r2[i])); + for(int i = 0; i < pack.r1.size(); ++i) + result &= gh.sellArtifact(m, hero, ArtifactInstanceID(pack.r1[i]), static_cast(pack.r2[i])); break; case EMarketMode::CREATURE_UNDEAD: - for(int i = 0; i < r1.size(); ++i) - result &= gh->transformInUndead(m, hero, SlotID(r1[i])); + for(int i = 0; i < pack.r1.size(); ++i) + result &= gh.transformInUndead(m, hero, SlotID(pack.r1[i])); break; case EMarketMode::RESOURCE_SKILL: - for(int i = 0; i < r2.size(); ++i) - result &= gh->buySecSkill(m, hero, SecondarySkill(r2[i])); + for(int i = 0; i < pack.r2.size(); ++i) + result &= gh.buySecSkill(m, hero, SecondarySkill(pack.r2[i])); break; case EMarketMode::CREATURE_EXP: { - std::vector slotIDs(r1.begin(), r1.end()); - std::vector count(val.begin(), val.end()); - return gh->sacrificeCreatures(m, hero, slotIDs, count); + std::vector slotIDs(pack.r1.begin(), pack.r1.end()); + std::vector count(pack.val.begin(), pack.val.end()); + result = gh.sacrificeCreatures(m, hero, slotIDs, count); + return; } case EMarketMode::ARTIFACT_EXP: { - std::vector positions(r1.begin(), r1.end()); - return gh->sacrificeArtifact(m, hero, positions); + std::vector positions(pack.r1.begin(), pack.r1.end()); + result = gh.sacrificeArtifact(m, hero, positions); + return; } default: - throwAndComplain(gh, "Unknown exchange mode!"); + gh.throwAndComplain(&pack, "Unknown exchange pack.mode!"); } - - return result; } -bool SetFormation::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitSetFormation(SetFormation & pack) { - throwOnWrongOwner(gh, hid); - return gh->setFormation(hid, formation); + gh.throwOnWrongOwner(&pack, pack.hid); + result = gh.setFormation(pack.hid, pack.formation); } -bool HireHero::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitHireHero(HireHero & pack) { - const CGObjectInstance * obj = gh->getObj(tid); + const CGObjectInstance * obj = gh.getObj(pack.tid); const CGTownInstance * town = dynamic_ptr_cast(obj); - if(town && PlayerRelations::ENEMIES == gh->getPlayerRelations(obj->tempOwner, gh->getPlayerAt(c))) - throwAndComplain(gh, "Can't buy hero in enemy town!"); + if(town && PlayerRelations::ENEMIES == gh.getPlayerRelations(obj->tempOwner, gh.getPlayerAt(pack.c))) + gh.throwAndComplain(&pack, "Can't buy hero in enemy town!"); - return gh->hireHero(obj, hid, player); + result = gh.hireHero(obj, pack.hid, pack.player); } -bool BuildBoat::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitBuildBoat(BuildBoat & pack) { - if(gh->getPlayerRelations(gh->getOwner(objid), gh->getPlayerAt(c)) == PlayerRelations::ENEMIES) - throwAndComplain(gh, "Can't build boat at enemy shipyard"); + if(gh.getPlayerRelations(gh.getOwner(pack.objid), gh.getPlayerAt(pack.c)) == PlayerRelations::ENEMIES) + gh.throwAndComplain(&pack, "Can't build boat at enemy shipyard"); - return gh->buildBoat(objid); + result = gh.buildBoat(pack.objid); } -bool QueryReply::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitQueryReply(QueryReply & pack) { - auto playerToConnection = gh->connections.find(player); - if(playerToConnection == gh->connections.end()) - throwAndComplain(gh, "No such player!"); - if(!vstd::contains(playerToConnection->second, c)) - throwAndComplain(gh, "Message came from wrong connection!"); - if(qid == QueryID(-1)) - throwAndComplain(gh, "Cannot answer the query with id -1!"); + 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)) + gh.throwAndComplain(&pack, "Cannot answer the query with pack.id -1!"); - assert(vstd::contains(gh->states.players, player)); - return gh->queryReply(qid, reply, player); + assert(vstd::contains(gh.states.players, pack.player)); + + result = gh.queryReply(pack.qid, pack.reply, pack.player); } -bool MakeAction::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitMakeAction(MakeAction & pack) { - const BattleInfo * b = GS(gh)->curB; + const BattleInfo * b = gs.curB; if(!b) - throwNotAllowedAction(); + gh.throwNotAllowedAction(&pack); if(b->tacticDistance) { - if(ba.actionType != EActionType::WALK && ba.actionType != EActionType::END_TACTIC_PHASE - && ba.actionType != EActionType::RETREAT && ba.actionType != EActionType::SURRENDER) - throwNotAllowedAction(); - if(!vstd::contains(gh->connections[b->sides[b->tacticsSide].color], c)) - throwNotAllowedAction(); + if(pack.ba.actionType != EActionType::WALK && pack.ba.actionType != EActionType::END_TACTIC_PHASE + && pack.ba.actionType != EActionType::RETREAT && pack.ba.actionType != EActionType::SURRENDER) + gh.throwNotAllowedAction(&pack); + if(!vstd::contains(gh.connections[b->sides[b->tacticsSide].color], pack.c)) + gh.throwNotAllowedAction(&pack); } else { auto active = b->battleActiveUnit(); if(!active) - throwNotAllowedAction(); + gh.throwNotAllowedAction(&pack); auto unitOwner = b->battleGetOwner(active); - if(!vstd::contains(gh->connections[unitOwner], c)) - throwNotAllowedAction(); + if(!vstd::contains(gh.connections[unitOwner], pack.c)) + gh.throwNotAllowedAction(&pack); } - return gh->makeBattleAction(ba); + + result = gh.makeBattleAction(pack.ba); } -bool MakeCustomAction::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitMakeCustomAction(MakeCustomAction & pack) { - const BattleInfo * b = GS(gh)->curB; + const BattleInfo * b = gs.curB; if(!b) - throwNotAllowedAction(); + gh.throwNotAllowedAction(&pack); if(b->tacticDistance) - throwNotAllowedAction(); + gh.throwNotAllowedAction(&pack); auto active = b->battleActiveUnit(); if(!active) - throwNotAllowedAction(); + gh.throwNotAllowedAction(&pack); auto unitOwner = b->battleGetOwner(active); - if(!vstd::contains(gh->connections[unitOwner], c)) - throwNotAllowedAction(); - if(ba.actionType != EActionType::HERO_SPELL) - throwNotAllowedAction(); - return gh->makeCustomAction(ba); + if(!vstd::contains(gh.connections[unitOwner], pack.c)) + gh.throwNotAllowedAction(&pack); + if(pack.ba.actionType != EActionType::HERO_SPELL) + gh.throwNotAllowedAction(&pack); + + result = gh.makeCustomAction(pack.ba); } -bool DigWithHero::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitDigWithHero(DigWithHero & pack) { - throwOnWrongOwner(gh, id); - return gh->dig(gh->getHero(id)); + gh.throwOnWrongOwner(&pack, pack.id); + result = gh.dig(gh.getHero(pack.id)); } -bool CastAdvSpell::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitCastAdvSpell(CastAdvSpell & pack) { - throwOnWrongOwner(gh, hid); + gh.throwOnWrongOwner(&pack, pack.hid); - const CSpell * s = sid.toSpell(); + const CSpell * s = pack.sid.toSpell(); if(!s) - throwNotAllowedAction(); - const CGHeroInstance * h = gh->getHero(hid); + gh.throwNotAllowedAction(&pack); + const CGHeroInstance * h = gh.getHero(pack.hid); if(!h) - throwNotAllowedAction(); + gh.throwNotAllowedAction(&pack); AdventureSpellCastParameters p; p.caster = h; - p.pos = pos; + p.pos = pack.pos; - return s->adventureCast(gh->spellEnv, p); + result = s->adventureCast(gh.spellEnv, p); } -bool PlayerMessage::applyGh(CGameHandler * gh) +void ApplyGhNetPackVisitor::visitPlayerMessage(PlayerMessage & pack) { - if(!player.isSpectator()) // TODO: clearly not a great way to verify permissions - throwOnWrongPlayer(gh, player); + if(!pack.player.isSpectator()) // TODO: clearly not a great way to verify permissions + gh.throwOnWrongPlayer(&pack, pack.player); - gh->playerMessage(player, text, currObj); - return true; + gh.playerMessage(pack.player, pack.text, pack.currObj); + result = true; } diff --git a/server/ServerNetPackVisitors.h b/server/ServerNetPackVisitors.h new file mode 100644 index 000000000..47aff3c12 --- /dev/null +++ b/server/ServerNetPackVisitors.h @@ -0,0 +1,61 @@ +/* + * ServerNetPackVisitors.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include "../lib/NetPackVisitor.h" + +class ApplyGhNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor) +{ +private: + bool result; + CGameHandler & gh; + CGameState & gs; + +public: + ApplyGhNetPackVisitor(CGameHandler & gh, CGameState & gs) + :gh(gh), gs(gs), result(false) + { + } + + bool getResult() const + { + return result; + } + + virtual void visitSaveGame(SaveGame & pack) override; + virtual void visitEndTurn(EndTurn & pack) override; + virtual void visitDismissHero(DismissHero & pack) override; + virtual void visitMoveHero(MoveHero & pack) override; + virtual void visitCastleTeleportHero(CastleTeleportHero & pack) override; + virtual void visitArrangeStacks(ArrangeStacks & pack) override; + virtual void visitBulkMoveArmy(BulkMoveArmy & pack) override; + virtual void visitBulkSplitStack(BulkSplitStack & pack) override; + virtual void visitBulkMergeStacks(BulkMergeStacks & pack) override; + virtual void visitBulkSmartSplitStack(BulkSmartSplitStack & pack) override; + virtual void visitDisbandCreature(DisbandCreature & pack) override; + virtual void visitBuildStructure(BuildStructure & pack) override; + virtual void visitRecruitCreatures(RecruitCreatures & pack) override; + virtual void visitUpgradeCreature(UpgradeCreature & pack) override; + virtual void visitGarrisonHeroSwap(GarrisonHeroSwap & pack) override; + virtual void visitExchangeArtifacts(ExchangeArtifacts & pack) override; + virtual void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) override; + virtual void visitAssembleArtifacts(AssembleArtifacts & pack) override; + virtual void visitBuyArtifact(BuyArtifact & pack) override; + virtual void visitTradeOnMarketplace(TradeOnMarketplace & pack) override; + virtual void visitSetFormation(SetFormation & pack) override; + virtual void visitHireHero(HireHero & pack) override; + virtual void visitBuildBoat(BuildBoat & pack) override; + virtual void visitQueryReply(QueryReply & pack) override; + virtual void visitMakeAction(MakeAction & pack) override; + virtual void visitMakeCustomAction(MakeCustomAction & pack) override; + virtual void visitDigWithHero(DigWithHero & pack) override; + virtual void visitCastAdvSpell(CastAdvSpell & pack) override; + virtual void visitPlayerMessage(PlayerMessage & pack) override; +}; \ No newline at end of file