Pārlūkot izejas kodu

Prefer to pass CGameState as reference instead of pointer

Ivan Savenko 6 mēneši atpakaļ
vecāks
revīzija
4d57a8ed36
67 mainītis faili ar 465 papildinājumiem un 466 dzēšanām
  1. 1 1
      AI/Nullkiller/Engine/Nullkiller.cpp
  2. 2 2
      AI/Nullkiller/Pathfinding/AIPathfinderConfig.cpp
  3. 1 1
      AI/Nullkiller/Pathfinding/AIPathfinderConfig.h
  4. 2 2
      AI/VCAI/Pathfinding/AIPathfinderConfig.cpp
  5. 1 1
      AI/VCAI/Pathfinding/AIPathfinderConfig.h
  6. 1 1
      AI/VCAI/VCAI.cpp
  7. 3 3
      CCallback.cpp
  8. 2 2
      CCallback.h
  9. 1 1
      client/CPlayerInterface.cpp
  10. 3 3
      client/CServerHandler.cpp
  11. 14 14
      client/Client.cpp
  12. 2 2
      client/Client.h
  13. 2 2
      client/ClientCommandManager.cpp
  14. 5 5
      client/NetPacksClient.cpp
  15. 1 1
      client/windows/GUIClasses.cpp
  16. 2 2
      lib/CArtHandler.cpp
  17. 5 5
      lib/CArtifactInstance.cpp
  18. 1 1
      lib/CArtifactInstance.h
  19. 1 1
      lib/CArtifactSet.h
  20. 1 1
      lib/CCreatureSet.cpp
  21. 79 79
      lib/CGameInfoCallback.cpp
  22. 2 2
      lib/CGameInfoCallback.h
  23. 1 1
      lib/CPlayerState.cpp
  24. 18 18
      lib/IGameCallback.cpp
  25. 6 6
      lib/gameState/CGameState.cpp
  26. 2 2
      lib/gameState/CGameState.h
  27. 1 1
      lib/json/JsonRandom.cpp
  28. 6 6
      lib/mapObjects/CArmedInstance.cpp
  29. 4 4
      lib/mapObjects/CArmedInstance.h
  30. 1 1
      lib/mapObjects/CGCreature.cpp
  31. 5 5
      lib/mapObjects/CGDwelling.cpp
  32. 20 20
      lib/mapObjects/CGHeroInstance.cpp
  33. 5 5
      lib/mapObjects/CGHeroInstance.h
  34. 3 3
      lib/mapObjects/CGObjectInstance.cpp
  35. 3 3
      lib/mapObjects/CGObjectInstance.h
  36. 1 1
      lib/mapObjects/CGResource.cpp
  37. 8 8
      lib/mapObjects/CGTownInstance.cpp
  38. 1 1
      lib/mapObjects/FlaggableMapObject.cpp
  39. 33 33
      lib/mapObjects/MiscObjects.cpp
  40. 2 2
      lib/mapObjects/MiscObjects.h
  41. 1 1
      lib/mapping/CMap.cpp
  42. 1 1
      lib/mapping/CMap.h
  43. 4 4
      lib/networkPacks/NetPacksLib.cpp
  44. 9 9
      lib/pathfinder/CGPathNode.cpp
  45. 3 3
      lib/pathfinder/CGPathNode.h
  46. 10 10
      lib/pathfinder/CPathfinder.cpp
  47. 6 6
      lib/pathfinder/CPathfinder.h
  48. 1 1
      lib/pathfinder/PathfinderCache.cpp
  49. 11 11
      lib/pathfinder/PathfinderOptions.cpp
  50. 5 5
      lib/pathfinder/PathfinderOptions.h
  51. 1 1
      lib/rewardable/Interface.cpp
  52. 2 2
      lib/serializer/Connection.cpp
  53. 1 1
      lib/serializer/Connection.h
  54. 59 59
      server/CGameHandler.cpp
  55. 2 2
      server/CGameHandler.h
  56. 1 1
      server/CVCMIServer.cpp
  57. 1 1
      server/NetPacksServer.cpp
  58. 1 1
      server/ServerSpellCastEnvironment.cpp
  59. 22 23
      server/TurnTimerHandler.cpp
  60. 11 11
      server/battles/BattleProcessor.cpp
  61. 12 12
      server/battles/BattleResultProcessor.cpp
  62. 6 6
      server/processors/HeroPoolProcessor.cpp
  63. 27 27
      server/processors/NewTurnProcessor.cpp
  64. 8 8
      server/processors/PlayerMessageProcessor.cpp
  65. 1 1
      server/processors/TurnOrderProcessor.cpp
  66. 5 5
      server/queries/VisitQueries.cpp
  67. 2 2
      test/mock/mock_IGameCallback.h

+ 1 - 1
AI/Nullkiller/Engine/Nullkiller.cpp

@@ -77,7 +77,7 @@ void Nullkiller::init(std::shared_ptr<CCallback> cb, AIGateway * gateway)
 
 	settings = std::make_unique<Settings>(cb->getStartInfo()->difficulty);
 
-	PathfinderOptions pathfinderOptions(cb.get());
+	PathfinderOptions pathfinderOptions(*cb);
 
 	pathfinderOptions.useTeleportTwoWay = true;
 	pathfinderOptions.useTeleportOneWay = settings->isOneWayMonolithUsageAllowed();

+ 2 - 2
AI/Nullkiller/Pathfinding/AIPathfinderConfig.cpp

@@ -44,7 +44,7 @@ namespace AIPathfinding
 		Nullkiller * ai,
 		std::shared_ptr<AINodeStorage> nodeStorage,
 		bool allowBypassObjects)
-		:PathfinderConfig(nodeStorage, cb, makeRuleset(cb, ai, nodeStorage, allowBypassObjects)), aiNodeStorage(nodeStorage)
+		:PathfinderConfig(nodeStorage, *cb, makeRuleset(cb, ai, nodeStorage, allowBypassObjects)), aiNodeStorage(nodeStorage)
 	{
 		options.canUseCast = true;
 		options.allowLayerTransitioningAfterBattle = true;
@@ -56,7 +56,7 @@ namespace AIPathfinding
 
 	AIPathfinderConfig::~AIPathfinderConfig() = default;
 
-	CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState * gs)
+	CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState & gs)
 	{
 		auto hero = aiNodeStorage->getHero(source.node);
 		auto & helper = pathfindingHelpers[hero];

+ 1 - 1
AI/Nullkiller/Pathfinding/AIPathfinderConfig.h

@@ -35,7 +35,7 @@ namespace AIPathfinding
 
 		~AIPathfinderConfig();
 
-		CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState * gs) override;
+		CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState & gs) override;
 	};
 }
 

+ 2 - 2
AI/VCAI/Pathfinding/AIPathfinderConfig.cpp

@@ -39,7 +39,7 @@ namespace AIPathfinding
 		CPlayerSpecificInfoCallback * cb,
 		VCAI * ai,
 		std::shared_ptr<AINodeStorage> nodeStorage)
-		:PathfinderConfig(nodeStorage, cb, makeRuleset(cb, ai, nodeStorage)), hero(nodeStorage->getHero())
+		:PathfinderConfig(nodeStorage, *cb, makeRuleset(cb, ai, nodeStorage)), hero(nodeStorage->getHero())
 	{
 		options.ignoreGuards = false;
 		options.useEmbarkAndDisembark = true;
@@ -51,7 +51,7 @@ namespace AIPathfinding
 
 	AIPathfinderConfig::~AIPathfinderConfig() = default;
 
-	CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState * gs)
+	CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState & gs)
 	{
 		if(!helper)
 		{

+ 1 - 1
AI/VCAI/Pathfinding/AIPathfinderConfig.h

@@ -30,6 +30,6 @@ namespace AIPathfinding
 
 		~AIPathfinderConfig();
 
-		CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState * gs) override;
+		CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState & gs) override;
 	};
 }

+ 1 - 1
AI/VCAI/VCAI.cpp

@@ -627,7 +627,7 @@ void VCAI::initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<C
 	playerID = *myCb->getPlayerID();
 	myCb->waitTillRealize = true;
 	myCb->unlockGsWhenWaiting = true;
-	pathfinderCache = std::make_unique<PathfinderCache>(myCb.get(), PathfinderOptions(myCb.get()));
+	pathfinderCache = std::make_unique<PathfinderCache>(myCb.get(), PathfinderOptions(*myCb));
 
 	if(!fh)
 		fh = new FuzzyHelper();

+ 3 - 3
CCallback.cpp

@@ -378,7 +378,7 @@ CCallback::~CCallback() = default;
 bool CCallback::canMoveBetween(const int3 &a, const int3 &b)
 {
 	//bidirectional
-	return gameState()->getMap().canMoveBetween(a, b);
+	return gameState().getMap().canMoveBetween(a, b);
 }
 
 std::optional<PlayerColor> CCallback::getPlayerID() const
@@ -388,10 +388,10 @@ std::optional<PlayerColor> CCallback::getPlayerID() const
 
 int3 CCallback::getGuardingCreaturePosition(int3 tile)
 {
-	if (!gameState()->getMap().isInTheMap(tile))
+	if (!gameState().getMap().isInTheMap(tile))
 		return int3(-1,-1,-1);
 
-	return gameState()->getMap().guardingCreaturePositions[tile.z][tile.x][tile.y];
+	return gameState().getMap().guardingCreaturePositions[tile.z][tile.x][tile.y];
 }
 
 void CCallback::dig( const CGObjectInstance *hero )

+ 2 - 2
CCallback.h

