瀏覽代碼

CClient no longer inherits from CGameInfoCallback

Ivan Savenko 5 月之前
父節點
當前提交
ff0f5290f7

+ 6 - 8
client/Client.cpp

@@ -91,6 +91,11 @@ CClient::CClient()
 
 CClient::~CClient() = default;
 
+IGameInfoCallback & CClient::gameInfo()
+{
+	return *gamestate;
+}
+
 const Services * CClient::services() const
 {
 	return LIBRARY; //todo: this should be LIBRARY
@@ -103,7 +108,7 @@ const CClient::BattleCb * CClient::battle(const BattleID & battleID) const
 
 const CClient::GameCb * CClient::game() const
 {
-	return this;
+	return gamestate.get();
 }
 
 vstd::CLoggerBase * CClient::logger() const
@@ -494,13 +499,6 @@ void CClient::startPlayerBattleAction(const BattleID & battleID, PlayerColor col
 	}
 }
 
-#if SCRIPTING_ENABLED
-scripting::Pool * CClient::getGlobalContextPool() const
-{
-	return clientScripts.get();
-}
-#endif
-
 void CClient::reinitScripting()
 {
 	clientEventBus = std::make_unique<events::EventBus>();

+ 4 - 7
client/Client.h

@@ -122,7 +122,7 @@ public:
 };
 
 /// Class which handles client - server logic
