mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	rework netpacks to avoid double typeinfo
This commit is contained in:
		| @@ -212,6 +212,8 @@ set(client_HEADERS | ||||
| 	CVideoHandler.h | ||||
| 	Client.h | ||||
| 	ClientCommandManager.h | ||||
| 	ClientNetPackVisitors.h | ||||
| 	LobbyClientNetPackVisitors.h | ||||
| 	resource.h | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -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 <boost/uuid/uuid_io.hpp> | ||||
| #include <boost/uuid/uuid_generators.hpp> | ||||
| #include "../lib/serializer/Cast.h" | ||||
| #include "LobbyClientNetPackVisitors.h" | ||||
|  | ||||
| #include <vcmi/events/EventBus.h> | ||||
|  | ||||
| @@ -86,15 +87,21 @@ public: | ||||
| 	bool applyOnLobbyHandler(CServerHandler * handler, void * pack) const override | ||||
| 	{ | ||||
| 		T * ptr = static_cast<T *>(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<T *>(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<CPackForLobby>(pack)) | ||||
| 			else | ||||
| 			{ | ||||
| 				if(applier->getApplier(typeList.getTypeID(pack))->applyOnLobbyHandler(this, pack)) | ||||
| 				{ | ||||
| 					if(!settings["session"]["headless"].Bool()) | ||||
| 					{ | ||||
| 						boost::unique_lock<boost::recursive_mutex> lock(*mx); | ||||
| 						packsForLobbyScreen.push_back(lobbyPack); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			else if(auto clientPack = dynamic_ptr_cast<CPackForClient>(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<boost::recursive_mutex> lock(*mx); | ||||
| 			packsForLobbyScreen.push_back(&lobbyPack); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CServerHandler::visitForClient(CPackForClient & clientPack) | ||||
| { | ||||
| 	client->handlePack(&clientPack); | ||||
| } | ||||
|  | ||||
| void CServerHandler::threadRunServer() | ||||
| { | ||||
| #if !defined(VCMI_ANDROID) && !defined(VCMI_IOS) | ||||
|   | ||||
| @@ -25,13 +25,13 @@ class CGameState; | ||||
| struct ClientPlayer; | ||||
| struct CPack; | ||||
| struct CPackForLobby; | ||||
| struct CPackForClient; | ||||
|  | ||||
| template<typename T> 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<CCampaignState> 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; | ||||
|   | ||||
| @@ -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<T *>(pack); | ||||
| 		ptr->applyCl(cl); | ||||
| 		ApplyClientNetPackVisitor visitor(*cl, *cl->gameState()); | ||||
| 		ptr->visit(visitor); | ||||
| 	} | ||||
| 	void applyOnClBefore(CClient * cl, void * pack) const override | ||||
| 	{ | ||||
| 		T * ptr = static_cast<T *>(pack); | ||||
| 		ptr->applyFirstCl(cl); | ||||
| 		ApplyFirstClientNetPackVisitor visitor(*cl, *cl->gameState()); | ||||
| 		ptr->visit(visitor); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
							
								
								
									
										132
									
								
								client/ClientNetPackVisitors.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								client/ClientNetPackVisitors.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
| }; | ||||
							
								
								
									
										56
									
								
								client/LobbyClientNetPackVisitors.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								client/LobbyClientNetPackVisitors.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
| }; | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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<CLobbyScreen>(static_cast<ESelectionScreen>(handler->screenType)); | ||||
| 		handler->state = EClientState::LOBBY; | ||||
| 		return true; | ||||
| 			GH.pushIntT<CLobbyScreen>(static_cast<ESelectionScreen>(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<CLoadingScreen>(std::bind(&CServerHandler::startGameplay, handler, initializedGameState)); | ||||
| 	GH.pushIntT<CLoadingScreen>(std::bind(&CServerHandler::startGameplay, &handler, pack.initializedGameState)); | ||||
| } | ||||
|  | ||||
| bool LobbyUpdateState::applyOnLobbyHandler(CServerHandler * handler) | ||||
| void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyUpdateState(LobbyUpdateState & pack) | ||||
| { | ||||
| 	hostChanged = state.hostClientId != handler->hostClientId; | ||||
| 	static_cast<LobbyState &>(*handler) = state; | ||||
| 	return true; | ||||
| 	pack.hostChanged = pack.state.hostClientId != handler.hostClientId; | ||||
| 	static_cast<LobbyState &>(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<CBonusSelection>(); | ||||
| 		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); | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										165
									
								
								lib/NetPackVisitor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								lib/NetPackVisitor.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										1168
									
								
								lib/NetPacks.h
									
									
									
									
									
								
							
							
						
						
									
										1168
									
								
								lib/NetPacks.h
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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<CConnection> 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: | ||||
| 	/// <summary> | ||||
| 	/// For basic types of netpacks hierarchy like CPackForClient. Called first. | ||||
| 	/// </summary> | ||||
| 	virtual void visitBasic(ICPackVisitor & cpackVisitor); | ||||
|  | ||||
| 	/// <summary> | ||||
| 	/// For leaf types of netpacks hierarchy. Called after visitBasic. | ||||
| 	/// </summary> | ||||
| 	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 <typename Handler> 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 | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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 <typename Handler> 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 <typename Handler> 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 <typename Handler> 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 <typename Handler> 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 <typename Handler> 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<StartInfo> 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 <typename Handler> 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 <typename Handler> 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 <typename Handler> 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<CMapInfo> mapInfo; | ||||
| 	std::shared_ptr<CMapGenOptions> mapGenOpts; | ||||
|  | ||||
| 	LobbySetMap() : mapInfo(nullptr), mapGenOpts(nullptr) {} | ||||
| 	bool applyOnServer(CVCMIServer * srv); | ||||
|  | ||||
| 	virtual void visitTyped(ICPackVisitor & visitor) override; | ||||
|  | ||||
| 	template <typename Handler> 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<CCampaignState> ourCampaign; | ||||
|  | ||||
| 	bool applyOnServer(CVCMIServer * srv); | ||||
| 	virtual void visitTyped(ICPackVisitor & visitor) override; | ||||
|  | ||||
| 	template <typename Handler> 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 <typename Handler> 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 <typename Handler> 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 <typename Handler> 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 <typename Handler> 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 <typename Handler> 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 <typename Handler> 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 <typename Handler> 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 <typename Handler> void serialize(Handler & h, const int version) | ||||
| 	{ | ||||
|   | ||||
| @@ -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 <typename T> 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<typename U> static CBaseForGHApply *getApplier(const U * t=nullptr) | ||||
| 	{ | ||||
| @@ -207,12 +207,16 @@ public: | ||||
| template <typename T> 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<T*>(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<CPack> : 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); | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
| @@ -14,6 +14,8 @@ set(server_HEADERS | ||||
| 		CGameHandler.h | ||||
| 		CQuery.h | ||||
| 		CVCMIServer.h | ||||
| 		LobbyNetPackVisitors.h | ||||
| 		ServerNetPackVisitors.h | ||||
| ) | ||||
|  | ||||
| assign_source_group(${server_SRCS} ${server_HEADERS}) | ||||
|   | ||||
| @@ -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 <jni.h> | ||||
| #include <android/log.h> | ||||
| @@ -81,10 +83,17 @@ public: | ||||
| 	bool applyOnServerBefore(CVCMIServer * srv, void * pack) const override | ||||
| 	{ | ||||
| 		T * ptr = static_cast<T *>(pack); | ||||
| 		if(ptr->checkClientPermissions(srv)) | ||||
| 		ClientPermissionsCheckerNetPackVisitor checker(*srv); | ||||
| 		ptr->visit(checker); | ||||
|  | ||||
| 		if(checker.getResult()) | ||||
| 		{ | ||||
| 			boost::unique_lock<boost::mutex> 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<T *>(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<CPackForLobby>(&packForLobby)); | ||||
| 	} | ||||
|  | ||||
| 	virtual void visitForServer(CPackForServer & serverPack) override | ||||
| 	{ | ||||
| 		gh.handleReceivedPack(&serverPack); | ||||
| 	} | ||||
|  | ||||
| 	virtual void visitForClient(CPackForClient & clientPack) override | ||||
| 	{ | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| void CVCMIServer::threadHandleClient(std::shared_ptr<CConnection> c) | ||||
| { | ||||
| 	setThreadName("CVCMIServer::handleConnection"); | ||||
| @@ -394,15 +433,9 @@ void CVCMIServer::threadHandleClient(std::shared_ptr<CConnection> c) | ||||
| 				} | ||||
| 				break; | ||||
| 			} | ||||
| 			 | ||||
| 			if(auto lobbyPack = dynamic_ptr_cast<CPackForLobby>(pack)) | ||||
| 			{ | ||||
| 				handleReceivedPack(std::unique_ptr<CPackForLobby>(lobbyPack)); | ||||
| 			} | ||||
| 			else if(auto serverPack = dynamic_ptr_cast<CPackForServer>(pack)) | ||||
| 			{ | ||||
| 				gh->handleReceivedPack(serverPack); | ||||
| 			} | ||||
|  | ||||
| 			CVCMIServerPackVisitor visitor(*this, *this->gh); | ||||
| 			pack->visit(visitor); | ||||
| 		} | ||||
| #ifndef _MSC_VER | ||||
| 	 } | ||||
|   | ||||
							
								
								
									
										92
									
								
								server/LobbyNetPackVisitors.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								server/LobbyNetPackVisitors.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
| }; | ||||
| @@ -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<LobbyStartGame> 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<std::string>()) | ||||
| 			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<boost::mutex> 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<std::string>()) | ||||
| 		{ | ||||
| 			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<boost::mutex> 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<LobbyChangeHost>(); | ||||
| 		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<boost::mutex> stateLock(srv->stateMutex); | ||||
| 	for(auto & c : srv->connections) | ||||
| 	boost::unique_lock<boost::mutex> 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<StartInfo>(*srv->gh->getStartInfo(true)); | ||||
| 	initializedGameState = srv->gh->gameState(); | ||||
| 	pack.initializedStartInfo = std::make_shared<StartInfo>(*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; | ||||
| } | ||||
|   | ||||
| @@ -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<Res::ERes>(r1[i]), PlayerColor(r2[i])); | ||||
| 		for(int i = 0; i < pack.r1.size(); ++i) | ||||
| 			result &= gh.sendResources(pack.val[i], player, static_cast<Res::ERes>(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<Res::ERes>(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<Res::ERes>(pack.r2[i])); | ||||
| 		break; | ||||
| 	case EMarketMode::RESOURCE_ARTIFACT: | ||||
| 		for(int i = 0; i < r1.size(); ++i) | ||||
| 			result &= gh->buyArtifact(m, hero, static_cast<Res::ERes>(r1[i]), ArtifactID(r2[i])); | ||||
| 		for(int i = 0; i < pack.r1.size(); ++i) | ||||
| 			result &= gh.buyArtifact(m, hero, static_cast<Res::ERes>(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<Res::ERes>(r2[i])); | ||||
| 		for(int i = 0; i < pack.r1.size(); ++i) | ||||
| 			result &= gh.sellArtifact(m, hero, ArtifactInstanceID(pack.r1[i]), static_cast<Res::ERes>(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<SlotID> slotIDs(r1.begin(), r1.end()); | ||||
| 		std::vector<ui32> count(val.begin(), val.end()); | ||||
| 		return gh->sacrificeCreatures(m, hero, slotIDs, count); | ||||
| 		std::vector<SlotID> slotIDs(pack.r1.begin(), pack.r1.end()); | ||||
| 		std::vector<ui32> count(pack.val.begin(), pack.val.end()); | ||||
| 		result = gh.sacrificeCreatures(m, hero, slotIDs, count); | ||||
| 		return; | ||||
| 	} | ||||
| 	case EMarketMode::ARTIFACT_EXP: | ||||
| 	{ | ||||
| 		std::vector<ArtifactPosition> positions(r1.begin(), r1.end()); | ||||
| 		return gh->sacrificeArtifact(m, hero, positions); | ||||
| 		std::vector<ArtifactPosition> 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<CGTownInstance>(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; | ||||
| } | ||||
|   | ||||
							
								
								
									
										61
									
								
								server/ServerNetPackVisitors.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								server/ServerNetPackVisitors.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user