@@ -152,8 +152,8 @@ class CCallback : public CPlayerSpecificInfoCallback, public CBattleCallback, pu
 {
 	std::shared_ptr<CGameState> gamestate;
 
-	CGameState * gameState() final { return gamestate.get(); }
-	const CGameState * gameState() const final { return gamestate.get(); }
+	CGameState & gameState() final { return *gamestate; }
+	const CGameState & gameState() const final { return *gamestate; }
 
 public:
 	CCallback(std::shared_ptr<CGameState> gamestate, std::optional<PlayerColor> Player, CClient * C);

+ 1 - 1
client/CPlayerInterface.cpp

@@ -153,7 +153,7 @@ void CPlayerInterface::initGameInterface(std::shared_ptr<Environment> ENV, std::
 	cb = CB;
 	env = ENV;
 
-	pathfinderCache = std::make_unique<PathfinderCache>(cb.get(), PathfinderOptions(cb.get()));
+	pathfinderCache = std::make_unique<PathfinderCache>(cb.get(), PathfinderOptions(*cb));
 	ENGINE->music().loadTerrainMusicThemes();
 	initializeHeroTownList();
 

+ 3 - 3
client/CServerHandler.cpp

@@ -634,11 +634,11 @@ void CServerHandler::startGameplay(std::shared_ptr<CGameState> gameState)
 
 void CServerHandler::showHighScoresAndEndGameplay(PlayerColor player, bool victory, const StatisticDataSet & statistic)
 {
-	HighScoreParameter param = HighScore::prepareHighScores(client->gameState(), player, victory);
+	HighScoreParameter param = HighScore::prepareHighScores(&client->gameState(), player, victory);
 
-	if(victory && client->gameState()->getStartInfo()->campState)
+	if(victory && client->gameState().getStartInfo()->campState)
 	{
-		startCampaignScenario(param, client->gameState()->getStartInfo()->campState, statistic);
+		startCampaignScenario(param, client->gameState().getStartInfo()->campState, statistic);
 	}
 	else
 	{

+ 14 - 14
client/Client.cpp

@@ -147,7 +147,7 @@ void CClient::loadGame(std::shared_ptr<CGameState> initializedGameState)
 
 void CClient::save(const std::string & fname)
 {
-	if(!gameState()->currentBattles.empty())
+	if(!gameState().currentBattles.empty())
 	{
 		logNetwork->error("Game cannot be saved during battle!");
 		return;
@@ -211,7 +211,7 @@ void CClient::initMapHandler()
 	// During loading CPlayerInterface from serialized state it's depend on MH
 	if(!settings["session"]["headless"].Bool())
 	{
-		GAME->setMapInstance(std::make_unique<CMapHandler>(&gameState()->getMap()));
+		GAME->setMapInstance(std::make_unique<CMapHandler>(&gameState().getMap()));
 		logNetwork->trace("Creating mapHandler: %d ms", GAME->server().th->getDiff());
 	}
 }
@@ -227,7 +227,7 @@ void CClient::initPlayerEnvironments()
 		logNetwork->info("Preparing environment for player %s", color.toString());
 		playerEnvironments[color] = std::make_shared<CPlayerEnvironment>(color, this, std::make_shared<CCallback>(gamestate, color, this));
 		
-		if(color.isValidPlayer() && !hasHumanPlayer && gameState()->players.at(color).isHuman())
+		if(color.isValidPlayer() && !hasHumanPlayer && gameState().players.at(color).isHuman())
 			hasHumanPlayer = true;
 	}
 
@@ -247,7 +247,7 @@ void CClient::initPlayerEnvironments()
 
 void CClient::initPlayerInterfaces()
 {
-	for(const auto & playerInfo : gameState()->getStartInfo()->playerInfos)
+	for(const auto & playerInfo : gameState().getStartInfo()->playerInfos)
 	{
 		PlayerColor color = playerInfo.first;
 		if(!vstd::contains(GAME->server().getAllClientPlayers(GAME->server().logicConnection->connectionID), color))
@@ -259,8 +259,8 @@ void CClient::initPlayerInterfaces()
 			if(playerInfo.second.isControlledByAI() || settings["session"]["onlyai"].Bool())
 			{
 				bool alliedToHuman = false;
-				for(const auto & allyInfo : gameState()->getStartInfo()->playerInfos)
-					if (gameState()->getPlayerTeam(allyInfo.first) == gameState()->getPlayerTeam(playerInfo.first) && allyInfo.second.isControlledByHuman())
+				for(const auto & allyInfo : gameState().getStartInfo()->playerInfos)
+					if (gameState().getPlayerTeam(allyInfo.first) == gameState().getPlayerTeam(playerInfo.first) && allyInfo.second.isControlledByHuman())
 						alliedToHuman = true;
 
 				auto AiToGive = aiNameForPlayer(playerInfo.second, false, alliedToHuman);
@@ -340,14 +340,14 @@ void CClient::installNewBattleInterface(std::shared_ptr<CBattleGameInterface> ba
 
 void CClient::handlePack(CPackForClient & pack)
 {
-	ApplyClientNetPackVisitor afterVisitor(*this, *gameState());
-	ApplyFirstClientNetPackVisitor beforeVisitor(*this, *gameState());
+	ApplyClientNetPackVisitor afterVisitor(*this, gameState());
+	ApplyFirstClientNetPackVisitor beforeVisitor(*this, gameState());
 
 	pack.visit(beforeVisitor);
 	logNetwork->trace("\tMade first apply on cl: %s", typeid(pack).name());
 	{
 		std::unique_lock lock(CGameState::mutex);
-		gameState()->apply(pack);
+		gameState().apply(pack);
 	}
 	logNetwork->trace("\tApplied on gs: %s", typeid(pack).name());
 	pack.visit(afterVisitor);
@@ -373,7 +373,7 @@ int CClient::sendRequest(const CPackForServer & request, PlayerColor player)
 
 void CClient::battleStarted(const BattleID & battleID)
 {
-	const BattleInfo * info = gameState()->getBattle(battleID);
+	const BattleInfo * info = gameState().getBattle(battleID);
 
 	std::shared_ptr<CPlayerInterface> att;
 	std::shared_ptr<CPlayerInterface> def;
@@ -459,8 +459,8 @@ void CClient::battleFinished(const BattleID & battleID)
 {
 	for(auto side : { BattleSide::ATTACKER, BattleSide::DEFENDER })
 	{
-		if(battleCallbacks.count(gameState()->getBattle(battleID)->getSide(side).color))
-			battleCallbacks[gameState()->getBattle(battleID)->getSide(side).color]->onBattleEnded(battleID);
+		if(battleCallbacks.count(gameState().getBattle(battleID)->getSide(side).color))
+			battleCallbacks[gameState().getBattle(battleID)->getSide(side).color]->onBattleEnded(battleID);
 	}
 
 	if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool())
@@ -478,11 +478,11 @@ void CClient::startPlayerBattleAction(const BattleID & battleID, PlayerColor col
 	{
 		// we want to avoid locking gamestate and causing UI to freeze while AI is making turn
 		auto unlockInterface = vstd::makeUnlockGuard(ENGINE->interfaceMutex);
-		battleint->activeStack(battleID, gameState()->getBattle(battleID)->battleGetStackByID(gameState()->getBattle(battleID)->activeStack, false));
+		battleint->activeStack(battleID, gameState().getBattle(battleID)->battleGetStackByID(gameState().getBattle(battleID)->activeStack, false));
 	}
 	else
 	{
-		battleint->activeStack(battleID, gameState()->getBattle(battleID)->battleGetStackByID(gameState()->getBattle(battleID)->activeStack, false));
+		battleint->activeStack(battleID, gameState().getBattle(battleID)->battleGetStackByID(gameState().getBattle(battleID)->activeStack, false));
 	}
 }
 

+ 2 - 2
client/Client.h

@@ -140,8 +140,8 @@ public:
 	vstd::CLoggerBase * logger() const override;
 	events::EventBus * eventBus() const override;
 
-	CGameState * gameState() final { return gamestate.get(); }
-	const CGameState * gameState() const final { return gamestate.get(); }
+	CGameState & gameState() final { return *gamestate; }
+	const CGameState & gameState() const final { return *gamestate; }
 
 	void newGame(std::shared_ptr<CGameState> gameState);
 	void loadGame(std::shared_ptr<CGameState> gameState);

+ 2 - 2
client/ClientCommandManager.cpp

@@ -140,7 +140,7 @@ void ClientCommandManager::handleControlaiCommand(std::istringstream& singleWord
 	if(GAME->interface())
 		color = GAME->interface()->playerID;
 
-	for(auto & elem : GAME->server().client->gameState()->players)
+	for(auto & elem : GAME->server().client->gameState().players)
 	{
 		if(!elem.first.isValidPlayer()
 			|| elem.second.human
@@ -557,7 +557,7 @@ void ClientCommandManager::giveTurn(const PlayerColor &colorIdentifier)
 	yt.player = colorIdentifier;
 	yt.queryID = QueryID::NONE;
 
-	ApplyClientNetPackVisitor visitor(*GAME->server().client, *GAME->server().client->gameState());
+	ApplyClientNetPackVisitor visitor(*GAME->server().client, GAME->server().client->gameState());
 	yt.visit(visitor);
 }
 

+ 5 - 5
client/NetPacksClient.cpp

@@ -100,16 +100,16 @@ void callAllInterfaces(CClient & cl, void (T::*ptr)(Args...), Args2 && ...args)
 template<typename T, typename ... Args, typename ... Args2>
 void callBattleInterfaceIfPresentForBothSides(CClient & cl, const BattleID & battleID, void (T::*ptr)(Args...), Args2 && ...args)
 {
-	assert(cl.gameState()->getBattle(battleID));
+	assert(cl.gameState().getBattle(battleID));
 
-	if(!cl.gameState()->getBattle(battleID))
+	if(!cl.gameState().getBattle(battleID))
 	{
 		logGlobal->error("Attempt to call battle interface without ongoing battle!");
 		return;
 	}
 
-	callOnlyThatBattleInterface(cl, cl.gameState()->getBattle(battleID)->getSide(BattleSide::ATTACKER).color, ptr, std::forward<Args2>(args)...);
-	callOnlyThatBattleInterface(cl, cl.gameState()->getBattle(battleID)->getSide(BattleSide::DEFENDER).color, ptr, std::forward<Args2>(args)...);
+	callOnlyThatBattleInterface(cl, cl.gameState().getBattle(battleID)->getSide(BattleSide::ATTACKER).color, ptr, std::forward<Args2>(args)...);
+	callOnlyThatBattleInterface(cl, cl.gameState().getBattle(battleID)->getSide(BattleSide::DEFENDER).color, ptr, std::forward<Args2>(args)...);
 	if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool() && GAME->interface()->battleInt)
 	{
 		callOnlyThatBattleInterface(cl, PlayerColor::SPECTATOR, ptr, std::forward<Args2>(args)...);
@@ -431,7 +431,7 @@ void ApplyClientNetPackVisitor::visitPlayerReinitInterface(PlayerReinitInterface
 
 		for(PlayerColor player(0); player < PlayerColor::PLAYER_LIMIT; ++player)
 		{
-			if(cl.gameState()->isPlayerMakingTurn(player))
+			if(cl.gameState().isPlayerMakingTurn(player))
 			{
 				callAllInterfaces(cl, &IGameEventsReceiver::playerStartsTurn, player);
 				callOnlyThatInterface(cl, player, &CGameInterface::yourTurn, QueryID::NONE);

+ 1 - 1
client/windows/GUIClasses.cpp

@@ -545,7 +545,7 @@ void CTavernWindow::addInvite()
 	if(!GAME->interface()->cb->getSettings().getBoolean(EGameSettings::HEROES_TAVERN_INVITE))
 		return;
 
-	const auto & heroesPool = GAME->server().client->gameState()->heroesPool;
+	const auto & heroesPool = GAME->server().client->gameState().heroesPool;
 	for(auto & elem : heroesPool->unusedHeroesFromPool())
 	{
 		bool heroAvailable = heroesPool->isHeroAvailableFor(elem.first, tavernObj->getOwner());

+ 2 - 2
lib/CArtHandler.cpp

@@ -948,11 +948,11 @@ bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockChe
 	return true; //no slot means not used
 }
 
-void CArtifactSet::artDeserializationFix(CGameState * gs, CBonusSystemNode *node)
+void CArtifactSet::artDeserializationFix(CGameState & gs, CBonusSystemNode *node)
 {
 	for(auto & elem : artifactsWorn)
 		if(elem.second.artifactID.hasValue() && !elem.second.locked)
-			node->attachToSource(*gs->getArtInstance(elem.second.artifactID));
+			node->attachToSource(*gs.getArtInstance(elem.second.artifactID));
 }
 
 void CArtifactSet::serializeJsonArtifacts(JsonSerializeFormat & handler, const std::string & fieldName, CMap * map)

+ 5 - 5
lib/CArtifactInstance.cpp

@@ -184,17 +184,17 @@ bool CArtifactInstance::isScroll() const
 	return getType()->isScroll();
 }
 
-void CArtifactInstance::attachToBonusSystem(CGameState * gs)
+void CArtifactInstance::attachToBonusSystem(CGameState & gs)
 {
 	for(PartInfo & part : partsInfo)
-		attachToSource(*gs->getArtInstance(part.artifactID));
+		attachToSource(*gs.getArtInstance(part.artifactID));
 }
 
 void CArtifactInstance::saveCompatibilityFixArtifactID(std::shared_ptr<CArtifactInstance> self)
 {
-	self->cb->gameState()->saveCompatibilityLastAllocatedArtifactID = ArtifactInstanceID(self->cb->gameState()->saveCompatibilityLastAllocatedArtifactID.getNum()+1);
-	self->id = self->cb->gameState()->saveCompatibilityLastAllocatedArtifactID;
-	self->cb->gameState()->saveCompatibilityUnregisteredArtifacts.push_back(self);
+	self->cb->gameState().saveCompatibilityLastAllocatedArtifactID = ArtifactInstanceID(self->cb->gameState().saveCompatibilityLastAllocatedArtifactID.getNum()+1);
+	self->id = self->cb->gameState().saveCompatibilityLastAllocatedArtifactID;
+	self->cb->gameState().saveCompatibilityUnregisteredArtifacts.push_back(self);
 }
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 1
lib/CArtifactInstance.h

@@ -92,7 +92,7 @@ public:
 	bool isCombined() const;
 	bool isScroll() const;
 	
-	void attachToBonusSystem(CGameState * gs);
+	void attachToBonusSystem(CGameState & gs);
 
 	template <typename Handler> void serialize(Handler & h)
 	{

+ 1 - 1
lib/CArtifactSet.h

@@ -80,7 +80,7 @@ public:
 		h & artifactsWorn;
 	}
 
-	void artDeserializationFix(CGameState * gs, CBonusSystemNode *node);
+	void artDeserializationFix(CGameState & gs, CBonusSystemNode *node);
 
 	void serializeJsonArtifacts(JsonSerializeFormat & handler, const std::string & fieldName, CMap * map);
 	const CArtifactInstance * getCombinedArtWithPart(const ArtifactID & partId) const;

+ 1 - 1
lib/CCreatureSet.cpp

@@ -776,7 +776,7 @@ ImagePath CStackInstance::bonusToGraphics(const std::shared_ptr<Bonus> & bonus)
 CArmedInstance * CStackInstance::getArmy()
 {
 	if (armyInstanceID.hasValue())
-		return dynamic_cast<CArmedInstance*>(cb->gameState()->getObjInstance(armyInstanceID));
+		return dynamic_cast<CArmedInstance*>(cb->gameState().getObjInstance(armyInstanceID));
 	return nullptr;
 }
 

+ 79 - 79
lib/CGameInfoCallback.cpp

@@ -53,22 +53,22 @@ int CGameInfoCallback::getResource(PlayerColor Player, GameResID which) const
 
 const PlayerSettings * CGameInfoCallback::getPlayerSettings(PlayerColor color) const
 {
-	return &gameState()->getStartInfo()->getIthPlayersSettings(color);
+	return &gameState().getStartInfo()->getIthPlayersSettings(color);
 }
 
 bool CGameInfoCallback::isAllowed(SpellID id) const
 {
-	return gameState()->getMap().allowedSpells.count(id) != 0;
+	return gameState().getMap().allowedSpells.count(id) != 0;
 }
 
 bool CGameInfoCallback::isAllowed(ArtifactID id) const
 {
-	return gameState()->getMap().allowedArtifact.count(id) != 0;
+	return gameState().getMap().allowedArtifact.count(id) != 0;
 }
 
 bool CGameInfoCallback::isAllowed(SecondarySkill id) const
 {
-	return gameState()->getMap().allowedAbilities.count(id) != 0;
+	return gameState().getMap().allowedAbilities.count(id) != 0;
 }
 
 std::optional<PlayerColor> CGameInfoCallback::getPlayerID() const
@@ -89,8 +89,8 @@ const PlayerState * CGameInfoCallback::getPlayerState(PlayerColor color, bool ve
 	{
 		return nullptr;
 	}
-	auto player = gameState()->players.find(color);
-	if (player != gameState()->players.end())
+	auto player = gameState().players.find(color);
+	if (player != gameState().players.end())
 	{
 		if (hasAccess(color))
 			return &player->second;
@@ -116,8 +116,8 @@ TurnTimerInfo CGameInfoCallback::getPlayerTurnTime(PlayerColor color) const
 		return TurnTimerInfo{};
 	}
 	
-	auto player = gameState()->players.find(color);
-	if(player != gameState()->players.end())
+	auto player = gameState().players.find(color);
+	if(player != gameState().players.end())
 	{
 		return player->second.turnTimer;
 	}
@@ -138,7 +138,7 @@ const CGObjectInstance* CGameInfoCallback::getObj(ObjectInstanceID objid, bool v
 		return nullptr;
 	}
 
-	const CGObjectInstance *ret = gameState()->getMap().getObject(objid);
+	const CGObjectInstance *ret = gameState().getMap().getObject(objid);
 	if(!ret)
 	{
 		if(verbose)
@@ -184,29 +184,29 @@ const IMarket * CGameInfoCallback::getMarket(ObjectInstanceID objid) const
 
 void CGameInfoCallback::fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo & out) const
 {
-	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
+	//std::shared_lock<std::shared_mutex> lock(*gameState().mx);
 	ERROR_RET_IF(!canGetFullInfo(obj), "Cannot get info about not owned object!");
 	ERROR_RET_IF(!obj->hasStackAtSlot(stackPos), "There is no such stack!");
-	gameState()->fillUpgradeInfo(obj, stackPos, out);
-	//return gameState()->fillUpgradeInfo(obj->getStack(stackPos));
+	gameState().fillUpgradeInfo(obj, stackPos, out);
+	//return gameState().fillUpgradeInfo(obj->getStack(stackPos));
 }
 
 const StartInfo * CGameInfoCallback::getStartInfo() const
 {
-	return gameState()->getStartInfo();
+	return gameState().getStartInfo();
 }
 
 const StartInfo * CGameInfoCallback::getInitialStartInfo() const
 {
-	return gameState()->getInitialStartInfo();
+	return gameState().getInitialStartInfo();
 }
 
 int32_t CGameInfoCallback::getSpellCost(const spells::Spell * sp, const CGHeroInstance * caster) const
 {
-	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
+	//std::shared_lock<std::shared_mutex> lock(*gameState().mx);
 	ERROR_RET_VAL_IF(!canGetFullInfo(caster), "Cannot get info about caster!", -1);
 	//if there is a battle
-	auto casterBattle = gameState()->getBattle(caster->getOwner());
+	auto casterBattle = gameState().getBattle(caster->getOwner());
 
 	if(casterBattle)
 		return casterBattle->battleGetSpellCost(sp, caster);
@@ -217,7 +217,7 @@ int32_t CGameInfoCallback::getSpellCost(const spells::Spell * sp, const CGHeroIn
 
 int64_t CGameInfoCallback::estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const
 {
-	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
+	//std::shared_lock<std::shared_mutex> lock(*gameState().mx);
 
 	ERROR_RET_VAL_IF(hero && !canGetFullInfo(hero), "Cannot get info about caster!", -1);
 
@@ -229,26 +229,26 @@ int64_t CGameInfoCallback::estimateSpellDamage(const CSpell * sp, const CGHeroIn
 
 void CGameInfoCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj)
 {
-	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
+	//std::shared_lock<std::shared_mutex> lock(*gameState().mx);
 	ERROR_RET_IF(!obj, "No guild object!");
 	ERROR_RET_IF(obj->ID == Obj::TOWN && !canGetFullInfo(obj), "Cannot get info about town guild object!");
 	//TODO: advmap object -> check if they're visited by our hero
 
 	if(obj->ID == Obj::TOWN || obj->ID == Obj::TAVERN)
 	{
-		int taverns = gameState()->players.at(*getPlayerID()).valOfBonuses(BonusType::THIEVES_GUILD_ACCESS);
-		gameState()->obtainPlayersStats(thi, taverns);
+		int taverns = gameState().players.at(*getPlayerID()).valOfBonuses(BonusType::THIEVES_GUILD_ACCESS);
+		gameState().obtainPlayersStats(thi, taverns);
 	}
 	else if(obj->ID == Obj::DEN_OF_THIEVES)
 	{
-		gameState()->obtainPlayersStats(thi, 20);
+		gameState().obtainPlayersStats(thi, 20);
 	}
 }
 
 int CGameInfoCallback::howManyTowns(PlayerColor Player) const
 {
 	ERROR_RET_VAL_IF(!hasAccess(Player), "Access forbidden!", -1);
-	return static_cast<int>(gameState()->players.at(Player).getTowns().size());
+	return static_cast<int>(gameState().players.at(Player).getTowns().size());
 }
 
 bool CGameInfoCallback::getTownInfo(const CGObjectInstance * town, InfoAboutTown & dest, const CGObjectInstance * selectedObject) const
@@ -276,20 +276,20 @@ bool CGameInfoCallback::getTownInfo(const CGObjectInstance * town, InfoAboutTown
 
 const IGameSettings & CGameInfoCallback::getSettings() const
 {
-	return gameState()->getSettings();
+	return gameState().getSettings();
 }
 
 int3 CGameInfoCallback::guardingCreaturePosition (int3 pos) const //FIXME: redundant?
 {
 	ERROR_RET_VAL_IF(!isVisible(pos), "Tile is not visible!", int3(-1,-1,-1));
-	return gameState()->guardingCreaturePosition(pos);
+	return gameState().guardingCreaturePosition(pos);
 }
 
 std::vector<const CGObjectInstance*> CGameInfoCallback::getGuardingCreatures (int3 pos) const
 {
 	ERROR_RET_VAL_IF(!isVisible(pos), "Tile is not visible!", std::vector<const CGObjectInstance*>());
 	std::vector<const CGObjectInstance*> ret;
-	for(auto * cr : gameState()->guardingCreatures(pos))
+	for(auto * cr : gameState().guardingCreatures(pos))
 	{
 		ret.push_back(cr);
 	}
@@ -298,7 +298,7 @@ std::vector<const CGObjectInstance*> CGameInfoCallback::getGuardingCreatures (in
 
 bool CGameInfoCallback::isTileGuardedUnchecked(int3 tile) const
 {
-	return !gameState()->guardingCreatures(tile).empty();
+	return !gameState().guardingCreatures(tile).empty();
 }
 
 bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero & dest, const CGObjectInstance * selectedObject) const
@@ -314,7 +314,7 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
 
 	if (infoLevel == InfoAboutHero::EInfoLevel::BASIC)
 	{
-		auto ourBattle = gameState()->getBattle(*getPlayerID());
+		auto ourBattle = gameState().getBattle(*getPlayerID());
 
 		if(ourBattle && ourBattle->playerHasAccessToHeroInfo(*getPlayerID(), h)) //if it's battle we can get enemy hero full data
 			infoLevel = InfoAboutHero::EInfoLevel::INBATTLE;
@@ -419,14 +419,14 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
 
 int CGameInfoCallback::getDate(Date mode) const
 {
-	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
-	return gameState()->getDate(mode);
+	//std::shared_lock<std::shared_mutex> lock(*gameState().mx);
+	return gameState().getDate(mode);
 }
 
 bool CGameInfoCallback::isVisible(int3 pos, const std::optional<PlayerColor> & Player) const
 {
-	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
-	return gameState()->isVisible(pos, Player);
+	//std::shared_lock<std::shared_mutex> lock(*gameState().mx);
+	return gameState().isVisible(pos, Player);
 }
 
 bool CGameInfoCallback::isVisible(int3 pos) const
@@ -436,7 +436,7 @@ bool CGameInfoCallback::isVisible(int3 pos) const
 
 bool CGameInfoCallback::isVisible(const CGObjectInstance * obj, const std::optional<PlayerColor> & Player) const
 {
-	return gameState()->isVisible(obj, Player);
+	return gameState().isVisible(obj, Player);
 }
 
 bool CGameInfoCallback::isVisible(const CGObjectInstance *obj) const
@@ -476,7 +476,7 @@ std::vector <const CGObjectInstance *> CGameInfoCallback::getVisitableObjs(int3
 std::vector<const CGObjectInstance *> CGameInfoCallback::getAllVisitableObjs() const
 {
 	std::vector<const CGObjectInstance *> ret;
-	for(auto & obj : gameState()->getMap().getObjects())
+	for(auto & obj : gameState().getMap().getObjects())
 		if(obj->isVisitable() && obj->ID != Obj::EVENT && isVisible(obj))
 			ret.push_back(obj);
 
@@ -504,7 +504,7 @@ std::vector <const CGObjectInstance *> CGameInfoCallback::getFlaggableObjects(in
 
 int3 CGameInfoCallback::getMapSize() const
 {
-	return int3(gameState()->getMap().width, gameState()->getMap().height, gameState()->getMap().twoLevel ? 2 : 1);
+	return int3(gameState().getMap().width, gameState().getMap().height, gameState().getMap().twoLevel ? 2 : 1);
 }
 
 std::vector<const CGHeroInstance *> CGameInfoCallback::getAvailableHeroes(const CGObjectInstance * townOrTavern) const
@@ -516,7 +516,7 @@ std::vector<const CGHeroInstance *> CGameInfoCallback::getAvailableHeroes(const
 	const CGTownInstance * town = getTown(townOrTavern->id);
 
 	if(townOrTavern->ID == Obj::TAVERN || (town && town->hasBuilt(BuildingID::TAVERN)))
-		return gameState()->heroesPool->getHeroesFor(*getPlayerID());
+		return gameState().heroesPool->getHeroesFor(*getPlayerID());
 
 	return ret;
 }
@@ -524,7 +524,7 @@ std::vector<const CGHeroInstance *> CGameInfoCallback::getAvailableHeroes(const
 const TerrainTile * CGameInfoCallback::getTile(int3 tile, bool verbose) const
 {
 	if(isVisible(tile))
-		return &gameState()->getMap().getTile(tile);
+		return &gameState().getMap().getTile(tile);
 
 	if(verbose)
 		logGlobal->error("\r\n%s: %s\r\n", BOOST_CURRENT_FUNCTION, tile.toString() + " is not visible!");
@@ -534,7 +534,7 @@ const TerrainTile * CGameInfoCallback::getTile(int3 tile, bool verbose) const
 const TerrainTile * CGameInfoCallback::getTileUnchecked(int3 tile) const
 {
 	if (isInTheMap(tile))
-		return &gameState()->getMap().getTile(tile);
+		return &gameState().getMap().getTile(tile);
 
 	return nullptr;
 }
@@ -544,7 +544,7 @@ EDiggingStatus CGameInfoCallback::getTileDigStatus(int3 tile, bool verbose) cons
 	if(!isVisible(tile))
 		return EDiggingStatus::UNKNOWN;
 
-	for(const auto & object : gameState()->getMap().getObjects())
+	for(const auto & object : gameState().getMap().getObjects())
 	{
 		if(object->ID == Obj::HOLE && object->anchorPos() == tile)
 			return EDiggingStatus::TILE_OCCUPIED;
@@ -623,17 +623,17 @@ EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, Bu
 
 const CMapHeader * CGameInfoCallback::getMapHeader() const
 {
-	return &gameState()->getMap();
+	return &gameState().getMap();
 }
 
 bool CGameInfoCallback::hasAccess(std::optional<PlayerColor> playerId) const
 {
-	return !getPlayerID() || getPlayerID()->isSpectator() || gameState()->getPlayerRelations(*playerId, *getPlayerID()) != PlayerRelations::ENEMIES;
+	return !getPlayerID() || getPlayerID()->isSpectator() || gameState().getPlayerRelations(*playerId, *getPlayerID()) != PlayerRelations::ENEMIES;
 }
 
 EPlayerStatus CGameInfoCallback::getPlayerStatus(PlayerColor player, bool verbose) const
 {
-	const PlayerState *ps = gameState()->getPlayerState(player, verbose);
+	const PlayerState *ps = gameState().getPlayerState(player, verbose);
 	ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!ps, verbose, "No such player!", EPlayerStatus::WRONG);
 
 	return ps->status;
@@ -645,11 +645,11 @@ std::string CGameInfoCallback::getTavernRumor(const CGObjectInstance * townOrTav
 	text.appendLocalString(EMetaText::GENERAL_TXT, 216);
 	
 	std::string extraText;
-	if(gameState()->currentRumor.type == RumorState::TYPE_NONE)
+	if(gameState().currentRumor.type == RumorState::TYPE_NONE)
 		return text.toString();
 
-	auto rumor = gameState()->currentRumor.last.at(gameState()->currentRumor.type);
-	switch(gameState()->currentRumor.type)
+	auto rumor = gameState().currentRumor.last.at(gameState().currentRumor.type);
+	switch(gameState().currentRumor.type)
 	{
 	case RumorState::TYPE_SPECIAL:
 		text.replaceLocalString(EMetaText::GENERAL_TXT, rumor.first);
@@ -660,7 +660,7 @@ std::string CGameInfoCallback::getTavernRumor(const CGObjectInstance * townOrTav
 
 		break;
 	case RumorState::TYPE_MAP:
-		text.replaceRawString(gameState()->getMap().rumors[rumor.first].text.toString());
+		text.replaceRawString(gameState().getMap().rumors[rumor.first].text.toString());
 		break;
 
 	case RumorState::TYPE_RAND:
@@ -673,7 +673,7 @@ std::string CGameInfoCallback::getTavernRumor(const CGObjectInstance * townOrTav
 
 PlayerRelations CGameInfoCallback::getPlayerRelations( PlayerColor color1, PlayerColor color2 ) const
 {
-	return gameState()->getPlayerRelations(color1, color2);
+	return gameState().getPlayerRelations(color1, color2);
 }
 
 bool CGameInfoCallback::canGetFullInfo(const CGObjectInstance *obj) const
@@ -684,7 +684,7 @@ bool CGameInfoCallback::canGetFullInfo(const CGObjectInstance *obj) const
 int CGameInfoCallback::getHeroCount( PlayerColor player, bool includeGarrisoned ) const
 {
 	int ret = 0;
-	const PlayerState *p = gameState()->getPlayerState(player);
+	const PlayerState *p = gameState().getPlayerState(player);
 	ERROR_RET_VAL_IF(!p, "No such player!", -1);
 
 	if(includeGarrisoned)
@@ -709,21 +709,21 @@ bool CGameInfoCallback::isOwnedOrVisited(const CGObjectInstance *obj) const
 
 bool CGameInfoCallback::isPlayerMakingTurn(PlayerColor player) const
 {
-	return gameState()->actingPlayers.count(player);
+	return gameState().actingPlayers.count(player);
 }
 
 int CPlayerSpecificInfoCallback::howManyTowns() const
 {
-	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
+	//std::shared_lock<std::shared_mutex> lock(*gameState().mx);
 	ERROR_RET_VAL_IF(!getPlayerID(), "Applicable only for player callbacks", -1);
 	return CGameInfoCallback::howManyTowns(*getPlayerID());
 }
 
 std::vector < const CGTownInstance *> CPlayerSpecificInfoCallback::getTownsInfo(bool onlyOur) const
 {
-	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
+	//std::shared_lock<std::shared_mutex> lock(*gameState().mx);
 	auto ret = std::vector < const CGTownInstance *>();
-	for(const auto & i : gameState()->players)
+	for(const auto & i : gameState().players)
 	{
 		for(const auto & town : i.second.getTowns())
 		{
@@ -732,12 +732,12 @@ std::vector < const CGTownInstance *> CPlayerSpecificInfoCallback::getTownsInfo(
 				ret.push_back(town);
 			}
 		}
-	} //	for ( std::map<int, PlayerState>::iterator i=gameState()->players.begin() ; i!=gameState()->players.end();i++)
+	} //	for ( std::map<int, PlayerState>::iterator i=gameState().players.begin() ; i!=gameState().players.end();i++)
 	return ret;
 }
 std::vector < const CGHeroInstance *> CPlayerSpecificInfoCallback::getHeroesInfo() const
 {
-	const auto * playerState = gameState()->getPlayerState(*getPlayerID());
+	const auto * playerState = gameState().getPlayerState(*getPlayerID());
 	return playerState->getHeroes();
 }
 
@@ -747,7 +747,7 @@ int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool
 		return -1;
 
 	size_t index = 0;
-	const auto & heroes = gameState()->players.at(*getPlayerID()).getHeroes();
+	const auto & heroes = gameState().players.at(*getPlayerID()).getHeroes();
 
 	for (auto & possibleHero : heroes)
 	{
@@ -762,35 +762,35 @@ int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool
 
 int3 CPlayerSpecificInfoCallback::getGrailPos( double *outKnownRatio )
 {
-	if (!getPlayerID() || gameState()->getMap().obeliskCount == 0)
+	if (!getPlayerID() || gameState().getMap().obeliskCount == 0)
 	{
 		*outKnownRatio = 0.0;
 	}
 	else
 	{
-		TeamID t = gameState()->getPlayerTeam(*getPlayerID())->id;
+		TeamID t = gameState().getPlayerTeam(*getPlayerID())->id;
 		double visited = 0.0;
-		if(gameState()->getMap().obelisksVisited.count(t))
-			visited = static_cast<double>(gameState()->getMap().obelisksVisited[t]);
+		if(gameState().getMap().obelisksVisited.count(t))
+			visited = static_cast<double>(gameState().getMap().obelisksVisited[t]);
 
-		*outKnownRatio = visited / gameState()->getMap().obeliskCount;
+		*outKnownRatio = visited / gameState().getMap().obeliskCount;
 	}
-	return gameState()->getMap().grailPos;
+	return gameState().getMap().grailPos;
 }
 
 std::vector < const CGObjectInstance * > CPlayerSpecificInfoCallback::getMyObjects() const
 {
-	return gameState()->getPlayerState(*getPlayerID())->getOwnedObjects();
+	return gameState().getPlayerState(*getPlayerID())->getOwnedObjects();
 }
 
 std::vector <QuestInfo> CPlayerSpecificInfoCallback::getMyQuests() const
 {
-	return gameState()->getPlayerState(*getPlayerID())->quests;
+	return gameState().getPlayerState(*getPlayerID())->quests;
 }
 
 int CPlayerSpecificInfoCallback::howManyHeroes(bool includeGarrisoned) const
 {
-	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
+	//std::shared_lock<std::shared_mutex> lock(*gameState().mx);
 	ERROR_RET_VAL_IF(!getPlayerID(), "Applicable only for player callbacks", -1);
 	return getHeroCount(*getPlayerID(), includeGarrisoned);
 }
@@ -822,24 +822,24 @@ const CGTownInstance* CPlayerSpecificInfoCallback::getTownBySerial(int serialId)
 
 int CPlayerSpecificInfoCallback::getResourceAmount(GameResID type) const
 {
-	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
+	//std::shared_lock<std::shared_mutex> lock(*gameState().mx);
 	ERROR_RET_VAL_IF(!getPlayerID(), "Applicable only for player callbacks", -1);
 	return getResource(*getPlayerID(), type);
 }
 
 TResources CPlayerSpecificInfoCallback::getResourceAmount() const
 {
-	//std::shared_lock<std::shared_mutex> lock(*gameState()->mx);
+	//std::shared_lock<std::shared_mutex> lock(*gameState().mx);
 	ERROR_RET_VAL_IF(!getPlayerID(), "Applicable only for player callbacks", TResources());
-	return gameState()->players.at(*getPlayerID()).resources;
+	return gameState().players.at(*getPlayerID()).resources;
 }
 
 const TeamState * CGameInfoCallback::getTeam( TeamID teamID ) const
 {
 	//rewritten by hand, AI calls this function a lot
 
-	auto team = gameState()->teams.find(teamID);
-	if (team != gameState()->teams.end())
+	auto team = gameState().teams.find(teamID);
+	if (team != gameState().teams.end())
 	{
 		const TeamState *ret = &team->second;
 		if(!getPlayerID().has_value()) //neutral (or invalid) player
@@ -864,8 +864,8 @@ const TeamState * CGameInfoCallback::getTeam( TeamID teamID ) const
 
 const TeamState * CGameInfoCallback::getPlayerTeam( PlayerColor color ) const
 {
-	auto player = gameState()->players.find(color);
-	if (player != gameState()->players.end())
+	auto player = gameState().players.find(color);
+	if (player != gameState().players.end())
 	{
 		return getTeam (player->second.team);
 	}
@@ -877,33 +877,33 @@ const TeamState * CGameInfoCallback::getPlayerTeam( PlayerColor color ) const
 
 bool CGameInfoCallback::isInTheMap(const int3 &pos) const
 {
-	return gameState()->getMap().isInTheMap(pos);
+	return gameState().getMap().isInTheMap(pos);
 }
 
 void CGameInfoCallback::getVisibleTilesInRange(std::unordered_set<int3> &tiles, int3 pos, int radious, int3::EDistanceFormula distanceFormula) const
 {
-	gameState()->getTilesInRange(tiles, pos, radious, ETileVisibility::REVEALED, *getPlayerID(),  distanceFormula);
+	gameState().getTilesInRange(tiles, pos, radious, ETileVisibility::REVEALED, *getPlayerID(),  distanceFormula);
 }
 
 void CGameInfoCallback::calculatePaths(const std::shared_ptr<PathfinderConfig> & config) const
 {
-	gameState()->calculatePaths(config);
+	gameState().calculatePaths(config);
 }
 
 const CArtifactInstance * CGameInfoCallback::getArtInstance( ArtifactInstanceID aid ) const
 {
-	return gameState()->getMap().getArtifactInstance(aid);
+	return gameState().getMap().getArtifactInstance(aid);
 }
 
 const CGObjectInstance * CGameInfoCallback::getObjInstance( ObjectInstanceID oid ) const
 {
-	return gameState()->getMap().getObject((oid));
+	return gameState().getMap().getObject((oid));
 }
 
 const CArtifactSet * CGameInfoCallback::getArtSet(const ArtifactLocation & loc) const
 {
-	auto gs = const_cast<CGameState*>(gameState());
-	return gs->getArtSet(loc);
+	auto & gs = const_cast<CGameState&>(gameState());
+	return gs.getArtSet(loc);
 }
 
 std::vector<ObjectInstanceID> CGameInfoCallback::getVisibleTeleportObjects(std::vector<ObjectInstanceID> ids, PlayerColor player) const
@@ -918,12 +918,12 @@ std::vector<ObjectInstanceID> CGameInfoCallback::getVisibleTeleportObjects(std::
 
 std::vector<ObjectInstanceID> CGameInfoCallback::getTeleportChannelEntrances(TeleportChannelID id, PlayerColor player) const
 {
-	return getVisibleTeleportObjects(gameState()->getMap().teleportChannels.at(id)->entrances, player);
+	return getVisibleTeleportObjects(gameState().getMap().teleportChannels.at(id)->entrances, player);
 }
 
 std::vector<ObjectInstanceID> CGameInfoCallback::getTeleportChannelExits(TeleportChannelID id, PlayerColor player) const
 {
-	return getVisibleTeleportObjects(gameState()->getMap().teleportChannels.at(id)->exits, player);
+	return getVisibleTeleportObjects(gameState().getMap().teleportChannels.at(id)->exits, player);
 }
 
 ETeleportChannelType CGameInfoCallback::getTeleportChannelType(TeleportChannelID id, PlayerColor player) const

+ 2 - 2
lib/CGameInfoCallback.h

@@ -132,8 +132,8 @@ public:
 class DLL_LINKAGE CGameInfoCallback : public IGameInfoCallback
 {
 protected:
-	virtual CGameState * gameState() = 0;
-	virtual const CGameState * gameState() const = 0;
+	virtual CGameState & gameState() = 0;
+	virtual const CGameState & gameState() const = 0;
 
 	bool hasAccess(std::optional<PlayerColor> playerId) const;
 

+ 1 - 1
lib/CPlayerState.cpp

@@ -107,7 +107,7 @@ std::vector<T> PlayerState::getObjectsOfType() const
 	std::vector<T> result;
 	for (const ObjectInstanceID & objectID : ownedObjects)
 	{
-		auto objectPtr = cb->gameState()->getObjInstance(objectID);
+		auto objectPtr = cb->gameState().getObjInstance(objectID);
 		auto casted = dynamic_cast<T>(objectPtr);
 		if (casted)
 			result.push_back(casted);

+ 18 - 18
lib/IGameCallback.cpp

@@ -58,17 +58,17 @@ VCMI_LIB_NAMESPACE_BEGIN
 void CPrivilegedInfoCallback::getFreeTiles(std::vector<int3> & tiles) const
 {
 	std::vector<int> floors;
-	floors.reserve(gameState()->getMap().levels());
-	for(int b = 0; b < gameState()->getMap().levels(); ++b)
+	floors.reserve(gameState().getMap().levels());
+	for(int b = 0; b < gameState().getMap().levels(); ++b)
 	{
 		floors.push_back(b);
 	}
 	const TerrainTile * tinfo = nullptr;
 	for (auto zd : floors)
 	{
-		for (int xd = 0; xd < gameState()->getMap().width; xd++)
+		for (int xd = 0; xd < gameState().getMap().width; xd++)
 		{
-			for (int yd = 0; yd < gameState()->getMap().height; yd++)
+			for (int yd = 0; yd < gameState().getMap().height; yd++)
 			{
 				tinfo = getTile(int3 (xd,yd,zd));
 				if (tinfo->isLand() && tinfo->getTerrain()->isPassable() && !tinfo->blocked()) //land and free
@@ -94,10 +94,10 @@ void CPrivilegedInfoCallback::getTilesInRange(std::unordered_set<int3> & tiles,
 		getAllTiles (tiles, player, -1, [](auto * tile){return true;});
 	else
 	{
-		const TeamState * team = !player ? nullptr : gameState()->getPlayerTeam(*player);
-		for (int xd = std::max<int>(pos.x - radious , 0); xd <= std::min<int>(pos.x + radious, gameState()->getMap().width - 1); xd++)
+		const TeamState * team = !player ? nullptr : gameState().getPlayerTeam(*player);
+		for (int xd = std::max<int>(pos.x - radious , 0); xd <= std::min<int>(pos.x + radious, gameState().getMap().width - 1); xd++)
 		{
-			for (int yd = std::max<int>(pos.y - radious, 0); yd <= std::min<int>(pos.y + radious, gameState()->getMap().height - 1); yd++)
+			for (int yd = std::max<int>(pos.y - radious, 0); yd <= std::min<int>(pos.y + radious, gameState().getMap().height - 1); yd++)
 			{
 				int3 tilePos(xd,yd,pos.z);
 				int distance = pos.dist(tilePos, distanceFormula);
@@ -126,7 +126,7 @@ void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3> & tiles, std:
 	std::vector<int> floors;
 	if(level == -1)
 	{
-		for(int b = 0; b < gameState()->getMap().levels(); ++b)
+		for(int b = 0; b < gameState().getMap().levels(); ++b)
 		{
 			floors.push_back(b);
 		}
@@ -136,9 +136,9 @@ void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3> & tiles, std:
 
 	for(auto zd: floors)
 	{
-		for(int xd = 0; xd < gameState()->getMap().width; xd++)
+		for(int xd = 0; xd < gameState().getMap().width; xd++)
 		{
-			for(int yd = 0; yd < gameState()->getMap().height; yd++)
+			for(int yd = 0; yd < gameState().getMap().height; yd++)
 			{
 				int3 coordinates(xd, yd, zd);
 				if (filter(getTile(coordinates)))
@@ -151,16 +151,16 @@ void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3> & tiles, std:
 void CPrivilegedInfoCallback::pickAllowedArtsSet(std::vector<ArtifactID> & out, vstd::RNG & rand)
 {
 	for (int j = 0; j < 3 ; j++)
-		out.push_back(gameState()->pickRandomArtifact(rand, CArtifact::ART_TREASURE));
+		out.push_back(gameState().pickRandomArtifact(rand, CArtifact::ART_TREASURE));
 	for (int j = 0; j < 3 ; j++)
-		out.push_back(gameState()->pickRandomArtifact(rand, CArtifact::ART_MINOR));
+		out.push_back(gameState().pickRandomArtifact(rand, CArtifact::ART_MINOR));
 
-	out.push_back(gameState()->pickRandomArtifact(rand, CArtifact::ART_MAJOR));
+	out.push_back(gameState().pickRandomArtifact(rand, CArtifact::ART_MAJOR));
 }
 
 void CPrivilegedInfoCallback::getAllowedSpells(std::vector<SpellID> & out, std::optional<ui16> level)
 {
-	for (auto const & spellID : gameState()->getMap().allowedSpells)
+	for (auto const & spellID : gameState().getMap().allowedSpells)
 	{
 		const auto * spell = spellID.toEntity(LIBRARY);
 
@@ -176,9 +176,9 @@ void CPrivilegedInfoCallback::getAllowedSpells(std::vector<SpellID> & out, std::
 
 TerrainTile * CNonConstInfoCallback::getTile(const int3 & pos)
 {
-	if(!gameState()->getMap().isInTheMap(pos))
+	if(!gameState().getMap().isInTheMap(pos))
 		return nullptr;
-	return &gameState()->getMap().getTile(pos);
+	return &gameState().getMap().getTile(pos);
 }
 
 CGHeroInstance * CNonConstInfoCallback::getHero(const ObjectInstanceID & objid)
@@ -208,12 +208,12 @@ PlayerState * CNonConstInfoCallback::getPlayerState(const PlayerColor & color, b
 
 CArtifactInstance * CNonConstInfoCallback::getArtInstance(const ArtifactInstanceID & aid)
 {
-	return gameState()->getMap().getArtifactInstance(aid);
+	return gameState().getMap().getArtifactInstance(aid);
 }
 
 CGObjectInstance * CNonConstInfoCallback::getObjInstance(const ObjectInstanceID & oid)
 {
-	return gameState()->getMap().getObject(oid);
+	return gameState().getMap().getObject(oid);
 }
 
 CArmedInstance * CNonConstInfoCallback::getArmyInstance(const ObjectInstanceID & oid)

+ 6 - 6
lib/gameState/CGameState.cpp

@@ -1119,7 +1119,7 @@ void CGameState::apply(CPackForClient & pack)
 
 void CGameState::calculatePaths(const std::shared_ptr<PathfinderConfig> & config) const
 {
-	CPathfinder pathfinder(const_cast<CGameState*>(this), config);
+	CPathfinder pathfinder(*const_cast<CGameState*>(this), config);
 	pathfinder.calculatePaths();
 }
 
@@ -1563,10 +1563,10 @@ void CGameState::buildBonusSystemTree()
 {
 	buildGlobalTeamPlayerTree();
 	for(auto & armed : map->getObjects<CArmedInstance>())
-		armed->attachToBonusSystem(this);
+		armed->attachToBonusSystem(*this);
 
 	for(auto & art : map->getArtifacts())
-		art->attachToBonusSystem(this);
+		art->attachToBonusSystem(*this);
 }
 
 void CGameState::restoreBonusSystemTree()
@@ -1575,13 +1575,13 @@ void CGameState::restoreBonusSystemTree()
 
 	buildGlobalTeamPlayerTree();
 	for(auto & armed : map->getObjects<CArmedInstance>())
-		armed->restoreBonusSystem(this);
+		armed->restoreBonusSystem(*this);
 
 	for(auto & art : map->getArtifacts())
-		art->attachToBonusSystem(this);
+		art->attachToBonusSystem(*this);
 
 	for(auto & heroID : map->getHeroesInPool())
-		map->tryGetFromHeroPool(heroID)->artDeserializationFix(this, map->tryGetFromHeroPool(heroID));
+		map->tryGetFromHeroPool(heroID)->artDeserializationFix(*this, map->tryGetFromHeroPool(heroID));
 
 	if (campaign)
 		campaign->setGamestate(this);

+ 2 - 2
lib/gameState/CGameState.h

@@ -75,8 +75,8 @@ public:
 	CGameState(IGameCallback * callback);
 	virtual ~CGameState();
 
-	CGameState * gameState() final { return this; }
-	const CGameState * gameState() const final { return this; }
+	CGameState & gameState() final { return *this; }
+	const CGameState & gameState() const final { return *this; }
 
 	void preInit(Services * services);
 

+ 1 - 1
lib/json/JsonRandom.cpp

@@ -407,7 +407,7 @@ JsonRandomizationException::JsonRandomizationException(const std::string & messa
 
 		std::set<ArtifactID> potentialPicks = filterKeys(value, allowedArts, variables);
 
-		return cb->gameState()->pickRandomArtifact(rng, potentialPicks);
+		return cb->gameState().pickRandomArtifact(rng, potentialPicks);
 	}
 
 	std::vector<ArtifactID> JsonRandom::loadArtifacts(const JsonNode & value, vstd::RNG & rng, const Variables & variables)

+ 6 - 6
lib/mapObjects/CArmedInstance.cpp

@@ -139,13 +139,13 @@ void CArmedInstance::armyChanged()
 	updateMoraleBonusFromArmy();
 }
 
-CBonusSystemNode & CArmedInstance::whereShouldBeAttached(CGameState * gs)
+CBonusSystemNode & CArmedInstance::whereShouldBeAttached(CGameState & gs)
 {
 	if(tempOwner.isValidPlayer())
-		if(auto * where = gs->getPlayerState(tempOwner))
+		if(auto * where = gs.getPlayerState(tempOwner))
 			return *where;
 
-	return gs->globalEffects;
+	return gs.globalEffects;
 }
 
 CBonusSystemNode & CArmedInstance::whatShouldBeAttached()
@@ -153,19 +153,19 @@ CBonusSystemNode & CArmedInstance::whatShouldBeAttached()
 	return *this;
 }
 
-void CArmedInstance::attachToBonusSystem(CGameState * gs)
+void CArmedInstance::attachToBonusSystem(CGameState & gs)
 {
 	whatShouldBeAttached().attachTo(whereShouldBeAttached(gs));
 }
 
-void CArmedInstance::restoreBonusSystem(CGameState * gs)
+void CArmedInstance::restoreBonusSystem(CGameState & gs)
 {
 	whatShouldBeAttached().attachTo(whereShouldBeAttached(gs));
 	for(const auto & elem : stacks)
 		elem.second->artDeserializationFix(gs, elem.second.get());
 }
 
-void CArmedInstance::detachFromBonusSystem(CGameState * gs)
+void CArmedInstance::detachFromBonusSystem(CGameState & gs)
 {
 	whatShouldBeAttached().detachFrom(whereShouldBeAttached(gs));
 }

+ 4 - 4
lib/mapObjects/CArmedInstance.h

@@ -28,7 +28,7 @@ private:
 	void attachUnitsToArmy();
 
 protected:
-	virtual CBonusSystemNode & whereShouldBeAttached(CGameState * gs);
+	virtual CBonusSystemNode & whereShouldBeAttached(CGameState & gs);
 	virtual CBonusSystemNode & whatShouldBeAttached();
 
 public:
@@ -45,9 +45,9 @@ public:
 	//IConstBonusProvider
 	const IBonusBearer* getBonusBearer() const override;
 
-	void attachToBonusSystem(CGameState * gs) override;
-	void detachFromBonusSystem(CGameState * gs) override;
-	void restoreBonusSystem(CGameState * gs) override;
+	void attachToBonusSystem(CGameState & gs) override;
+	void detachFromBonusSystem(CGameState & gs) override;
+	void restoreBonusSystem(CGameState & gs) override;
 	//////////////////////////////////////////////////////////////////////////
 
 	CArmedInstance(IGameCallback *cb);

+ 1 - 1
lib/mapObjects/CGCreature.cpp

@@ -492,7 +492,7 @@ void CGCreature::fight( const CGHeroInstance *h ) const
 			const auto & upgrades = getStack(slotID).getCreature()->upgrades;
 			if(!upgrades.empty())
 			{
-				auto it = RandomGeneratorUtil::nextItem(upgrades, cb->gameState()->getRandomGenerator());
+				auto it = RandomGeneratorUtil::nextItem(upgrades, cb->gameState().getRandomGenerator());
 				cb->changeStackType(StackLocation(id, slotID), it->toCreature());
 			}
 		}

+ 5 - 5
lib/mapObjects/CGDwelling.cpp

@@ -66,18 +66,18 @@ FactionID CGDwelling::randomizeFaction(vstd::RNG & rand)
 
 	if (!randomizationInfo->instanceId.empty())
 	{
-		auto iter = cb->gameState()->getMap().instanceNames.find(randomizationInfo->instanceId);
+		auto iter = cb->gameState().getMap().instanceNames.find(randomizationInfo->instanceId);
 
-		if(iter == cb->gameState()->getMap().instanceNames.end())
+		if(iter == cb->gameState().getMap().instanceNames.end())
 			logGlobal->error("Map object not found: %s", randomizationInfo->instanceId);
 		linkedTown = dynamic_cast<CGTownInstance *>(iter->second.get());
 	}
 
 	if (randomizationInfo->identifier != 0)
 	{
-		for(auto & townID : cb->gameState()->getMap().getAllTowns())
+		for(auto & townID : cb->gameState().getMap().getAllTowns())
 		{
-			auto town = cb->gameState()->getTown(townID);
+			auto town = cb->gameState().getTown(townID);
 			if(town && town->identifier == randomizationInfo->identifier)
 			{
 				linkedTown = town;
@@ -222,7 +222,7 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
 		return;
 	}
 
-	PlayerRelations relations = cb->gameState()->getPlayerRelations( h->tempOwner, tempOwner );
+	PlayerRelations relations = cb->gameState().getPlayerRelations( h->tempOwner, tempOwner );
 
 	if ( relations == PlayerRelations::ALLIES )
 		return;//do not allow recruiting or capturing

+ 20 - 20
lib/mapObjects/CGHeroInstance.cpp

@@ -327,7 +327,7 @@ CGTownInstance * CGHeroInstance::getVisitedTown()
 	if (!visitedTown.hasValue())
 		return nullptr;
 
-	return dynamic_cast<CGTownInstance*>(cb->gameState()->getObjInstance(visitedTown));
+	return dynamic_cast<CGTownInstance*>(cb->gameState().getObjInstance(visitedTown));
 }
 
 void CGHeroInstance::setVisitedTown(const CGTownInstance * town, bool garrisoned)
@@ -373,7 +373,7 @@ TObjectTypeHandler CGHeroInstance::getObjectHandler() const
 void CGHeroInstance::updateAppearance()
 {
 	auto handler = LIBRARY->objtypeh->getHandlerFor(Obj::HERO, getHeroClass()->getIndex());
-	auto terrain = cb->gameState()->getTile(visitablePos())->getTerrainID();
+	auto terrain = cb->gameState().getTile(visitablePos())->getTerrainID();
 	auto app = handler->getOverride(terrain, this);
 	if (app)
 		appearance = app;
@@ -406,7 +406,7 @@ void CGHeroInstance::initHero(vstd::RNG & rand)
 		// hero starts with default spellbook presence status
 		if(!getArt(ArtifactPosition::SPELLBOOK) && getHeroType()->haveSpellBook)
 		{
-			auto artifact = cb->gameState()->createArtifact(ArtifactID::SPELLBOOK);
+			auto artifact = cb->gameState().createArtifact(ArtifactID::SPELLBOOK);
 			putArtifact(ArtifactPosition::SPELLBOOK, artifact);
 		}
 	}
@@ -415,7 +415,7 @@ void CGHeroInstance::initHero(vstd::RNG & rand)
 
 	if(!getArt(ArtifactPosition::MACH4))
 	{
-		auto artifact = cb->gameState()->createArtifact(ArtifactID::CATAPULT);
+		auto artifact = cb->gameState().createArtifact(ArtifactID::CATAPULT);
 		putArtifact(ArtifactPosition::MACH4, artifact); //everyone has a catapult
 	}
 
@@ -528,7 +528,7 @@ void CGHeroInstance::initArmy(vstd::RNG & rand, IArmyDescriptor * dst)
 
 				if(!getArt(slot))
 				{
-					auto artifact = cb->gameState()->createArtifact(aid);
+					auto artifact = cb->gameState().createArtifact(aid);
 					putArtifact(slot, artifact);
 				}
 				else
@@ -559,7 +559,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 
 	if (ID == Obj::HERO)
 	{
-		if( cb->gameState()->getPlayerRelations(tempOwner, h->tempOwner) != PlayerRelations::ENEMIES)
+		if( cb->gameState().getPlayerRelations(tempOwner, h->tempOwner) != PlayerRelations::ENEMIES)
 		{
 			//exchange
 			cb->heroExchange(h->id, id);
@@ -584,7 +584,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 			
 			ObjectInstanceID boatId;
 			const auto boatPos = visitablePos();
-			if (cb->gameState()->getMap().getTile(boatPos).isWater())
+			if (cb->gameState().getMap().getTile(boatPos).isWater())
 			{
 				smp.val = movementPointsLimit(false);
 				if (!inBoat())
@@ -672,7 +672,7 @@ void CGHeroInstance::pickRandomObject(vstd::RNG & rand)
 
 	if (ID == Obj::RANDOM_HERO)
 	{
-		auto selectedHero = cb->gameState()->pickNextHeroType(getOwner());
+		auto selectedHero = cb->gameState().pickNextHeroType(getOwner());
 
 		ID = Obj::HERO;
 		subID = selectedHero;
@@ -1282,7 +1282,7 @@ void CGHeroInstance::removeSpellbook()
 
 	if(hasSpellbook())
 	{
-		cb->gameState()->getMap().removeArtifactInstance(*this, ArtifactPosition::SPELLBOOK);
+		cb->gameState().getMap().removeArtifactInstance(*this, ArtifactPosition::SPELLBOOK);
 	}
 }
 
@@ -1311,7 +1311,7 @@ const CGBoat * CGHeroInstance::getBoat() const
 CGBoat * CGHeroInstance::getBoat()
 {
 	if (boardedBoat.hasValue())
-		return dynamic_cast<CGBoat*>(cb->gameState()->getObjInstance(boardedBoat));
+		return dynamic_cast<CGBoat*>(cb->gameState().getObjInstance(boardedBoat));
 	return nullptr;
 }
 
@@ -1332,35 +1332,35 @@ void CGHeroInstance::setBoat(CGBoat* newBoat)
 	}
 }
 
-void CGHeroInstance::restoreBonusSystem(CGameState * gs)
+void CGHeroInstance::restoreBonusSystem(CGameState & gs)
 {
 	CArmedInstance::restoreBonusSystem(gs);
 	artDeserializationFix(gs, this);
 	if (boardedBoat.hasValue())
 	{
-		auto boat = gs->getObjInstance(boardedBoat);
+		auto boat = gs.getObjInstance(boardedBoat);
 		if (boat)
 			attachTo(dynamic_cast<CGBoat&>(*boat));
 	}
 }
 
-void CGHeroInstance::attachToBonusSystem(CGameState * gs)
+void CGHeroInstance::attachToBonusSystem(CGameState & gs)
 {
 	CArmedInstance::attachToBonusSystem(gs);
 	if (boardedBoat.hasValue())
 	{
-		auto boat = gs->getObjInstance(boardedBoat);
+		auto boat = gs.getObjInstance(boardedBoat);
 		if (boat)
 			attachTo(dynamic_cast<CGBoat&>(*boat));
 	}
 }
 
-void CGHeroInstance::detachFromBonusSystem(CGameState * gs)
+void CGHeroInstance::detachFromBonusSystem(CGameState & gs)
 {
 	CArmedInstance::detachFromBonusSystem(gs);
 	if (boardedBoat.hasValue())
 	{
-		auto boat = gs->getObjInstance(boardedBoat);
+		auto boat = gs.getObjInstance(boardedBoat);
 		if (boat)
 			detachFrom(dynamic_cast<CGBoat&>(*boat));
 	}
@@ -1377,7 +1377,7 @@ CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(const bool isBat
 	return const_cast<CGTownInstance*>(getVisitedTown());
 }
 
-CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(CGameState * gs)
+CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(CGameState & gs)
 {
 	if(getVisitedTown())
 		return whereShouldBeAttachedOnSiege(getVisitedTown()->isBattleOutsideTown(this));
@@ -1385,11 +1385,11 @@ CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(CGameState * gs)
 	return &CArmedInstance::whereShouldBeAttached(gs);
 }
 
-CBonusSystemNode & CGHeroInstance::whereShouldBeAttached(CGameState * gs)
+CBonusSystemNode & CGHeroInstance::whereShouldBeAttached(CGameState & gs)
 {
 	if(visitedTown.hasValue())
 	{
-		auto town = gs->getTown(visitedTown);
+		auto town = gs.getTown(visitedTown);
 		if(isGarrisoned())
 			return *town;
 		else
@@ -1819,7 +1819,7 @@ void CGHeroInstance::serializeCommonOptions(JsonSerializeFormat & handler)
 	handler.serializeIdArray("spellBook", spells);
 
 	if(handler.saving)
-		CArtifactSet::serializeJsonArtifacts(handler, "artifacts", &cb->gameState()->getMap());
+		CArtifactSet::serializeJsonArtifacts(handler, "artifacts", &cb->gameState().getMap());
 }
 
 void CGHeroInstance::serializeJsonOptions(JsonSerializeFormat & handler)

+ 5 - 5
lib/mapObjects/CGHeroInstance.h

@@ -291,7 +291,7 @@ public:
 	ArtBearer::ArtBearer bearerType() const override;
 
 	///IBonusBearer
-	CBonusSystemNode & whereShouldBeAttached(CGameState * gs) override;
+	CBonusSystemNode & whereShouldBeAttached(CGameState & gs) override;
 	std::string nodeName() const override;
 	si32 manaLimit() const override;
 
@@ -299,7 +299,7 @@ public:
 	const IBonusBearer* getBonusBearer() const override;
 
 	CBonusSystemNode * whereShouldBeAttachedOnSiege(const bool isBattleOutsideTown) const;
-	CBonusSystemNode * whereShouldBeAttachedOnSiege(CGameState * gs);
+	CBonusSystemNode * whereShouldBeAttachedOnSiege(CGameState & gs);
 
 	///spells::Caster
 	int32_t getCasterUnitId() const override;
@@ -331,9 +331,9 @@ public:
 
 	void afterAddToMap(CMap * map) override;
 	void afterRemoveFromMap(CMap * map) override;
-	void attachToBonusSystem(CGameState * gs) override;
-	void detachFromBonusSystem(CGameState * gs) override;
-	void restoreBonusSystem(CGameState * gs) override;
+	void attachToBonusSystem(CGameState & gs) override;
+	void detachFromBonusSystem(CGameState & gs) override;
+	void restoreBonusSystem(CGameState & gs) override;
 
 	void updateFrom(const JsonNode & data) override;
 

+ 3 - 3
lib/mapObjects/CGObjectInstance.cpp

@@ -122,10 +122,10 @@ void CGObjectInstance::setType(MapObjectID newID, MapObjectSubID newSubID)
 {
 	auto position = visitablePos();
 	auto oldOffset = getVisitableOffset();
-	auto &tile = cb->gameState()->getMap().getTile(position);
+	auto &tile = cb->gameState().getMap().getTile(position);
 
 	//recalculate blockvis tiles - new appearance might have different blockmap than before
-	cb->gameState()->getMap().hideObject(this);
+	cb->gameState().getMap().hideObject(this);
 	auto handler = LIBRARY->objtypeh->getHandlerFor(newID, newSubID);
 
 	if(!handler->getTemplates(tile.getTerrainID()).empty())
@@ -155,7 +155,7 @@ void CGObjectInstance::setType(MapObjectID newID, MapObjectSubID newSubID)
 	this->ID = Obj(newID);
 	this->subID = newSubID;
 
-	cb->gameState()->getMap().showObject(this);
+	cb->gameState().getMap().showObject(this);
 }
 
 void CGObjectInstance::pickRandomObject(vstd::RNG & rand)

+ 3 - 3
lib/mapObjects/CGObjectInstance.h

@@ -139,9 +139,9 @@ public:
 
 	virtual void afterAddToMap(CMap * map){};
 	virtual void afterRemoveFromMap(CMap * map){};
-	virtual void attachToBonusSystem(CGameState * gs){};
-	virtual void detachFromBonusSystem(CGameState * gs){};
-	virtual void restoreBonusSystem(CGameState * gs){};
+	virtual void attachToBonusSystem(CGameState & gs){};
+	virtual void detachFromBonusSystem(CGameState & gs){};
+	virtual void restoreBonusSystem(CGameState & gs){};
 
 	///Entry point of binary (de-)serialization
 	template <typename Handler> void serialize(Handler &h)

+ 1 - 1
lib/mapObjects/CGResource.cpp

@@ -108,7 +108,7 @@ void CGResource::collectRes(const PlayerColor & player) const
 		sii.text.replaceName(resourceID());
 	}
 	sii.components.emplace_back(ComponentType::RESOURCE, resourceID(), amount);
-	sii.soundID = soundBase::pickup01 + cb->gameState()->getRandomGenerator().nextInt(6);
+	sii.soundID = soundBase::pickup01 + cb->gameState().getRandomGenerator().nextInt(6);
 	cb->showInfoDialog(&sii);
 	cb->removeObject(this, player);
 }

+ 8 - 8
lib/mapObjects/CGTownInstance.cpp

@@ -305,7 +305,7 @@ void CGTownInstance::setOwner(const PlayerColor & player) const
 
 void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
 {
-	if(cb->gameState()->getPlayerRelations( getOwner(), h->getOwner() ) == PlayerRelations::ENEMIES)
+	if(cb->gameState().getPlayerRelations( getOwner(), h->getOwner() ) == PlayerRelations::ENEMIES)
 	{
 		if(armedGarrison() || getVisitingHero())
 		{
@@ -330,7 +330,7 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
 			auto heroColor = h->getOwner();
 			onTownCaptured(heroColor);
 
-			if(cb->gameState()->getPlayerStatus(heroColor) == EPlayerStatus::WINNER)
+			if(cb->gameState().getPlayerStatus(heroColor) == EPlayerStatus::WINNER)
 			{
 				return; //we just won game, we do not need to perform any extra actions
 				//TODO: check how does H3 behave, visiting town on victory can affect campaigns (spells learned, +1 stat building visited)
@@ -624,7 +624,7 @@ void CGTownInstance::removeCapitols(const PlayerColor & owner) const
 {
 	if (hasCapitol()) // search if there's an older capitol
 	{
-		PlayerState* state = cb->gameState()->getPlayerState(owner); //get all towns owned by player
+		PlayerState* state = cb->gameState().getPlayerState(owner); //get all towns owned by player
 		for (const auto & otherTown : state->getTowns())
 		{
 			if (otherTown != this && otherTown->hasCapitol())
@@ -674,14 +674,14 @@ std::vector<TradeItemBuy> CGTownInstance::availableItemsIds(EMarketMode mode) co
 	if(mode == EMarketMode::RESOURCE_ARTIFACT)
 	{
 		std::vector<TradeItemBuy> ret;
-		for(const ArtifactID a : cb->gameState()->getMap().townMerchantArtifacts)
+		for(const ArtifactID a : cb->gameState().getMap().townMerchantArtifacts)
 			ret.push_back(a);
 
 		return ret;
 	}
 	else if ( mode == EMarketMode::RESOURCE_SKILL )
 	{
-		return cb->gameState()->getMap().townUniversitySkills;
+		return cb->gameState().getMap().townUniversitySkills;
 	}
 	else
 		return IMarket::availableItemsIds(mode);
@@ -694,7 +694,7 @@ ObjectInstanceID CGTownInstance::getObjInstanceID() const
 
 void CGTownInstance::updateAppearance()
 {
-	auto terrain = cb->gameState()->getTile(visitablePos())->getTerrainID();
+	auto terrain = cb->gameState().getTile(visitablePos())->getTerrainID();
 	//FIXME: not the best way to do this
 	auto app = getObjectHandler()->getOverride(terrain, this);
 	if (app)
@@ -776,7 +776,7 @@ void CGTownInstance::setVisitingHero(CGHeroInstance *h)
 	}
 	else if (visitingHero.hasValue())
 	{
-		auto oldVisitor = dynamic_cast<CGHeroInstance*>(cb->gameState()->getObjInstance(visitingHero));
+		auto oldVisitor = dynamic_cast<CGHeroInstance*>(cb->gameState().getObjInstance(visitingHero));
 		oldVisitor->detachFromBonusSystem(cb->gameState());
 		oldVisitor->setVisitedTown(nullptr, false);
 		oldVisitor->attachToBonusSystem(cb->gameState());
@@ -798,7 +798,7 @@ void CGTownInstance::setGarrisonedHero(CGHeroInstance *h)
 	}
 	else if (garrisonHero.hasValue())
 	{
-		auto oldVisitor = dynamic_cast<CGHeroInstance*>(cb->gameState()->getObjInstance(garrisonHero));
+		auto oldVisitor = dynamic_cast<CGHeroInstance*>(cb->gameState().getObjInstance(garrisonHero));
 		oldVisitor->detachFromBonusSystem(cb->gameState());
 		oldVisitor->setVisitedTown(nullptr, false);
 		oldVisitor->attachToBonusSystem(cb->gameState());

+ 1 - 1
lib/mapObjects/FlaggableMapObject.cpp

@@ -88,7 +88,7 @@ void FlaggableMapObject::giveBonusTo(const PlayerColor & player, bool onInit) co
 		// Proper fix would be to make FlaggableMapObject into bonus system node
 		// Unfortunately this will cause saves breakage
 		if(onInit)
-			gb.applyGs(cb->gameState());
+			gb.applyGs(&cb->gameState());
 		else
 			cb->sendAndApply(gb);
 	}

+ 33 - 33
lib/mapObjects/MiscObjects.cpp

@@ -74,7 +74,7 @@ bool CTeamVisited::wasVisited(const TeamID & team) const
 //CGMine
 void CGMine::onHeroVisit( const CGHeroInstance * h ) const
 {
-	auto relations = cb->gameState()->getPlayerRelations(h->tempOwner, tempOwner);
+	auto relations = cb->gameState().getPlayerRelations(h->tempOwner, tempOwner);
 
 	if(relations == PlayerRelations::SAME_PLAYER) //we're visiting our mine
 	{
@@ -298,7 +298,7 @@ ObjectInstanceID CGTeleport::getRandomExit(const CGHeroInstance * h) const
 {
 	auto passableExits = getPassableExits(cb->gameState(), h, getAllExits(true));
 	if(!passableExits.empty())
-		return *RandomGeneratorUtil::nextItem(passableExits, cb->gameState()->getRandomGenerator());
+		return *RandomGeneratorUtil::nextItem(passableExits, cb->gameState().getRandomGenerator());
 
 	return ObjectInstanceID();
 }
@@ -320,10 +320,10 @@ bool CGTeleport::isConnected(const CGObjectInstance * src, const CGObjectInstanc
 	return isConnected(srcObj, dstObj);
 }
 
-bool CGTeleport::isExitPassable(const CGameState * gs, const CGHeroInstance * h, const CGObjectInstance * obj)
+bool CGTeleport::isExitPassable(const CGameState & gs, const CGHeroInstance * h, const CGObjectInstance * obj)
 {
-	ObjectInstanceID topObjectID = gs->getMap().getTile(obj->visitablePos()).topVisitableObj();
-	const CGObjectInstance * topObject = gs->getObjInstance(topObjectID);
+	ObjectInstanceID topObjectID = gs.getMap().getTile(obj->visitablePos()).topVisitableObj();
+	const CGObjectInstance * topObject = gs.getObjInstance(topObjectID);
 
 	if(topObject->ID == Obj::HERO)
 	{
@@ -331,7 +331,7 @@ bool CGTeleport::isExitPassable(const CGameState * gs, const CGHeroInstance * h,
 			return false;
 
 		// Check if it's friendly hero or not
-		if(gs->getPlayerRelations(h->tempOwner, topObject->tempOwner) != PlayerRelations::ENEMIES)
+		if(gs.getPlayerRelations(h->tempOwner, topObject->tempOwner) != PlayerRelations::ENEMIES)
 		{
 			// Exchange between heroes only possible via subterranean gates
 			if(!dynamic_cast<const CGSubterraneanGate *>(obj))
@@ -341,11 +341,11 @@ bool CGTeleport::isExitPassable(const CGameState * gs, const CGHeroInstance * h,
 	return true;
 }
 
-std::vector<ObjectInstanceID> CGTeleport::getPassableExits(const CGameState * gs, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits)
+std::vector<ObjectInstanceID> CGTeleport::getPassableExits(const CGameState & gs, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits)
 {
 	vstd::erase_if(exits, [&](const ObjectInstanceID & exit) -> bool 
 	{
-		return !isExitPassable(gs, h, gs->getObj(exit));
+		return !isExitPassable(gs, h, gs.getObj(exit));
 	});
 	return exits;
 }
@@ -376,7 +376,7 @@ void CGTeleport::addToChannel(std::map<TeleportChannelID, std::shared_ptr<Telepo
 
 TeleportChannelID CGMonolith::findMeChannel(const std::vector<Obj> & IDs, MapObjectSubID SubID) const
 {
-	for(auto teleportObj : cb->gameState()->getMap().getObjects<CGMonolith>())
+	for(auto teleportObj : cb->gameState().getMap().getObjects<CGMonolith>())
 	{
 		if(vstd::contains(IDs, teleportObj->ID) && teleportObj->subID == SubID)
 			return teleportObj->channel;
@@ -453,9 +453,9 @@ void CGMonolith::initObj(vstd::RNG & rand)
 
 	channel = findMeChannel(IDs, subID);
 	if(channel == TeleportChannelID())
-		channel = TeleportChannelID(static_cast<si32>(cb->gameState()->getMap().teleportChannels.size()));
+		channel = TeleportChannelID(static_cast<si32>(cb->gameState().getMap().teleportChannels.size()));
 
-	addToChannel(cb->gameState()->getMap().teleportChannels, this);
+	addToChannel(cb->gameState().getMap().teleportChannels, this);
 }
 
 void CGSubterraneanGate::onHeroVisit( const CGHeroInstance * h ) const
@@ -485,7 +485,7 @@ void CGSubterraneanGate::postInit(IGameCallback * cb) //matches subterranean gat
 {
 	//split on underground and surface gates
 	std::vector<CGSubterraneanGate *> gatesSplit[2]; //surface and underground gates
-	for(auto gate : cb->gameState()->getMap().getObjects<CGSubterraneanGate>())
+	for(auto gate : cb->gameState().getMap().getObjects<CGSubterraneanGate>())
 	{
 		gatesSplit[gate->visitablePos().z].push_back(gate);
 	}
@@ -500,8 +500,8 @@ void CGSubterraneanGate::postInit(IGameCallback * cb) //matches subterranean gat
 	{
 		if(obj->channel == TeleportChannelID())
 		{ // if object not linked to channel then create new channel
-			obj->channel = TeleportChannelID(static_cast<si32>(cb->gameState()->getMap().teleportChannels.size()));
-			addToChannel(cb->gameState()->getMap().teleportChannels, obj);
+			obj->channel = TeleportChannelID(static_cast<si32>(cb->gameState().getMap().teleportChannels.size()));
+			addToChannel(cb->gameState().getMap().teleportChannels, obj);
 		}
 	};
 
@@ -528,7 +528,7 @@ void CGSubterraneanGate::postInit(IGameCallback * cb) //matches subterranean gat
 		if(best.first >= 0) //found pair
 		{
 			gatesSplit[1][best.first]->channel = objCurrent->channel;
-			addToChannel(cb->gameState()->getMap().teleportChannels, gatesSplit[1][best.first]);
+			addToChannel(cb->gameState().getMap().teleportChannels, gatesSplit[1][best.first]);
 		}
 	}
 
@@ -599,7 +599,7 @@ void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer
 
 		const auto * obj = cb->getObj(exit);
 		std::set<int3> tiles = obj->getBlockedPos();
-		dPos = *RandomGeneratorUtil::nextItem(tiles, cb->gameState()->getRandomGenerator());
+		dPos = *RandomGeneratorUtil::nextItem(tiles, cb->gameState().getRandomGenerator());
 	}
 
 	cb->moveHero(hero->id, hero->convertFromVisitablePos(dPos), EMovementMode::MONOLITH);
@@ -630,19 +630,19 @@ void CGArtifact::pickRandomObject(vstd::RNG & rand)
 	switch(ID.toEnum())
 	{
 		case MapObjectID::RANDOM_ART:
-			subID = cb->gameState()->pickRandomArtifact(rand, CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC);
+			subID = cb->gameState().pickRandomArtifact(rand, CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC);
 			break;
 		case MapObjectID::RANDOM_TREASURE_ART:
-			subID = cb->gameState()->pickRandomArtifact(rand, CArtifact::ART_TREASURE);
+			subID = cb->gameState().pickRandomArtifact(rand, CArtifact::ART_TREASURE);
 			break;
 		case MapObjectID::RANDOM_MINOR_ART:
-			subID = cb->gameState()->pickRandomArtifact(rand, CArtifact::ART_MINOR);
+			subID = cb->gameState().pickRandomArtifact(rand, CArtifact::ART_MINOR);
 			break;
 		case MapObjectID::RANDOM_MAJOR_ART:
-			subID = cb->gameState()->pickRandomArtifact(rand, CArtifact::ART_MAJOR);
+			subID = cb->gameState().pickRandomArtifact(rand, CArtifact::ART_MAJOR);
 			break;
 		case MapObjectID::RANDOM_RELIC_ART:
-			subID = cb->gameState()->pickRandomArtifact(rand, CArtifact::ART_RELIC);
+			subID = cb->gameState().pickRandomArtifact(rand, CArtifact::ART_RELIC);
 			break;
 	}
 
@@ -666,9 +666,9 @@ void CGArtifact::initObj(vstd::RNG & rand)
 	if(ID == Obj::ARTIFACT)
 	{
 		if (!storedArtifact.hasValue())
-			setArtifactInstance(cb->gameState()->createArtifact(ArtifactID()));
+			setArtifactInstance(cb->gameState().createArtifact(ArtifactID()));
 
-		auto * artifact = cb->gameState()->getArtInstance(storedArtifact);
+		auto * artifact = cb->gameState().getArtInstance(storedArtifact);
 
 		if(!artifact->getType())
 			artifact->setType(getArtifactType().toArtifact());
@@ -881,7 +881,7 @@ std::vector<CreatureID> CGGarrison::providedCreatures() const
 
 void CGGarrison::onHeroVisit (const CGHeroInstance *h) const
 {
-	auto relations = cb->gameState()->getPlayerRelations(h->tempOwner, tempOwner);
+	auto relations = cb->gameState().getPlayerRelations(h->tempOwner, tempOwner);
 	if (relations == PlayerRelations::ENEMIES && stacksCount() > 0) {
 		//TODO: Find a way to apply magic garrison effects in battle.
 		cb->startBattle(h, this);
@@ -953,7 +953,7 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const
 
 		std::vector<const CGObjectInstance *> eyes;
 
-		for (const auto & object : cb->gameState()->getMap().getObjects<CGMagi>())
+		for (const auto & object : cb->gameState().getMap().getObjects<CGMagi>())
 		{
 			if (object->ID == Obj::EYE_OF_MAGI && object->subID == this->subID)
 				eyes.push_back(object);
@@ -1100,7 +1100,7 @@ const IObjectInterface * CGShipyard::getObject() const
 
 void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
 {
-	if(cb->gameState()->getPlayerRelations(tempOwner, h->tempOwner) == PlayerRelations::ENEMIES)
+	if(cb->gameState().getPlayerRelations(tempOwner, h->tempOwner) == PlayerRelations::ENEMIES)
 		cb->setOwner(this, h->tempOwner);
 
 	if(shipyardStatus() != IBoatGenerator::GOOD)
@@ -1152,7 +1152,7 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
 	InfoWindow iw;
 	iw.type = EInfoWindowMode::AUTO;
 	iw.player = h->tempOwner;
-	TeamState *ts = cb->gameState()->getPlayerTeam(h->tempOwner);
+	TeamState *ts = cb->gameState().getPlayerTeam(h->tempOwner);
 	assert(ts);
 	TeamID team = ts->id;
 
@@ -1181,7 +1181,7 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
 
 void CGObelisk::initObj(vstd::RNG & rand)
 {
-	cb->gameState()->getMap().obeliskCount++;
+	cb->gameState().getMap().obeliskCount++;
 }
 
 std::string CGObelisk::getHoverText(PlayerColor player) const
@@ -1200,13 +1200,13 @@ void CGObelisk::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
 	{
 		case ObjProperty::OBELISK_VISITED:
 			{
-				auto progress = ++cb->gameState()->getMap().obelisksVisited[identifier.as<TeamID>()];
-				logGlobal->debug("Player %d: obelisk progress %d / %d", identifier.getNum(), static_cast<int>(progress) , static_cast<int>(cb->gameState()->getMap().obeliskCount));
+				auto progress = ++cb->gameState().getMap().obelisksVisited[identifier.as<TeamID>()];
+				logGlobal->debug("Player %d: obelisk progress %d / %d", identifier.getNum(), static_cast<int>(progress) , static_cast<int>(cb->gameState().getMap().obeliskCount));
 
-				if(progress > cb->gameState()->getMap().obeliskCount)
+				if(progress > cb->gameState().getMap().obeliskCount)
 				{
-					logGlobal->error("Visited %d of %d", static_cast<int>(progress), cb->gameState()->getMap().obeliskCount);
-					throw std::runtime_error("Player visited " + std::to_string(progress) + " obelisks out of " + std::to_string(cb->gameState()->getMap().obeliskCount) + " present on map!");
+					logGlobal->error("Visited %d of %d", static_cast<int>(progress), cb->gameState().getMap().obeliskCount);
+					throw std::runtime_error("Player visited " + std::to_string(progress) + " obelisks out of " + std::to_string(cb->gameState().getMap().obeliskCount) + " present on map!");
 				}
 
 				break;

+ 2 - 2
lib/mapObjects/MiscObjects.h

@@ -220,8 +220,8 @@ public:
 	static bool isConnected(const CGTeleport * src, const CGTeleport * dst);
 	static bool isConnected(const CGObjectInstance * src, const CGObjectInstance * dst);
 	static void addToChannel(std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > &channelsList, const CGTeleport * obj);
-	static std::vector<ObjectInstanceID> getPassableExits(const CGameState * gs, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits);
-	static bool isExitPassable(const CGameState * gs, const CGHeroInstance * h, const CGObjectInstance * obj);
+	static std::vector<ObjectInstanceID> getPassableExits(const CGameState & gs, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits);
+	static bool isExitPassable(const CGameState & gs, const CGHeroInstance * h, const CGObjectInstance * obj);
 
 	template <typename Handler> void serialize(Handler &h)
 	{

+ 1 - 1
lib/mapping/CMap.cpp

@@ -937,7 +937,7 @@ const CGObjectInstance * CMap::getObject(ObjectInstanceID obj) const
 void CMap::saveCompatibilityStoreAllocatedArtifactID()
 {
 	if (!artInstances.empty())
-		cb->gameState()->saveCompatibilityLastAllocatedArtifactID = artInstances.back()->getId();
+		cb->gameState().saveCompatibilityLastAllocatedArtifactID = artInstances.back()->getId();
 }
 
 void CMap::saveCompatibilityAddMissingArtifact(std::shared_ptr<CArtifactInstance> artifact)

+ 1 - 1
lib/mapping/CMap.h

@@ -144,7 +144,7 @@ public:
 	CGObjectInstance * getObject(ObjectInstanceID obj);
 	const CGObjectInstance * getObject(ObjectInstanceID obj) const;
 
-	void attachToBonusSystem(CGameState * gs);
+	void attachToBonusSystem(CGameState & gs);
 
 	template<typename ObjectType = CGObjectInstance>
 	std::vector<const ObjectType *> getObjects() const

+ 4 - 4
lib/networkPacks/NetPacksLib.cpp

@@ -1430,7 +1430,7 @@ void HeroRecruited::applyGs(CGameState *gs)
 	gs->getMap().addNewObject(h);
 
 	p->addOwnedObject(h.get());
-	h->attachToBonusSystem(gs);
+	h->attachToBonusSystem(*gs);
 
 	if(t)
 		t->setVisitingHero(h.get());
@@ -1477,7 +1477,7 @@ void NewObject::applyGs(CGameState *gs)
 	// attach newly spawned wandering monster to global bonus system node
 	auto newArmy = std::dynamic_pointer_cast<CArmedInstance>(newObject);
 	if (newArmy)
-		newArmy->attachToBonusSystem(gs);
+		newArmy->attachToBonusSystem(*gs);
 
 	logGlobal->debug("Added object id=%d; name=%s", newObject->id, newObject->getObjectName());
 }
@@ -1961,9 +1961,9 @@ void SetObjectProperty::applyGs(CGameState *gs)
 			}
 		}
 
-		cai->detachFromBonusSystem(gs);
+		cai->detachFromBonusSystem(*gs);
 		obj->setProperty(what, identifier);
-		cai->attachToBonusSystem(gs);
+		cai->attachToBonusSystem(*gs);
 	}
 	else //not an armed instance
 	{

+ 9 - 9
lib/pathfinder/CGPathNode.cpp

@@ -100,7 +100,7 @@ PathNodeInfo::PathNodeInfo()
 {
 }
 
-void PathNodeInfo::setNode(CGameState * gs, CGPathNode * n)
+void PathNodeInfo::setNode(CGameState & gs, CGPathNode * n)
 {
 	node = n;
 	guarded = false;
@@ -110,14 +110,14 @@ void PathNodeInfo::setNode(CGameState * gs, CGPathNode * n)
 		assert(node->coord.isValid());
 
 		coord = node->coord;
-		tile = gs->getTile(coord);
+		tile = gs.getTile(coord);
 		nodeObject = nullptr;
 		nodeHero = nullptr;
 
 		ObjectInstanceID topObjectID = tile->topVisitableObj();
 		if (topObjectID.hasValue())
 		{
-			nodeObject = gs->getObjInstance(topObjectID);
+			nodeObject = gs.getObjInstance(topObjectID);
 
 			if (nodeObject->ID == Obj::HERO)
 			{
@@ -125,28 +125,28 @@ void PathNodeInfo::setNode(CGameState * gs, CGPathNode * n)
 				ObjectInstanceID bottomObjectID = tile->topVisitableObj(true);
 
 				if (bottomObjectID.hasValue())
-					nodeObject = gs->getObjInstance(bottomObjectID);
+					nodeObject = gs.getObjInstance(bottomObjectID);
 			}
 		}
 	}
 
 }
 
-void PathNodeInfo::updateInfo(CPathfinderHelper * hlp, CGameState * gs)
+void PathNodeInfo::updateInfo(CPathfinderHelper * hlp, CGameState & gs)
 {
-	if(gs->guardingCreaturePosition(node->coord).isValid() && !isInitialPosition)
+	if(gs.guardingCreaturePosition(node->coord).isValid() && !isInitialPosition)
 	{
 		guarded = true;
 	}
 
 	if(nodeObject)
 	{
-		objectRelations = gs->getPlayerRelations(hlp->owner, nodeObject->tempOwner);
+		objectRelations = gs.getPlayerRelations(hlp->owner, nodeObject->tempOwner);
 	}
 
 	if(nodeHero)
 	{
-		heroRelations = gs->getPlayerRelations(hlp->owner, nodeHero->tempOwner);
+		heroRelations = gs.getPlayerRelations(hlp->owner, nodeHero->tempOwner);
 	}
 }
 
@@ -164,7 +164,7 @@ CDestinationNodeInfo::CDestinationNodeInfo():
 {
 }
 
-void CDestinationNodeInfo::setNode(CGameState * gs, CGPathNode * n)
+void CDestinationNodeInfo::setNode(CGameState & gs, CGPathNode * n)
 {
 	PathNodeInfo::setNode(gs, n);
 

+ 3 - 3
lib/pathfinder/CGPathNode.h

@@ -219,9 +219,9 @@ struct DLL_LINKAGE PathNodeInfo
 
 	PathNodeInfo();
 
-	virtual void setNode(CGameState * gs, CGPathNode * n);
+	virtual void setNode(CGameState & gs, CGPathNode * n);
 
-	void updateInfo(CPathfinderHelper * hlp, CGameState * gs);
+	void updateInfo(CPathfinderHelper * hlp, CGameState & gs);
 
 	bool isNodeObjectVisitable() const;
 };
@@ -237,7 +237,7 @@ struct DLL_LINKAGE CDestinationNodeInfo : public PathNodeInfo
 
 	CDestinationNodeInfo();
 
-	void setNode(CGameState * gs, CGPathNode * n) override;
+	void setNode(CGameState & gs, CGPathNode * n) override;
 
 	virtual bool isBetterWay() const;
 };

+ 10 - 10
lib/pathfinder/CPathfinder.cpp

@@ -74,7 +74,7 @@ void CPathfinderHelper::calculateNeighbourTiles(NeighbourTilesVector & result, c
 	}
 }
 
-CPathfinder::CPathfinder(CGameState * gamestate, std::shared_ptr<PathfinderConfig> config):
+CPathfinder::CPathfinder(CGameState & gamestate, std::shared_ptr<PathfinderConfig> config):
 	gamestate(gamestate),
 	config(std::move(config))
 {
@@ -111,9 +111,9 @@ void CPathfinder::calculatePaths()
 
 	for(auto * initialNode : initialNodes)
 	{
-		if(!gamestate->isInTheMap(initialNode->coord)/* || !gameState()->getMap().isInTheMap(dest)*/) //check input
+		if(!gamestate.isInTheMap(initialNode->coord)/* || !gameState().getMap().isInTheMap(dest)*/) //check input
 		{
-			logGlobal->error("CGameState::calculatePaths: Hero outside the gameState()->map? How dare you...");
+			logGlobal->error("CGameState::calculatePaths: Hero outside the gameState().map? How dare you...");
 			throw std::runtime_error("Wrong checksum");
 		}
 
@@ -251,7 +251,7 @@ TeleporterTilesVector CPathfinderHelper::getAllowedTeleportChannelExits(const Te
 			auto pos = obj->getBlockedPos();
 			for(const auto & p : pos)
 			{
-				ObjectInstanceID topObject = gameState()->getMap().getTile(p).topVisitableObj();
+				ObjectInstanceID topObject = gameState().getMap().getTile(p).topVisitableObj();
 				if(topObject.hasValue() && getObj(topObject)->ID == obj->ID)
 					allowedExits.push_back(p);
 			}
@@ -390,7 +390,7 @@ EPathNodeAction CPathfinder::getTeleportDestAction() const
 
 bool CPathfinder::isDestinationGuardian() const
 {
-	return gamestate->guardingCreaturePosition(destination.node->coord) == destination.node->coord;
+	return gamestate.guardingCreaturePosition(destination.node->coord) == destination.node->coord;
 }
 
 void CPathfinderHelper::initializePatrol()
@@ -402,7 +402,7 @@ void CPathfinderHelper::initializePatrol()
 		if(hero->patrol.patrolRadius)
 		{
 			state = PATROL_RADIUS;
-			gameState()->getTilesInRange(patrolTiles, hero->patrol.initialPos, hero->patrol.patrolRadius, ETileVisibility::REVEALED, std::optional<PlayerColor>(), int3::DIST_MANHATTAN);
+			gameState().getTilesInRange(patrolTiles, hero->patrol.initialPos, hero->patrol.patrolRadius, ETileVisibility::REVEALED, std::optional<PlayerColor>(), int3::DIST_MANHATTAN);
 		}
 		else
 			state = PATROL_LOCKED;
@@ -414,12 +414,12 @@ void CPathfinderHelper::initializePatrol()
 void CPathfinder::initializeGraph()
 {
 	INodeStorage * nodeStorage = config->nodeStorage.get();
-	nodeStorage->initialize(config->options, gamestate);
+	nodeStorage->initialize(config->options, &gamestate);
 }
 
 bool CPathfinderHelper::canMoveBetween(const int3 & a, const int3 & b) const
 {
-	return gameState()->checkForVisitableDir(a, b);
+	return gameState().checkForVisitableDir(a, b);
 }
 
 bool CPathfinderHelper::isAllowedTeleportEntrance(const CGTeleport * obj) const
@@ -497,7 +497,7 @@ int CPathfinderHelper::getGuardiansCount(int3 tile) const
 	return getGuardingCreatures(tile).size();
 }
 
-CPathfinderHelper::CPathfinderHelper(CGameState * gs, const CGHeroInstance * Hero, const PathfinderOptions & Options):
+CPathfinderHelper::CPathfinderHelper(CGameState & gs, const CGHeroInstance * Hero, const PathfinderOptions & Options):
 	gs(gs),
 	turn(-1),
 	owner(Hero->tempOwner),
@@ -572,7 +572,7 @@ void CPathfinderHelper::getNeighbours(
 	const boost::logic::tribool & onLand,
 	const bool limitCoastSailing) const
 {
-	const CMap * map = &gameState()->getMap();
+	const CMap * map = &gameState().getMap();
 	const TerrainType * sourceTerrain = sourceTile.getTerrain();
 
 	static constexpr std::array dirs = {

+ 6 - 6
lib/pathfinder/CPathfinder.h

@@ -33,13 +33,13 @@ public:
 	friend class CPathfinderHelper;
 
 	CPathfinder(
-		CGameState * _gs,
+		CGameState & _gs,
 		std::shared_ptr<PathfinderConfig> config);
 
 	void calculatePaths(); //calculates possible paths for hero, uses current hero position and movement left; returns pointer to newly allocated CPath or nullptr if path does not exists
 
 private:
-	CGameState * gamestate;
+	CGameState & gamestate;
 
 	using ELayer = EPathfindingLayer;
 
@@ -69,7 +69,7 @@ class DLL_LINKAGE CPathfinderHelper : private CGameInfoCallback
 	/// returns base movement cost for movement between specific tiles. Does not accounts for diagonal movement or last tile exception
 	ui32 getTileMovementCost(const TerrainTile & dest, const TerrainTile & from, const TurnInfo * ti) const;
 
-	CGameState * gs;
+	CGameState & gs;
 public:
 	enum EPatrolState
 	{
@@ -88,10 +88,10 @@ public:
 	bool canCastWaterWalk;
 	bool whirlpoolProtection;
 
-	CPathfinderHelper(CGameState * gs, const CGHeroInstance * Hero, const PathfinderOptions & Options);
+	CPathfinderHelper(CGameState & gs, const CGHeroInstance * Hero, const PathfinderOptions & Options);
 	virtual ~CPathfinderHelper();
-	CGameState * gameState() final { return gs; }
-	const CGameState * gameState() const final { return gs; }
+	CGameState & gameState() final { return gs; }
+	const CGameState & gameState() const final { return gs; }
 	void initializePatrol();
 	bool isHeroPatrolLocked() const;
 	bool canMoveFromNode(const PathNodeInfo & source) const;

+ 1 - 1
lib/pathfinder/PathfinderCache.cpp

@@ -20,7 +20,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 std::shared_ptr<PathfinderConfig> PathfinderCache::createConfig(const CGHeroInstance * h, CPathsInfo & out)
 {
-	auto config = std::make_shared<SingleHeroPathfinderConfig>(out, cb, h);
+	auto config = std::make_shared<SingleHeroPathfinderConfig>(out, *cb, h);
 	config->options = options;
 
 	return config;

+ 11 - 11
lib/pathfinder/PathfinderOptions.cpp

@@ -19,16 +19,16 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-PathfinderOptions::PathfinderOptions(const CGameInfoCallback * cb)
+PathfinderOptions::PathfinderOptions(const CGameInfoCallback & cb)
 	: useFlying(true)
 	, useWaterWalking(true)
-	, ignoreGuards(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_IGNORE_GUARDS))
-	, useEmbarkAndDisembark(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_USE_BOAT))
-	, useTeleportTwoWay(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_TWO_WAY))
-	, useTeleportOneWay(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_UNIQUE))
-	, useTeleportOneWayRandom(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_RANDOM))
-	, useTeleportWhirlpool(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_USE_WHIRLPOOL))
-	, originalFlyRules(cb->getSettings().getBoolean(EGameSettings::PATHFINDER_ORIGINAL_FLY_RULES))
+	, ignoreGuards(cb.getSettings().getBoolean(EGameSettings::PATHFINDER_IGNORE_GUARDS))
+	, useEmbarkAndDisembark(cb.getSettings().getBoolean(EGameSettings::PATHFINDER_USE_BOAT))
+	, useTeleportTwoWay(cb.getSettings().getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_TWO_WAY))
+	, useTeleportOneWay(cb.getSettings().getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_UNIQUE))
+	, useTeleportOneWayRandom(cb.getSettings().getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_RANDOM))
+	, useTeleportWhirlpool(cb.getSettings().getBoolean(EGameSettings::PATHFINDER_USE_WHIRLPOOL))
+	, originalFlyRules(cb.getSettings().getBoolean(EGameSettings::PATHFINDER_ORIGINAL_FLY_RULES))
 	, useCastleGate(false)
 	, lightweightFlyingMode(false)
 	, oneTurnSpecialLayersLimit(true)
@@ -39,7 +39,7 @@ PathfinderOptions::PathfinderOptions(const CGameInfoCallback * cb)
 {
 }
 
-PathfinderConfig::PathfinderConfig(std::shared_ptr<INodeStorage> nodeStorage, const CGameInfoCallback * callback, std::vector<std::shared_ptr<IPathfindingRule>> rules):
+PathfinderConfig::PathfinderConfig(std::shared_ptr<INodeStorage> nodeStorage, const CGameInfoCallback & callback, std::vector<std::shared_ptr<IPathfindingRule>> rules):
 	nodeStorage(std::move(nodeStorage)),
 	rules(std::move(rules)),
 	options(callback)
@@ -59,13 +59,13 @@ std::vector<std::shared_ptr<IPathfindingRule>> SingleHeroPathfinderConfig::build
 
 SingleHeroPathfinderConfig::~SingleHeroPathfinderConfig() = default;
 
-SingleHeroPathfinderConfig::SingleHeroPathfinderConfig(CPathsInfo & out, const CGameInfoCallback * gs, const CGHeroInstance * hero)
+SingleHeroPathfinderConfig::SingleHeroPathfinderConfig(CPathsInfo & out, const CGameInfoCallback & gs, const CGHeroInstance * hero)
 	: PathfinderConfig(std::make_shared<NodeStorage>(out, hero), gs, buildRuleSet())
 	, hero(hero)
 {
 }
 
-CPathfinderHelper * SingleHeroPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState * gs)
+CPathfinderHelper * SingleHeroPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState & gs)
 {
 	if (!pathfinderHelper)
 		pathfinderHelper = std::make_unique<CPathfinderHelper>(gs, hero, options);

+ 5 - 5
lib/pathfinder/PathfinderOptions.h

@@ -85,7 +85,7 @@ struct DLL_LINKAGE PathfinderOptions
 	/// </summary>
 	bool allowLayerTransitioningAfterBattle;
 
-	PathfinderOptions(const CGameInfoCallback * callback);
+	PathfinderOptions(const CGameInfoCallback & callback);
 };
 
 class DLL_LINKAGE PathfinderConfig
@@ -97,11 +97,11 @@ public:
 
 	PathfinderConfig(
 		std::shared_ptr<INodeStorage> nodeStorage,
-		const CGameInfoCallback * callback,
+		const CGameInfoCallback & callback,
 		std::vector<std::shared_ptr<IPathfindingRule>> rules);
 	virtual ~PathfinderConfig() = default;
 
-	virtual CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState * gs) = 0;
+	virtual CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState & gs) = 0;
 };
 
 class DLL_LINKAGE SingleHeroPathfinderConfig : public PathfinderConfig
@@ -111,10 +111,10 @@ private:
 	const CGHeroInstance * hero;
 
 public:
-	SingleHeroPathfinderConfig(CPathsInfo & out, const CGameInfoCallback * gs, const CGHeroInstance * hero);
+	SingleHeroPathfinderConfig(CPathsInfo & out, const CGameInfoCallback & gs, const CGHeroInstance * hero);
 	virtual ~SingleHeroPathfinderConfig();
 
-	CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState * gs) override;
+	CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState & gs) override;
 
 	static std::vector<std::shared_ptr<IPathfindingRule>> buildRuleSet();
 };

+ 1 - 1
lib/rewardable/Interface.cpp

@@ -93,7 +93,7 @@ void Rewardable::Interface::grantRewardBeforeLevelup(const Rewardable::VisitInfo
 
 		if (props.hide)
 		{
-			for (auto & player : cb->gameState()->players)
+			for (auto & player : cb->gameState().players)
 			{
 				if (cb->getPlayerStatus(player.first) == EPlayerStatus::INGAME && cb->getPlayerRelations(player.first, hero->getOwner()) == PlayerRelations::ENEMIES)
 					cb->changeFogOfWar(tiles, player.first, ETileVisibility::HIDDEN);

+ 2 - 2
lib/serializer/Connection.cpp

@@ -129,9 +129,9 @@ void CConnection::setCallback(IGameCallback * cb)
 	deserializer->cb = cb;
 }
 
-void CConnection::enterGameplayConnectionMode(CGameState * gs)
+void CConnection::enterGameplayConnectionMode(CGameState & gs)
 {
-	setCallback(gs->cb);
+	setCallback(gs.cb);
 }
 
 void CConnection::setSerializationVersion(ESerializationVersion version)

+ 1 - 1
lib/serializer/Connection.h

@@ -51,7 +51,7 @@ public:
 
 	void enterLobbyConnectionMode();
 	void setCallback(IGameCallback * cb);
-	void enterGameplayConnectionMode(CGameState * gs);
+	void enterGameplayConnectionMode(CGameState & gs);
 	void setSerializationVersion(ESerializationVersion version);
 };
 

+ 59 - 59
server/CGameHandler.cpp

@@ -114,7 +114,7 @@ const Services * CGameHandler::services() const
 
 const CGameHandler::BattleCb * CGameHandler::battle(const BattleID & battleID) const
 {
-	return gameState()->getBattle(battleID);
+	return gameState().getBattle(battleID);
 }
 
 const CGameHandler::GameCb * CGameHandler::game() const
@@ -349,8 +349,8 @@ void CGameHandler::giveExperience(const CGHeroInstance * hero, TExpType amountTo
 	TExpType maxExp = LIBRARY->heroh->reqExp(LIBRARY->heroh->maxSupportedLevel());
 	TExpType currExp = hero->exp;
 
-	if (gameState()->getMap().levelLimit != 0)
-		maxExp = LIBRARY->heroh->reqExp(gameState()->getMap().levelLimit);
+	if (gameState().getMap().levelLimit != 0)
+		maxExp = LIBRARY->heroh->reqExp(gameState().getMap().levelLimit);
 
 	TExpType canGainExp = 0;
 	if (maxExp > currExp)
@@ -424,7 +424,7 @@ void CGameHandler::changeSecSkill(const CGHeroInstance * hero, SecondarySkill wh
 
 void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
 {
-	if(gameLobby().getState() == EServerState::SHUTDOWN || !gameState() || !gameState()->getStartInfo())
+	if(gameLobby().getState() == EServerState::SHUTDOWN || !gameState().getStartInfo())
 	{
 		assert(0); // game should have shut down before reaching this point!
 		return;
@@ -433,7 +433,7 @@ void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
 	for(auto & playerConnections : connections)
 	{
 		PlayerColor playerId = playerConnections.first;
-		auto * playerSettings = gameState()->getStartInfo()->getPlayersSettings(playerId.getNum());
+		auto * playerSettings = gameState().getStartInfo()->getPlayersSettings(playerId.getNum());
 		if(!playerSettings)
 			continue;
 		
@@ -444,7 +444,7 @@ void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
 		logGlobal->trace("Player %s disconnected. Notifying remaining players", playerId.toString());
 
 		// this player have left the game - broadcast infowindow to all in-game players
-		for (auto i = gameState()->players.cbegin(); i!=gameState()->players.cend(); i++)
+		for (auto i = gameState().players.cbegin(); i!=gameState().players.cend(); i++)
 		{
 			if (i->first == playerId)
 				continue;
@@ -551,10 +551,10 @@ void CGameHandler::init(StartInfo *si, Load::ProgressAccumulator & progressTrack
 	gs->init(&mapService, si, progressTracking);
 	logGlobal->info("Gamestate initialized!");
 
-	for (const auto & elem : gameState()->players)
+	for (const auto & elem : gameState().players)
 		turnOrder->addPlayer(elem.first);
 
-//	for (auto & elem : gameState()->getMap().allHeroes)
+//	for (auto & elem : gameState().getMap().allHeroes)
 //	{
 //		if(elem)
 //			heroPool->getHeroSkillsRandomGenerator(elem->getHeroTypeID()); // init RMG seed
@@ -619,12 +619,12 @@ void CGameHandler::onPlayerTurnEnded(PlayerColor which)
 
 void CGameHandler::addStatistics(StatisticDataSet &stat) const
 {
-	for (const auto & elem : gameState()->players)
+	for (const auto & elem : gameState().players)
 	{
 		if (elem.first == PlayerColor::NEUTRAL || !elem.first.isValidPlayer())
 			continue;
 
-		auto data = StatisticDataSet::createEntry(&elem.second, gameState());
+		auto data = StatisticDataSet::createEntry(&elem.second, &gameState());
 
 		stat.add(data);
 	}
@@ -632,14 +632,14 @@ void CGameHandler::addStatistics(StatisticDataSet &stat) const
 
 void CGameHandler::onNewTurn()
 {
-	logGlobal->trace("Turn %d", gameState()->day+1);
+	logGlobal->trace("Turn %d", gameState().day+1);
 
 	bool firstTurn = !getDate(Date::DAY);
 	bool newMonth = getDate(Date::DAY_OF_MONTH) == 28;
 
 	if (firstTurn)
 	{
-		for (auto obj : gameState()->getMap().getObjects<CGHeroInstance>())
+		for (auto obj : gameState().getMap().getObjects<CGHeroInstance>())
 		{
 			if (obj->ID == Obj::PRISON) //give imprisoned hero 0 exp to level him up. easiest to do at this point
 			{
@@ -647,18 +647,18 @@ void CGameHandler::onNewTurn()
 			}
 		}
 
-		for (const auto & elem : gameState()->players)
+		for (const auto & elem : gameState().players)
 			heroPool->onNewWeek(elem.first);
 
 	}
 	else
 	{
-		addStatistics(gameState()->statistic); // write at end of turn
+		addStatistics(gameState().statistic); // write at end of turn
 	}
 
-	for (const auto & townID : gameState()->getMap().getAllTowns())
+	for (const auto & townID : gameState().getMap().getAllTowns())
 	{
-		auto t = gameState()->getTown(townID);
+		auto t = gameState().getTown(townID);
 		PlayerColor player = t->tempOwner;
 
 		if(t->hasBuilt(BuildingID::GRAIL)
@@ -671,12 +671,12 @@ void CGameHandler::onNewTurn()
 		}
 	}
 
-	for (const auto & townID : gameState()->getMap().getAllTowns())
+	for (const auto & townID : gameState().getMap().getAllTowns())
 	{
-		auto t = gameState()->getTown(townID);
+		auto t = gameState().getTown(townID);
 		if (t->hasBonusOfType (BonusType::DARKNESS))
 		{
-			for (auto & player : gameState()->players)
+			for (auto & player : gameState().players)
 			{
 				if (getPlayerStatus(player.first) == EPlayerStatus::INGAME &&
 					getPlayerRelations(player.first, t->tempOwner) == PlayerRelations::ENEMIES)
@@ -699,7 +699,7 @@ void CGameHandler::onNewTurn()
 		checkVictoryLossConditionsForAll(); // check for map turn limit
 
 	//call objects
-	for (auto & elem : gameState()->getMap().getObjects())
+	for (auto & elem : gameState().getMap().getObjects())
 	{
 		if (elem)
 			elem->newTurn(getRandomGenerator());
@@ -733,7 +733,7 @@ void CGameHandler::start(bool resume)
 	{
 		onNewTurn();
 		events::TurnStarted::defaultExecute(serverEventBus.get());
-		for(auto & player : gameState()->players)
+		for(auto & player : gameState().players)
 			turnTimerHandler->onGameplayStart(player.first);
 	}
 	else
@@ -803,7 +803,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 	// not turn of that hero or player can't simply teleport hero (at least not with this function)
 	if(!h || (asker != PlayerColor::NEUTRAL && movementMode != EMovementMode::STANDARD))
 	{
-		if(h && getStartInfo()->turnTimerInfo.isEnabled() && gameState()->players.at(h->getOwner()).turnTimer.turnTimer == 0)
+		if(h && getStartInfo()->turnTimerInfo.isEnabled() && gameState().players.at(h->getOwner()).turnTimer.turnTimer == 0)
 			return true; //timer expired, no error
 		
 		logGlobal->error("Illegal call to move hero!");
@@ -813,25 +813,25 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 	logGlobal->trace("Player %d (%s) wants to move hero %d from %s to %s", asker, asker.toString(), hid.getNum(), h->anchorPos().toString(), dst.toString());
 	const int3 hmpos = h->convertToVisitablePos(dst);
 
-	if (!gameState()->getMap().isInTheMap(hmpos))
+	if (!gameState().getMap().isInTheMap(hmpos))
 	{
 		logGlobal->error("Destination tile is outside the map!");
 		return false;
 	}
 
 	const TerrainTile t = *getTile(hmpos);
-	const int3 guardPos = gameState()->guardingCreaturePosition(hmpos);
+	const int3 guardPos = gameState().guardingCreaturePosition(hmpos);
 	CGObjectInstance * objectToVisit = nullptr;
 	CGObjectInstance * guardian = nullptr;
 
 	if (!t.visitableObjects.empty())
-		objectToVisit = gameState()->getObjInstance(t.visitableObjects.back());
+		objectToVisit = gameState().getObjInstance(t.visitableObjects.back());
 
 	if (isInTheMap(guardPos))
 	{
 		for (auto const & objectID : getTile(guardPos)->visitableObjects)
 		{
-			auto object = gameState()->getObjInstance(objectID);
+			auto object = gameState().getObjInstance(objectID);
 
 			if (object->ID == MapObjectID::MONSTER) // exclude other objects, such as hero flying above monster
 				guardian = object;
@@ -852,7 +852,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 	tmh.movePoints = h->movementPointsRemaining();
 
 	//check if destination tile is available
-	auto pathfinderHelper = std::make_unique<CPathfinderHelper>(gameState(), h, PathfinderOptions(this));
+	auto pathfinderHelper = std::make_unique<CPathfinderHelper>(gameState(), h, PathfinderOptions(*this));
 	auto ti = pathfinderHelper->getTurnInfo();
 
 	const bool canFly = ti->hasFlyingMovement() || (h->inBoat() && h->getBoat()->layer == EPathfindingLayer::AIR);
@@ -912,8 +912,8 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 	// should be called if hero changes tile but before applying TryMoveHero package
 	auto leaveTile = [&]()
 	{
-		for(const auto & objID : gameState()->getMap().getTile(h->visitablePos()).visitableObjects)
-			gameState()->getObjInstance(objID)->onHeroLeave(h);
+		for(const auto & objID : gameState().getMap().getTile(h->visitablePos()).visitableObjects)
+			gameState().getObjInstance(objID)->onHeroLeave(h);
 
 		this->getTilesInRange(tmh.fowRevealed, h->getSightCenter()+(tmh.end-tmh.start), h->getSightRadius(), ETileVisibility::HIDDEN, h->tempOwner);
 	};
@@ -1041,7 +1041,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 
 		turnTimerHandler->setEndTurnAllowed(h->getOwner(), !movingOntoWater && !movingOntoObstacle);
 		doMove(TryMoveHero::SUCCESS, lookForGuards, visitDest, LEAVING_TILE);
-		gameState()->statistic.accumulatedValues[asker].movementPointsUsed += tmh.movePoints;
+		gameState().statistic.accumulatedValues[asker].movementPointsUsed += tmh.movePoints;
 		return true;
 	}
 }
@@ -1085,7 +1085,7 @@ void CGameHandler::setOwner(const CGObjectInstance * obj, const PlayerColor owne
 	const CGTownInstance * town = dynamic_cast<const CGTownInstance *>(obj);
 	if (town) //town captured
 	{
-		gameState()->statistic.accumulatedValues[owner].lastCapturedTownDay = gameState()->getDate(Date::DAY);
+		gameState().statistic.accumulatedValues[owner].lastCapturedTownDay = gameState().getDate(Date::DAY);
 
 		if (owner.isValidPlayer()) //new owner is real player
 		{
@@ -1454,7 +1454,7 @@ void CGameHandler::sendToAllClients(CPackForClient & pack)
 void CGameHandler::sendAndApply(CPackForClient & pack)
 {
 	sendToAllClients(pack);
-	gameState()->apply(pack);
+	gameState().apply(pack);
 	logNetwork->trace("\tApplied on gameState(): %s", typeid(pack).name());
 }
 
@@ -1545,7 +1545,7 @@ void CGameHandler::save(const std::string & filename)
 	try
 	{
 		CSaveFile save(*CResourceHandler::get("local")->getResourceName(savePath));
-		gameState()->saveGame(save);
+		gameState().saveGame(save);
 		logGlobal->info("Saving server state");
 		save.save(*this);
 		logGlobal->info("Game has been successfully saved!");
@@ -1610,8 +1610,8 @@ bool CGameHandler::load(const std::string & filename)
 		gameLobby().announceMessage(str);
 		return false;
 	}
-	gameState()->preInit(LIBRARY);
-	gameState()->updateOnLoad(gameLobby().si.get());
+	gameState().preInit(LIBRARY);
+	gameState().updateOnLoad(gameLobby().si.get());
 	return true;
 }
 
@@ -2186,7 +2186,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
 	if(!force)
 	{
 		giveResources(t->tempOwner, -requestedBuilding->resources);
-		gameState()->statistic.accumulatedValues[t->tempOwner].spentResourcesForBuildings += requestedBuilding->resources;
+		gameState().statistic.accumulatedValues[t->tempOwner].spentResourcesForBuildings += requestedBuilding->resources;
 	}
 
 	//We know what has been built, apply changes. Do this as final step to properly update town window
@@ -2274,7 +2274,7 @@ bool CGameHandler::razeStructure (ObjectInstanceID tid, BuildingID bid)
 
 bool CGameHandler::spellResearch(ObjectInstanceID tid, SpellID spellAtSlot, bool accepted)
 {
-	CGTownInstance *t = gameState()->getTown(tid);
+	CGTownInstance *t = gameState().getTown(tid);
 
 	if(!getSettings().getBoolean(EGameSettings::TOWNS_SPELL_RESEARCH) && complain("Spell research not allowed!"))
 		return false;
@@ -2386,7 +2386,7 @@ bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst
 	//recruit
 	TResources cost = (c->getFullRecruitCost() * cram);
 	giveResources(army->tempOwner, -cost);
-	gameState()->statistic.accumulatedValues[army->tempOwner].spentResourcesForArmy += cost;
+	gameState().statistic.accumulatedValues[army->tempOwner].spentResourcesForArmy += cost;
 
 	SetAvailableCreatures sac;
 	sac.tid = objid;
@@ -2449,7 +2449,7 @@ bool CGameHandler::upgradeCreature(ObjectInstanceID objid, SlotID pos, CreatureI
 
 	//take resources
 	giveResources(player, -totalCost);
-	gameState()->statistic.accumulatedValues[player].spentResourcesForArmy += totalCost;
+	gameState().statistic.accumulatedValues[player].spentResourcesForArmy += totalCost;
 
 	//upgrade creature
 	changeStackType(StackLocation(obj->id, pos), upgID.toCreature());
@@ -2675,7 +2675,7 @@ bool CGameHandler::bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceI
 	auto & slotsDstSrc = ma.artsPack1;
 
 	// Temporary fitting set for artifacts. Used to select available slots before sending data.
-	CArtifactFittingSet artFittingSet(gameState()->cb, pdstSet->bearerType());
+	CArtifactFittingSet artFittingSet(gameState().cb, pdstSet->bearerType());
 
 	auto moveArtifact = [this, &artFittingSet, dstId](const CArtifactInstance * artifact,
 		ArtifactPosition srcSlot, std::vector<MoveArtifactInfo> & slots) -> void
@@ -3061,7 +3061,7 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, GameRe
 	if(dynamic_cast<const CGTownInstance *>(m))
 	{
 		saa.id = ObjectInstanceID::NONE;
-		saa.arts = gameState()->getMap().townMerchantArtifacts;
+		saa.arts = gameState().getMap().townMerchantArtifacts;
 	}
 	else if(const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(m)) //black market
 	{
@@ -3151,8 +3151,8 @@ bool CGameHandler::tradeResources(const IMarket *market, ui32 amountToSell, Play
 	giveResource(player, toSell, -b1 * amountToBoy);
 	giveResource(player, toBuy, b2 * amountToBoy);
 
-	gameState()->statistic.accumulatedValues[player].tradeVolume[toSell] += -b1 * amountToBoy;
-	gameState()->statistic.accumulatedValues[player].tradeVolume[toBuy] += b2 * amountToBoy;
+	gameState().statistic.accumulatedValues[player].tradeVolume[toSell] += -b1 * amountToBoy;
+	gameState().statistic.accumulatedValues[player].tradeVolume[toBuy] += b2 * amountToBoy;
 
 	return true;
 }
@@ -3478,7 +3478,7 @@ bool CGameHandler::buildBoat(ObjectInstanceID objid, PlayerColor playerID)
 	}
 
 	int3 tile = obj->bestLocation();
-	if (!gameState()->getMap().isInTheMap(tile))
+	if (!gameState().getMap().isInTheMap(tile))
 	{
 		complain("Cannot find appropriate tile for a boat!");
 		return false;
@@ -3514,7 +3514,7 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
 
 	if(!p || p->status != EPlayerStatus::INGAME) return;
 
-	auto victoryLossCheckResult = gameState()->checkForVictoryAndLoss(player);
+	auto victoryLossCheckResult = gameState().checkForVictoryAndLoss(player);
 
 	if (victoryLossCheckResult.victory() || victoryLossCheckResult.loss())
 	{
@@ -3525,14 +3525,14 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
 		PlayerEndsGame peg;
 		peg.player = player;
 		peg.victoryLossCheckResult = victoryLossCheckResult;
-		peg.statistic = StatisticDataSet(gameState()->statistic);
+		peg.statistic = StatisticDataSet(gameState().statistic);
 		addStatistics(peg.statistic); // add last turn befor win / loss
 		sendAndApply(peg);
 
 		if (victoryLossCheckResult.victory())
 		{
 			//one player won -> all enemies lost
-			for (auto i = gameState()->players.cbegin(); i!=gameState()->players.cend(); i++)
+			for (auto i = gameState().players.cbegin(); i!=gameState().players.cend(); i++)
 			{
 				if (i->first != player && getPlayerState(i->first)->status == EPlayerStatus::INGAME)
 				{
@@ -3568,7 +3568,7 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
 			}
 
 			//player lost -> all his objects become unflagged (neutral)
-			for (auto obj : gameState()->getMap().getObjects()) //unflag objs
+			for (auto obj : gameState().getMap().getObjects()) //unflag objs
 			{
 				if (obj && obj->tempOwner == player)
 					setOwner(obj, PlayerColor::NEUTRAL);
@@ -3578,7 +3578,7 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
 			std::set<PlayerColor> playerColors;
 
 			//do not copy player state (CBonusSystemNode) by value
-			for (const auto &playerState : gameState()->players) //players may have different colors, iterate over players and not integers
+			for (const auto &playerState : gameState().players) //players may have different colors, iterate over players and not integers
 			{
 				if (playerState.first != player)
 					playerColors.insert(playerState.first);
@@ -3624,7 +3624,7 @@ bool CGameHandler::dig(const CGHeroInstance *h)
 	InfoWindow iw;
 	iw.type = EInfoWindowMode::AUTO;
 	iw.player = h->tempOwner;
-	if (gameState()->getMap().grailPos == h->visitablePos())
+	if (gameState().getMap().grailPos == h->visitablePos())
 	{
 		ArtifactID grail = ArtifactID::GRAIL;
 
@@ -3656,9 +3656,9 @@ void CGameHandler::visitObjectOnTile(const TerrainTile &t, const CGHeroInstance
 	{
 		//to prevent self-visiting heroes on space press
 		if (t.visitableObjects.back() != h->id)
-			objectVisited(gameState()->getObjInstance(t.visitableObjects.back()), h);
+			objectVisited(gameState().getObjInstance(t.visitableObjects.back()), h);
 		else if (t.visitableObjects.size() > 1)
-			objectVisited(gameState()->getObjInstance(*(t.visitableObjects.end()-2)),h);
+			objectVisited(gameState().getObjInstance(*(t.visitableObjects.end()-2)),h);
 	}
 }
 
@@ -4055,7 +4055,7 @@ void CGameHandler::spawnWanderingMonsters(CreatureID creatureID)
 void CGameHandler::synchronizeArtifactHandlerLists()
 {
 	UpdateArtHandlerLists uahl;
-	uahl.allocatedArtifacts = gameState()->allocatedArtifacts;
+	uahl.allocatedArtifacts = gameState().allocatedArtifacts;
 	sendAndApply(uahl);
 }
 
@@ -4246,18 +4246,18 @@ std::shared_ptr<CGObjectInstance> CGameHandler::createNewObject(const int3 & vis
 {
 	TerrainId terrainType = ETerrainId::NONE;
 
-	if (!gameState()->isInTheMap(visitablePosition))
+	if (!gameState().isInTheMap(visitablePosition))
 		throw std::runtime_error("Attempt to create object outside map at " + visitablePosition.toString());
 
-	const TerrainTile & t = gameState()->getMap().getTile(visitablePosition);
+	const TerrainTile & t = gameState().getMap().getTile(visitablePosition);
 	terrainType = t.getTerrainID();
 
 	auto handler = LIBRARY->objtypeh->getHandlerFor(objectID, subID);
 
-	auto o = handler->create(gameState()->cb, nullptr);
+	auto o = handler->create(gameState().cb, nullptr);
 	handler->configureObject(o.get(), getRandomGenerator());
 	assert(o->ID == objectID);
-	gameState()->getMap().generateUniqueInstanceName(o.get());
+	gameState().getMap().generateUniqueInstanceName(o.get());
 
 	assert(!handler->getTemplates(terrainType).empty());
 	if (handler->getTemplates().empty())
@@ -4286,7 +4286,7 @@ void CGameHandler::createWanderingMonster(const int3 & visitablePosition, Creatu
 	cre->character = 2;
 	cre->gainedArtifact = ArtifactID::NONE;
 	cre->identifier = -1;
-	cre->addToSlot(SlotID(0), std::make_unique<CStackInstance>(gameState()->cb, creature, -1)); //add placeholder stack
+	cre->addToSlot(SlotID(0), std::make_unique<CStackInstance>(gameState().cb, creature, -1)); //add placeholder stack
 
 	newObject(createdObject, PlayerColor::NEUTRAL);
 }
@@ -4305,7 +4305,7 @@ void CGameHandler::createHole(const int3 & visitablePosition, PlayerColor initia
 
 void CGameHandler::newObject(std::shared_ptr<CGObjectInstance> object, PlayerColor initiator)
 {
-	object->initObj(gameState()->getRandomGenerator());
+	object->initObj(gameState().getRandomGenerator());
 
 	NewObject no;
 	no.newObject = object;

+ 2 - 2
server/CGameHandler.h

@@ -92,8 +92,8 @@ public:
 	bool isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2);
 	void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
 
-	CGameState * gameState() final { return gs.get(); }
-	const CGameState * gameState() const final { return gs.get(); }
+	CGameState & gameState() final { return *gs; }
+	const CGameState & gameState() const final { return *gs; }
 
 	// Helpers to create new object of specified type
 

+ 1 - 1
server/CVCMIServer.cpp

@@ -294,7 +294,7 @@ bool CVCMIServer::prepareToStartGame()
 void CVCMIServer::startGameImmediately()
 {
 	for(auto activeConnection : activeConnections)
-		activeConnection->enterGameplayConnectionMode(gh->gs.get());
+		activeConnection->enterGameplayConnectionMode(*gh->gs);
 
 	gh->start(si->mode == EStartMode::LOAD_GAME);
 	setState(EServerState::GAMEPLAY);

+ 1 - 1
server/NetPacksServer.cpp

@@ -397,7 +397,7 @@ void ApplyGhNetPackVisitor::visitQueryReply(QueryReply & pack)
 void ApplyGhNetPackVisitor::visitSaveLocalState(SaveLocalState & pack)
 {
 	gh.throwIfWrongPlayer(connection, &pack);
-	*gh.gameState()->getPlayerState(pack.player)->playerLocalSettings = pack.data;
+	*gh.gameState().getPlayerState(pack.player)->playerLocalSettings = pack.data;
 	result = true;
 }
 

+ 1 - 1
server/ServerSpellCastEnvironment.cpp

@@ -86,7 +86,7 @@ const CGameInfoCallback * ServerSpellCastEnvironment::getCb() const
 
 const CMap * ServerSpellCastEnvironment::getMap() const
 {
-	return &gh->gameState()->getMap();
+	return &gh->gameState().getMap();
 }
 
 bool ServerSpellCastEnvironment::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode mode)

+ 22 - 23
server/TurnTimerHandler.cpp

@@ -93,13 +93,13 @@ void TurnTimerHandler::update(int waitTimeMs)
 		return;
 
 	for(PlayerColor player(0); player < PlayerColor::PLAYER_LIMIT; ++player)
-		if(gameHandler.gameState()->isPlayerMakingTurn(player))
+		if(gameHandler.gameState().isPlayerMakingTurn(player))
 			onPlayerMakingTurn(player, waitTimeMs);
 
 	// create copy for iterations - battle might end during onBattleLoop call
 	std::vector<BattleID> ongoingBattles;
 
-	for (auto & battle : gameHandler.gameState()->currentBattles)
+	for (auto & battle : gameHandler.gameState().currentBattles)
 		ongoingBattles.push_back(battle->battleID);
 
 	for (auto & battleID : ongoingBattles)
@@ -123,9 +123,8 @@ bool TurnTimerHandler::timerCountDown(int & timer, int initialTimer, PlayerColor
 
 void TurnTimerHandler::onPlayerMakingTurn(PlayerColor player, int waitTime)
 {
-	const auto * gs = gameHandler.gameState();
 	const auto * si = gameHandler.getStartInfo();
-	if(!si || !gs || !si->turnTimerInfo.isEnabled())
+	if(!si || !si->turnTimerInfo.isEnabled())
 		return;
 	
 	auto & timer = timers[player];
@@ -149,9 +148,9 @@ void TurnTimerHandler::onPlayerMakingTurn(PlayerColor player, int waitTime)
 
 bool TurnTimerHandler::isPvpBattle(const BattleID & battleID) const
 {
-	const auto * gs = gameHandler.gameState();
-	auto attacker = gs->getBattle(battleID)->getSidePlayer(BattleSide::ATTACKER);
-	auto defender = gs->getBattle(battleID)->getSidePlayer(BattleSide::DEFENDER);
+	const auto & gs = gameHandler.gameState();
+	auto attacker = gs.getBattle(battleID)->getSidePlayer(BattleSide::ATTACKER);
+	auto defender = gs.getBattle(battleID)->getSidePlayer(BattleSide::DEFENDER);
 	if(attacker.isValidPlayer() && defender.isValidPlayer())
 	{
 		const auto * attackerState = gameHandler.getPlayerState(attacker);
@@ -164,13 +163,13 @@ bool TurnTimerHandler::isPvpBattle(const BattleID & battleID) const
 
 void TurnTimerHandler::onBattleStart(const BattleID & battleID)
 {
-	const auto * gs = gameHandler.gameState();
+	const auto & gs = gameHandler.gameState();
 	const auto * si = gameHandler.getStartInfo();
-	if(!si || !gs)
+	if(!si)
 		return;
 
-	auto attacker = gs->getBattle(battleID)->getSidePlayer(BattleSide::ATTACKER);
-	auto defender = gs->getBattle(battleID)->getSidePlayer(BattleSide::DEFENDER);
+	auto attacker = gs.getBattle(battleID)->getSidePlayer(BattleSide::ATTACKER);
+	auto defender = gs.getBattle(battleID)->getSidePlayer(BattleSide::DEFENDER);
 	
 	bool pvpBattle = isPvpBattle(battleID);
 	
@@ -191,9 +190,9 @@ void TurnTimerHandler::onBattleStart(const BattleID & battleID)
 
 void TurnTimerHandler::onBattleEnd(const BattleID & battleID)
 {
-	const auto * gs = gameHandler.gameState();
+	const auto & gs = gameHandler.gameState();
 	const auto * si = gameHandler.getStartInfo();
-	if(!si || !gs)
+	if(!si)
 	{
 		assert(0);
 		return;
@@ -202,8 +201,8 @@ void TurnTimerHandler::onBattleEnd(const BattleID & battleID)
 	if (!si->turnTimerInfo.isBattleEnabled())
 		return;
 	
-	auto attacker = gs->getBattle(battleID)->getSidePlayer(BattleSide::ATTACKER);
-	auto defender = gs->getBattle(battleID)->getSidePlayer(BattleSide::DEFENDER);
+	auto attacker = gs.getBattle(battleID)->getSidePlayer(BattleSide::ATTACKER);
+	auto defender = gs.getBattle(battleID)->getSidePlayer(BattleSide::DEFENDER);
 	
 	for(auto i : {attacker, defender})
 	{
@@ -219,9 +218,9 @@ void TurnTimerHandler::onBattleEnd(const BattleID & battleID)
 
 void TurnTimerHandler::onBattleNextStack(const BattleID & battleID, const CStack & stack)
 {
-	const auto * gs = gameHandler.gameState();
+	const auto & gs = gameHandler.gameState();
 	const auto * si = gameHandler.getStartInfo();
-	if(!si || !gs || !gs->getBattle(battleID))
+	if(!si || !gs.getBattle(battleID))
 	{
 		assert(0);
 		return;
@@ -245,9 +244,9 @@ void TurnTimerHandler::onBattleNextStack(const BattleID & battleID, const CStack
 
 void TurnTimerHandler::onBattleLoop(const BattleID & battleID, int waitTime)
 {
-	const auto * gs = gameHandler.gameState();
+	const auto & gs = gameHandler.gameState();
 	const auto * si = gameHandler.getStartInfo();
-	if(!si || !gs)
+	if(!si)
 	{
 		assert(0);
 		return;
@@ -258,19 +257,19 @@ void TurnTimerHandler::onBattleLoop(const BattleID & battleID, int waitTime)
 
 	BattleSide side = BattleSide::NONE;
 	const CStack * stack = nullptr;
-	bool isTactisPhase = gs->getBattle(battleID)->battleTacticDist() > 0;
+	bool isTactisPhase = gs.getBattle(battleID)->battleTacticDist() > 0;
 	
 	if(isTactisPhase)
-		side = gs->getBattle(battleID)->battleGetTacticsSide();
+		side = gs.getBattle(battleID)->battleGetTacticsSide();
 	else
 	{
-		stack = gs->getBattle(battleID)->battleGetStackByID(gs->getBattle(battleID)->getActiveStackID());
+		stack = gs.getBattle(battleID)->battleGetStackByID(gs.getBattle(battleID)->getActiveStackID());
 		if(!stack || !stack->getOwner().isValidPlayer())
 			return;
 		side = stack->unitSide();
 	}
 	
-	auto player = gs->getBattle(battleID)->getSidePlayer(side);
+	auto player = gs.getBattle(battleID)->getSidePlayer(side);
 	if(!player.isValidPlayer())
 		return;
 	

+ 11 - 11
server/battles/BattleProcessor.cpp

@@ -58,7 +58,7 @@ void BattleProcessor::engageIntoBattle(PlayerColor player)
 void BattleProcessor::restartBattle(const BattleID & battleID, const CArmedInstance *army1, const CArmedInstance *army2, int3 tile,
 								const CGHeroInstance *hero1, const CGHeroInstance *hero2, const BattleLayout & layout, const CGTownInstance *town)
 {
-	auto battle = gameHandler->gameState()->getBattle(battleID);
+	auto battle = gameHandler->gameState().getBattle(battleID);
 
 	auto lastBattleQuery = std::dynamic_pointer_cast<CBattleQuery>(gameHandler->queries->topQuery(battle->getSide(BattleSide::ATTACKER).color));
 	if(!lastBattleQuery)
@@ -98,15 +98,15 @@ void BattleProcessor::restartBattle(const BattleID & battleID, const CArmedInsta
 void BattleProcessor::startBattle(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile,
 								const CGHeroInstance *hero1, const CGHeroInstance *hero2, const BattleLayout & layout, const CGTownInstance *town)
 {
-	assert(gameHandler->gameState()->getBattle(army1->getOwner()) == nullptr);
-	assert(gameHandler->gameState()->getBattle(army2->getOwner()) == nullptr);
+	assert(gameHandler->gameState().getBattle(army1->getOwner()) == nullptr);
+	assert(gameHandler->gameState().getBattle(army2->getOwner()) == nullptr);
 
 	BattleSideArray<const CArmedInstance *> armies{army1, army2};
 	BattleSideArray<const CGHeroInstance*>heroes{hero1, hero2};
 
 	auto battleID = setupBattle(tile, armies, heroes, layout, town); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
 
-	const auto * battle = gameHandler->gameState()->getBattle(battleID);
+	const auto * battle = gameHandler->gameState().getBattle(battleID);
 	assert(battle);
 	
 	//add battle bonuses based from player state only when attacks neutral creatures
@@ -160,10 +160,10 @@ BattleID BattleProcessor::setupBattle(int3 tile, BattleSideArray<const CArmedIns
 	TerrainId terrain = t.getTerrainID();
 	if (town)
 		terrain = town->getNativeTerrain();
-	else if (gameHandler->gameState()->getMap().isCoastalTile(tile)) //coastal tile is always ground
+	else if (gameHandler->gameState().getMap().isCoastalTile(tile)) //coastal tile is always ground
 		terrain = ETerrainId::SAND;
 
-	BattleField battlefieldType = gameHandler->gameState()->battleGetBattlefieldType(tile, gameHandler->getRandomGenerator());
+	BattleField battlefieldType = gameHandler->gameState().battleGetBattlefieldType(tile, gameHandler->getRandomGenerator());
 
 	if (town)
 	{
@@ -175,8 +175,8 @@ BattleID BattleProcessor::setupBattle(int3 tile, BattleSideArray<const CArmedIns
 
 	//send info about battles
 	BattleStart bs;
-	bs.info = BattleInfo::setupBattle(gameHandler->gameState()->cb, tile, terrain, battlefieldType, armies, heroes, layout, town);
-	bs.battleID = gameHandler->gameState()->nextBattleID;
+	bs.info = BattleInfo::setupBattle(gameHandler->gameState().cb, tile, terrain, battlefieldType, armies, heroes, layout, town);
+	bs.battleID = gameHandler->gameState().nextBattleID;
 
 	engageIntoBattle(bs.info->getSide(BattleSide::ATTACKER).color);
 	engageIntoBattle(bs.info->getSide(BattleSide::DEFENDER).color);
@@ -273,13 +273,13 @@ void BattleProcessor::updateGateState(const CBattleInfoCallback & battle)
 
 bool BattleProcessor::makePlayerBattleAction(const BattleID & battleID, PlayerColor player, const BattleAction &ba)
 {
-	const auto * battle = gameHandler->gameState()->getBattle(battleID);
+	const auto * battle = gameHandler->gameState().getBattle(battleID);
 
 	if (!battle)
 		return false;
 
 	bool result = actionsProcessor->makePlayerBattleAction(*battle, player, ba);
-	if (gameHandler->gameState()->getBattle(battleID) != nullptr && !resultProcessor->battleIsEnding(*battle))
+	if (gameHandler->gameState().getBattle(battleID) != nullptr && !resultProcessor->battleIsEnding(*battle))
 		flowProcessor->onActionMade(*battle, ba);
 	return result;
 }
@@ -297,7 +297,7 @@ bool BattleProcessor::makeAutomaticBattleAction(const CBattleInfoCallback & batt
 
 void BattleProcessor::endBattleConfirm(const BattleID & battleID)
 {
-	auto battle = gameHandler->gameState()->getBattle(battleID);
+	auto battle = gameHandler->gameState().getBattle(battleID);
 	assert(battle);
 
 	if (!battle)

+ 12 - 12
server/battles/BattleResultProcessor.cpp

@@ -337,25 +337,25 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
 	if(loserHero && !finishingBattle->isDraw())
 	{
 		const CGHeroInstance * strongestHero = nullptr;
-		for(auto & hero : gameHandler->gameState()->getPlayerState(finishingBattle->loser)->getHeroes())
+		for(auto & hero : gameHandler->gameState().getPlayerState(finishingBattle->loser)->getHeroes())
 			if(!strongestHero || hero->exp > strongestHero->exp)
 				strongestHero = hero;
 		if(strongestHero->id == finishingBattle->loserId && strongestHero->level > 5)
-			gameHandler->gameState()->statistic.accumulatedValues[finishingBattle->victor].lastDefeatedStrongestHeroDay = gameHandler->gameState()->getDate(Date::DAY);
+			gameHandler->gameState().statistic.accumulatedValues[finishingBattle->victor].lastDefeatedStrongestHeroDay = gameHandler->gameState().getDate(Date::DAY);
 	}
 	if(battle.sideToPlayer(BattleSide::ATTACKER) == PlayerColor::NEUTRAL || battle.sideToPlayer(BattleSide::DEFENDER) == PlayerColor::NEUTRAL)
 	{
-		gameHandler->gameState()->statistic.accumulatedValues[battle.sideToPlayer(BattleSide::ATTACKER)].numBattlesNeutral++;
-		gameHandler->gameState()->statistic.accumulatedValues[battle.sideToPlayer(BattleSide::DEFENDER)].numBattlesNeutral++;
+		gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(BattleSide::ATTACKER)].numBattlesNeutral++;
+		gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(BattleSide::DEFENDER)].numBattlesNeutral++;
 		if(!finishingBattle->isDraw())
-			gameHandler->gameState()->statistic.accumulatedValues[battle.sideToPlayer(finishingBattle->winnerSide)].numWinBattlesNeutral++;
+			gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(finishingBattle->winnerSide)].numWinBattlesNeutral++;
 	}
 	else
 	{
-		gameHandler->gameState()->statistic.accumulatedValues[battle.sideToPlayer(BattleSide::ATTACKER)].numBattlesPlayer++;
-		gameHandler->gameState()->statistic.accumulatedValues[battle.sideToPlayer(BattleSide::DEFENDER)].numBattlesPlayer++;
+		gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(BattleSide::ATTACKER)].numBattlesPlayer++;
+		gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(BattleSide::DEFENDER)].numBattlesPlayer++;
 		if(!finishingBattle->isDraw())
-			gameHandler->gameState()->statistic.accumulatedValues[battle.sideToPlayer(finishingBattle->winnerSide)].numWinBattlesPlayer++;
+			gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(finishingBattle->winnerSide)].numWinBattlesPlayer++;
 	}
 
 	BattleResultAccepted raccepted;
@@ -394,12 +394,12 @@ void BattleResultProcessor::battleFinalize(const BattleID & battleID, const Batt
 	// but the battle consequences are applied after final player is unblocked. Hard to abuse...
 	// Still, it looks like a hole.
 
-	const auto battle = std::find_if(gameHandler->gameState()->currentBattles.begin(), gameHandler->gameState()->currentBattles.end(),
+	const auto battle = std::find_if(gameHandler->gameState().currentBattles.begin(), gameHandler->gameState().currentBattles.end(),
 		[battleID](const auto & desiredBattle)
 		{
 			return desiredBattle->battleID == battleID;
 		});
-	assert(battle != gameHandler->gameState()->currentBattles.end());
+	assert(battle != gameHandler->gameState().currentBattles.end());
 
 	const auto winnerHero = (*battle)->battleGetFightingHero(finishingBattle->winnerSide);
 	const auto loserHero = (*battle)->battleGetFightingHero(CBattleInfoEssentials::otherSide(finishingBattle->winnerSide));
@@ -499,13 +499,13 @@ void BattleResultProcessor::battleFinalize(const BattleID & battleID, const Batt
 
 	if (result.result == EBattleResult::SURRENDER)
 	{
-		gameHandler->gameState()->statistic.accumulatedValues[finishingBattle->loser].numHeroSurrendered++;
+		gameHandler->gameState().statistic.accumulatedValues[finishingBattle->loser].numHeroSurrendered++;
 		gameHandler->heroPool->onHeroSurrendered(finishingBattle->loser, loserHero);
 	}
 
 	if (result.result == EBattleResult::ESCAPE)
 	{
-		gameHandler->gameState()->statistic.accumulatedValues[finishingBattle->loser].numHeroEscaped++;
+		gameHandler->gameState().statistic.accumulatedValues[finishingBattle->loser].numHeroEscaped++;
 		gameHandler->heroPool->onHeroEscaped(finishingBattle->loser, loserHero);
 	}
 

+ 6 - 6
server/processors/HeroPoolProcessor.cpp

@@ -34,7 +34,7 @@ HeroPoolProcessor::HeroPoolProcessor(CGameHandler * gameHandler)
 
 TavernHeroSlot HeroPoolProcessor::selectSlotForRole(const PlayerColor & player, TavernSlotRole roleID)
 {
-	const auto & heroesPool = gameHandler->gameState()->heroesPool;
+	const auto & heroesPool = gameHandler->gameState().heroesPool;
 
 	const auto & heroes = heroesPool->getHeroesFor(player);
 
@@ -110,7 +110,7 @@ void HeroPoolProcessor::selectNewHeroForSlot(const PlayerColor & color, TavernHe
 	sah.replenishPoints = true;
 
 	CGHeroInstance *newHero = nextHero.hasValue()?
-		gameHandler->gameState()->heroesPool->unusedHeroesFromPool()[nextHero]:
+		gameHandler->gameState().heroesPool->unusedHeroesFromPool()[nextHero]:
 		pickHeroFor(needNativeHero, color);
 
 	if (newHero)
@@ -150,7 +150,7 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy
 	const PlayerState * playerState = gameHandler->getPlayerState(player);
 	const CGObjectInstance * mapObject = gameHandler->getObj(objectID);
 	const CGTownInstance * town = gameHandler->getTown(objectID);
-	const auto & heroesPool = gameHandler->gameState()->heroesPool;
+	const auto & heroesPool = gameHandler->gameState().heroesPool;
 
 	if (!mapObject && gameHandler->complain("Invalid map object!"))
 		return false;
@@ -256,7 +256,7 @@ std::vector<const CHeroClass *> HeroPoolProcessor::findAvailableClassesFor(const
 {
 	std::vector<const CHeroClass *> result;
 
-	const auto & heroesPool = gameHandler->gameState()->heroesPool;
+	const auto & heroesPool = gameHandler->gameState().heroesPool;
 	FactionID factionID = gameHandler->getPlayerSettings(player)->castle;
 
 	for(const auto & elem : heroesPool->unusedHeroesFromPool())
@@ -278,7 +278,7 @@ std::vector<CGHeroInstance *> HeroPoolProcessor::findAvailableHeroesFor(const Pl
 {
 	std::vector<CGHeroInstance *> result;
 
-	const auto & heroesPool = gameHandler->gameState()->heroesPool;
+	const auto & heroesPool = gameHandler->gameState().heroesPool;
 
 	for(const auto & elem : heroesPool->unusedHeroesFromPool())
 	{
@@ -303,7 +303,7 @@ const CHeroClass * HeroPoolProcessor::pickClassFor(bool isNative, const PlayerCo
 	}
 
 	FactionID factionID = gameHandler->getPlayerSettings(player)->castle;
-	const auto & heroesPool = gameHandler->gameState()->heroesPool;
+	const auto & heroesPool = gameHandler->gameState().heroesPool;
 	const auto & currentTavern = heroesPool->getHeroesFor(player);
 
 	std::vector<const CHeroClass *> potentialClasses = findAvailableClassesFor(player);

+ 27 - 27
server/processors/NewTurnProcessor.cpp

@@ -41,9 +41,9 @@ NewTurnProcessor::NewTurnProcessor(CGameHandler * gameHandler)
 
 void NewTurnProcessor::handleTimeEvents(PlayerColor color)
 {
-	for (auto const & event : gameHandler->gameState()->getMap().events)
+	for (auto const & event : gameHandler->gameState().getMap().events)
 	{
-		if (!event.occursToday(gameHandler->gameState()->day))
+		if (!event.occursToday(gameHandler->gameState().day))
 			continue;
 
 		if (!event.affectsPlayer(color, gameHandler->getPlayerState(color)->isHuman()))
@@ -77,7 +77,7 @@ void NewTurnProcessor::handleTownEvents(const CGTownInstance * town)
 {
 	for (auto const & event : town->events)
 	{
-		if (!event.occursToday(gameHandler->gameState()->day))
+		if (!event.occursToday(gameHandler->gameState().day))
 			continue;
 
 		PlayerColor player = town->getOwner();
@@ -134,7 +134,7 @@ void NewTurnProcessor::handleTownEvents(const CGTownInstance * town)
 
 void NewTurnProcessor::onPlayerTurnStarted(PlayerColor which)
 {
-	const auto * playerState = gameHandler->gameState()->getPlayerState(which);
+	const auto * playerState = gameHandler->gameState().getPlayerState(which);
 
 	handleTimeEvents(which);
 	for (const auto * t : playerState->getTowns())
@@ -153,7 +153,7 @@ void NewTurnProcessor::onPlayerTurnStarted(PlayerColor which)
 
 void NewTurnProcessor::onPlayerTurnEnded(PlayerColor which)
 {
-	const auto * playerState = gameHandler->gameState()->getPlayerState(which);
+	const auto * playerState = gameHandler->gameState().getPlayerState(which);
 	assert(playerState->status == EPlayerStatus::INGAME);
 
 	if (playerState->getTowns().empty())
@@ -186,7 +186,7 @@ void NewTurnProcessor::onPlayerTurnEnded(PlayerColor which)
 ResourceSet NewTurnProcessor::generatePlayerIncome(PlayerColor playerID, bool newWeek)
 {
 	const auto & playerSettings = gameHandler->getPlayerSettings(playerID);
-	const PlayerState & state = gameHandler->gameState()->players.at(playerID);
+	const PlayerState & state = gameHandler->gameState().players.at(playerID);
 	ResourceSet income;
 
 	for (const auto & town : state.getTowns())
@@ -249,9 +249,9 @@ ResourceSet NewTurnProcessor::generatePlayerIncome(PlayerColor playerID, bool ne
 	if (!state.isHuman())
 	{
 		// Initialize bonuses for different resources
-		int difficultyIndex = gameHandler->gameState()->getStartInfo()->difficulty;
+		int difficultyIndex = gameHandler->gameState().getStartInfo()->difficulty;
 		const std::string & difficultyName = GameConstants::DIFFICULTY_NAMES[difficultyIndex];
-		const JsonNode & weeklyBonusesConfig = gameHandler->gameState()->getSettings().getValue(EGameSettings::RESOURCES_WEEKLY_BONUSES_AI);
+		const JsonNode & weeklyBonusesConfig = gameHandler->gameState().getSettings().getValue(EGameSettings::RESOURCES_WEEKLY_BONUSES_AI);
 		const JsonNode & difficultyConfig = weeklyBonusesConfig[difficultyName];
 
 		// Distribute weekly bonuses over 7 days, depending on the current day of the week
@@ -259,7 +259,7 @@ ResourceSet NewTurnProcessor::generatePlayerIncome(PlayerColor playerID, bool ne
 		{
 			const std::string & name = GameConstants::RESOURCE_NAMES[i];
 			int64_t weeklyBonus = difficultyConfig[name].Integer();
-			int64_t dayOfWeek = gameHandler->gameState()->getDate(Date::DAY_OF_WEEK);
+			int64_t dayOfWeek = gameHandler->gameState().getDate(Date::DAY_OF_WEEK);
 			int64_t dailyIncome = incomeHandicapped[i];
 			int64_t amountTillToday = dailyIncome * weeklyBonus * (dayOfWeek-1) / 7 / 100;
 			int64_t amountAfterToday = dailyIncome * weeklyBonus * dayOfWeek / 7 / 100;
@@ -436,7 +436,7 @@ RumorState NewTurnProcessor::pickNewRumor()
 	static const std::vector<RumorState::ERumorType> rumorTypes = {RumorState::TYPE_MAP, RumorState::TYPE_SPECIAL, RumorState::TYPE_RAND, RumorState::TYPE_RAND};
 	std::vector<RumorState::ERumorTypeSpecial> sRumorTypes = {
 															  RumorState::RUMOR_OBELISKS, RumorState::RUMOR_ARTIFACTS, RumorState::RUMOR_ARMY, RumorState::RUMOR_INCOME};
-	if(gameHandler->gameState()->getMap().grailPos.isValid()) // Grail should always be on map, but I had related crash I didn't manage to reproduce
+	if(gameHandler->gameState().getMap().grailPos.isValid()) // Grail should always be on map, but I had related crash I didn't manage to reproduce
 		sRumorTypes.push_back(RumorState::RUMOR_GRAIL);
 
 	int rumorId = -1;
@@ -451,11 +451,11 @@ RumorState NewTurnProcessor::pickNewRumor()
 			case RumorState::TYPE_SPECIAL:
 			{
 				SThievesGuildInfo tgi;
-				gameHandler->gameState()->obtainPlayersStats(tgi, 20);
+				gameHandler->gameState().obtainPlayersStats(tgi, 20);
 				rumorId = *RandomGeneratorUtil::nextItem(sRumorTypes, rand);
 				if(rumorId == RumorState::RUMOR_GRAIL)
 				{
-					rumorExtra = gameHandler->gameState()->getTile(gameHandler->gameState()->getMap().grailPos)->getTerrainID().getNum();
+					rumorExtra = gameHandler->gameState().getTile(gameHandler->gameState().getMap().grailPos)->getTerrainID().getNum();
 					break;
 				}
 
@@ -484,9 +484,9 @@ RumorState NewTurnProcessor::pickNewRumor()
 			}
 			case RumorState::TYPE_MAP:
 				// Makes sure that map rumors only used if there enough rumors too choose from
-				if(!gameHandler->gameState()->getMap().rumors.empty() && (gameHandler->gameState()->getMap().rumors.size() > 1 || !gameHandler->gameState()->currentRumor.last.count(RumorState::TYPE_MAP)))
+				if(!gameHandler->gameState().getMap().rumors.empty() && (gameHandler->gameState().getMap().rumors.size() > 1 || !gameHandler->gameState().currentRumor.last.count(RumorState::TYPE_MAP)))
 				{
-					rumorId = rand.nextInt(gameHandler->gameState()->getMap().rumors.size() - 1);
+					rumorId = rand.nextInt(gameHandler->gameState().getMap().rumors.size() - 1);
 					break;
 				}
 				else
@@ -507,9 +507,9 @@ RumorState NewTurnProcessor::pickNewRumor()
 
 std::tuple<EWeekType, CreatureID> NewTurnProcessor::pickWeekType(bool newMonth)
 {
-	for (const auto & townID : gameHandler->gameState()->getMap().getAllTowns())
+	for (const auto & townID : gameHandler->gameState().getMap().getAllTowns())
 	{
-		auto t = gameHandler->gameState()->getTown(townID);
+		auto t = gameHandler->gameState().getTown(townID);
 		if (t->hasBuilt(BuildingID::GRAIL, ETownType::INFERNO))
 			return { EWeekType::DEITYOFFIRE, CreatureID::IMP };
 	}
@@ -565,7 +565,7 @@ std::vector<SetMana> NewTurnProcessor::updateHeroesManaPoints()
 {
 	std::vector<SetMana> result;
 
-	for (auto & elem : gameHandler->gameState()->players)
+	for (auto & elem : gameHandler->gameState().players)
 	{
 		for (CGHeroInstance *h : elem.second.getHeroes())
 		{
@@ -582,13 +582,13 @@ std::vector<SetMovePoints> NewTurnProcessor::updateHeroesMovementPoints()
 {
 	std::vector<SetMovePoints> result;
 
-	for (auto & elem : gameHandler->gameState()->players)
+	for (auto & elem : gameHandler->gameState().players)
 	{
 		for (CGHeroInstance *h : elem.second.getHeroes())
 		{
 			auto ti = h->getTurnInfo(1);
 			// NOTE: this code executed when bonuses of previous day not yet updated (this happen in NewTurn::applyGs). See issue 2356
-			int32_t newMovementPoints = h->movementPointsLimitCached(gameHandler->gameState()->getMap().getTile(h->visitablePos()).isLand(), ti.get());
+			int32_t newMovementPoints = h->movementPointsLimitCached(gameHandler->gameState().getMap().getTile(h->visitablePos()).isLand(), ti.get());
 
 			if (newMovementPoints != h->movementPointsRemaining())
 				result.emplace_back(h->id, newMovementPoints, true);
@@ -643,7 +643,7 @@ NewTurn NewTurnProcessor::generateNewTurnPack()
 	NewTurn n;
 	n.specialWeek = EWeekType::FIRST_WEEK;
 	n.creatureid = CreatureID::NONE;
-	n.day = gameHandler->gameState()->day + 1;
+	n.day = gameHandler->gameState().day + 1;
 
 	bool firstTurn = !gameHandler->getDate(Date::DAY);
 	bool newWeek = gameHandler->getDate(Date::DAY_OF_WEEK) == 7; //day numbers are confusing, as day was not yet switched
@@ -651,7 +651,7 @@ NewTurn NewTurnProcessor::generateNewTurnPack()
 
 	if (!firstTurn)
 	{
-		for (const auto & player : gameHandler->gameState()->players)
+		for (const auto & player : gameHandler->gameState().players)
 			n.playerIncome[player.first] = generatePlayerIncome(player.first, newWeek);
 	}
 
@@ -667,9 +667,9 @@ NewTurn NewTurnProcessor::generateNewTurnPack()
 
 	if (newWeek)
 	{
-		for (const auto & townID : gameHandler->gameState()->getMap().getAllTowns())
+		for (const auto & townID : gameHandler->gameState().getMap().getAllTowns())
 		{
-			auto t = gameHandler->gameState()->getTown(townID);
+			auto t = gameHandler->gameState().getTown(townID);
 			n.availableCreatures.push_back(generateTownGrowth(t, n.specialWeek, n.creatureid, firstTurn));
 		}
 	}
@@ -699,9 +699,9 @@ void NewTurnProcessor::onNewTurn()
 
 	if (newWeek)
 	{
-		for (const auto & townID : gameHandler->gameState()->getMap().getAllTowns())
+		for (const auto & townID : gameHandler->gameState().getMap().getAllTowns())
 		{
-			auto t = gameHandler->gameState()->getTown(townID);
+			auto t = gameHandler->gameState().getTown(townID);
 			if (t->hasBuilt(BuildingSubID::PORTAL_OF_SUMMONING))
 				gameHandler->setPortalDwelling(t, true, (n.specialWeek == EWeekType::PLAGUE ? true : false)); //set creatures for Portal of Summoning
 		}
@@ -709,9 +709,9 @@ void NewTurnProcessor::onNewTurn()
 
 	if (newWeek && !firstTurn)
 	{
-		for (const auto & townID : gameHandler->gameState()->getMap().getAllTowns())
+		for (const auto & townID : gameHandler->gameState().getMap().getAllTowns())
 		{
-			auto t = gameHandler->gameState()->getTown(townID);
+			auto t = gameHandler->gameState().getTown(townID);
 			if (!t->getOwner().isValidPlayer())
 				updateNeutralTownGarrison(t, 1 + gameHandler->getDate(Date::DAY) / 7);
 		}

+ 8 - 8
server/processors/PlayerMessageProcessor.cpp

@@ -127,7 +127,7 @@ void PlayerMessageProcessor::commandSave(PlayerColor player, const std::vector<s
 void PlayerMessageProcessor::commandCheaters(PlayerColor player, const std::vector<std::string> & words)
 {
 	int playersCheated = 0;
-	for(const auto & player : gameHandler->gameState()->players)
+	for(const auto & player : gameHandler->gameState().players)
 	{
 		if(player.second.cheated)
 		{
@@ -148,7 +148,7 @@ void PlayerMessageProcessor::commandStatistic(PlayerColor player, const std::vec
 	if(!isHost)
 		return;
 
-	std::string path = gameHandler->gameState()->statistic.writeCsv();
+	std::string path = gameHandler->gameState().statistic.writeCsv();
 
 	auto str = MetaString::createFromTextID("vcmi.broadcast.statisticFile");
 	str.replaceRawString(path);
@@ -484,7 +484,7 @@ void PlayerMessageProcessor::cheatGiveScrolls(PlayerColor player, const CGHeroIn
 		return;
 
 	for(const auto & spell : LIBRARY->spellh->objects)
-		if(gameHandler->gameState()->isAllowed(spell->getId()) && !spell->isSpecial())
+		if(gameHandler->gameState().isAllowed(spell->getId()) && !spell->isSpecial())
 		{
 			gameHandler->giveHeroNewScroll(hero, spell->getId(), ArtifactPosition::FIRST_AVAILABLE);
 		}
@@ -606,8 +606,8 @@ void PlayerMessageProcessor::cheatMapReveal(PlayerColor player, bool reveal)
 	FoWChange fc;
 	fc.mode = reveal ? ETileVisibility::REVEALED : ETileVisibility::HIDDEN;
 	fc.player = player;
-	const auto & fowMap = gameHandler->gameState()->getPlayerTeam(player)->fogOfWarMap;
-	const auto & mapSize = gameHandler->gameState()->getMapSize();
+	const auto & fowMap = gameHandler->gameState().getPlayerTeam(player)->fogOfWarMap;
+	const auto & mapSize = gameHandler->gameState().getMapSize();
 	auto hlp_tab = new int3[mapSize.x * mapSize.y * mapSize.z];
 	int lastUnc = 0;
 
@@ -626,9 +626,9 @@ void PlayerMessageProcessor::cheatMapReveal(PlayerColor player, bool reveal)
 
 void PlayerMessageProcessor::cheatPuzzleReveal(PlayerColor player)
 {
-	TeamState *t = gameHandler->gameState()->getPlayerTeam(player);
+	TeamState *t = gameHandler->gameState().getPlayerTeam(player);
 
-	for(auto & obj : gameHandler->gameState()->getMap().getObjects<CGObelisk>())
+	for(auto & obj : gameHandler->gameState().getMap().getObjects<CGObelisk>())
 	{
 		if(!obj->wasVisited(player))
 		{
@@ -724,7 +724,7 @@ bool PlayerMessageProcessor::handleCheatCode(const std::string & cheat, PlayerCo
 
 	bool playerTargetedCheat = false;
 
-	for (const auto & i : gameHandler->gameState()->players)
+	for (const auto & i : gameHandler->gameState().players)
 	{
 		if (words.empty())
 			break;

+ 1 - 1
server/processors/TurnOrderProcessor.cpp

@@ -109,7 +109,7 @@ bool TurnOrderProcessor::playersInContact(PlayerColor left, PlayerColor right) c
 	const auto * leftInfo = gameHandler->getPlayerState(left, false);
 	const auto * rightInfo = gameHandler->getPlayerState(right, false);
 
-	for (auto obj : gameHandler->gameState()->getMap().getObjects())
+	for (auto obj : gameHandler->gameState().getMap().getObjects())
 	{
 		if (obj->asOwnable())
 		{

+ 5 - 5
server/queries/VisitQueries.cpp

@@ -34,8 +34,8 @@ bool VisitQuery::blocksPack(const CPackForServer * pack) const
 
 void MapObjectVisitQuery::onExposure(QueryPtr topQuery)
 {
-	auto object = gh->gameState()->getObjInstance(visitedObject);
-	auto hero = gh->gameState()->getHero(visitingHero);
+	auto object = gh->gameState().getObjInstance(visitedObject);
+	auto hero = gh->gameState().getHero(visitingHero);
 
 	//Object may have been removed and deleted.
 	if (object)
@@ -52,7 +52,7 @@ MapObjectVisitQuery::MapObjectVisitQuery(CGameHandler * owner, const CGObjectIns
 
 void MapObjectVisitQuery::onRemoval(PlayerColor color)
 {
-	auto object = gh->gameState()->getObjInstance(visitedObject);
+	auto object = gh->gameState().getObjInstance(visitedObject);
 
 	gh->objectVisitEnded(visitingHero, players.front());
 
@@ -73,8 +73,8 @@ TownBuildingVisitQuery::TownBuildingVisitQuery(CGameHandler * owner, const CGTow
 
 void TownBuildingVisitQuery::onExposure(QueryPtr topQuery)
 {
-	auto object = gh->gameState()->getObjInstance(visitedObject);
-	auto hero = gh->gameState()->getHero(visitingHero);
+	auto object = gh->gameState().getObjInstance(visitedObject);
+	auto hero = gh->gameState().getHero(visitingHero);
 
 	topQuery->notifyObjectAboutRemoval(object, hero);
 

+ 2 - 2
test/mock/mock_IGameCallback.h

@@ -28,8 +28,8 @@ public:
 	virtual ~GameCallbackMock();
 
 	void setGameState(std::shared_ptr<CGameState> gameState);
-	CGameState * gameState() final { return gamestate.get(); }
-	const CGameState * gameState() const final { return gamestate.get(); }
+	CGameState & gameState() final { return *gamestate; }
+	const CGameState & gameState() const final { return *gamestate; }
 
 
 	///STUBS, to be removed as long as same methods moved from GameHandler