-class CClient : public CGameInfoCallback, public Environment, public IClient
+class CClient : public Environment, public IClient
 {
 	std::shared_ptr<CGameState> gamestate;
 public:
@@ -142,8 +142,9 @@ public:
 	vstd::CLoggerBase * logger() const override;
 	events::EventBus * eventBus() const override;
 
-	CGameState & gameState() final { return *gamestate; }
-	const CGameState & gameState() const final { return *gamestate; }
+	CGameState & gameState() { return *gamestate; }
+	const CGameState & gameState() const { return *gamestate; }
+	IGameInfoCallback & gameInfo();
 
 	void newGame(std::shared_ptr<CGameState> gameState);
 	void loadGame(std::shared_ptr<CGameState> gameState);
@@ -179,10 +180,6 @@ public:
 
 	void removeGUI() const;
 
-#if SCRIPTING_ENABLED
-	scripting::Pool * getGlobalContextPool() const override;
-#endif
-
 private:
 	std::map<PlayerColor, std::shared_ptr<CBattleCallback>> battleCallbacks; //callbacks given to player interfaces
 	std::map<PlayerColor, std::shared_ptr<CPlayerEnvironment>> playerEnvironments;

+ 3 - 3
client/ClientCommandManager.cpp

@@ -90,7 +90,7 @@ void ClientCommandManager::handleGoSoloCommand()
 		// unlikely it will work but just in case to be consistent
 		for(auto & color : GAME->server().getAllClientPlayers(GAME->server().logicConnection->connectionID))
 		{
-			if(color.isValidPlayer() && GAME->server().client->getStartInfo()->playerInfos.at(color).isControlledByHuman())
+			if(color.isValidPlayer() && GAME->server().client->gameInfo().getStartInfo()->playerInfos.at(color).isControlledByHuman())
 			{
 				GAME->server().client->installNewPlayerInterface(std::make_shared<CPlayerInterface>(color), color);
 			}
@@ -103,9 +103,9 @@ void ClientCommandManager::handleGoSoloCommand()
 		
 		for(auto & color : GAME->server().getAllClientPlayers(GAME->server().logicConnection->connectionID))
 		{
-			if(color.isValidPlayer() && GAME->server().client->getStartInfo()->playerInfos.at(color).isControlledByHuman())
+			if(color.isValidPlayer() && GAME->server().client->gameInfo().getStartInfo()->playerInfos.at(color).isControlledByHuman())
 			{
-				auto AiToGive = GAME->server().client->aiNameForPlayer(*GAME->server().client->getPlayerSettings(color), false, false);
+				auto AiToGive = GAME->server().client->aiNameForPlayer(*GAME->server().client->gameInfo().getPlayerSettings(color), false, false);
 				printCommandMessage("Player " + color.toString() + " will be lead by " + AiToGive, ELogLevel::INFO);
 				GAME->server().client->installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), color);
 			}

+ 4 - 4
client/ClientNetPackVisitors.h

@@ -23,10 +23,10 @@ class ApplyClientNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
 {
 private:
 	CClient & cl;
-	CGameState & gs;
+	const CGameState & gs;
 
 public:
-	ApplyClientNetPackVisitor(CClient & cl, CGameState & gs)
+	ApplyClientNetPackVisitor(CClient & cl, const CGameState & gs)
 		:cl(cl), gs(gs)
 	{
 	}
@@ -109,10 +109,10 @@ class ApplyFirstClientNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisi
 {
 private:
 	CClient & cl;
-	CGameState & gs;
+	const CGameState & gs;
 
 public:
-	ApplyFirstClientNetPackVisitor(CClient & cl, CGameState & gs)
+	ApplyFirstClientNetPackVisitor(CClient & cl, const CGameState & gs)
 		:cl(cl), gs(gs)
 	{
 	}

+ 64 - 64
client/NetPacksClient.cpp

@@ -124,7 +124,7 @@ void ApplyClientNetPackVisitor::visitSetResources(SetResources & pack)
 
 void ApplyClientNetPackVisitor::visitSetPrimSkill(SetPrimSkill & pack)
 {
-	const CGHeroInstance * h = cl.getHero(pack.id);
+	const CGHeroInstance * h = cl.gameInfo().getHero(pack.id);
 	if(!h)
 	{
 		logNetwork->error("Cannot find hero with pack.id %d", pack.id.getNum());
@@ -135,7 +135,7 @@ void ApplyClientNetPackVisitor::visitSetPrimSkill(SetPrimSkill & pack)
 
 void ApplyClientNetPackVisitor::visitSetSecSkill(SetSecSkill & pack)
 {
-	const CGHeroInstance *h = cl.getHero(pack.id);
+	const CGHeroInstance *h = cl.gameInfo().getHero(pack.id);
 	if(!h)
 	{
 		logNetwork->error("Cannot find hero with pack.id %d", pack.id.getNum());
@@ -146,7 +146,7 @@ void ApplyClientNetPackVisitor::visitSetSecSkill(SetSecSkill & pack)
 
 void ApplyClientNetPackVisitor::visitHeroVisitCastle(HeroVisitCastle & pack)
 {
-	const CGHeroInstance *h = cl.getHero(pack.hid);
+	const CGHeroInstance *h = cl.gameInfo().getHero(pack.hid);
 	
 	if(pack.start())
 	{
@@ -156,7 +156,7 @@ void ApplyClientNetPackVisitor::visitHeroVisitCastle(HeroVisitCastle & pack)
 
 void ApplyClientNetPackVisitor::visitSetMana(SetMana & pack)
 {
-	const CGHeroInstance *h = cl.getHero(pack.hid);
+	const CGHeroInstance *h = cl.gameInfo().getHero(pack.hid);
 	callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroManaPointsChanged, h);
 
 	if(settings["session"]["headless"].Bool())
@@ -168,7 +168,7 @@ void ApplyClientNetPackVisitor::visitSetMana(SetMana & pack)
 
 void ApplyClientNetPackVisitor::visitSetMovePoints(SetMovePoints & pack)
 {
-	const CGHeroInstance *h = cl.getHero(pack.hid);
+	const CGHeroInstance *h = cl.gameInfo().getHero(pack.hid);
 	callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroMovePointsChanged, h);
 }
 
@@ -182,11 +182,11 @@ void ApplyClientNetPackVisitor::visitFoWChange(FoWChange & pack)
 {
 	for(auto &i : cl.playerint)
 	{
-		if(cl.getPlayerRelations(i.first, pack.player) == PlayerRelations::SAME_PLAYER && pack.waitForDialogs && GAME->interface() == i.second.get())
+		if(cl.gameInfo().getPlayerRelations(i.first, pack.player) == PlayerRelations::SAME_PLAYER && pack.waitForDialogs && GAME->interface() == i.second.get())
 		{
 			GAME->interface()->waitWhileDialog();
 		}
-		if(cl.getPlayerRelations(i.first, pack.player) != PlayerRelations::ENEMIES)
+		if(cl.gameInfo().getPlayerRelations(i.first, pack.player) != PlayerRelations::ENEMIES)
 		{
 			if(pack.mode == ETileVisibility::REVEALED)
 				i.second->tileRevealed(pack.tiles);
@@ -199,7 +199,7 @@ void ApplyClientNetPackVisitor::visitFoWChange(FoWChange & pack)
 
 static void dispatchGarrisonChange(CClient & cl, ObjectInstanceID army1, ObjectInstanceID army2)
 {
-	auto obj1 = cl.getObj(army1);
+	auto obj1 = cl.gameInfo().getObj(army1);
 	if(!obj1)
 	{
 		logNetwork->error("Cannot find army with pack.id %d", army1.getNum());
@@ -210,7 +210,7 @@ static void dispatchGarrisonChange(CClient & cl, ObjectInstanceID army1, ObjectI
 
 	if(army2 != ObjectInstanceID() && army2 != army1)
 	{
-		auto obj2 = cl.getObj(army2);
+		auto obj2 = cl.gameInfo().getObj(army2);
 		if(!obj2)
 		{
 			logNetwork->error("Cannot find army with pack.id %d", army2.getNum());
@@ -265,20 +265,20 @@ void ApplyClientNetPackVisitor::visitBulkRebalanceStacks(BulkRebalanceStacks & p
 
 void ApplyClientNetPackVisitor::visitPutArtifact(PutArtifact & pack)
 {
-	callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactPut, pack.al);
+	callInterfaceIfPresent(cl, cl.gameState().getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactPut, pack.al);
 	if(pack.askAssemble)
-		callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::askToAssembleArtifact, pack.al);
+		callInterfaceIfPresent(cl, cl.gameState().getOwner(pack.al.artHolder), &IGameEventsReceiver::askToAssembleArtifact, pack.al);
 }
 
 void ApplyClientNetPackVisitor::visitBulkEraseArtifacts(BulkEraseArtifacts & pack)
 {
 	for(const auto & slotErase : pack.posPack)
-		callInterfaceIfPresent(cl, cl.getOwner(pack.artHolder), &IGameEventsReceiver::artifactRemoved, ArtifactLocation(pack.artHolder, slotErase));
+		callInterfaceIfPresent(cl, cl.gameState().getOwner(pack.artHolder), &IGameEventsReceiver::artifactRemoved, ArtifactLocation(pack.artHolder, slotErase));
 }
 
 void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
 {
-	const auto dstOwner = cl.getOwner(pack.dstArtHolder);
+	const auto dstOwner = cl.gameState().getOwner(pack.dstArtHolder);
 	const auto applyMove = [this, &pack, dstOwner](const std::vector<MoveArtifactInfo> & artsPack)
 	{
 		for(const auto & slotToMove : artsPack)
@@ -318,18 +318,18 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
 
 void ApplyClientNetPackVisitor::visitAssembledArtifact(AssembledArtifact & pack)
 {
-	callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactAssembled, pack.al);
+	callInterfaceIfPresent(cl, cl.gameState().getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactAssembled, pack.al);
 }
 
 void ApplyClientNetPackVisitor::visitDisassembledArtifact(DisassembledArtifact & pack)
 {
-	callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactDisassembled, pack.al);
+	callInterfaceIfPresent(cl, cl.gameState().getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactDisassembled, pack.al);
 }
 
 void ApplyClientNetPackVisitor::visitHeroVisit(HeroVisit & pack)
 {
-	auto hero = cl.getHero(pack.heroId);
-	auto obj = cl.getObj(pack.objId, false);
+	auto hero = cl.gameInfo().getHero(pack.heroId);
+	auto obj = cl.gameInfo().getObj(pack.objId, false);
 	callInterfaceIfPresent(cl, pack.player, &IGameEventsReceiver::heroVisit, hero, obj, pack.starting);
 }
 
@@ -369,14 +369,14 @@ void ApplyClientNetPackVisitor::visitGiveBonus(GiveBonus & pack)
 
 void ApplyFirstClientNetPackVisitor::visitChangeObjPos(ChangeObjPos & pack)
 {
-	CGObjectInstance *obj = gs.getObjInstance(pack.objid);
+	const CGObjectInstance *obj = gs.getObjInstance(pack.objid);
 	GAME->map().onObjectFadeOut(obj, pack.initiator);
 	GAME->map().waitForOngoingAnimations();
 }
 
 void ApplyClientNetPackVisitor::visitChangeObjPos(ChangeObjPos & pack)
 {
-	CGObjectInstance *obj = gs.getObjInstance(pack.objid);
+	const CGObjectInstance *obj = gs.getObjInstance(pack.objid);
 	GAME->map().onObjectFadeIn(obj, pack.initiator);
 	GAME->map().waitForOngoingAnimations();
 	callAllInterfaces(cl, &CGameInterface::invalidatePaths);
@@ -386,8 +386,8 @@ void ApplyClientNetPackVisitor::visitPlayerEndsGame(PlayerEndsGame & pack)
 {
 	callAllInterfaces(cl, &IGameEventsReceiver::gameOver, pack.player, pack.victoryLossCheckResult);
 
-	bool localHumanWinsGame = vstd::contains(cl.playerint, pack.player) && cl.getPlayerState(pack.player)->human && pack.victoryLossCheckResult.victory();
-	bool lastHumanEndsGame = GAME->server().howManyPlayerInterfaces() == 1 && vstd::contains(cl.playerint, pack.player) && cl.getPlayerState(pack.player)->human && !settings["session"]["spectate"].Bool();
+	bool localHumanWinsGame = vstd::contains(cl.playerint, pack.player) && cl.gameInfo().getPlayerState(pack.player)->human && pack.victoryLossCheckResult.victory();
+	bool lastHumanEndsGame = GAME->server().howManyPlayerInterfaces() == 1 && vstd::contains(cl.playerint, pack.player) && cl.gameInfo().getPlayerState(pack.player)->human && !settings["session"]["spectate"].Bool();
 
 	if(lastHumanEndsGame || localHumanWinsGame)
 	{
@@ -466,7 +466,7 @@ void ApplyClientNetPackVisitor::visitRemoveBonus(RemoveBonus & pack)
 
 void ApplyFirstClientNetPackVisitor::visitRemoveObject(RemoveObject & pack)
 {
-	const CGObjectInstance *o = cl.getObj(pack.objectID);
+	const CGObjectInstance *o = cl.gameInfo().getObj(pack.objectID);
 
 	GAME->map().onObjectFadeOut(o, pack.initiator);
 
@@ -475,7 +475,7 @@ void ApplyFirstClientNetPackVisitor::visitRemoveObject(RemoveObject & pack)
 	{
 		//below line contains little cheat for AI so it will be aware of deletion of enemy heroes that moved or got re-covered by FoW
 		//TODO: loose requirements as next AI related crashes appear, for example another pack.player collects object that got re-covered by FoW, unsure if AI code workarounds this
-		if(gs.isVisibleFor(o, i->first) || (!cl.getPlayerState(i->first)->human && o->ID == Obj::HERO && o->tempOwner != i->first))
+		if(gs.isVisibleFor(o, i->first) || (!cl.gameInfo().getPlayerState(i->first)->human && o->ID == Obj::HERO && o->tempOwner != i->first))
 			i->second->objectRemoved(o, pack.initiator);
 	}
 
@@ -492,7 +492,7 @@ void ApplyClientNetPackVisitor::visitRemoveObject(RemoveObject & pack)
 
 void ApplyFirstClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)
 {
-	CGHeroInstance *h = gs.getHero(pack.id);
+	const CGHeroInstance *h = gs.getHero(pack.id);
 
 	switch (pack.result)
 	{
@@ -510,7 +510,7 @@ void ApplyFirstClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)
 
 void ApplyClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)
 {
-	const CGHeroInstance *h = cl.getHero(pack.id);
+	const CGHeroInstance *h = cl.gameInfo().getHero(pack.id);
 	callAllInterfaces(cl, &CGameInterface::invalidatePaths);
 
 	switch(pack.result)
@@ -532,7 +532,7 @@ void ApplyClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)
 	PlayerColor player = h->tempOwner;
 
 	for(auto &i : cl.playerint)
-		if(cl.getPlayerRelations(i.first, player) != PlayerRelations::ENEMIES)
+		if(cl.gameInfo().getPlayerRelations(i.first, player) != PlayerRelations::ENEMIES)
 			i.second->tileRevealed(pack.fowRevealed);
 
 	for(auto i=cl.playerint.begin(); i!=cl.playerint.end(); i++)
@@ -544,7 +544,7 @@ void ApplyClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)
 			|| gs.isVisibleFor(h->convertToVisitablePos(pack.end), i->first))
 		{
 			// pack.src and pack.dst of enemy hero move may be not visible => 'verbose' should be false
-			const bool verbose = cl.getPlayerRelations(i->first, player) != PlayerRelations::ENEMIES;
+			const bool verbose = cl.gameInfo().getPlayerRelations(i->first, player) != PlayerRelations::ENEMIES;
 			i->second->heroMoved(pack, verbose);
 		}
 	}
@@ -552,7 +552,7 @@ void ApplyClientNetPackVisitor::visitTryMoveHero(TryMoveHero & pack)
 
 void ApplyClientNetPackVisitor::visitNewStructures(NewStructures & pack)
 {
-	CGTownInstance *town = gs.getTown(pack.tid);
+	const CGTownInstance *town = gs.getTown(pack.tid);
 	for(const auto & id : pack.bid)
 	{
 		callInterfaceIfPresent(cl, town->getOwner(), &IGameEventsReceiver::buildChanged, town, id, 1);
@@ -565,7 +565,7 @@ void ApplyClientNetPackVisitor::visitNewStructures(NewStructures & pack)
 
 void ApplyClientNetPackVisitor::visitRazeStructures(RazeStructures & pack)
 {
-	CGTownInstance * town = gs.getTown(pack.tid);
+	const CGTownInstance * town = gs.getTown(pack.tid);
 	for(const auto & id : pack.bid)
 	{
 		callInterfaceIfPresent(cl, town->getOwner(), &IGameEventsReceiver::buildChanged, town, id, 2);
@@ -578,11 +578,11 @@ void ApplyClientNetPackVisitor::visitRazeStructures(RazeStructures & pack)
 
 void ApplyClientNetPackVisitor::visitSetAvailableCreatures(SetAvailableCreatures & pack)
 {
-	const CGDwelling * dw = static_cast<const CGDwelling*>(cl.getObj(pack.tid));
+	const CGDwelling * dw = static_cast<const CGDwelling*>(cl.gameInfo().getObj(pack.tid));
 
 	PlayerColor p;
 	if(dw->ID == Obj::WAR_MACHINE_FACTORY) //War Machines Factory is not flaggable, it's "owned" by visitor
-		p = cl.getObjInstance(cl.getTile(dw->visitablePos())->visitableObjects.back())->getOwner();
+		p = cl.gameInfo().getObjInstance(cl.gameInfo().getTile(dw->visitablePos())->visitableObjects.back())->getOwner();
 	else
 		p = dw->tempOwner;
 
@@ -591,9 +591,9 @@ void ApplyClientNetPackVisitor::visitSetAvailableCreatures(SetAvailableCreatures
 
 void ApplyClientNetPackVisitor::visitSetHeroesInTown(SetHeroesInTown & pack)
 {
-	CGTownInstance * t = gs.getTown(pack.tid);
-	CGHeroInstance * hGarr  = gs.getHero(pack.garrison);
-	CGHeroInstance * hVisit = gs.getHero(pack.visiting);
+	const CGTownInstance * t = gs.getTown(pack.tid);
+	const CGHeroInstance * hGarr  = gs.getHero(pack.garrison);
+	const CGHeroInstance * hVisit = gs.getHero(pack.visiting);
 
 	//inform all players that see this object
 	for(auto i = cl.playerint.cbegin(); i != cl.playerint.cend(); ++i)
@@ -612,7 +612,7 @@ void ApplyClientNetPackVisitor::visitSetHeroesInTown(SetHeroesInTown & pack)
 
 void ApplyClientNetPackVisitor::visitHeroRecruited(HeroRecruited & pack)
 {
-	auto * h = gs.getMap().getHero(pack.hid);
+	const auto * h = gs.getMap().getHero(pack.hid);
 	if(h->getHeroTypeID() != pack.hid)
 	{
 		logNetwork->error("Something wrong with hero recruited!");
@@ -628,7 +628,7 @@ void ApplyClientNetPackVisitor::visitHeroRecruited(HeroRecruited & pack)
 
 void ApplyClientNetPackVisitor::visitGiveHero(GiveHero & pack)
 {
-	CGHeroInstance *h = gs.getHero(pack.id);
+	const CGHeroInstance *h = gs.getHero(pack.id);
 	GAME->map().onObjectInstantAdd(h, h->getOwner());
 	callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroCreated, h);
 }
@@ -681,14 +681,14 @@ void ApplyClientNetPackVisitor::visitSetObjectProperty(SetObjectProperty & pack)
 
 void ApplyClientNetPackVisitor::visitHeroLevelUp(HeroLevelUp & pack)
 {
-	const CGHeroInstance * hero = cl.getHero(pack.heroId);
+	const CGHeroInstance * hero = cl.gameInfo().getHero(pack.heroId);
 	assert(hero);
 	callOnlyThatInterface(cl, pack.player, &CGameInterface::heroGotLevel, hero, pack.primskill, pack.skills, pack.queryID);
 }
 
 void ApplyClientNetPackVisitor::visitCommanderLevelUp(CommanderLevelUp & pack)
 {
-	const CGHeroInstance * hero = cl.getHero(pack.heroId);
+	const CGHeroInstance * hero = cl.gameInfo().getHero(pack.heroId);
 	assert(hero);
 	const auto & commander = hero->getCommander();
 	assert(commander);
@@ -706,8 +706,8 @@ void ApplyClientNetPackVisitor::visitBlockingDialog(BlockingDialog & pack)
 
 void ApplyClientNetPackVisitor::visitGarrisonDialog(GarrisonDialog & pack)
 {
-	const CGHeroInstance *h = cl.getHero(pack.hid);
-	const CArmedInstance *obj = static_cast<const CArmedInstance*>(cl.getObj(pack.objid));
+	const CGHeroInstance *h = cl.gameInfo().getHero(pack.hid);
+	const CArmedInstance *obj = static_cast<const CArmedInstance*>(cl.gameInfo().getObj(pack.objid));
 
 	callOnlyThatInterface(cl, h->getOwner(), &CGameInterface::showGarrisonDialog, obj, h, pack.removableUnits, pack.queryID);
 }
@@ -719,7 +719,7 @@ void ApplyClientNetPackVisitor::visitExchangeDialog(ExchangeDialog & pack)
 
 void ApplyClientNetPackVisitor::visitTeleportDialog(TeleportDialog & pack)
 {
-	const CGHeroInstance *h = cl.getHero(pack.hero);
+	const CGHeroInstance *h = cl.gameInfo().getHero(pack.hero);
 	callOnlyThatInterface(cl, h->getOwner(), &CGameInterface::showTeleportDialog, h, pack.channel, pack.exits, pack.impassable, pack.queryID);
 }
 
@@ -948,7 +948,7 @@ void ApplyClientNetPackVisitor::visitAdvmapSpellCast(AdvmapSpellCast & pack)
 {
 	callAllInterfaces(cl, &CGameInterface::invalidatePaths);
 
-	auto caster = cl.getHero(pack.casterID);
+	auto caster = cl.gameInfo().getHero(pack.casterID);
 	if(caster)
 		//consider notifying other interfaces that see hero?
 		callInterfaceIfPresent(cl, caster->getOwner(), &IGameEventsReceiver::advmapSpellCast, caster, pack.spellID);
@@ -968,15 +968,15 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
 	case EOpenWindowMode::RECRUITMENT_FIRST:
 	case EOpenWindowMode::RECRUITMENT_ALL:
 		{
-			const CGDwelling *dw = dynamic_cast<const CGDwelling*>(cl.getObj(ObjectInstanceID(pack.object)));
-			const CArmedInstance *dst = dynamic_cast<const CArmedInstance*>(cl.getObj(ObjectInstanceID(pack.visitor)));
+			const CGDwelling *dw = dynamic_cast<const CGDwelling*>(cl.gameInfo().getObj(ObjectInstanceID(pack.object)));
+			const CArmedInstance *dst = dynamic_cast<const CArmedInstance*>(cl.gameInfo().getObj(ObjectInstanceID(pack.visitor)));
 			callInterfaceIfPresent(cl, dst->tempOwner, &IGameEventsReceiver::showRecruitmentDialog, dw, dst, pack.window == EOpenWindowMode::RECRUITMENT_FIRST ? 0 : -1, pack.queryID);
 		}
 		break;
 	case EOpenWindowMode::SHIPYARD_WINDOW:
 		{
 			assert(pack.queryID == QueryID::NONE);
-			const auto * sy = dynamic_cast<const IShipyard *>(cl.getObj(ObjectInstanceID(pack.object)));
+			const auto * sy = dynamic_cast<const IShipyard *>(cl.gameInfo().getObj(ObjectInstanceID(pack.object)));
 			callInterfaceIfPresent(cl, sy->getObject()->getOwner(), &IGameEventsReceiver::showShipyardDialog, sy);
 		}
 		break;
@@ -984,27 +984,27 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
 		{
 			assert(pack.queryID == QueryID::NONE);
 			//displays Thieves' Guild window (when hero enters Den of Thieves)
-			const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
-			const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
+			const CGObjectInstance *obj = cl.gameInfo().getObj(ObjectInstanceID(pack.object));
+			const CGHeroInstance *hero = cl.gameInfo().getHero(ObjectInstanceID(pack.visitor));
 			callInterfaceIfPresent(cl, hero->getOwner(), &IGameEventsReceiver::showThievesGuildWindow, obj);
 		}
 		break;
 	case EOpenWindowMode::UNIVERSITY_WINDOW:
 		{
 			//displays University window (when hero enters University on adventure map)
-			const auto * market = cl.getMarket(ObjectInstanceID(pack.object));
-			const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
+			const auto * market = cl.gameState().getMarket(ObjectInstanceID(pack.object));
+			const CGHeroInstance *hero = cl.gameInfo().getHero(ObjectInstanceID(pack.visitor));
 			callInterfaceIfPresent(cl, hero->tempOwner, &IGameEventsReceiver::showUniversityWindow, market, hero, pack.queryID);
 		}
 		break;
 	case EOpenWindowMode::MARKET_WINDOW:
 		{
 			//displays Thieves' Guild window (when hero enters Den of Thieves)
-			const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
-			const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
-			const auto market = cl.getMarket(pack.object);
-			const auto * tile = cl.getTile(obj->visitablePos());
-			const auto * topObject = cl.getObjInstance(tile->visitableObjects.back());
+			const CGObjectInstance *obj = cl.gameInfo().getObj(ObjectInstanceID(pack.object));
+			const CGHeroInstance *hero = cl.gameInfo().getHero(ObjectInstanceID(pack.visitor));
+			const auto market = cl.gameState().getMarket(pack.object);
+			const auto * tile = cl.gameInfo().getTile(obj->visitablePos());
+			const auto * topObject = cl.gameInfo().getObjInstance(tile->visitableObjects.back());
 			callInterfaceIfPresent(cl, topObject->getOwner(), &IGameEventsReceiver::showMarketWindow, market, hero, pack.queryID);
 		}
 		break;
@@ -1012,24 +1012,24 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
 		{
 			assert(pack.queryID == QueryID::NONE);
 			//displays Hill fort window
-			const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
-			const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
-			const auto * tile = cl.getTile(obj->visitablePos());
-			const auto * topObject = cl.getObjInstance(tile->visitableObjects.back());
+			const CGObjectInstance *obj = cl.gameInfo().getObj(ObjectInstanceID(pack.object));
+			const CGHeroInstance *hero = cl.gameInfo().getHero(ObjectInstanceID(pack.visitor));
+			const auto * tile = cl.gameInfo().getTile(obj->visitablePos());
+			const auto * topObject = cl.gameInfo().getObjInstance(tile->visitableObjects.back());
 			callInterfaceIfPresent(cl, topObject->getOwner(), &IGameEventsReceiver::showHillFortWindow, obj, hero);
 		}
 		break;
 	case EOpenWindowMode::PUZZLE_MAP:
 		{
 			assert(pack.queryID == QueryID::NONE);
-			const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
+			const CGHeroInstance *hero = cl.gameInfo().getHero(ObjectInstanceID(pack.visitor));
 			callInterfaceIfPresent(cl, hero->getOwner(), &IGameEventsReceiver::showPuzzleMap);
 		}
 		break;
 	case EOpenWindowMode::TAVERN_WINDOW:
 		{
-			const CGObjectInstance *obj1 = cl.getObj(ObjectInstanceID(pack.object));
-			const CGHeroInstance * hero = cl.getHero(ObjectInstanceID(pack.visitor));
+			const CGObjectInstance *obj1 = cl.gameInfo().getObj(ObjectInstanceID(pack.object));
+			const CGHeroInstance * hero = cl.gameInfo().getHero(ObjectInstanceID(pack.visitor));
 			callInterfaceIfPresent(cl, hero->tempOwner, &IGameEventsReceiver::showTavernWindow, obj1, hero, pack.queryID);
 		}
 		break;
@@ -1065,10 +1065,10 @@ void ApplyClientNetPackVisitor::visitSetAvailableArtifacts(SetAvailableArtifacts
 	}
 	else
 	{
-		const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(cl.getObj(ObjectInstanceID(pack.id)));
+		const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(cl.gameInfo().getObj(ObjectInstanceID(pack.id)));
 		assert(bm);
-		const auto * tile = cl.getTile(bm->visitablePos());
-		const auto * topObject = cl.getObjInstance(tile->visitableObjects.back());
+		const auto * tile = cl.gameInfo().getTile(bm->visitablePos());
+		const auto * topObject = cl.gameInfo().getObjInstance(tile->visitableObjects.back());
 
 		callInterfaceIfPresent(cl, topObject->getOwner(), &IGameEventsReceiver::availableArtifactsChanged, bm);
 	}

+ 1 - 1
client/NetPacksLobbyClient.cpp

@@ -148,7 +148,7 @@ void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyPrepareStartGame(LobbyPrepareS
 {
 	handler.client = std::make_unique<CClient>();
 	handler.logicConnection->enterLobbyConnectionMode();
-	handler.logicConnection->setCallback(handler.client.get());
+	handler.logicConnection->setCallback(&handler.client->gameInfo());
 }
 
 void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack)

+ 12 - 0
lib/mapping/CMap.cpp

@@ -262,6 +262,18 @@ CGHeroInstance * CMap::getHero(HeroTypeID heroID)
 	return nullptr;
 }
 
+const CGHeroInstance * CMap::getHero(HeroTypeID heroID) const
+{
+	for (const auto & objectID : heroesOnMap)
+	{
+		const auto hero = std::dynamic_pointer_cast<CGHeroInstance>(objects.at(objectID.getNum()));
+
+		if (hero->getHeroTypeID() == heroID)
+			return hero.get();
+	}
+	return nullptr;
+}
+
 bool CMap::isCoastalTile(const int3 & pos) const
 {
 	//todo: refactoring: extract neighbour tile iterator and use it in GameState

+ 1 - 0
lib/mapping/CMap.h

@@ -233,6 +233,7 @@ public:
 
 	/// Returns pointer to hero of specified type if hero is present on map
 	CGHeroInstance * getHero(HeroTypeID heroId);
+	const CGHeroInstance * getHero(HeroTypeID heroId) const;
 
 	/// Returns ID's of all heroes that are currently present on map
 	/// Includes all garrisoned and imprisoned heroes