Browse Source

Completely remove IGameCallback class

- CClient now inherits directly from CPrivilegedInfoCallback, like
IGameCallback did before. However CClient no longer needs dummy
implementation of IGameEventCallback
- CGObjectInstance hierarchy now uses CPrivilegedInfoCallback for
callback. Actual events can only be emitted in calls that receive
IGameEventCallback pointer, e.g. heroVisit
- CGameHandler now inherits directly from both CPrivilegedInfoCallback
and IGameEventCallback as it did before via IGameCallback
Ivan Savenko 5 months ago
parent
commit
716da918f8
100 changed files with 826 additions and 912 deletions
  1. 1 1
      AI/Nullkiller/Pathfinding/AINodeStorage.cpp
  2. 1 1
      AI/VCAI/Pathfinding/AINodeStorage.cpp
  3. 0 9
      client/Client.cpp
  4. 3 64
      client/Client.h
  5. 5 5
      lib/CCreatureSet.cpp
  6. 5 5
      lib/CCreatureSet.h
  7. 2 2
      lib/CMakeLists.txt
  8. 2 2
      lib/CPlayerState.cpp
  9. 1 1
      lib/CPlayerState.h
  10. 4 4
      lib/battle/BattleInfo.cpp
  11. 3 3
      lib/battle/BattleInfo.h
  12. 3 3
      lib/battle/BattleLayout.cpp
  13. 3 3
      lib/battle/BattleLayout.h
  14. 1 1
      lib/battle/SideInBattle.cpp
  15. 11 0
      lib/callback/CPrivilegedInfoCallback.h
  16. 3 3
      lib/callback/GameCallbackHolder.h
  17. 0 43
      lib/callback/IGameCallback.h
  18. 2 0
      lib/callback/IGameEventCallback.h
  19. 1 1
      lib/campaign/CampaignState.cpp
  20. 2 2
      lib/campaign/CampaignState.h
  21. 2 2
      lib/entities/artifact/ArtSlotInfo.cpp
  22. 1 1
      lib/entities/artifact/ArtSlotInfo.h
  23. 1 1
      lib/entities/artifact/CArtifactFittingSet.cpp
  24. 2 2
      lib/entities/artifact/CArtifactFittingSet.h
  25. 3 3
      lib/entities/artifact/CArtifactInstance.cpp
  26. 2 2
      lib/entities/artifact/CArtifactInstance.h
  27. 1 1
      lib/entities/artifact/CArtifactSet.cpp
  28. 2 2
      lib/entities/artifact/CArtifactSet.h
  29. 64 64
      lib/gameState/CGameState.cpp
  30. 23 30
      lib/gameState/CGameState.h
  31. 7 7
      lib/gameState/CGameStateCampaign.cpp
  32. 7 2
      lib/gameState/CGameStateCampaign.h
  33. 1 1
      lib/json/JsonRandom.cpp
  34. 2 2
      lib/mapObjectConstructors/AObjectTypeHandler.h
  35. 2 2
      lib/mapObjectConstructors/CDefaultObjectTypeHandler.h
  36. 2 2
      lib/mapObjectConstructors/CRewardableConstructor.cpp
  37. 2 2
      lib/mapObjectConstructors/CRewardableConstructor.h
  38. 2 2
      lib/mapObjectConstructors/CommonConstructors.cpp
  39. 1 1
      lib/mapObjectConstructors/CommonConstructors.h
  40. 3 3
      lib/mapObjects/CArmedInstance.cpp
  41. 2 2
      lib/mapObjects/CArmedInstance.h
  42. 49 48
      lib/mapObjects/CGCreature.cpp
  43. 9 9
      lib/mapObjects/CGCreature.h
  44. 29 28
      lib/mapObjects/CGDwelling.cpp
  45. 7 7
      lib/mapObjects/CGDwelling.h
  46. 18 17
      lib/mapObjects/CGHeroInstance.cpp
  47. 3 3
      lib/mapObjects/CGHeroInstance.h
  48. 10 9
      lib/mapObjects/CGMarket.cpp
  49. 4 4
      lib/mapObjects/CGMarket.h
  50. 8 7
      lib/mapObjects/CGObjectInstance.cpp
  51. 3 3
      lib/mapObjects/CGObjectInstance.h
  52. 26 25
      lib/mapObjects/CGPandoraBox.cpp
  53. 7 7
      lib/mapObjects/CGPandoraBox.h
  54. 15 14
      lib/mapObjects/CGResource.cpp
  55. 4 4
      lib/mapObjects/CGResource.h
  56. 36 35
      lib/mapObjects/CGTownInstance.cpp
  57. 11 11
      lib/mapObjects/CGTownInstance.h
  58. 36 35
      lib/mapObjects/CQuest.cpp
  59. 9 9
      lib/mapObjects/CQuest.h
  60. 34 33
      lib/mapObjects/CRewardableObject.cpp
  61. 11 11
      lib/mapObjects/CRewardableObject.h
  62. 18 17
      lib/mapObjects/FlaggableMapObject.cpp
  63. 3 3
      lib/mapObjects/FlaggableMapObject.h
  64. 1 1
      lib/mapObjects/IMarket.cpp
  65. 4 4
      lib/mapObjects/IMarket.h
  66. 11 10
      lib/mapObjects/IObjectInterface.cpp
  67. 10 9
      lib/mapObjects/IObjectInterface.h
  68. 85 84
      lib/mapObjects/MiscObjects.cpp
  69. 26 26
      lib/mapObjects/MiscObjects.h
  70. 21 20
      lib/mapObjects/TownBuildingInstance.cpp
  71. 9 9
      lib/mapObjects/TownBuildingInstance.h
  72. 2 2
      lib/mapping/CMap.cpp
  73. 1 1
      lib/mapping/CMap.h
  74. 2 2
      lib/mapping/CMapService.cpp
  75. 6 6
      lib/mapping/CMapService.h
  76. 1 1
      lib/mapping/MapFormatH3M.cpp
  77. 1 1
      lib/mapping/MapFormatH3M.h
  78. 1 1
      lib/mapping/MapFormatJson.cpp
  79. 1 1
      lib/mapping/MapFormatJson.h
  80. 2 2
      lib/mapping/ObstacleProxy.cpp
  81. 3 3
      lib/mapping/ObstacleProxy.h
  82. 1 1
      lib/pathfinder/CPathfinder.cpp
  83. 1 1
      lib/pathfinder/TurnInfo.cpp
  84. 6 6
      lib/rewardable/Info.cpp
  85. 7 7
      lib/rewardable/Info.h
  86. 53 52
      lib/rewardable/Interface.cpp
  87. 10 10
      lib/rewardable/Interface.h
  88. 1 1
      lib/rewardable/Limiter.cpp
  89. 1 1
      lib/rmg/CMapGenerator.cpp
  90. 2 2
      lib/rmg/CMapGenerator.h
  91. 1 1
      lib/rmg/RmgMap.cpp
  92. 1 1
      lib/rmg/RmgMap.h
  93. 1 1
      lib/serializer/BinaryDeserializer.h
  94. 1 1
      lib/serializer/CLoadFile.cpp
  95. 1 1
      lib/serializer/CLoadFile.h
  96. 1 1
      lib/serializer/Connection.cpp
  97. 2 2
      lib/serializer/Connection.h
  98. 3 3
      lib/serializer/SerializerReflection.cpp
  99. 5 5
      lib/serializer/SerializerReflection.h
  100. 6 6
      server/CGameHandler.cpp

+ 1 - 1
AI/Nullkiller/Pathfinding/AINodeStorage.cpp

@@ -14,7 +14,7 @@
 #include "../Goals/Goals.h"
 #include "../AIGateway.h"
 #include "../Engine/Nullkiller.h"
-#include "../../../lib/callback/IGameCallback.h"
+#include "../../../lib/callback/CPrivilegedInfoCallback.h"
 #include "../../../lib/mapping/CMap.h"
 #include "../../../lib/mapObjects/MapObjects.h"
 #include "../../../lib/pathfinder/CPathfinder.h"

+ 1 - 1
AI/VCAI/Pathfinding/AINodeStorage.cpp

@@ -11,7 +11,7 @@
 #include "AINodeStorage.h"
 #include "Actions/TownPortalAction.h"
 #include "../Goals/Goals.h"
-#include "../../../lib/callback/IGameCallback.h"
+#include "../../../lib/callback/CPrivilegedInfoCallback.h"
 #include "../../../lib/mapping/CMap.h"
 #include "../../../lib/mapObjects/MapObjects.h"
 #include "../../../lib/pathfinder/CPathfinder.h"

+ 0 - 9
client/Client.cpp

@@ -494,15 +494,6 @@ void CClient::startPlayerBattleAction(const BattleID & battleID, PlayerColor col
 	}
 }
 
-
-
-vstd::RNG & CClient::getRandomGenerator()
-{
-	// Client should use CRandomGenerator::getDefault() for UI logic
-	// Gamestate should never call this method on client!
-	throw std::runtime_error("Illegal access to random number generator from client code!");
-}
-
 #if SCRIPTING_ENABLED
 scripting::Pool * CClient::getGlobalContextPool() const
 {

+ 3 - 64
client/Client.h

@@ -13,13 +13,14 @@
 #include <vcmi/Environment.h>
 
 #include "../lib/callback/IClient.h"
-#include "../lib/callback/IGameCallback.h"
+#include "../lib/callback/CPrivilegedInfoCallback.h"
 #include "../lib/ConditionalWait.h"
 #include "../lib/ResourceSet.h"
 
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+struct CPackForClient;
 struct CPackForServer;
 class IBattleEventsReceiver;
 class CBattleGameInterface;
@@ -121,7 +122,7 @@ public:
 };
 
 /// Class which handles client - server logic
-class CClient : public IGameCallback, public Environment, public IClient
+class CClient : public CPrivilegedInfoCallback, public Environment, public IClient
 {
 	std::shared_ptr<CGameState> gamestate;
 public:
@@ -176,70 +177,8 @@ public:
 	friend class CCallback; //handling players actions
 	friend class CBattleCallback; //handling players actions
 
-	void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> & spells) override {};
-	void setResearchedSpells(const CGTownInstance * town, int level, const std::vector<SpellID> & spells, bool accepted) override {};
-	bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) override {return false;};
-	void createBoat(const int3 & visitablePosition, BoatId type, PlayerColor initiator) override {};
-	void setOwner(const CGObjectInstance * obj, PlayerColor owner) override {};
-	void giveExperience(const CGHeroInstance * hero, TExpType val) override {};
-	void changePrimSkill(const CGHeroInstance * hero, PrimarySkill which, si64 val, bool abs = false) override {};
-	void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs = false) override {};
-
-	void showBlockingDialog(const IObjectInterface * caller, BlockingDialog * iw) override {};
-	void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) override {};
-	void showTeleportDialog(TeleportDialog * iw) override {};
-	void showObjectWindow(const CGObjectInstance * object, EOpenWindowMode window, const CGHeroInstance * visitor, bool addQuery) override {};
-	void giveResource(PlayerColor player, GameResID which, int val) override {};
-	void giveResources(PlayerColor player, ResourceSet resources) override {};
-
-	void giveCreatures(const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet & creatures, bool remove) override {};
-	void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> & creatures, bool forceRemoval) override {};
-	bool changeStackType(const StackLocation & sl, const CCreature * c) override {return false;};
-	bool changeStackCount(const StackLocation & sl, TQuantity count, bool absoluteValue = false) override {return false;};
-	bool insertNewStack(const StackLocation & sl, const CCreature * c, TQuantity count) override {return false;};
-	bool eraseStack(const StackLocation & sl, bool forceRemoval = false) override {return false;};
-	bool swapStacks(const StackLocation & sl1, const StackLocation & sl2) override {return false;}
-	bool addToSlot(const StackLocation & sl, const CCreature * c, TQuantity count) override {return false;}
-	void tryJoiningArmy(const CArmedInstance * src, const CArmedInstance * dst, bool removeObjWhenFinished, bool allowMerging) override {}
-	bool moveStack(const StackLocation & src, const StackLocation & dst, TQuantity count = -1) override {return false;}
-
-	void removeAfterVisit(const ObjectInstanceID & id) override {};
-	bool swapGarrisonOnSiege(ObjectInstanceID tid) override {return false;};
-	bool giveHeroNewArtifact(const CGHeroInstance * h, const ArtifactID & artId, const ArtifactPosition & pos) override {return false;};
-	bool giveHeroNewScroll(const CGHeroInstance * h, const SpellID & spellId, const ArtifactPosition & pos) override {return false;};
-	bool putArtifact(const ArtifactLocation & al, const ArtifactInstanceID & id, std::optional<bool> askAssemble) override {return false;};
-	void removeArtifact(const ArtifactLocation & al) override {};
-	bool moveArtifact(const PlayerColor & player, const ArtifactLocation & al1, const ArtifactLocation & al2) override {return false;};
-
-	void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {};
-	void visitCastleObjects(const CGTownInstance * obj, const CGHeroInstance * hero) override {};
-	void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {};
-	void startBattle(const CArmedInstance * army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, const BattleLayout & layout, const CGTownInstance * town) override {}; //use hero=nullptr for no hero
-	void startBattle(const CArmedInstance * army1, const CArmedInstance * army2) override {}; //if any of armies is hero, hero will be used
-	bool moveHero(ObjectInstanceID hid, int3 dst, EMovementMode movementMode, bool transit = false, PlayerColor asker = PlayerColor::NEUTRAL) override {return false;};
-	void giveHeroBonus(GiveBonus * bonus) override {};
-	void setMovePoints(SetMovePoints * smp) override {};
-	void setMovePoints(ObjectInstanceID hid, int val, bool absolute) override {};
-	void setManaPoints(ObjectInstanceID hid, int val) override {};
-	void giveHero(ObjectInstanceID id, PlayerColor player, ObjectInstanceID boatId = ObjectInstanceID()) override {};
-	void changeObjPos(ObjectInstanceID objid, int3 newPos, const PlayerColor & initiator) override {};
-	void sendAndApply(CPackForClient & pack) override {};
-	void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override {};
-	void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) override {};
-
-	void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, ETileVisibility mode) override {}
-	void changeFogOfWar(const std::unordered_set<int3> & tiles, PlayerColor player, ETileVisibility mode) override {}
-
-	void setObjPropertyValue(ObjectInstanceID objid, ObjProperty prop, int32_t value) override {};
-	void setObjPropertyID(ObjectInstanceID objid, ObjProperty prop, ObjPropertyID identifier) override {};
-	void setRewardableObjectConfiguration(ObjectInstanceID objid, const Rewardable::Configuration & configuration) override {};
-	void setRewardableObjectConfiguration(ObjectInstanceID townInstanceID, BuildingID buildingID, const Rewardable::Configuration & configuration) override{};
-
-	void showInfoDialog(InfoWindow * iw) override {};
 	void removeGUI() const;
 
-	vstd::RNG & getRandomGenerator() override;
-
 #if SCRIPTING_ENABLED
 	scripting::Pool * getGlobalContextPool() const override;
 #endif

+ 5 - 5
lib/CCreatureSet.cpp

@@ -14,7 +14,7 @@
 #include "CCreatureHandler.h"
 #include "GameLibrary.h"
 #include "IGameSettings.h"
-#include "callback/IGameCallback.h"
+#include "callback/CPrivilegedInfoCallback.h"
 #include "entities/hero/CHeroHandler.h"
 #include "mapObjects/CGHeroInstance.h"
 #include "modding/ModScope.h"
@@ -707,7 +707,7 @@ void CCreatureSet::serializeJson(JsonSerializeFormat & handler, const std::strin
 	}
 }
 
-CStackInstance::CStackInstance(IGameCallback *cb, bool isHypothetic)
+CStackInstance::CStackInstance(CPrivilegedInfoCallback *cb, bool isHypothetic)
 	: CBonusSystemNode(isHypothetic)
 	, CStackBasicDescriptor(nullptr, 0)
 	, CArtifactSet(cb)
@@ -719,7 +719,7 @@ CStackInstance::CStackInstance(IGameCallback *cb, bool isHypothetic)
 	setNodeType(STACK_INSTANCE);
 }
 
-CStackInstance::CStackInstance(IGameCallback *cb, const CreatureID & id, TQuantity Count, bool isHypothetic)
+CStackInstance::CStackInstance(CPrivilegedInfoCallback *cb, const CreatureID & id, TQuantity Count, bool isHypothetic)
 	: CStackInstance(cb, false)
 {
 	setType(id);
@@ -1034,11 +1034,11 @@ const IBonusBearer* CStackInstance::getBonusBearer() const
 	return this;
 }
 
-CCommanderInstance::CCommanderInstance(IGameCallback *cb)
+CCommanderInstance::CCommanderInstance(CPrivilegedInfoCallback *cb)
 	:CStackInstance(cb)
 {}
 
-CCommanderInstance::CCommanderInstance(IGameCallback *cb, const CreatureID & id)
+CCommanderInstance::CCommanderInstance(CPrivilegedInfoCallback *cb, const CreatureID & id)
 	: CStackInstance(cb)
 	, name("Commando")
 {

+ 5 - 5
lib/CCreatureSet.h

@@ -78,7 +78,7 @@ class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDe
 
 	CArmedInstance * armyInstance = nullptr; //stack must be part of some army, army must be part of some object
 
-	IGameCallback * getCallback() const final { return cb; }
+	CPrivilegedInfoCallback * getCallback() const final { return cb; }
 
 	TExpType totalExperience;//commander needs same amount of exp as hero
 public:
@@ -146,8 +146,8 @@ public:
 	virtual int getLevel() const; //different for regular stack and commander
 	CreatureID getCreatureID() const; //-1 if not available
 	std::string getName() const; //plural or singular
-	CStackInstance(IGameCallback *cb, bool isHypothetic	= false);
-	CStackInstance(IGameCallback *cb, const CreatureID & id, TQuantity count, bool isHypothetic = false);
+	CStackInstance(CPrivilegedInfoCallback *cb, bool isHypothetic	= false);
+	CStackInstance(CPrivilegedInfoCallback *cb, const CreatureID & id, TQuantity count, bool isHypothetic = false);
 	virtual ~CStackInstance() = default;
 
 	void setType(const CreatureID & creID);
@@ -182,8 +182,8 @@ public:
 	std::vector <ui8> secondarySkills; //ID -> level
 	std::set <ui8> specialSkills;
 	//std::vector <CArtifactInstance *> arts;
-	CCommanderInstance(IGameCallback *cb);
-	CCommanderInstance(IGameCallback *cb, const CreatureID & id);
+	CCommanderInstance(CPrivilegedInfoCallback *cb);
+	CCommanderInstance(CPrivilegedInfoCallback *cb, const CreatureID & id);
 	void setAlive (bool alive);
 	void levelUp ();
 

+ 2 - 2
lib/CMakeLists.txt

@@ -475,7 +475,7 @@ set(lib_MAIN_HEADERS
 	callback/IBattleEventsReceiver.h
 	callback/IClient.h
 	callback/IGameActionCallback.h
-	callback/IGameCallback.h
+	callback/CPrivilegedInfoCallback.h
 	callback/IGameEventCallback.h
 	callback/IGameEventsReceiver.h
 	callback/IGameInfoCallback.h
@@ -831,7 +831,7 @@ endif()
 if(MINGW AND CMAKE_BUILD_TYPE STREQUAL "Debug")
 	set_source_files_properties(
 		serializer/SerializerReflection.cpp
-		IGameCallback.cpp
+		CPrivilegedInfoCallback.cpp
 		PROPERTIES
 		COMPILE_OPTIONS "-Wa,-mbig-obj")
 endif()

+ 2 - 2
lib/CPlayerState.cpp

@@ -11,7 +11,7 @@
 
 #include "CPlayerState.h"
 #include "GameLibrary.h"
-#include "callback/IGameCallback.h"
+#include "callback/CPrivilegedInfoCallback.h"
 #include "mapObjects/CGHeroInstance.h"
 #include "mapObjects/CGTownInstance.h"
 #include "gameState/CGameState.h"
@@ -21,7 +21,7 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-PlayerState::PlayerState(IGameCallback *cb)
+PlayerState::PlayerState(CPrivilegedInfoCallback *cb)
 	: CBonusSystemNode(PLAYER)
 	, GameCallbackHolder(cb)
 	, color(-1)

+ 1 - 1
lib/CPlayerState.h

@@ -75,7 +75,7 @@ public:
 	std::optional<ui8> daysWithoutCastle;
 	TurnTimerInfo turnTimer;
 
-	PlayerState(IGameCallback *cb);
+	PlayerState(CPrivilegedInfoCallback *cb);
 	~PlayerState();
 
 	std::string nodeName() const override;

+ 4 - 4
lib/battle/BattleInfo.cpp

@@ -15,7 +15,7 @@
 #include "bonuses/Limiters.h"
 #include "bonuses/Updaters.h"
 #include "../CStack.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
 #include "../entities/artifact/CArtifact.h"
 #include "../entities/building/TownFortifications.h"
 #include "../filesystem/Filesystem.h"
@@ -156,7 +156,7 @@ struct RangeGenerator
 	std::function<int()> myRand;
 };
 
-std::unique_ptr<BattleInfo> BattleInfo::setupBattle(IGameCallback *cb, const int3 & tile, TerrainId terrain, const BattleField & battlefieldType, BattleSideArray<const CArmedInstance *> armies, BattleSideArray<const CGHeroInstance *> heroes, const BattleLayout & layout, const CGTownInstance * town)
+std::unique_ptr<BattleInfo> BattleInfo::setupBattle(CPrivilegedInfoCallback *cb, const int3 & tile, TerrainId terrain, const BattleField & battlefieldType, BattleSideArray<const CArmedInstance *> armies, BattleSideArray<const CGHeroInstance *> heroes, const BattleLayout & layout, const CGTownInstance * town)
 {
 	CMP_stack cmpst;
 	auto currentBattle = std::make_unique<BattleInfo>(cb, layout);
@@ -458,13 +458,13 @@ CStack * BattleInfo::getStack(int stackID, bool onlyAlive)
 	return const_cast<CStack *>(battleGetStackByID(stackID, onlyAlive));
 }
 
-BattleInfo::BattleInfo(IGameCallback *cb, const BattleLayout & layout):
+BattleInfo::BattleInfo(CPrivilegedInfoCallback *cb, const BattleLayout & layout):
 	BattleInfo(cb)
 {
 	*this->layout = layout;
 }
 
-BattleInfo::BattleInfo(IGameCallback *cb)
+BattleInfo::BattleInfo(CPrivilegedInfoCallback *cb)
 	:GameCallbackHolder(cb),
 	sides({SideInBattle(cb), SideInBattle(cb)}),
 	layout(std::make_unique<BattleLayout>()),

+ 3 - 3
lib/battle/BattleInfo.h

@@ -74,8 +74,8 @@ public:
 	}
 
 	//////////////////////////////////////////////////////////////////////////
-	BattleInfo(IGameCallback *cb, const BattleLayout & layout);
-	BattleInfo(IGameCallback *cb);
+	BattleInfo(CPrivilegedInfoCallback *cb, const BattleLayout & layout);
+	BattleInfo(CPrivilegedInfoCallback *cb);
 	virtual ~BattleInfo();
 
 	const IBattleInfo * getBattle() const override;
@@ -164,7 +164,7 @@ public:
 	const CGHeroInstance * getHero(const PlayerColor & player) const; //returns fighting hero that belongs to given player
 
 	void localInit();
-	static std::unique_ptr<BattleInfo> setupBattle(IGameCallback *cb, const int3 & tile, TerrainId, const BattleField & battlefieldType, BattleSideArray<const CArmedInstance *> armies, BattleSideArray<const CGHeroInstance *> heroes, const BattleLayout & layout, const CGTownInstance * town);
+	static std::unique_ptr<BattleInfo> setupBattle(CPrivilegedInfoCallback *cb, const int3 & tile, TerrainId, const BattleField & battlefieldType, BattleSideArray<const CArmedInstance *> armies, BattleSideArray<const CGHeroInstance *> heroes, const BattleLayout & layout, const CGTownInstance * town);
 
 	BattleSide whatSide(const PlayerColor & player) const;
 

+ 3 - 3
lib/battle/BattleLayout.cpp

@@ -12,18 +12,18 @@
 
 #include "../GameSettings.h"
 #include "../GameLibrary.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
 #include "../json/JsonNode.h"
 #include "../mapObjects/CArmedInstance.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-BattleLayout BattleLayout::createDefaultLayout(IGameCallback * cb, const CArmedInstance * attacker, const CArmedInstance * defender)
+BattleLayout BattleLayout::createDefaultLayout(CPrivilegedInfoCallback * cb, const CArmedInstance * attacker, const CArmedInstance * defender)
 {
 	return createLayout(cb, "default", attacker, defender);
 }
 
-BattleLayout BattleLayout::createLayout(IGameCallback * cb, const std::string & layoutName, const CArmedInstance * attacker, const CArmedInstance * defender)
+BattleLayout BattleLayout::createLayout(CPrivilegedInfoCallback * cb, const std::string & layoutName, const CArmedInstance * attacker, const CArmedInstance * defender)
 {
 	const auto & loadHex = [](const JsonNode & node)
 	{

+ 3 - 3
lib/battle/BattleLayout.h

@@ -17,7 +17,7 @@
 VCMI_LIB_NAMESPACE_BEGIN
 
 class CArmedInstance;
-class IGameCallback;
+class CPrivilegedInfoCallback;
 
 struct DLL_EXPORT BattleLayout
 {
@@ -32,8 +32,8 @@ struct DLL_EXPORT BattleLayout
 	bool tacticsAllowed = false;
 	bool obstaclesAllowed = false;
 
-	static BattleLayout createDefaultLayout(IGameCallback * cb, const CArmedInstance * attacker, const CArmedInstance * defender);
-	static BattleLayout createLayout(IGameCallback * cb, const std::string & layoutName, const CArmedInstance * attacker, const CArmedInstance * defender);
+	static BattleLayout createDefaultLayout(CPrivilegedInfoCallback * cb, const CArmedInstance * attacker, const CArmedInstance * defender);
+	static BattleLayout createLayout(CPrivilegedInfoCallback * cb, const std::string & layoutName, const CArmedInstance * attacker, const CArmedInstance * defender);
 };
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 1
lib/battle/SideInBattle.cpp

@@ -10,7 +10,7 @@
 #include "StdInc.h"
 #include "SideInBattle.h"
 
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
 #include "../mapObjects/CGHeroInstance.h"
 
 VCMI_LIB_NAMESPACE_BEGIN

+ 11 - 0
lib/callback/CPrivilegedInfoCallback.h

@@ -18,9 +18,20 @@ namespace vstd
 	class RNG;
 }
 
+#if SCRIPTING_ENABLED
+	namespace scripting
+	{
+	class Pool;
+	}
+#endif
+
 class DLL_LINKAGE CPrivilegedInfoCallback : public CGameInfoCallback
 {
 public:
+#if SCRIPTING_ENABLED
+	virtual scripting::Pool * getGlobalContextPool() const = 0;
+#endif
+
 	using CGameInfoCallback::gameState; // make public
 
 	//used for random spawns

+ 3 - 3
lib/callback/GameCallbackHolder.h

@@ -11,14 +11,14 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-class IGameCallback;
+class CPrivilegedInfoCallback;
 
 class DLL_LINKAGE GameCallbackHolder
 {
 public:
-	IGameCallback * cb;
+	CPrivilegedInfoCallback * cb;
 
-	explicit GameCallbackHolder(IGameCallback *cb):
+	explicit GameCallbackHolder(CPrivilegedInfoCallback *cb):
 		cb(cb)
 	{}
 };

+ 0 - 43
lib/callback/IGameCallback.h

@@ -1,43 +0,0 @@
-/*
- * IGameCallback.h, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
-#pragma once
-
-#include "CPrivilegedInfoCallback.h"
-#include "IGameEventCallback.h"
-
-VCMI_LIB_NAMESPACE_BEGIN
-
-#if SCRIPTING_ENABLED
-namespace scripting
-{
-	class Pool;
-}
-#endif
-
-/// Interface class for handling general game logic and actions
-class DLL_LINKAGE IGameCallback : public CPrivilegedInfoCallback, public IGameEventCallback
-{
-public:
-	virtual ~IGameCallback(){};
-
-#if SCRIPTING_ENABLED
-	virtual scripting::Pool * getGlobalContextPool() const = 0;
-#endif
-
-	//get info
-	virtual bool isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero) { return false; }
-
-	friend struct CPack;
-	friend struct CPackForClient;
-	friend struct CPackForServer;
-};
-
-
-VCMI_LIB_NAMESPACE_END

+ 2 - 0
lib/callback/IGameEventCallback.h

@@ -115,6 +115,8 @@ public:
 
 	virtual void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) = 0;
 
+	virtual bool isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero) = 0;
+
 	virtual vstd::RNG & getRandomGenerator() = 0;
 };
 

+ 1 - 1
lib/campaign/CampaignState.cpp

@@ -420,7 +420,7 @@ std::optional<ui8> CampaignState::getBonusID(CampaignScenarioID which) const
 	return chosenCampaignBonuses.at(which);
 }
 
-std::unique_ptr<CMap> CampaignState::getMap(CampaignScenarioID scenarioId, IGameCallback * cb)
+std::unique_ptr<CMap> CampaignState::getMap(CampaignScenarioID scenarioId, CPrivilegedInfoCallback * cb)
 {
 	// FIXME: there is certainly better way to handle maps inside campaigns
 	if(scenarioId == CampaignScenarioID::NONE)

+ 2 - 2
lib/campaign/CampaignState.h

@@ -28,7 +28,7 @@ class CMap;
 class CMapHeader;
 class CMapInfo;
 class JsonNode;
-class IGameCallback;
+class CPrivilegedInfoCallback;
 
 class DLL_LINKAGE CampaignRegions
 {
@@ -338,7 +338,7 @@ public:
 	/// Returns true if all available scenarios have been completed and campaign is finished
 	bool isCampaignFinished() const;
 
-	std::unique_ptr<CMap> getMap(CampaignScenarioID scenarioId, IGameCallback * cb);
+	std::unique_ptr<CMap> getMap(CampaignScenarioID scenarioId, CPrivilegedInfoCallback * cb);
 	std::unique_ptr<CMapHeader> getMapHeader(CampaignScenarioID scenarioId) const;
 	std::shared_ptr<CMapInfo> getMapInfo(CampaignScenarioID scenarioId) const;
 

+ 2 - 2
lib/entities/artifact/ArtSlotInfo.cpp

@@ -11,11 +11,11 @@
 #include "StdInc.h"
 #include "ArtSlotInfo.h"
 
-#include "../../callback/IGameCallback.h"
+#include "../../callback/CPrivilegedInfoCallback.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-ArtSlotInfo::ArtSlotInfo(IGameCallback * cb)
+ArtSlotInfo::ArtSlotInfo(CPrivilegedInfoCallback * cb)
 	: GameCallbackHolder(cb)
 {
 }

+ 1 - 1
lib/entities/artifact/ArtSlotInfo.h

@@ -21,7 +21,7 @@ struct DLL_LINKAGE ArtSlotInfo : public GameCallbackHolder
 	ArtifactInstanceID artifactID;
 	bool locked = false; //if locked, then artifact points to the combined artifact
 
-	explicit ArtSlotInfo(IGameCallback * cb);
+	explicit ArtSlotInfo(CPrivilegedInfoCallback * cb);
 	ArtSlotInfo(const CArtifactInstance * artifact, bool locked);
 
 	const CArtifactInstance * getArt() const;

+ 1 - 1
lib/entities/artifact/CArtifactFittingSet.cpp

@@ -13,7 +13,7 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-CArtifactFittingSet::CArtifactFittingSet(IGameCallback *cb, ArtBearer bearer)
+CArtifactFittingSet::CArtifactFittingSet(CPrivilegedInfoCallback *cb, ArtBearer bearer)
 	: CArtifactSet(cb)
 	, GameCallbackHolder(cb)
 	, bearer(bearer)

+ 2 - 2
lib/entities/artifact/CArtifactFittingSet.h

@@ -18,13 +18,13 @@ VCMI_LIB_NAMESPACE_BEGIN
 // Used to try on artifacts before the claimed changes have been applied
 class DLL_LINKAGE CArtifactFittingSet : public CArtifactSet, public GameCallbackHolder
 {
-	IGameCallback * getCallback() const final
+	CPrivilegedInfoCallback * getCallback() const final
 	{
 		return cb;
 	}
 
 public:
-	CArtifactFittingSet(IGameCallback * cb, ArtBearer Bearer);
+	CArtifactFittingSet(CPrivilegedInfoCallback * cb, ArtBearer Bearer);
 	explicit CArtifactFittingSet(const CArtifactSet & artSet);
 	ArtBearer bearerType() const override;
 

+ 3 - 3
lib/entities/artifact/CArtifactInstance.cpp

@@ -14,7 +14,7 @@
 #include "CArtifact.h"
 #include "CArtifactSet.h"
 
-#include "../../callback/IGameCallback.h"
+#include "../../callback/CPrivilegedInfoCallback.h"
 #include "../../gameState/CGameState.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
@@ -125,13 +125,13 @@ void CGrowingArtifactInstance::growingUp()
 	}
 }
 
-CArtifactInstance::CArtifactInstance(IGameCallback *cb, const CArtifact * art)
+CArtifactInstance::CArtifactInstance(CPrivilegedInfoCallback *cb, const CArtifact * art)
 	:CArtifactInstance(cb)
 {
 	setType(art);
 }
 
-CArtifactInstance::CArtifactInstance(IGameCallback *cb)
+CArtifactInstance::CArtifactInstance(CPrivilegedInfoCallback *cb)
 	: CBonusSystemNode(ARTIFACT_INSTANCE)
 	, CCombinedArtifactInstance(cb)
 {

+ 2 - 2
lib/entities/artifact/CArtifactInstance.h

@@ -82,8 +82,8 @@ class DLL_LINKAGE CArtifactInstance final
 	ArtifactID artTypeID;
 
 public:
-	CArtifactInstance(IGameCallback *cb, const CArtifact * art);
-	CArtifactInstance(IGameCallback *cb);
+	CArtifactInstance(CPrivilegedInfoCallback *cb, const CArtifact * art);
+	CArtifactInstance(CPrivilegedInfoCallback *cb);
 	void setType(const CArtifact * art);
 	std::string nodeName() const override;
 	ArtifactID getTypeId() const;

+ 1 - 1
lib/entities/artifact/CArtifactSet.cpp

@@ -184,7 +184,7 @@ CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(const ArtifactPosition &
 	return resArtPlacement;
 }
 
-CArtifactSet::CArtifactSet(IGameCallback * cb)
+CArtifactSet::CArtifactSet(CPrivilegedInfoCallback * cb)
 	:artifactsTransitionPos(cb)
 {}
 

+ 2 - 2
lib/entities/artifact/CArtifactSet.h

@@ -40,11 +40,11 @@ public:
 	bool hasScroll(const SpellID & aid, bool onlyWorn = false) const;
 	bool isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck = false) const;
 
-	virtual IGameCallback * getCallback() const = 0;
+	virtual CPrivilegedInfoCallback * getCallback() const = 0;
 	virtual ArtBearer bearerType() const = 0;
 	virtual ArtPlacementMap putArtifact(const ArtifactPosition & slot, const CArtifactInstance * art);
 	virtual void removeArtifact(const ArtifactPosition & slot);
-	CArtifactSet(IGameCallback * cb);
+	CArtifactSet(CPrivilegedInfoCallback * cb);
 	virtual ~CArtifactSet() = default;
 
 	template <typename Handler> void serialize(Handler &h)

+ 64 - 64
lib/gameState/CGameState.cpp

@@ -31,7 +31,7 @@
 #include "../bonuses/Propagators.h"
 #include "../bonuses/Updaters.h"
 #include "../battle/BattleInfo.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
 #include "../campaign/CampaignState.h"
 #include "../constants/StringConstants.h"
 #include "../entities/artifact/ArtifactUtils.h"
@@ -71,7 +71,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 std::shared_mutex CGameState::mutex;
 
-HeroTypeID CGameState::pickNextHeroType(const PlayerColor & owner)
+HeroTypeID CGameState::pickNextHeroType(vstd::RNG & randomGenerator, const PlayerColor & owner)
 {
 	const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(owner);
 	if(ps.hero.isValid() && !isUsedHero(HeroTypeID(ps.hero))) //we haven't used selected hero
@@ -79,10 +79,10 @@ HeroTypeID CGameState::pickNextHeroType(const PlayerColor & owner)
 		return HeroTypeID(ps.hero);
 	}
 
-	return pickUnusedHeroTypeRandomly(owner);
+	return pickUnusedHeroTypeRandomly(randomGenerator, owner);
 }
 
-HeroTypeID CGameState::pickUnusedHeroTypeRandomly(const PlayerColor & owner)
+HeroTypeID CGameState::pickUnusedHeroTypeRandomly(vstd::RNG & randomGenerator, const PlayerColor & owner)
 {
 	//list of available heroes for this faction and others
 	std::vector<HeroTypeID> factionHeroes;
@@ -100,13 +100,13 @@ HeroTypeID CGameState::pickUnusedHeroTypeRandomly(const PlayerColor & owner)
 	// select random hero native to "our" faction
 	if(!factionHeroes.empty())
 	{
-		return *RandomGeneratorUtil::nextItem(factionHeroes, getRandomGenerator());
+		return *RandomGeneratorUtil::nextItem(factionHeroes, randomGenerator);
 	}
 
 	logGlobal->warn("Cannot find free hero of appropriate faction for player %s - trying to get first available...", owner.toString());
 	if(!otherHeroes.empty())
 	{
-		return *RandomGeneratorUtil::nextItem(otherHeroes, getRandomGenerator());
+		return *RandomGeneratorUtil::nextItem(otherHeroes, randomGenerator);
 	}
 
 	logGlobal->error("No free allowed heroes!");
@@ -150,7 +150,7 @@ int CGameState::getDate(Date mode) const
 	return getDate(day, mode);
 }
 
-CGameState::CGameState(IGameCallback * callback)
+CGameState::CGameState(CPrivilegedInfoCallback * callback)
 	: GameCallbackHolder(callback)
 {
 	heroesPool = std::make_unique<TavernHeroesPool>(this);
@@ -173,7 +173,7 @@ void CGameState::preInit(Services * newServices)
 	services = newServices;
 }
 
-void CGameState::init(const IMapService * mapService, StartInfo * si, Load::ProgressAccumulator & progressTracking, bool allowSavingRandomMap)
+void CGameState::init(const IMapService * mapService, StartInfo * si, vstd::RNG & randomGenerator, Load::ProgressAccumulator & progressTracking, bool allowSavingRandomMap)
 {
 	assert(services);
 	assert(cb);
@@ -184,7 +184,7 @@ void CGameState::init(const IMapService * mapService, StartInfo * si, Load::Prog
 	switch(scenarioOps->mode)
 	{
 	case EStartMode::NEW_GAME:
-		initNewGame(mapService, allowSavingRandomMap, progressTracking);
+		initNewGame(mapService, randomGenerator, allowSavingRandomMap, progressTracking);
 		break;
 	case EStartMode::CAMPAIGN:
 		initCampaign();
@@ -202,20 +202,20 @@ void CGameState::init(const IMapService * mapService, StartInfo * si, Load::Prog
 	initGlobalBonuses();
 	initPlayerStates();
 	if (campaign)
-		campaign->placeCampaignHeroes();
+		campaign->placeCampaignHeroes(randomGenerator);
 	removeHeroPlaceholders();
-	initGrailPosition();
-	initRandomFactionsForPlayers();
-	randomizeMapObjects();
-	placeStartingHeroes();
+	initGrailPosition(randomGenerator);
+	initRandomFactionsForPlayers(randomGenerator);
+	randomizeMapObjects(randomGenerator);
+	placeStartingHeroes(randomGenerator);
 	initOwnedObjects();
 	initDifficulty();
-	initHeroes();
-	initStartingBonus();
-	initTowns();
-	initTownNames();
+	initHeroes(randomGenerator);
+	initStartingBonus(randomGenerator);
+	initTowns(randomGenerator);
+	initTownNames(randomGenerator);
 	placeHeroesInTowns();
-	initMapObjects();
+	initMapObjects(randomGenerator);
 	buildBonusSystemTree();
 	initVisitingAndGarrisonedHeroes();
 	initFogOfWar();
@@ -291,7 +291,7 @@ void CGameState::updateOnLoad(StartInfo * si)
 	scenarioOps->simturnsInfo = si->simturnsInfo;
 }
 
-void CGameState::initNewGame(const IMapService * mapService, bool allowSavingRandomMap, Load::ProgressAccumulator & progressTracking)
+void CGameState::initNewGame(const IMapService * mapService, vstd::RNG & randomGenerator, bool allowSavingRandomMap, Load::ProgressAccumulator & progressTracking)
 {
 	if(scenarioOps->createRandomMap())
 	{
@@ -299,7 +299,7 @@ void CGameState::initNewGame(const IMapService * mapService, bool allowSavingRan
 		CStopWatch sw;
 
 		// Gen map
-		CMapGenerator mapGenerator(*scenarioOps->mapGenOptions, cb, getRandomGenerator().nextInt());
+		CMapGenerator mapGenerator(*scenarioOps->mapGenOptions, cb, randomGenerator.nextInt());
 		progressTracking.include(mapGenerator);
 
 		map = mapGenerator.generate();
@@ -425,7 +425,7 @@ void CGameState::initDifficulty()
 		campaign->initStartingResources();
 }
 
-void CGameState::initGrailPosition()
+void CGameState::initGrailPosition(vstd::RNG & randomGenerator)
 {
 	logGlobal->debug("\tPicking grail position");
 	//pick grail location
@@ -463,7 +463,7 @@ void CGameState::initGrailPosition()
 
 		if(!allowedPos.empty())
 		{
-			map->grailPos = *RandomGeneratorUtil::nextItem(allowedPos, getRandomGenerator());
+			map->grailPos = *RandomGeneratorUtil::nextItem(allowedPos, randomGenerator);
 		}
 		else
 		{
@@ -472,14 +472,14 @@ void CGameState::initGrailPosition()
 	}
 }
 
-void CGameState::initRandomFactionsForPlayers()
+void CGameState::initRandomFactionsForPlayers(vstd::RNG & randomGenerator)
 {
 	logGlobal->debug("\tPicking random factions for players");
 	for(auto & elem : scenarioOps->playerInfos)
 	{
 		if(elem.second.castle==FactionID::RANDOM)
 		{
-			auto randomID = getRandomGenerator().nextInt((int)map->players[elem.first.getNum()].allowedFactions.size() - 1);
+			auto randomID = randomGenerator.nextInt((int)map->players[elem.first.getNum()].allowedFactions.size() - 1);
 			auto iter = map->players[elem.first.getNum()].allowedFactions.begin();
 			std::advance(iter, randomID);
 
@@ -488,12 +488,12 @@ void CGameState::initRandomFactionsForPlayers()
 	}
 }
 
-void CGameState::randomizeMapObjects()
+void CGameState::randomizeMapObjects(vstd::RNG & randomGenerator)
 {
 	logGlobal->debug("\tRandomizing objects");
 	for(const auto & object : map->getObjects())
 	{
-		object->pickRandomObject(getRandomGenerator());
+		object->pickRandomObject(randomGenerator);
 
 		//handle Favouring Winds - mark tiles under it
 		if(object->ID == Obj::FAVORABLE_WINDS)
@@ -562,7 +562,7 @@ void CGameState::placeStartingHero(const PlayerColor & playerColor, const HeroTy
 	map->getEditManager()->insertObject(hero);
 }
 
-void CGameState::placeStartingHeroes()
+void CGameState::placeStartingHeroes(vstd::RNG & randomGenerator)
 {
 	logGlobal->debug("\tGiving starting hero");
 
@@ -576,7 +576,7 @@ void CGameState::placeStartingHeroes()
 			if (campaign && campaign->playerHasStartingHero(playerColor))
 				continue;
 
-			HeroTypeID heroTypeId = pickNextHeroType(playerColor);
+			HeroTypeID heroTypeId = pickNextHeroType(randomGenerator, playerColor);
 			if(playerSettingPair.second.hero == HeroTypeID::NONE || playerSettingPair.second.hero == HeroTypeID::RANDOM)
 				playerSettingPair.second.hero = heroTypeId;
 
@@ -594,7 +594,7 @@ void CGameState::removeHeroPlaceholders()
 	}
 }
 
-void CGameState::initHeroes()
+void CGameState::initHeroes(vstd::RNG & randomGenerator)
 {
 	//heroes instances initialization
 	for (auto heroID : map->getHeroesOnMap())
@@ -605,7 +605,7 @@ void CGameState::initHeroes()
 			logGlobal->warn("Hero with uninitialized owner!");
 			continue;
 		}
-		hero->initHero(getRandomGenerator());
+		hero->initHero(randomGenerator);
 	}
 
 	// generate boats for all heroes on water
@@ -622,7 +622,7 @@ void CGameState::initHeroes()
 		{
 			auto handler = LIBRARY->objtypeh->getHandlerFor(Obj::BOAT, hero->getBoatType().getNum());
 			auto boat = std::dynamic_pointer_cast<CGBoat>(handler->create(cb, nullptr));
-			handler->configureObject(boat.get(), getRandomGenerator());
+			handler->configureObject(boat.get(), randomGenerator);
 
 			boat->setAnchorPos(hero->anchorPos());
 			boat->appearance = handler->getTemplates().front();
@@ -648,7 +648,7 @@ void CGameState::initHeroes()
 			heroInPool = newHeroPtr.get();
 		}
 		map->generateUniqueInstanceName(heroInPool);
-		heroInPool->initHero(getRandomGenerator());
+		heroInPool->initHero(randomGenerator);
 		heroesPool->addHeroToPool(htype);
 	}
 
@@ -685,7 +685,7 @@ void CGameState::initFogOfWar()
 	}
 }
 
-void CGameState::initStartingBonus()
+void CGameState::initStartingBonus(vstd::RNG & randomGenerator)
 {
 	if (scenarioOps->mode == EStartMode::CAMPAIGN)
 		return;
@@ -697,25 +697,25 @@ void CGameState::initStartingBonus()
 	{
 		//starting bonus
 		if(scenarioOps->playerInfos[elem.first].bonus == PlayerStartingBonus::RANDOM)
-			scenarioOps->playerInfos[elem.first].bonus = static_cast<PlayerStartingBonus>(getRandomGenerator().nextInt(2));
+			scenarioOps->playerInfos[elem.first].bonus = static_cast<PlayerStartingBonus>(randomGenerator.nextInt(2));
 
 		switch(scenarioOps->playerInfos[elem.first].bonus)
 		{
 		case PlayerStartingBonus::GOLD:
-			elem.second.resources[EGameResID::GOLD] += getRandomGenerator().nextInt(5, 10) * 100;
+			elem.second.resources[EGameResID::GOLD] += randomGenerator.nextInt(5, 10) * 100;
 			break;
 		case PlayerStartingBonus::RESOURCE:
 			{
 				auto res = (*LIBRARY->townh)[scenarioOps->playerInfos[elem.first].castle]->town->primaryRes;
 				if(res == EGameResID::WOOD_AND_ORE)
 				{
-					int amount = getRandomGenerator().nextInt(5, 10);
+					int amount = randomGenerator.nextInt(5, 10);
 					elem.second.resources[EGameResID::WOOD] += amount;
 					elem.second.resources[EGameResID::ORE] += amount;
 				}
 				else
 				{
-					elem.second.resources[res] += getRandomGenerator().nextInt(3, 6);
+					elem.second.resources[res] += randomGenerator.nextInt(3, 6);
 				}
 				break;
 			}
@@ -726,7 +726,7 @@ void CGameState::initStartingBonus()
 					logGlobal->error("Cannot give starting artifact - no heroes!");
 					break;
 				}
-				const Artifact * toGive = pickRandomArtifact(getRandomGenerator(), EArtifactClass::ART_TREASURE).toEntity(LIBRARY);
+				const Artifact * toGive = pickRandomArtifact(randomGenerator, EArtifactClass::ART_TREASURE).toEntity(LIBRARY);
 
 				CGHeroInstance *hero = elem.second.getHeroes()[0];
 				if(!giveHeroArtifact(hero, toGive->getId()))
@@ -737,7 +737,7 @@ void CGameState::initStartingBonus()
 	}
 }
 
-void CGameState::initTownNames()
+void CGameState::initTownNames(vstd::RNG & randomGenerator)
 {
 	std::map<FactionID, std::vector<int>> availableNames;
 	for(const auto & faction : LIBRARY->townh->getDefaultAllowed())
@@ -770,9 +770,9 @@ void CGameState::initTownNames()
 
 		// If town has no available names (for example - all were picked) - pick names from some other faction that still has names available
 		if(!availableNames.count(faction))
-			faction = RandomGeneratorUtil::nextItem(availableNames, getRandomGenerator())->first;
+			faction = RandomGeneratorUtil::nextItem(availableNames, randomGenerator)->first;
 
-		auto nameIt = RandomGeneratorUtil::nextItem(availableNames[faction], getRandomGenerator());
+		auto nameIt = RandomGeneratorUtil::nextItem(availableNames[faction], randomGenerator);
 		vti->setNameTextId(faction.toFaction()->town->getRandomNameTextID(*nameIt));
 
 		availableNames[faction].erase(nameIt);
@@ -781,7 +781,7 @@ void CGameState::initTownNames()
 	}
 }
 
-void CGameState::initTowns()
+void CGameState::initTowns(vstd::RNG & randomGenerator)
 {
 	logGlobal->debug("\tTowns");
 
@@ -816,7 +816,7 @@ void CGameState::initTowns()
 
 			for(int i = 0; i < definesBuildingsChances.size(); i++)
 			{
-				if((getRandomGenerator().nextInt(1,100) <= definesBuildingsChances[i]))
+				if((randomGenerator.nextInt(1,100) <= definesBuildingsChances[i]))
 				{
 					vti->addBuilding(basicDwellings[i]);
 				}
@@ -912,7 +912,7 @@ void CGameState::initTowns()
 
 		while(!vti->possibleSpells.empty())
 		{
-			size_t index = RandomGeneratorUtil::nextItemWeighted(spellWeights, getRandomGenerator());
+			size_t index = RandomGeneratorUtil::nextItemWeighted(spellWeights, randomGenerator);
 
 			const auto * s = vti->possibleSpells[index].toSpell();
 			vti->spells[s->getLevel()-1].push_back(s->id);
@@ -923,12 +923,12 @@ void CGameState::initTowns()
 	}
 }
 
-void CGameState::initMapObjects()
+void CGameState::initMapObjects(vstd::RNG & randomGenerator)
 {
 	logGlobal->debug("\tObject initialization");
 
 	for(auto & obj : map->getObjects())
-		obj->initObj(getRandomGenerator());
+		obj->initObj(randomGenerator);
 
 	logGlobal->debug("\tObject initialization done");
 	for(auto & q : map->getObjects<CGSeerHut>())
@@ -1029,7 +1029,7 @@ BattleInfo * CGameState::getBattle(const BattleID & battle)
 	return nullptr;
 }
 
-BattleField CGameState::battleGetBattlefieldType(int3 tile, vstd::RNG & rand)
+BattleField CGameState::battleGetBattlefieldType(int3 tile, vstd::RNG & randomGenerator)
 {
 	assert(tile.isValid());
 
@@ -1063,7 +1063,7 @@ BattleField CGameState::battleGetBattlefieldType(int3 tile, vstd::RNG & rand)
 	if (t.getTerrain()->battleFields.empty())
 		throw std::runtime_error("Failed to find battlefield for terrain " + t.getTerrain()->getJsonKey());
 
-	return BattleField(*RandomGeneratorUtil::nextItem(t.getTerrain()->battleFields, rand));
+	return BattleField(*RandomGeneratorUtil::nextItem(t.getTerrain()->battleFields, randomGenerator));
 }
 
 void CGameState::fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out) const
@@ -1656,19 +1656,12 @@ CGHeroInstance * CGameState::getUsedHero(const HeroTypeID & hid) const
 	return nullptr;
 }
 
-
-
 TeamState::TeamState()
 {
 	setNodeType(TEAM);
 }
 
-vstd::RNG & CGameState::getRandomGenerator()
-{
-	return cb->getRandomGenerator();
-}
-
-ArtifactID CGameState::pickRandomArtifact(vstd::RNG & rand, std::optional<EArtifactClass> type, std::function<bool(ArtifactID)> accepts)
+ArtifactID CGameState::pickRandomArtifact(vstd::RNG & randomGenerator, std::optional<EArtifactClass> type, std::function<bool(ArtifactID)> accepts)
 {
 	std::set<ArtifactID> potentialPicks;
 
@@ -1691,10 +1684,10 @@ ArtifactID CGameState::pickRandomArtifact(vstd::RNG & rand, std::optional<EArtif
 		potentialPicks.insert(artifact->getId());
 	}
 
-	return pickRandomArtifact(rand, potentialPicks);
+	return pickRandomArtifact(randomGenerator, potentialPicks);
 }
 
-ArtifactID CGameState::pickRandomArtifact(vstd::RNG & rand, std::set<ArtifactID> potentialPicks)
+ArtifactID CGameState::pickRandomArtifact(vstd::RNG & randomGenerator, std::set<ArtifactID> potentialPicks)
 {
 	// No allowed artifacts at all - give Grail - this can't be banned (hopefully)
 	// FIXME: investigate how such cases are handled by H3 - some heavily customized user-made maps likely rely on H3 behavior
@@ -1718,19 +1711,19 @@ ArtifactID CGameState::pickRandomArtifact(vstd::RNG & rand, std::set<ArtifactID>
 
 	assert(!preferredPicks.empty());
 
-	ArtifactID artID = *RandomGeneratorUtil::nextItem(preferredPicks, rand);
+	ArtifactID artID = *RandomGeneratorUtil::nextItem(preferredPicks, randomGenerator);
 	allocatedArtifacts[artID] += 1; // record +1 more usage
 	return artID;
 }
 
-ArtifactID CGameState::pickRandomArtifact(vstd::RNG & rand, std::function<bool(ArtifactID)> accepts)
+ArtifactID CGameState::pickRandomArtifact(vstd::RNG & randomGenerator, std::function<bool(ArtifactID)> accepts)
 {
-	return pickRandomArtifact(rand, std::nullopt, std::move(accepts));
+	return pickRandomArtifact(randomGenerator, std::nullopt, std::move(accepts));
 }
 
-ArtifactID CGameState::pickRandomArtifact(vstd::RNG & rand, std::optional<EArtifactClass> type)
+ArtifactID CGameState::pickRandomArtifact(vstd::RNG & randomGenerator, std::optional<EArtifactClass> type)
 {
-	return pickRandomArtifact(rand, type, [](const ArtifactID &) { return true; });
+	return pickRandomArtifact(randomGenerator, type, [](const ArtifactID &) { return true; });
 }
 
 CArtifactInstance * CGameState::createScroll(const SpellID & spellId)
@@ -1782,6 +1775,13 @@ void CGameState::loadGame(CLoadFile & file)
 	}
 }
 
+#if SCRIPTING_ENABLED
+scripting::Pool * CGameState::getGlobalContextPool() const
+{
+	return nullptr; // TODO
+}
+#endif
+
 void CGameState::saveCompatibilityRegisterMissingArtifacts()
 {
 	for( const auto & newArtifact : saveCompatibilityUnregisteredArtifacts)

+ 23 - 30
lib/gameState/CGameState.h

@@ -68,7 +68,7 @@ public:
 	/// list of players currently making turn. Usually - just one, except for simturns
 	std::set<PlayerColor> actingPlayers;
 
-	CGameState(IGameCallback * callback);
+	CGameState(CPrivilegedInfoCallback * callback);
 	virtual ~CGameState();
 
 	CGameState & gameState() final { return *this; }
@@ -76,7 +76,7 @@ public:
 
 	void preInit(Services * services);
 
-	void init(const IMapService * mapService, StartInfo * si, Load::ProgressAccumulator &, bool allowSavingRandomMap = true);
+	void init(const IMapService * mapService, StartInfo * si, vstd::RNG & randomGenerator, Load::ProgressAccumulator &, bool allowSavingRandomMap = true);
 	void updateOnLoad(StartInfo * si);
 
 	ui32 day; //total number of days in game
@@ -94,10 +94,10 @@ public:
 
 	bool giveHeroArtifact(CGHeroInstance * h, const ArtifactID & aid);
 	/// picks next free hero type of the H3 hero init sequence -> chosen starting hero, then unused hero type randomly
-	HeroTypeID pickNextHeroType(const PlayerColor & owner);
+	HeroTypeID pickNextHeroType(vstd::RNG & randomGenerator, const PlayerColor & owner);
 
 	void apply(CPackForClient & pack);
-	BattleField battleGetBattlefieldType(int3 tile, vstd::RNG & rand);
+	BattleField battleGetBattlefieldType(int3 tile, vstd::RNG & randomGenerator);
 
 	void fillUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out) const override;
 	PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2) const override;
@@ -107,10 +107,10 @@ public:
 	std::vector<const CGObjectInstance*> guardingCreatures (int3 pos) const;
 
 	/// Gets a artifact ID randomly and removes the selected artifact from this handler.
-	ArtifactID pickRandomArtifact(vstd::RNG & rand, std::optional<EArtifactClass> type);
-	ArtifactID pickRandomArtifact(vstd::RNG & rand, std::function<bool(ArtifactID)> accepts);
-	ArtifactID pickRandomArtifact(vstd::RNG & rand, std::optional<EArtifactClass> type, std::function<bool(ArtifactID)> accepts);
-	ArtifactID pickRandomArtifact(vstd::RNG & rand, std::set<ArtifactID> filtered);
+	ArtifactID pickRandomArtifact(vstd::RNG & randomGenerator, std::optional<EArtifactClass> type);
+	ArtifactID pickRandomArtifact(vstd::RNG & randomGenerator, std::function<bool(ArtifactID)> accepts);
+	ArtifactID pickRandomArtifact(vstd::RNG & randomGenerator, std::optional<EArtifactClass> type, std::function<bool(ArtifactID)> accepts);
+	ArtifactID pickRandomArtifact(vstd::RNG & randomGenerator, std::set<ArtifactID> filtered);
 
 	/// Creates instance of spell scroll artifact with provided spell
 	CArtifactInstance * createScroll(const SpellID & spellId);
@@ -165,16 +165,9 @@ public:
 	static int getDate(int day, Date mode);
 	int getDate(Date mode=Date::DAY) const override; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
 
-	// ----- getters, setters -----
-
-	/// This RNG should only be used inside GS or CPackForClient-derived applyGs
-	/// If this doesn't work for your code that mean you need a new netpack
-	///
-	/// Client-side must use vstd::RNG::getDefault which is not serialized
-	///
-	/// CGameHandler have it's own getter for vstd::RNG::getDefault
-	/// Any server-side code outside of GH must use vstd::RNG::getDefault
-	vstd::RNG & getRandomGenerator();
+#if SCRIPTING_ENABLED
+	scripting::Pool * getGlobalContextPool() const override;
+#endif
 
 	void saveGame(CSaveFile & file) const;
 	void loadGame(CLoadFile & file);
@@ -206,24 +199,24 @@ public:
 
 private:
 	// ----- initialization -----
-	void initNewGame(const IMapService * mapService, bool allowSavingRandomMap, Load::ProgressAccumulator & progressTracking);
+	void initNewGame(const IMapService * mapService, vstd::RNG & randomGenerator, bool allowSavingRandomMap, Load::ProgressAccumulator & progressTracking);
 	void initGlobalBonuses();
-	void initGrailPosition();
-	void initRandomFactionsForPlayers();
+	void initGrailPosition(vstd::RNG & randomGenerator);
+	void initRandomFactionsForPlayers(vstd::RNG & randomGenerator);
 	void initOwnedObjects();
-	void randomizeMapObjects();
+	void randomizeMapObjects(vstd::RNG & randomGenerator);
 	void initPlayerStates();
-	void placeStartingHeroes();
+	void placeStartingHeroes(vstd::RNG & randomGenerator);
 	void placeStartingHero(const PlayerColor & playerColor, const HeroTypeID & heroTypeId, int3 townPos);
 	void removeHeroPlaceholders();
 	void initDifficulty();
-	void initHeroes();
+	void initHeroes(vstd::RNG & randomGenerator);
 	void placeHeroesInTowns();
 	void initFogOfWar();
-	void initStartingBonus();
-	void initTowns();
-	void initTownNames();
-	void initMapObjects();
+	void initStartingBonus(vstd::RNG & randomGenerator);
+	void initTowns(vstd::RNG & randomGenerator);
+	void initTownNames(vstd::RNG & randomGenerator);
+	void initMapObjects(vstd::RNG & randomGenerator);
 	void initVisitingAndGarrisonedHeroes();
 	void initCampaign();
 
@@ -238,7 +231,7 @@ private:
 	CGHeroInstance * getUsedHero(const HeroTypeID & hid) const;
 	bool isUsedHero(const HeroTypeID & hid) const; //looks in heroes and prisons
 	std::set<HeroTypeID> getUnusedAllowedHeroes(bool alsoIncludeNotAllowed = false) const;
-	HeroTypeID pickUnusedHeroTypeRandomly(const PlayerColor & owner); // picks a unused hero type randomly
+	HeroTypeID pickUnusedHeroTypeRandomly(vstd::RNG & randomGenerator, const PlayerColor & owner); // picks a unused hero type randomly
 	UpgradeInfo fillUpgradeInfo(const CStackInstance &stack) const;
 
 	// ---- data -----
@@ -247,7 +240,7 @@ private:
 	/// Pointer to campaign state manager. Nullptr for single scenarios
 	std::unique_ptr<CGameStateCampaign> campaign;
 
-	friend class IGameCallback;
+	friend class CPrivilegedInfoCallback;
 	friend class CMapHandler;
 	friend class CGameHandler;
 };

+ 7 - 7
lib/gameState/CGameStateCampaign.cpp

@@ -72,7 +72,7 @@ std::optional<CampaignScenarioID> CGameStateCampaign::getHeroesSourceScenario()
 	return campaignState->lastScenario();
 }
 
-void CGameStateCampaign::trimCrossoverHeroesParameters(const CampaignTravel & travelOptions)
+void CGameStateCampaign::trimCrossoverHeroesParameters(vstd::RNG & randomGenerator, const CampaignTravel & travelOptions)
 {
 	// TODO this logic (what should be kept) should be part of CScenarioTravel and be exposed via some clean set of methods
 	if(!travelOptions.whatHeroKeeps.experience)
@@ -80,7 +80,7 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(const CampaignTravel & tr
 		//trimming experience
 		for(auto & hero : campaignHeroReplacements)
 		{
-			hero.hero->initExp(gameState->getRandomGenerator());
+			hero.hero->initExp(randomGenerator);
 		}
 	}
 
@@ -208,7 +208,7 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(const CampaignTravel & tr
 	}
 }
 
-void CGameStateCampaign::placeCampaignHeroes()
+void CGameStateCampaign::placeCampaignHeroes(vstd::RNG & randomGenerator)
 {
 	// place bonus hero
 	auto campaignState = gameState->scenarioOps->campState;
@@ -224,7 +224,7 @@ void CGameStateCampaign::placeCampaignHeroes()
 			HeroTypeID heroTypeId = HeroTypeID(campaignBonus->info2);
 			if(heroTypeId == HeroTypeID::CAMP_RANDOM) // random bonus hero
 			{
-				heroTypeId = gameState->pickUnusedHeroTypeRandomly(playerColor);
+				heroTypeId = gameState->pickUnusedHeroTypeRandomly(randomGenerator, playerColor);
 			}
 
 			gameState->placeStartingHero(playerColor, HeroTypeID(heroTypeId), gameState->map->players[playerColor.getNum()].posOfMainTown);
@@ -235,7 +235,7 @@ void CGameStateCampaign::placeCampaignHeroes()
 	generateCampaignHeroesToReplace();
 
 	logGlobal->debug("\tPrepare crossover heroes");
-	trimCrossoverHeroesParameters(campaignState->scenario(*campaignState->currentScenario()).travelOptions);
+	trimCrossoverHeroesParameters(randomGenerator, campaignState->scenario(*campaignState->currentScenario()).travelOptions);
 
 	// remove same heroes on the map which will be added through crossover heroes
 	// INFO: we will remove heroes because later it may be possible that the API doesn't allow having heroes
@@ -275,14 +275,14 @@ void CGameStateCampaign::placeCampaignHeroes()
 		HeroTypeID heroTypeId;
 		if(hero->ID == Obj::HERO)
 		{
-			heroTypeId = gameState->pickUnusedHeroTypeRandomly(hero->tempOwner);
+			heroTypeId = gameState->pickUnusedHeroTypeRandomly(randomGenerator, hero->tempOwner);
 		}
 		else if(hero->ID == Obj::PRISON)
 		{
 			auto unusedHeroTypeIds = gameState->getUnusedAllowedHeroes();
 			if(!unusedHeroTypeIds.empty())
 			{
-				heroTypeId = (*RandomGeneratorUtil::nextItem(unusedHeroTypeIds, gameState->getRandomGenerator()));
+				heroTypeId = (*RandomGeneratorUtil::nextItem(unusedHeroTypeIds, randomGenerator));
 			}
 			else
 			{

+ 7 - 2
lib/gameState/CGameStateCampaign.h

@@ -21,6 +21,11 @@ class CGHeroInstance;
 class CGameState;
 class CMap;
 
+namespace vstd
+{
+	class RNG;
+}
+
 struct CampaignHeroReplacement
 {
 	CampaignHeroReplacement(std::shared_ptr<CGHeroInstance> hero, const ObjectInstanceID & heroPlaceholderId);
@@ -46,7 +51,7 @@ class CGameStateCampaign : public Serializeable
 	std::optional<CampaignBonus> currentBonus() const;
 
 	/// Trims hero parameters that should not transfer between scenarios according to travelOptions flags
-	void trimCrossoverHeroesParameters(const CampaignTravel & travelOptions);
+	void trimCrossoverHeroesParameters(vstd::RNG & randomGenerator, const CampaignTravel & travelOptions);
 
 	void replaceHeroesPlaceholders();
 	void transferMissingArtifacts(const CampaignTravel & travelOptions);
@@ -58,7 +63,7 @@ public:
 	CGameStateCampaign(CGameState * owner);
 	void setGamestate(CGameState * owner);
 
-	void placeCampaignHeroes();
+	void placeCampaignHeroes(vstd::RNG & randomGenerator);
 	void initStartingResources();
 	void initHeroes();
 	void initTowns();

+ 1 - 1
lib/json/JsonRandom.cpp

@@ -18,7 +18,7 @@
 
 #include "JsonBonus.h"
 
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
 #include "../constants/StringConstants.h"
 #include "../GameLibrary.h"
 #include "../CCreatureHandler.h"

+ 2 - 2
lib/mapObjectConstructors/AObjectTypeHandler.h

@@ -23,7 +23,7 @@ class RNG;
 class ObjectTemplate;
 class CGObjectInstance;
 class IObjectInfo;
-class IGameCallback;
+class CPrivilegedInfoCallback;
 
 /// Class responsible for creation of objects of specific type & subtype
 class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
@@ -118,7 +118,7 @@ public:
 
 	/// Creates object and set up core properties (like ID/subID). Object is NOT initialized
 	/// to allow creating objects before game start (e.g. map loading)
-	virtual std::shared_ptr<CGObjectInstance> create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const = 0;
+	virtual std::shared_ptr<CGObjectInstance> create(CPrivilegedInfoCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const = 0;
 
 	/// Configures object properties. Should be re-entrable, resetting state of the object if necessarily
 	/// This should set remaining properties, including randomized or depending on map

+ 2 - 2
lib/mapObjectConstructors/CDefaultObjectTypeHandler.h

@@ -27,7 +27,7 @@ class CDefaultObjectTypeHandler : public AObjectTypeHandler
 		randomizeObject(castedObject, rng);
 	}
 
-	std::shared_ptr<CGObjectInstance> create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const final
+	std::shared_ptr<CGObjectInstance> create(CPrivilegedInfoCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const final
 	{
 		auto result = createObject(cb);
 
@@ -44,7 +44,7 @@ class CDefaultObjectTypeHandler : public AObjectTypeHandler
 protected:
 	virtual void initializeObject(ObjectType * object) const {}
 	virtual void randomizeObject(ObjectType * object, vstd::RNG & rng) const {}
-	virtual std::shared_ptr<ObjectType> createObject(IGameCallback * cb) const
+	virtual std::shared_ptr<ObjectType> createObject(CPrivilegedInfoCallback * cb) const
 	{
 		return std::make_shared<ObjectType>(cb);
 	}

+ 2 - 2
lib/mapObjectConstructors/CRewardableConstructor.cpp

@@ -37,7 +37,7 @@ bool CRewardableConstructor::hasNameTextID() const
 	return !objectInfo.getParameters()["name"].isNull();
 }
 
-std::shared_ptr<CGObjectInstance> CRewardableConstructor::create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const
+std::shared_ptr<CGObjectInstance> CRewardableConstructor::create(CPrivilegedInfoCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const
 {
 	auto ret = std::make_shared<CRewardableObject>(cb);
 	preInitObject(ret.get());
@@ -55,7 +55,7 @@ void CRewardableConstructor::assignBonuses(std::vector<Bonus> & bonuses, MapObje
 	}
 }
 
-Rewardable::Configuration CRewardableConstructor::generateConfiguration(IGameCallback * cb, vstd::RNG & rand, MapObjectID objectID, const std::map<std::string, JsonNode> & presetVariables) const
+Rewardable::Configuration CRewardableConstructor::generateConfiguration(CPrivilegedInfoCallback * cb, vstd::RNG & rand, MapObjectID objectID, const std::map<std::string, JsonNode> & presetVariables) const
 {
 	Rewardable::Configuration result;
 	result.variables.preset = presetVariables;

+ 2 - 2
lib/mapObjectConstructors/CRewardableConstructor.h

@@ -28,13 +28,13 @@ class DLL_LINKAGE CRewardableConstructor : public AObjectTypeHandler
 public:
 	bool hasNameTextID() const override;
 
-	std::shared_ptr<CGObjectInstance> create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
+	std::shared_ptr<CGObjectInstance> create(CPrivilegedInfoCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
 
 	void configureObject(CGObjectInstance * object, vstd::RNG & rng) const override;
 
 	std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const override;
 
-	Rewardable::Configuration generateConfiguration(IGameCallback * cb, vstd::RNG & rand, MapObjectID objectID, const std::map<std::string, JsonNode> & presetVariables) const;
+	Rewardable::Configuration generateConfiguration(CPrivilegedInfoCallback * cb, vstd::RNG & rand, MapObjectID objectID, const std::map<std::string, JsonNode> & presetVariables) const;
 };
 
 VCMI_LIB_NAMESPACE_END

+ 2 - 2
lib/mapObjectConstructors/CommonConstructors.cpp

@@ -17,7 +17,7 @@
 #include "../GameLibrary.h"
 
 #include "../CConfigHandler.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
 #include "../entities/faction/CTownHandler.h"
 #include "../entities/hero/CHeroClass.h"
 #include "../json/JsonUtils.h"
@@ -318,7 +318,7 @@ bool MarketInstanceConstructor::hasDescription() const
 	return !descriptionTextID.empty();
 }
 
-std::shared_ptr<CGMarket> MarketInstanceConstructor::createObject(IGameCallback * cb) const
+std::shared_ptr<CGMarket> MarketInstanceConstructor::createObject(CPrivilegedInfoCallback * cb) const
 {
 	if(marketModes.size() == 1)
 	{

+ 1 - 1
lib/mapObjectConstructors/CommonConstructors.h

@@ -137,7 +137,7 @@ class MarketInstanceConstructor : public CDefaultObjectTypeHandler<CGMarket>
 
 	void initTypeData(const JsonNode & config) override;
 public:
-	std::shared_ptr<CGMarket> createObject(IGameCallback * cb) const override;
+	std::shared_ptr<CGMarket> createObject(CPrivilegedInfoCallback * cb) const override;
 	void randomizeObject(CGMarket * object, vstd::RNG & rng) const override;
 
 	const std::set<EMarketMode> & availableModes() const;

+ 3 - 3
lib/mapObjects/CArmedInstance.cpp

@@ -13,7 +13,7 @@
 
 #include "../CCreatureHandler.h"
 #include "../CPlayerState.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
 #include "../entities/faction/CFaction.h"
 #include "../entities/faction/CTown.h"
 #include "../entities/faction/CTownHandler.h"
@@ -41,12 +41,12 @@ void CArmedInstance::randomizeArmy(FactionID type)
 	}
 }
 
-CArmedInstance::CArmedInstance(IGameCallback *cb)
+CArmedInstance::CArmedInstance(CPrivilegedInfoCallback *cb)
 	:CArmedInstance(cb, false)
 {
 }
 
-CArmedInstance::CArmedInstance(IGameCallback *cb, bool isHypothetic):
+CArmedInstance::CArmedInstance(CPrivilegedInfoCallback *cb, bool isHypothetic):
 	CGObjectInstance(cb),
 	CBonusSystemNode(isHypothetic),
 	nonEvilAlignmentMix(this, Selector::type()(BonusType::NONEVIL_ALIGNMENT_MIX)), // Take Angelic Alliance troop-mixing freedom of non-evil units into account.

+ 2 - 2
lib/mapObjects/CArmedInstance.h

@@ -50,8 +50,8 @@ public:
 	void restoreBonusSystem(CGameState & gs) override;
 	//////////////////////////////////////////////////////////////////////////
 
-	CArmedInstance(IGameCallback *cb);
-	CArmedInstance(IGameCallback *cb, bool isHypothetic);
+	CArmedInstance(CPrivilegedInfoCallback *cb);
+	CArmedInstance(CPrivilegedInfoCallback *cb, bool isHypothetic);
 
 	PlayerColor getOwner() const override
 	{

+ 49 - 48
lib/mapObjects/CGCreature.cpp

@@ -15,7 +15,8 @@
 #include "../texts/CGeneralTextHandler.h"
 #include "../CConfigHandler.h"
 #include "../IGameSettings.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../gameState/CGameState.h"
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../networkPacks/PacksForClient.h"
@@ -154,7 +155,7 @@ std::vector<Component> CGCreature::getPopupComponents(PlayerColor player) const
 	};
 }
 
-void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
+void CGCreature::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	//show message
 	if(!message.empty())
@@ -163,18 +164,18 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
 		iw.player = h->tempOwner;
 		iw.text = message;
 		iw.type = EInfoWindowMode::MODAL;
-		cb->showInfoDialog(&iw);
+		gameEvents.showInfoDialog(&iw);
 	}
 	
 	int action = takenAction(h);
 	switch( action ) //decide what we do...
 	{
 	case FIGHT:
-		fight(h);
+		fight(gameEvents, h);
 		break;
 	case FLEE:
 		{
-			flee(h);
+			flee(gameEvents, h);
 			break;
 		}
 	case JOIN_FOR_FREE: //join for free
@@ -183,7 +184,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
 			ynd.player = h->tempOwner;
 			ynd.text.appendLocalString(EMetaText::ADVOB_TXT, 86);
 			ynd.text.replaceName(getCreatureID(), getJoiningAmount());
-			cb->showBlockingDialog(this, &ynd);
+			gameEvents.showBlockingDialog(this, &ynd);
 			break;
 		}
 	default: //join for gold
@@ -199,7 +200,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
 			boost::algorithm::replace_first(tmp, "%d", std::to_string(action));
 			boost::algorithm::replace_first(tmp,"%s",getCreature()->getNamePluralTranslated());
 			ynd.text.appendRawString(tmp);
-			cb->showBlockingDialog(this, &ynd);
+			gameEvents.showBlockingDialog(this, &ynd);
 			break;
 		}
 	}
@@ -304,19 +305,19 @@ void CGCreature::initObj(vstd::RNG & rand)
 	refusedJoining = false;
 }
 
-void CGCreature::newTurn(vstd::RNG & rand) const
+void CGCreature::newTurn(IGameEventCallback & gameEvents) const
 {//Works only for stacks of single type of size up to 2 millions
 	if (!notGrowingTeam)
 	{
 		if (stacks.begin()->second->getCount() < cb->getSettings().getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_CAP) && cb->getDate(Date::DAY_OF_WEEK) == 1 && cb->getDate(Date::DAY) > 1)
 		{
 			ui32 power = static_cast<ui32>(temppower * (100 + cb->getSettings().getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_PERCENT)) / 100);
-			cb->setObjPropertyValue(id, ObjProperty::MONSTER_COUNT, std::min<uint32_t>(power / 1000, cb->getSettings().getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_CAP))); //set new amount
-			cb->setObjPropertyValue(id, ObjProperty::MONSTER_POWER, power); //increase temppower
+			gameEvents.setObjPropertyValue(id, ObjProperty::MONSTER_COUNT, std::min<uint32_t>(power / 1000, cb->getSettings().getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_CAP))); //set new amount
+			gameEvents.setObjPropertyValue(id, ObjProperty::MONSTER_POWER, power); //increase temppower
 		}
 	}
 	if (cb->getSettings().getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
-		cb->setObjPropertyValue(id, ObjProperty::MONSTER_EXP, cb->getSettings().getInteger(EGameSettings::CREATURES_DAILY_STACK_EXPERIENCE)); //for testing purpose
+		gameEvents.setObjPropertyValue(id, ObjProperty::MONSTER_EXP, cb->getSettings().getInteger(EGameSettings::CREATURES_DAILY_STACK_EXPERIENCE)); //for testing purpose
 }
 void CGCreature::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
 {
@@ -403,34 +404,34 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
 		return FIGHT;
 }
 
-void CGCreature::fleeDecision(const CGHeroInstance *h, ui32 pursue) const
+void CGCreature::fleeDecision(IGameEventCallback & gameEvents, const CGHeroInstance *h, ui32 pursue) const
 {
 	if(refusedJoining)
-		cb->setObjPropertyValue(id, ObjProperty::MONSTER_REFUSED_JOIN, false);
+		gameEvents.setObjPropertyValue(id, ObjProperty::MONSTER_REFUSED_JOIN, false);
 
 	if(pursue)
 	{
-		fight(h);
+		fight(gameEvents, h);
 	}
 	else
 	{
-		cb->removeObject(this, h->getOwner());
+		gameEvents.removeObject(this, h->getOwner());
 	}
 }
 
-void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) const
+void CGCreature::joinDecision(IGameEventCallback & gameEvents, const CGHeroInstance *h, int cost, ui32 accept) const
 {
 	if(!accept)
 	{
 		if(takenAction(h,false) == FLEE)
 		{
-			cb->setObjPropertyValue(id, ObjProperty::MONSTER_REFUSED_JOIN, true);
-			flee(h);
+			gameEvents.setObjPropertyValue(id, ObjProperty::MONSTER_REFUSED_JOIN, true);
+			flee(gameEvents, h);
 		}
 		else //they fight
 		{
-			h->showInfoDialog(87, 0, EInfoWindowMode::MODAL);//Insulted by your refusal of their offer, the monsters attack!
-			fight(h);
+			h->showInfoDialog(gameEvents, 87, 0, EInfoWindowMode::MODAL);//Insulted by your refusal of their offer, the monsters attack!
+			fight(gameEvents, h);
 		}
 	}
 	else //accepted
@@ -440,27 +441,27 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
 			InfoWindow iw;
 			iw.player = h->tempOwner;
 			iw.text.appendLocalString(EMetaText::GENERAL_TXT,29);  //You don't have enough gold
-			cb->showInfoDialog(&iw);
+			gameEvents.showInfoDialog(&iw);
 
 			//act as if player refused
-			joinDecision(h,cost,false);
+			joinDecision(gameEvents, h, cost, false);
 			return;
 		}
 
 		//take gold
 		if(cost)
-			cb->giveResource(h->tempOwner,EGameResID::GOLD,-cost);
+			gameEvents.giveResource(h->tempOwner,EGameResID::GOLD,-cost);
 
-		giveReward(h);
+		giveReward(gameEvents, h);
 
 		for(auto & stack : this->stacks)
 			stack.second->setCount(getJoiningAmount());
 
-		cb->tryJoiningArmy(this, h, true, true);
+		gameEvents.tryJoiningArmy(this, h, true, true);
 	}
 }
 
-void CGCreature::fight( const CGHeroInstance *h ) const
+void CGCreature::fight(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	//split stacks
 	int stacksCount = getNumberOfStacks(h);
@@ -475,13 +476,13 @@ void CGCreature::fight( const CGHeroInstance *h ) const
 	for (int slotID = 1; slotID < a; ++slotID)
 	{
 		int stackSize = m + 1;
-		cb->moveStack(StackLocation(id, sourceSlot), StackLocation(id, SlotID(slotID)), stackSize);
+		gameEvents.moveStack(StackLocation(id, sourceSlot), StackLocation(id, SlotID(slotID)), stackSize);
 	}
 	for (int slotID = a; slotID < stacksCount; ++slotID)
 	{
 		int stackSize = m;
 		if (slotID) //don't do this when a = 0 -> stack is single
-			cb->moveStack(StackLocation(id, sourceSlot), StackLocation(id, SlotID(slotID)), stackSize);
+			gameEvents.moveStack(StackLocation(id, sourceSlot), StackLocation(id, SlotID(slotID)), stackSize);
 	}
 	if (stacksCount > 1)
 	{
@@ -491,36 +492,36 @@ 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());
-				cb->changeStackType(StackLocation(id, slotID), it->toCreature());
+				auto it = RandomGeneratorUtil::nextItem(upgrades, gameEvents.getRandomGenerator());
+				gameEvents.changeStackType(StackLocation(id, slotID), it->toCreature());
 			}
 		}
 	}
 
-	cb->startBattle(h, this);
+	gameEvents.startBattle(h, this);
 
 }
 
-void CGCreature::flee( const CGHeroInstance * h ) const
+void CGCreature::flee(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	BlockingDialog ynd(true,false);
 	ynd.player = h->tempOwner;
 	ynd.text.appendLocalString(EMetaText::ADVOB_TXT,91);
 	ynd.text.replaceName(getCreatureID(), getStackCount(SlotID(0)));
-	cb->showBlockingDialog(this, &ynd);
+	gameEvents.showBlockingDialog(this, &ynd);
 }
 
-void CGCreature::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
+void CGCreature::battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const
 {
 	if(result.winner == BattleSide::ATTACKER)
 	{
-		giveReward(hero);
-		cb->removeObject(this, hero->getOwner());
+		giveReward(gameEvents, hero);
+		gameEvents.removeObject(this, hero->getOwner());
 	}
 	else if(result.winner == BattleSide::NONE) // draw
 	{
 		// guarded reward is lost forever on draw
-		cb->removeObject(this, hero->getOwner());
+		gameEvents.removeObject(this, hero->getOwner());
 	}
 	else
 	{
@@ -531,13 +532,13 @@ void CGCreature::battleFinished(const CGHeroInstance *hero, const BattleResult &
 		{
 			if(cre->isMyDirectUpgrade(i->second->getCreature()))
 			{
-				cb->changeStackType(StackLocation(id, i->first), cre); //un-upgrade creatures
+				gameEvents.changeStackType(StackLocation(id, i->first), cre); //un-upgrade creatures
 			}
 		}
 
 		//first stack has to be at slot 0 -> if original one got killed, move there first remaining stack
 		if(!hasStackAtSlot(SlotID(0)))
-			cb->moveStack(StackLocation(id, stacks.begin()->first), StackLocation(id, SlotID(0)), stacks.begin()->second->getCount());
+			gameEvents.moveStack(StackLocation(id, stacks.begin()->first), StackLocation(id, SlotID(0)), stacks.begin()->second->getCount());
 
 		while(stacks.size() > 1) //hopefully that's enough
 		{
@@ -548,20 +549,20 @@ void CGCreature::battleFinished(const CGHeroInstance *hero, const BattleResult &
 			if(slot == i->first) //no reason to move stack to its own slot
 				break;
 			else
-				cb->moveStack(StackLocation(id, i->first), StackLocation(id, slot), i->second->getCount());
+				gameEvents.moveStack(StackLocation(id, i->first), StackLocation(id, slot), i->second->getCount());
 		}
 
-		cb->setObjPropertyValue(id, ObjProperty::MONSTER_POWER, stacks.begin()->second->getCount() * 1000); //remember casualties
+		gameEvents.setObjPropertyValue(id, ObjProperty::MONSTER_POWER, stacks.begin()->second->getCount() * 1000); //remember casualties
 	}
 }
 
-void CGCreature::blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const
+void CGCreature::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const
 {
 	auto action = takenAction(hero);
 	if(!refusedJoining && action >= JOIN_FOR_FREE) //higher means price
-		joinDecision(hero, action, answer);
+		joinDecision(gameEvents, hero, action, answer);
 	else if(action != FIGHT)
-		fleeDecision(hero, answer);
+		fleeDecision(gameEvents, hero, answer);
 	else
 		assert(0);
 }
@@ -620,14 +621,14 @@ int CGCreature::getNumberOfStacks(const CGHeroInstance *hero) const
 	return split;
 }
 
-void CGCreature::giveReward(const CGHeroInstance * h) const
+void CGCreature::giveReward(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	InfoWindow iw;
 	iw.player = h->tempOwner;
 
 	if(!resources.empty())
 	{
-		cb->giveResources(h->tempOwner, resources);
+		gameEvents.giveResources(h->tempOwner, resources);
 		for(const auto & res : GameResID::ALL_RESOURCES())
 		{
 			if(resources[res] > 0)
@@ -637,7 +638,7 @@ void CGCreature::giveReward(const CGHeroInstance * h) const
 
 	if(gainedArtifact != ArtifactID::NONE)
 	{
-		cb->giveHeroNewArtifact(h, gainedArtifact, ArtifactPosition::FIRST_AVAILABLE);
+		gameEvents.giveHeroNewArtifact(h, gainedArtifact, ArtifactPosition::FIRST_AVAILABLE);
 		iw.components.emplace_back(ComponentType::ARTIFACT, gainedArtifact);
 	}
 
@@ -646,7 +647,7 @@ void CGCreature::giveReward(const CGHeroInstance * h) const
 		iw.type = EInfoWindowMode::AUTO;
 		iw.text.appendLocalString(EMetaText::ADVOB_TXT, 183); // % has found treasure
 		iw.text.replaceRawString(h->getNameTranslated());
-		cb->showInfoDialog(&iw);
+		gameEvents.showInfoDialog(&iw);
 	}
 }
 

+ 9 - 9
lib/mapObjects/CGCreature.h

@@ -38,7 +38,7 @@ public:
 
 	bool refusedJoining = false;
 
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	std::string getHoverText(PlayerColor player) const override;
 	std::string getHoverText(const CGHeroInstance * hero) const override;
 	std::string getPopupText(PlayerColor player) const override;
@@ -46,9 +46,9 @@ public:
 	std::vector<Component> getPopupComponents(PlayerColor player) const override;
 	void initObj(vstd::RNG & rand) override;
 	void pickRandomObject(vstd::RNG & rand) override;
-	void newTurn(vstd::RNG & rand) const override;
-	void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
-	void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
+	void newTurn(IGameEventCallback & gameEvents) const override;
+	void battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const override;
+	void blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const override;
 	CreatureID getCreatureID() const;
 	const CCreature * getCreature() const;
 	TQuantity getJoiningAmount() const;
@@ -76,13 +76,13 @@ protected:
 	void serializeJsonOptions(JsonSerializeFormat & handler) override;
 
 private:
-	void fight(const CGHeroInstance *h) const;
-	void flee( const CGHeroInstance * h ) const;
-	void fleeDecision(const CGHeroInstance *h, ui32 pursue) const;
-	void joinDecision(const CGHeroInstance *h, int cost, ui32 accept) const;
+	void fight(IGameEventCallback & gameEvents, const CGHeroInstance * h) const;
+	void flee(IGameEventCallback & gameEvents, const CGHeroInstance * h) const;
+	void fleeDecision(IGameEventCallback & gameEvents, const CGHeroInstance * h, ui32 pursue) const;
+	void joinDecision(IGameEventCallback & gameEvents, const CGHeroInstance * h, int cost, ui32 accept) const;
 
 	int takenAction(const CGHeroInstance *h, bool allowJoin=true) const; //action on confrontation: -2 - fight, -1 - flee, >=0 - will join for given value of gold (may be 0)
-	void giveReward(const CGHeroInstance * h) const;
+	void giveReward(IGameEventCallback & gameEvents, const CGHeroInstance * h) const;
 	std::string getMonsterLevelText() const;
 };
 

+ 29 - 28
lib/mapObjects/CGDwelling.cpp

@@ -10,7 +10,8 @@
 
 #include "StdInc.h"
 #include "CGDwelling.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../serializer/JsonSerializeFormat.h"
 #include "../entities/faction/CTownHandler.h"
 #include "../mapping/CMap.h"
@@ -46,7 +47,7 @@ void CGDwellingRandomizationInfo::serializeJson(JsonSerializeFormat & handler)
 	}
 }
 
-CGDwelling::CGDwelling(IGameCallback *cb):
+CGDwelling::CGDwelling(CPrivilegedInfoCallback *cb):
 	CArmedInstance(cb)
 {}
 
@@ -209,7 +210,7 @@ void CGDwelling::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
 	}
 }
 
-void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
+void CGDwelling::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	if(ID == Obj::REFUGEE_CAMP && !creatures[0].first) //Refugee Camp, no available cres
 	{
@@ -218,7 +219,7 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
 		iw.player = h->tempOwner;
 		iw.text.appendLocalString(EMetaText::ADVOB_TXT, 44); //{%s} \n\n The camp is deserted.  Perhaps you should try next week.
 		iw.text.replaceName(ID, subID);
-		cb->sendAndApply(iw);
+		gameEvents.sendAndApply(iw);
 		return;
 	}
 
@@ -238,14 +239,14 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
 		else
 			bd.text.replaceLocalString(EMetaText::ARRAY_TXT, 173 + (int)Slots().begin()->second->getQuantityID()*3);
 		bd.text.replaceName(*Slots().begin()->second);
-		cb->showBlockingDialog(this, &bd);
+		gameEvents.showBlockingDialog(this, &bd);
 		return;
 	}
 
 	// TODO this shouldn't be hardcoded
 	if(relations == PlayerRelations::ENEMIES && ID != Obj::WAR_MACHINE_FACTORY && ID != Obj::REFUGEE_CAMP)
 	{
-		cb->setOwner(this, h->tempOwner);
+		gameEvents.setOwner(this, h->tempOwner);
 	}
 
 	BlockingDialog bd (true,false);
@@ -274,10 +275,10 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
 		bd.flags |= BlockingDialog::SAFE_TO_AUTOACCEPT;
 	}
 
-	cb->showBlockingDialog(this, &bd);
+	gameEvents.showBlockingDialog(this, &bd);
 }
 
-void CGDwelling::newTurn(vstd::RNG & rand) const
+void CGDwelling::newTurn(IGameEventCallback & gameEvents) const
 {
 	if(cb->getDate(Date::DAY_OF_WEEK) != 1) //not first day of week
 		return;
@@ -288,7 +289,7 @@ void CGDwelling::newTurn(vstd::RNG & rand) const
 
 	if(ID == Obj::REFUGEE_CAMP) //if it's a refugee camp, we need to pick an available creature
 	{
-		cb->setObjPropertyID(id, ObjProperty::AVAILABLE_CREATURE, LIBRARY->creh->pickRandomMonster(rand));
+		gameEvents.setObjPropertyID(id, ObjProperty::AVAILABLE_CREATURE, LIBRARY->creh->pickRandomMonster(gameEvents.getRandomGenerator()));
 	}
 
 	bool change = false;
@@ -318,9 +319,9 @@ void CGDwelling::newTurn(vstd::RNG & rand) const
 	}
 
 	if(change)
-		cb->sendAndApply(sac);
+		gameEvents.sendAndApply(sac);
 
-	updateGuards();
+	updateGuards(gameEvents);
 }
 
 std::vector<Component> CGDwelling::getPopupComponents(PlayerColor player) const
@@ -356,7 +357,7 @@ std::vector<Component> CGDwelling::getPopupComponents(PlayerColor player) const
 	return result;
 }
 
-void CGDwelling::updateGuards() const
+void CGDwelling::updateGuards(IGameEventCallback & gameEvents) const
 {
 	//TODO: store custom guard config and use it
 	//TODO: store boolean flag for guards
@@ -386,7 +387,7 @@ void CGDwelling::updateGuards() const
 				csc.slot = slot;
 				csc.count = crea->getGrowth() * 3;
 				csc.absoluteValue = true;
-				cb->sendAndApply(csc);
+				gameEvents.sendAndApply(csc);
 			}
 			else //slot is empty, create whole new stack
 			{
@@ -395,13 +396,13 @@ void CGDwelling::updateGuards() const
 				ns.slot = slot;
 				ns.type = crea->getId();
 				ns.count = crea->getGrowth() * 3;
-				cb->sendAndApply(ns);
+				gameEvents.sendAndApply(ns);
 			}
 		}
 	}
 }
 
-void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
+void CGDwelling::heroAcceptsCreatures(IGameEventCallback & gameEvents, const CGHeroInstance *h) const
 {
 	CreatureID crid = creatures[0].second[0];
 	auto *crs = crid.toCreature();
@@ -420,7 +421,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
 					std::pair<SlotID, SlotID> toMerge;
 					if (h->mergeableStacks(toMerge))
 					{
-						cb->moveStack(StackLocation(h->id, toMerge.first), StackLocation(h->id, toMerge.second), -1); //merge toMerge.first into toMerge.second
+						gameEvents.moveStack(StackLocation(h->id, toMerge.first), StackLocation(h->id, toMerge.second), -1); //merge toMerge.first into toMerge.second
 						assert(!h->hasStackAtSlot(toMerge.first)); //we have now a new free slot
 					}
 				}
@@ -434,7 +435,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
 				iw.player = h->tempOwner;
 				iw.text.appendLocalString(EMetaText::GENERAL_TXT, 425);//The %s would join your hero, but there aren't enough provisions to support them.
 				iw.text.replaceNamePlural(crid);
-				cb->showInfoDialog(&iw);
+				gameEvents.showInfoDialog(&iw);
 			}
 			else //give creatures
 			{
@@ -451,9 +452,9 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
 				iw.text.replaceNumber(count);
 				iw.text.replaceNamePlural(crid);
 
-				cb->showInfoDialog(&iw);
-				cb->sendAndApply(sac);
-				cb->addToSlot(StackLocation(h->id, slot), crs, count);
+				gameEvents.showInfoDialog(&iw);
+				gameEvents.sendAndApply(sac);
+				gameEvents.addToSlot(StackLocation(h->id, slot), crs, count);
 			}
 		}
 		else //there no creatures
@@ -463,7 +464,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
 			iw.text.appendLocalString(EMetaText::GENERAL_TXT, 422); //There are no %s here to recruit.
 			iw.text.replaceNamePlural(crid);
 			iw.player = h->tempOwner;
-			cb->sendAndApply(iw);
+			gameEvents.sendAndApply(iw);
 		}
 	}
 	else
@@ -485,33 +486,33 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
 				else
 					entry.first = 1;
 			}
-			cb->sendAndApply(sac);
+			gameEvents.sendAndApply(sac);
 		}
 
 		auto windowMode = (ID == Obj::CREATURE_GENERATOR1 || ID == Obj::REFUGEE_CAMP) ? EOpenWindowMode::RECRUITMENT_FIRST : EOpenWindowMode::RECRUITMENT_ALL;
-		cb->showObjectWindow(this, windowMode, h, true);
+		gameEvents.showObjectWindow(this, windowMode, h, true);
 	}
 }
 
-void CGDwelling::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
+void CGDwelling::battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const
 {
 	if (result.winner == BattleSide::ATTACKER)
 	{
-		onHeroVisit(hero);
+		onHeroVisit(gameEvents, hero);
 	}
 }
 
-void CGDwelling::blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const
+void CGDwelling::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const
 {
 	auto relations = cb->getPlayerRelations(getOwner(), hero->getOwner());
 	if(stacksCount() > 0  && relations == PlayerRelations::ENEMIES) //guards present
 	{
 		if(answer)
-			cb->startBattle(hero, this);
+			gameEvents.startBattle(hero, this);
 	}
 	else if(answer)
 	{
-		heroAcceptsCreatures(hero);
+		heroAcceptsCreatures(gameEvents, hero);
 	}
 }
 

+ 7 - 7
lib/mapObjects/CGDwelling.h

@@ -39,7 +39,7 @@ public:
 	std::optional<CGDwellingRandomizationInfo> randomizationInfo; //random dwelling options; not serialized
 	TCreaturesSet creatures; //creatures[level] -> <vector of alternative ids (base creature and upgrades, creatures amount>
 
-	CGDwelling(IGameCallback *cb);
+	CGDwelling(CPrivilegedInfoCallback *cb);
 	~CGDwelling() override;
 
 	const IOwnableObject * asOwnable() const final;
@@ -55,15 +55,15 @@ private:
 
 	void pickRandomObject(vstd::RNG & rand) override;
 	void initObj(vstd::RNG & rand) override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
-	void newTurn(vstd::RNG & rand) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
+	void newTurn(IGameEventCallback & gameEvents) const override;
 	void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
-	void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
-	void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
+	void battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const override;
+	void blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const override;
 	std::vector<Component> getPopupComponents(PlayerColor player) const override;
 
-	void updateGuards() const;
-	void heroAcceptsCreatures(const CGHeroInstance *h) const;
+	void updateGuards(IGameEventCallback & gameEvents) const;
+	void heroAcceptsCreatures(IGameEventCallback & gameEvents, const CGHeroInstance *h) const;
 
 public:
 	template <typename Handler> void serialize(Handler &h)

+ 18 - 17
lib/mapObjects/CGHeroInstance.cpp

@@ -15,7 +15,8 @@
 #include <vcmi/spells/Spell.h>
 #include <vstd/RNG.h>
 
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "../TerrainHandler.h"
 #include "../RoadHandler.h"
@@ -253,7 +254,7 @@ int CGHeroInstance::movementPointsLimitCached(bool onLand, const TurnInfo * ti)
 		return ti->getMovePointsLimitWater();
 }
 
-CGHeroInstance::CGHeroInstance(IGameCallback * cb)
+CGHeroInstance::CGHeroInstance(CPrivilegedInfoCallback * cb)
 	: CArmedInstance(cb),
 	CArtifactSet(cb),
 	tacticFormationEnabled(false),
@@ -554,7 +555,7 @@ bool CGHeroInstance::needsLastStack() const
 	return true;
 }
 
-void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
+void CGHeroInstance::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	if(h == this) return; //exclude potential self-visiting
 
@@ -563,14 +564,14 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 		if( cb->gameState().getPlayerRelations(tempOwner, h->tempOwner) != PlayerRelations::ENEMIES)
 		{
 			//exchange
-			cb->heroExchange(h->id, id);
+			gameEvents.heroExchange(h->id, id);
 		}
 		else //battle
 		{
 			if(getVisitedTown()) //we're in town
-				getVisitedTown()->onHeroVisit(h); //town will handle attacking
+				getVisitedTown()->onHeroVisit(gameEvents, h); //town will handle attacking
 			else
-				cb->startBattle(h,	this);
+				gameEvents.startBattle(h,	this);
 		}
 	}
 	else if(ID == Obj::PRISON)
@@ -580,9 +581,9 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 			//update hero parameters
 			SetMovePoints smp;
 			smp.hid = id;
-			
-			cb->setManaPoints (id, manaLimit());
-			
+
+			gameEvents.setManaPoints(id, manaLimit());
+
 			ObjectInstanceID boatId;
 			const auto boatPos = visitablePos();
 			if (cb->gameState().getMap().getTile(boatPos).isWater())
@@ -591,7 +592,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 				if (!inBoat())
 				{
 					//Create a new boat for hero
-					cb->createBoat(boatPos, getBoatType(), h->getOwner());
+					gameEvents.createBoat(boatPos, getBoatType(), h->getOwner());
 					boatId = cb->getTopObj(boatPos)->id;
 				}
 			}
@@ -599,15 +600,15 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 			{
 				smp.val = movementPointsLimit(true);
 			}
-			cb->giveHero(id, h->tempOwner, boatId); //recreates def and adds hero to player
-			cb->setObjPropertyID(id, ObjProperty::ID, Obj(Obj::HERO)); //set ID to 34 AFTER hero gets correct flag color
-			cb->setMovePoints (&smp);
+			gameEvents.giveHero(id, h->tempOwner, boatId); //recreates def and adds hero to player
+			gameEvents.setObjPropertyID(id, ObjProperty::ID, Obj(Obj::HERO)); //set ID to 34 AFTER hero gets correct flag color
+			gameEvents.setMovePoints (&smp);
 
-			h->showInfoDialog(102);
+			h->showInfoDialog(gameEvents, 102);
 		}
 		else //already 8 wandering heroes
 		{
-			h->showInfoDialog(103);
+			h->showInfoDialog(gameEvents, 103);
 		}
 	}
 }
@@ -667,13 +668,13 @@ void CGHeroInstance::SecondarySkillsInfo::resetWisdomCounter()
 	wisdomCounter = 0;
 }
 
-void CGHeroInstance::pickRandomObject(vstd::RNG & rand)
+void CGHeroInstance::pickRandomObject(vstd::RNG & randomGenerator)
 {
 	assert(ID == Obj::HERO || ID == Obj::PRISON || ID == Obj::RANDOM_HERO);
 
 	if (ID == Obj::RANDOM_HERO)
 	{
-		auto selectedHero = cb->gameState().pickNextHeroType(getOwner());
+		auto selectedHero = cb->gameState().pickNextHeroType(randomGenerator, getOwner());
 
 		ID = Obj::HERO;
 		subID = selectedHero;

+ 3 - 3
lib/mapObjects/CGHeroInstance.h

@@ -72,7 +72,7 @@ class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator,
 	ui32 movement; //remaining movement points
 	bool inTownGarrison; // if hero is in town garrison
 
-	IGameCallback * getCallback() const final { return cb; }
+	CPrivilegedInfoCallback * getCallback() const final { return cb; }
 
 public:
 	//////////////////////////////////////////////////////////////////////////
@@ -281,7 +281,7 @@ public:
 	/// If this hero perishes, the scenario is failed
 	bool isMissionCritical() const;
 
-	CGHeroInstance(IGameCallback *cb);
+	CGHeroInstance(CPrivilegedInfoCallback *cb);
 	virtual ~CGHeroInstance();
 
 	PlayerColor getOwner() const override;
@@ -321,7 +321,7 @@ public:
 	void updateAppearance();
 
 	void pickRandomObject(vstd::RNG & rand) override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	std::string getObjectName() const override;
 	std::string getHoverText(PlayerColor player) const override;
 	std::string getMovementPointsTextIfOwner(PlayerColor player) const;

+ 10 - 9
lib/mapObjects/CGMarket.cpp

@@ -11,7 +11,8 @@
 #include "StdInc.h"
 #include "CGMarket.h"
 
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "../CCreatureHandler.h"
 #include "CGTownInstance.h"
@@ -34,9 +35,9 @@ void CGMarket::initObj(vstd::RNG & rand)
 	getObjectHandler()->configureObject(this, rand);
 }
 
-void CGMarket::onHeroVisit(const CGHeroInstance * h) const
+void CGMarket::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
-	cb->showObjectWindow(this, EOpenWindowMode::MARKET_WINDOW, h, true);
+	gameEvents.showObjectWindow(this, EOpenWindowMode::MARKET_WINDOW, h, true);
 }
 
 std::string CGMarket::getPopupText(PlayerColor player) const
@@ -77,7 +78,7 @@ std::set<EMarketMode> CGMarket::availableModes() const
 	return getMarketHandler()->availableModes();
 }
 
-CGMarket::CGMarket(IGameCallback *cb)
+CGMarket::CGMarket(CPrivilegedInfoCallback *cb)
 	: CGObjectInstance(cb)
 	, IMarket(cb)
 {}
@@ -98,7 +99,7 @@ std::vector<TradeItemBuy> CGBlackMarket::availableItemsIds(EMarketMode mode) con
 	}
 }
 
-void CGBlackMarket::newTurn(vstd::RNG & rand) const
+void CGBlackMarket::newTurn(IGameEventCallback & gameEvents) const
 {
 	int resetPeriod = cb->getSettings().getInteger(EGameSettings::MARKETS_BLACK_MARKET_RESTOCK_PERIOD);
 
@@ -110,8 +111,8 @@ void CGBlackMarket::newTurn(vstd::RNG & rand) const
 
 	SetAvailableArtifacts saa;
 	saa.id = id;
-	cb->pickAllowedArtsSet(saa.arts, rand);
-	cb->sendAndApply(saa);
+	cb->pickAllowedArtsSet(saa.arts, gameEvents.getRandomGenerator());
+	gameEvents.sendAndApply(saa);
 }
 
 std::vector<TradeItemBuy> CGUniversity::availableItemsIds(EMarketMode mode) const
@@ -131,9 +132,9 @@ std::string CGUniversity::getSpeechTranslated() const
 	return getMarketHandler()->getSpeechTranslated();
 }
 
-void CGUniversity::onHeroVisit(const CGHeroInstance * h) const
+void CGUniversity::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
-	cb->showObjectWindow(this, EOpenWindowMode::UNIVERSITY_WINDOW, h, true);
+	gameEvents.showObjectWindow(this, EOpenWindowMode::UNIVERSITY_WINDOW, h, true);
 }
 
 VCMI_LIB_NAMESPACE_END

+ 4 - 4
lib/mapObjects/CGMarket.h

@@ -22,9 +22,9 @@ protected:
 	std::shared_ptr<MarketInstanceConstructor> getMarketHandler() const;
 
 public:
-	CGMarket(IGameCallback *cb);
+	CGMarket(CPrivilegedInfoCallback *cb);
 	///IObjectInterface
-	void onHeroVisit(const CGHeroInstance * h) const override; //open trading window
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override; //open trading window
 	void initObj(vstd::RNG & rand) override;//set skills for trade
 
 	std::string getPopupText(PlayerColor player) const override;
@@ -44,7 +44,7 @@ public:
 
 	std::vector<ArtifactID> artifacts; //available artifacts
 
-	void newTurn(vstd::RNG & rand) const override; //reset artifacts for black market every month
+	void newTurn(IGameEventCallback & gameEvents) const override; //reset artifacts for black market every month
 	std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const override;
 
 	template <typename Handler> void serialize(Handler &h)
@@ -64,7 +64,7 @@ public:
 	std::vector<TradeItemBuy> skills; //available skills
 
 	std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const override;
-	void onHeroVisit(const CGHeroInstance * h) const override; //open window
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override; //open window
 
 	template <typename Handler> void serialize(Handler &h)
 	{

+ 8 - 7
lib/mapObjects/CGObjectInstance.cpp

@@ -14,7 +14,8 @@
 #include "CGHeroInstance.h"
 #include "ObjectTemplate.h"
 
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../gameState/CGameState.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "../constants/StringConstants.h"
@@ -30,7 +31,7 @@
 VCMI_LIB_NAMESPACE_BEGIN
 
 //TODO: remove constructor
-CGObjectInstance::CGObjectInstance(IGameCallback *cb):
+CGObjectInstance::CGObjectInstance(CPrivilegedInfoCallback *cb):
 	IObjectInterface(cb),
 	pos(-1,-1,-1),
 	ID(Obj::NO_OBJ),
@@ -223,7 +224,7 @@ int3 CGObjectInstance::getVisitableOffset() const
 	return appearance->getVisitableOffset();
 }
 
-void CGObjectInstance::giveDummyBonus(const ObjectInstanceID & heroID, BonusDuration::Type duration) const
+void CGObjectInstance::giveDummyBonus(IGameEventCallback & gameEvents, const ObjectInstanceID & heroID, BonusDuration::Type duration) const
 {
 	GiveBonus gbonus;
 	gbonus.bonus.type = BonusType::NONE;
@@ -231,7 +232,7 @@ void CGObjectInstance::giveDummyBonus(const ObjectInstanceID & heroID, BonusDura
 	gbonus.bonus.duration = duration;
 	gbonus.bonus.source = BonusSource::OBJECT_TYPE;
 	gbonus.bonus.sid = BonusSourceID(ID);
-	cb->giveHeroBonus(&gbonus);
+	gameEvents.giveHeroBonus(&gbonus);
 }
 
 std::string CGObjectInstance::getObjectName() const
@@ -298,19 +299,19 @@ std::vector<Component> CGObjectInstance::getPopupComponents(const CGHeroInstance
 	return getPopupComponents(hero->getOwner());
 }
 
-void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const
+void CGObjectInstance::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	switch(ID.toEnum())
 	{
 	case Obj::SANCTUARY:
 		{
 			//You enter the sanctuary and immediately feel as if a great weight has been lifted off your shoulders.  You feel safe here.
-			h->showInfoDialog(114);
+			h->showInfoDialog(gameEvents, 114);
 		}
 		break;
 	case Obj::TAVERN:
 		{
-			cb->showObjectWindow(this, EOpenWindowMode::TAVERN_WINDOW, h, true);
+			gameEvents.showObjectWindow(this, EOpenWindowMode::TAVERN_WINDOW, h, true);
 		}
 		break;
 	}

+ 3 - 3
lib/mapObjects/CGObjectInstance.h

@@ -45,7 +45,7 @@ public:
 
 	std::string instanceName;
 
-	CGObjectInstance(IGameCallback *cb);
+	CGObjectInstance(CPrivilegedInfoCallback *cb);
 	~CGObjectInstance() override;
 
 	MapObjectID getObjGroupIndex() const override;
@@ -133,7 +133,7 @@ public:
 
 	void initObj(vstd::RNG & rand) override;
 	void pickRandomObject(vstd::RNG & rand) override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	/// method for synchronous update. Note: For new properties classes should override setPropertyDer instead
 	void setProperty(ObjProperty what, ObjPropertyID identifier) final;
 
@@ -170,7 +170,7 @@ protected:
 	void setType(MapObjectID ID, MapObjectSubID subID);
 
 	/// Gives dummy bonus from this object to hero. Can be used to track visited state
-	void giveDummyBonus(const ObjectInstanceID & heroID, BonusDuration::Type duration = BonusDuration::ONE_DAY) const;
+	void giveDummyBonus(IGameEventCallback & gameEvents, const ObjectInstanceID & heroID, BonusDuration::Type duration = BonusDuration::ONE_DAY) const;
 
 	///Serialize object-type specific options
 	virtual void serializeJsonOptions(JsonSerializeFormat & handler);

+ 26 - 25
lib/mapObjects/CGPandoraBox.cpp

@@ -18,7 +18,8 @@
 
 #include "../CSkillHandler.h"
 #include "../StartInfo.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../constants/StringConstants.h"
 #include "../networkPacks/PacksForClient.h"
 #include "../networkPacks/PacksForClientBattle.h"
@@ -48,12 +49,12 @@ void CGPandoraBox::initObj(vstd::RNG & rand)
 	CRewardableObject::initObj(rand);
 }
 
-void CGPandoraBox::grantRewardWithMessage(const CGHeroInstance * h, int index, bool markAsVisit) const
+void CGPandoraBox::grantRewardWithMessage(IGameEventCallback & gameEvents, const CGHeroInstance * h, int index, bool markAsVisit) const
 {
 	auto vi = configuration.info.at(index);
 	if(!vi.message.empty())
 	{
-		CRewardableObject::grantRewardWithMessage(h, index, markAsVisit);
+		CRewardableObject::grantRewardWithMessage(gameEvents, h, index, markAsVisit);
 		return;
 	}
 	
@@ -74,7 +75,7 @@ void CGPandoraBox::grantRewardWithMessage(const CGHeroInstance * h, int index, b
 		reward.loadComponents(iw.components, h);
 		iw.type = EInfoWindowMode::MODAL;
 		if(!iw.components.empty())
-			cb->showInfoDialog(&iw);
+			gameEvents.showInfoDialog(&iw);
 	};
 
 	Rewardable::Reward temp;
@@ -166,43 +167,43 @@ void CGPandoraBox::grantRewardWithMessage(const CGHeroInstance * h, int index, b
 	
 	// grant reward afterwards. Note that it may remove object
 	if(markAsVisit)
-		markAsVisited(h);
-	grantReward(index, h);
+		markAsVisited(gameEvents, h);
+	grantReward(gameEvents, index, h);
 }
 
-void CGPandoraBox::onHeroVisit(const CGHeroInstance * h) const
+void CGPandoraBox::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	BlockingDialog bd (true, false);
 	bd.player = h->getOwner();
 	bd.text.appendLocalString(EMetaText::ADVOB_TXT, 14);
-	cb->showBlockingDialog(this, &bd);
+	gameEvents.showBlockingDialog(this, &bd);
 }
 
-void CGPandoraBox::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
+void CGPandoraBox::battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const
 {
 	if(result.winner == BattleSide::ATTACKER)
 	{
-		CRewardableObject::onHeroVisit(hero);
+		CRewardableObject::onHeroVisit(gameEvents, hero);
 	}
 }
 
-void CGPandoraBox::blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const
+void CGPandoraBox::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const
 {
 	if(answer)
 	{
 		if(stacksCount() > 0) //if pandora's box is protected by army
 		{
-			hero->showInfoDialog(16, 0, EInfoWindowMode::MODAL);
-			cb->startBattle(hero, this); //grants things after battle
+			hero->showInfoDialog(gameEvents, 16, 0, EInfoWindowMode::MODAL);
+			gameEvents.startBattle(hero, this); //grants things after battle
 		}
 		else if(getAvailableRewards(hero, Rewardable::EEventType::EVENT_FIRST_VISIT).empty())
 		{
-			hero->showInfoDialog(15);
-			cb->removeObject(this, hero->getOwner());
+			hero->showInfoDialog(gameEvents, 15);
+			gameEvents.removeObject(this, hero->getOwner());
 		}
 		else //if it gives something without battle
 		{
-			CRewardableObject::onHeroVisit(hero);
+			CRewardableObject::onHeroVisit(gameEvents, hero);
 		}
 	}
 }
@@ -287,12 +288,12 @@ void CGEvent::init()
 	}
 }
 
-void CGEvent::grantRewardWithMessage(const CGHeroInstance * contextHero, int rewardIndex, bool markAsVisit) const
+void CGEvent::grantRewardWithMessage(IGameEventCallback & gameEvents, const CGHeroInstance * contextHero, int rewardIndex, bool markAsVisit) const
 {
-	CRewardableObject::grantRewardWithMessage(contextHero, rewardIndex, markAsVisit);
+	CRewardableObject::grantRewardWithMessage(gameEvents, contextHero, rewardIndex, markAsVisit);
 }
 
-void CGEvent::onHeroVisit( const CGHeroInstance * h ) const
+void CGEvent::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	if(availableFor.count(h->tempOwner) == 0)
 		return;
@@ -300,13 +301,13 @@ void CGEvent::onHeroVisit( const CGHeroInstance * h ) const
 	if(cb->getPlayerSettings(h->tempOwner)->isControlledByHuman())
 	{
 		if(humanActivate)
-			activated(h);
+			activated(gameEvents, h);
 	}
 	else if(computerActivate)
-		activated(h);
+		activated(gameEvents, h);
 }
 
-void CGEvent::activated( const CGHeroInstance * h ) const
+void CGEvent::activated(IGameEventCallback & gameEvents, const CGHeroInstance * h ) const
 {
 	if(stacksCount() > 0)
 	{
@@ -316,12 +317,12 @@ void CGEvent::activated( const CGHeroInstance * h ) const
 			iw.text = message;
 		else
 			iw.text.appendLocalString(EMetaText::ADVOB_TXT, 16);
-		cb->showInfoDialog(&iw);
-		cb->startBattle(h, this);
+		gameEvents.showInfoDialog(&iw);
+		gameEvents.startBattle(h, this);
 	}
 	else
 	{
-		CRewardableObject::onHeroVisit(h);
+		CRewardableObject::onHeroVisit(gameEvents, h);
 	}
 }
 

+ 7 - 7
lib/mapObjects/CGPandoraBox.h

@@ -24,9 +24,9 @@ public:
 	MetaString message;
 
 	void initObj(vstd::RNG & rand) override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
-	void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
-	void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
+	void battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const override;
+	void blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -34,7 +34,7 @@ public:
 		h & message;
 	}
 protected:
-	void grantRewardWithMessage(const CGHeroInstance * contextHero, int rewardIndex, bool markAsVisit) const override;
+	void grantRewardWithMessage(IGameEventCallback & gameEvents, const CGHeroInstance * contextHero, int rewardIndex, bool markAsVisit) const override;
 	
 	virtual void init();
 	void serializeJsonOptions(JsonSerializeFormat & handler) override;
@@ -59,14 +59,14 @@ public:
 		h & humanActivate;
 	}
 
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 protected:
-	void grantRewardWithMessage(const CGHeroInstance * contextHero, int rewardIndex, bool markAsVisit) const override;
+	void grantRewardWithMessage(IGameEventCallback & gameEvents, const CGHeroInstance * contextHero, int rewardIndex, bool markAsVisit) const override;
 	
 	void init() override;
 	void serializeJsonOptions(JsonSerializeFormat & handler) override;
 private:
-	void activated(const CGHeroInstance * h) const;
+	void activated(IGameEventCallback & gameEvents, const CGHeroInstance * h) const;
 };
 
 VCMI_LIB_NAMESPACE_END

+ 15 - 14
lib/mapObjects/CGResource.cpp

@@ -11,7 +11,8 @@
 #include "StdInc.h"
 #include "CGResource.h"
 
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../mapObjectConstructors/CommonConstructors.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "../networkPacks/PacksForClient.h"
@@ -71,7 +72,7 @@ void CGResource::initObj(vstd::RNG & rand)
 	getResourceHandler()->randomizeObject(this, rand);
 }
 
-void CGResource::onHeroVisit( const CGHeroInstance * h ) const
+void CGResource::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	if(stacksCount())
 	{
@@ -80,20 +81,20 @@ void CGResource::onHeroVisit( const CGHeroInstance * h ) const
 			BlockingDialog ynd(true,false);
 			ynd.player = h->getOwner();
 			ynd.text = message;
-			cb->showBlockingDialog(this, &ynd);
+			gameEvents.showBlockingDialog(this, &ynd);
 		}
 		else
 		{
-			blockingDialogAnswered(h, true); //behave as if player accepted battle
+			blockingDialogAnswered(gameEvents, h, true); //behave as if player accepted battle
 		}
 	}
 	else
-		collectRes(h->getOwner());
+		collectRes(gameEvents, h->getOwner());
 }
 
-void CGResource::collectRes(const PlayerColor & player) const
+void CGResource::collectRes(IGameEventCallback & gameEvents, const PlayerColor & player) const
 {
-	cb->giveResource(player, resourceID(), amount);
+	gameEvents.giveResource(player, resourceID(), amount);
 	InfoWindow sii;
 	sii.player = player;
 	if(!message.empty())
@@ -108,21 +109,21 @@ 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);
-	cb->showInfoDialog(&sii);
-	cb->removeObject(this, player);
+	sii.soundID = soundBase::pickup01 + gameEvents.getRandomGenerator().nextInt(6);
+	gameEvents.showInfoDialog(&sii);
+	gameEvents.removeObject(this, player);
 }
 
-void CGResource::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
+void CGResource::battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const
 {
 	if(result.winner == BattleSide::ATTACKER) //attacker won
-		collectRes(hero->getOwner());
+		collectRes(gameEvents, hero->getOwner());
 }
 
-void CGResource::blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const
+void CGResource::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const
 {
 	if(answer)
-		cb->startBattle(hero, this);
+		gameEvents.startBattle(hero, this);
 }
 
 void CGResource::serializeJsonOptions(JsonSerializeFormat & handler)

+ 4 - 4
lib/mapObjects/CGResource.h

@@ -28,17 +28,17 @@ class DLL_LINKAGE CGResource : public CArmedInstance
 
 	std::shared_ptr<ResourceInstanceConstructor> getResourceHandler() const;
 	int getAmountMultiplier() const;
-	void collectRes(const PlayerColor & player) const;
+	void collectRes(IGameEventCallback & gameEvents, const PlayerColor & player) const;
 	void serializeJsonOptions(JsonSerializeFormat & handler) override;
 
 public:
 	using CArmedInstance::CArmedInstance;
 
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	void initObj(vstd::RNG & rand) override;
 	void pickRandomObject(vstd::RNG & rand) override;
-	void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
-	void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
+	void battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const override;
+	void blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const override;
 	std::string getHoverText(PlayerColor player) const override;
 
 	GameResID resourceID() const;

+ 36 - 35
lib/mapObjects/CGTownInstance.cpp

@@ -24,7 +24,8 @@
 #include "../CPlayerState.h"
 #include "../StartInfo.h"
 #include "../TerrainHandler.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../entities/building/CBuilding.h"
 #include "../entities/faction/CTownHandler.h"
 #include "../mapObjectConstructors/AObjectTypeHandler.h"
@@ -263,7 +264,7 @@ TownFortifications CGTownInstance::fortificationsLevel() const
 	return result;
 }
 
-CGTownInstance::CGTownInstance(IGameCallback *cb):
+CGTownInstance::CGTownInstance(CPrivilegedInfoCallback *cb):
 	CGDwelling(cb),
 	IMarket(cb),
 	built(0),
@@ -297,13 +298,13 @@ bool CGTownInstance::needsLastStack() const
 	return getGarrisonHero() != nullptr;
 }
 
-void CGTownInstance::setOwner(const PlayerColor & player) const
+void CGTownInstance::setOwner(IGameEventCallback & gameEvents, const PlayerColor & player) const
 {
-	removeCapitols(player);
-	cb->setOwner(this, player);
+	removeCapitols(gameEvents, player);
+	gameEvents.setOwner(this, player);
 }
 
-void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
+void CGTownInstance::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	if(cb->gameState().getPlayerRelations( getOwner(), h->getOwner() ) == PlayerRelations::ENEMIES)
 	{
@@ -319,23 +320,23 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
 				auto * nodeSiege = defendingHero->whereShouldBeAttachedOnSiege(isBattleOutside);
 
 				if(nodeSiege == (CBonusSystemNode *)this)
-					cb->swapGarrisonOnSiege(this->id);
+					gameEvents.swapGarrisonOnSiege(this->id);
 
 				const_cast<CGHeroInstance *>(defendingHero)->setVisitedTown(this, false); //hack to return visitor from garrison after battle
 			}
-			cb->startBattle(h, defendingArmy, getSightCenter(), h, defendingHero, BattleLayout::createDefaultLayout(cb, h, defendingArmy), (isBattleOutside ? nullptr : this));
+			gameEvents.startBattle(h, defendingArmy, getSightCenter(), h, defendingHero, BattleLayout::createDefaultLayout(cb, h, defendingArmy), (isBattleOutside ? nullptr : this));
 		}
 		else
 		{
 			auto heroColor = h->getOwner();
-			onTownCaptured(heroColor);
+			onTownCaptured(gameEvents, heroColor);
 
 			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)
 			}
-			cb->heroVisitCastle(this, h);
+			gameEvents.heroVisitCastle(this, h);
 		}
 	}
 	else
@@ -348,9 +349,9 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
 			scp.heroid = h->id;
 			scp.which = SetCommanderProperty::ALIVE;
 			scp.amount = 1;
-			cb->sendAndApply(scp);
+			gameEvents.sendAndApply(scp);
 		}
-		cb->heroVisitCastle(this, h);
+		gameEvents.heroVisitCastle(this, h);
 		// TODO(vmarkovtsev): implement payment for rising the commander
 		if (commander_recover) // info window about commander
 		{
@@ -358,17 +359,17 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
 			iw.player = h->tempOwner;
 			iw.text.appendRawString(h->getCommander()->getName());
 			iw.components.emplace_back(ComponentType::CREATURE, h->getCommander()->getId(), h->getCommander()->getCount());
-			cb->showInfoDialog(&iw);
+			gameEvents.showInfoDialog(&iw);
 		}
 	}
 }
 
-void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const
+void CGTownInstance::onHeroLeave(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	//FIXME: find out why this issue appears on random maps
 	if(getVisitingHero() == h)
 	{
-		cb->stopHeroVisitCastle(this, h);
+		gameEvents.stopHeroVisitCastle(this, h);
 		logGlobal->trace("%s correctly left town %s", h->getNameTranslated(), getNameTranslated());
 	}
 	else
@@ -535,17 +536,17 @@ void CGTownInstance::initializeNeutralTownGarrison(vstd::RNG & rand)
 	}
 }
 
-void CGTownInstance::newTurn(vstd::RNG & rand) const
+void CGTownInstance::newTurn(IGameEventCallback & gameEvents) const
 {
 	for(const auto & building : rewardableBuildings)
-		building.second->newTurn(rand);
+		building.second->newTurn(gameEvents);
 		
 	if(hasBuilt(BuildingSubID::BANK) && bonusValue.second > 0)
 	{
 		TResources res;
 		res[EGameResID::GOLD] = -500;
-		cb->giveResources(getOwner(), res);
-		cb->setObjPropertyValue(id, ObjProperty::BONUS_VALUE_SECOND, bonusValue.second - 500);
+		gameEvents.giveResources(getOwner(), res);
+		gameEvents.setObjPropertyValue(id, ObjProperty::BONUS_VALUE_SECOND, bonusValue.second - 500);
 	}
 }
 
@@ -577,7 +578,7 @@ const IObjectInterface * CGTownInstance::getObject() const
 	return this;
 }
 
-void CGTownInstance::mergeGarrisonOnSiege() const
+void CGTownInstance::mergeGarrisonOnSiege(IGameEventCallback & gameEvents) const
 {
 	auto getWeakestStackSlot = [&](ui64 powerLimit)
 	{
@@ -610,17 +611,17 @@ void CGTownInstance::mergeGarrisonOnSiege() const
 		});
 		auto dst = getVisitingHero()->getSlotFor(pair.second->getCreatureID());
 		if(dst.validSlot())
-			cb->moveStack(StackLocation(id, pair.first), StackLocation(getVisitingHero()->id, dst), -1);
+			gameEvents.moveStack(StackLocation(id, pair.first), StackLocation(getVisitingHero()->id, dst), -1);
 		else
 		{
 			dst = getWeakestStackSlot(static_cast<int>(pair.second->getPower()));
 			if(dst.validSlot())
-				cb->swapStacks(StackLocation(id, pair.first), StackLocation(getVisitingHero()->id, dst));
+				gameEvents.swapStacks(StackLocation(id, pair.first), StackLocation(getVisitingHero()->id, dst));
 		}
 	}
 }
 
-void CGTownInstance::removeCapitols(const PlayerColor & owner) const
+void CGTownInstance::removeCapitols(IGameEventCallback & gameEvents, const PlayerColor & owner) const
 {
 	if (hasCapitol()) // search if there's an older capitol
 	{
@@ -633,18 +634,18 @@ void CGTownInstance::removeCapitols(const PlayerColor & owner) const
 				rs.tid = id;
 				rs.bid.insert(BuildingID::CAPITOL);
 				rs.destroyed = destroyed;
-				cb->sendAndApply(rs);
+				gameEvents.sendAndApply(rs);
 				return;
 			}
 		}
 	}
 }
 
-void CGTownInstance::clearArmy() const
+void CGTownInstance::clearArmy(IGameEventCallback & gameEvents) const
 {
 	while(!stacks.empty())
 	{
-		cb->eraseStack(StackLocation(id, stacks.begin()->first), true);
+		gameEvents.eraseStack(StackLocation(id, stacks.begin()->first), true);
 	}
 }
 
@@ -999,12 +1000,12 @@ CBuilding::TRequired CGTownInstance::genBuildingRequirements(const BuildingID &
 	return ret;
 }
 
-void CGTownInstance::addHeroToStructureVisitors(const CGHeroInstance *h, si64 structureInstanceID ) const
+void CGTownInstance::addHeroToStructureVisitors(IGameEventCallback & gameEvents, const CGHeroInstance *h, si64 structureInstanceID ) const
 {
 	if(getVisitingHero() == h)
-		cb->setObjPropertyValue(id, ObjProperty::STRUCTURE_ADD_VISITING_HERO, structureInstanceID); //add to visitors
+		gameEvents.setObjPropertyValue(id, ObjProperty::STRUCTURE_ADD_VISITING_HERO, structureInstanceID); //add to visitors
 	else if(getGarrisonHero() == h)
-		cb->setObjPropertyValue(id, ObjProperty::STRUCTURE_ADD_GARRISONED_HERO, structureInstanceID); //then it must be garrisoned hero
+		gameEvents.setObjPropertyValue(id, ObjProperty::STRUCTURE_ADD_GARRISONED_HERO, structureInstanceID); //then it must be garrisoned hero
 	else
 	{
 		//should never ever happen
@@ -1013,19 +1014,19 @@ void CGTownInstance::addHeroToStructureVisitors(const CGHeroInstance *h, si64 st
 	}
 }
 
-void CGTownInstance::battleFinished(const CGHeroInstance * hero, const BattleResult & result) const
+void CGTownInstance::battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance * hero, const BattleResult & result) const
 {
 	if(result.winner == BattleSide::ATTACKER)
 	{
-		clearArmy();
-		onTownCaptured(hero->getOwner());
+		clearArmy(gameEvents);
+		onTownCaptured(gameEvents, hero->getOwner());
 	}
 }
 
-void CGTownInstance::onTownCaptured(const PlayerColor & winner) const
+void CGTownInstance::onTownCaptured(IGameEventCallback & gameEvents, const PlayerColor & winner) const
 {
-	setOwner(winner);
-	cb->changeFogOfWar(getSightCenter(), getSightRadius(), winner, ETileVisibility::REVEALED);
+	setOwner(gameEvents, winner);
+	gameEvents.changeFogOfWar(getSightCenter(), getSightRadius(), winner, ETileVisibility::REVEALED);
 }
 
 void CGTownInstance::afterAddToMap(CMap * map)

+ 11 - 11
lib/mapObjects/CGTownInstance.h

@@ -183,10 +183,10 @@ public:
 
 	LogicalExpression<BuildingID> genBuildingRequirements(const BuildingID & build, bool deep = false) const;
 
-	void mergeGarrisonOnSiege() const; // merge garrison into army of visiting hero
-	void removeCapitols(const PlayerColor & owner) const;
-	void clearArmy() const;
-	void addHeroToStructureVisitors(const CGHeroInstance *h, si64 structureInstanceID) const; //hero must be visiting or garrisoned in town
+	void mergeGarrisonOnSiege(IGameEventCallback & gameEvents) const; // merge garrison into army of visiting hero
+	void removeCapitols(IGameEventCallback & gameEvents, const PlayerColor & owner) const;
+	void clearArmy(IGameEventCallback & gameEvents) const;
+	void addHeroToStructureVisitors(IGameEventCallback & gameEvents, const CGHeroInstance *h, si64 structureInstanceID) const; //hero must be visiting or garrisoned in town
 	void deleteTownBonus(BuildingID bid);
 
 	/// Returns damage range for secondary towers of this town
@@ -207,16 +207,16 @@ public:
 	/// Returns true if provided war machine is available in any of built buildings of this town
 	bool isWarMachineAvailable(ArtifactID) const;
 
-	CGTownInstance(IGameCallback *cb);
+	CGTownInstance(CPrivilegedInfoCallback *cb);
 	virtual ~CGTownInstance();
 
 	///IObjectInterface overrides
-	void newTurn(vstd::RNG & rand) const override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
-	void onHeroLeave(const CGHeroInstance * h) const override;
+	void newTurn(IGameEventCallback & gameEvents) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
+	void onHeroLeave(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	void initObj(vstd::RNG & rand) override;
 	void pickRandomObject(vstd::RNG & rand) override;
-	void battleFinished(const CGHeroInstance * hero, const BattleResult & result) const override;
+	void battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance * hero, const BattleResult & result) const override;
 	std::string getObjectName() const override;
 
 	void fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const override;
@@ -234,8 +234,8 @@ protected:
 
 private:
 	FactionID randomizeFaction(vstd::RNG & rand);
-	void setOwner(const PlayerColor & owner) const;
-	void onTownCaptured(const PlayerColor & winner) const;
+	void setOwner(IGameEventCallback & gameEvents, const PlayerColor & owner) const;
+	void onTownCaptured(IGameEventCallback & gameEvents, const PlayerColor & winner) const;
 	int getDwellingBonus(const std::vector<CreatureID>& creatureIds, const std::vector<const CGObjectInstance* >& dwellings) const;
 	bool townEnvisagesBuilding(BuildingSubID::EBuildingSubID bid) const;
 	void initializeConfigurableBuildings(vstd::RNG & rand);

+ 36 - 35
lib/mapObjects/CQuest.cpp

@@ -17,7 +17,8 @@
 #include "../texts/CGeneralTextHandler.h"
 #include "CGCreature.h"
 #include "../IGameSettings.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../entities/artifact/CArtifact.h"
 #include "../entities/hero/CHeroHandler.h"
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
@@ -119,7 +120,7 @@ bool CQuest::checkQuest(const CGHeroInstance * h) const
 	return true;
 }
 
-void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h, bool allowFullArmyRemoval) const
+void CQuest::completeQuest(IGameEventCallback & gameEvents, const CGHeroInstance *h, bool allowFullArmyRemoval) const
 {
 	// FIXME: this should be part of 'reward', and not hacking into limiter state that should only limit access to such reward
 
@@ -127,7 +128,7 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h, bool all
 	{
 		if(h->hasArt(elem))
 		{
-			cb->removeArtifact(ArtifactLocation(h->id, h->getArtPos(elem, false)));
+			gameEvents.removeArtifact(ArtifactLocation(h->id, h->getArtPos(elem, false)));
 			continue;
 		}
 
@@ -138,13 +139,13 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h, bool all
 			auto parts = assembly->getPartsInfo();
 
 			// Remove the assembly
-			cb->removeArtifact(ArtifactLocation(h->id, h->getArtPos(assembly)));
+			gameEvents.removeArtifact(ArtifactLocation(h->id, h->getArtPos(assembly)));
 
 			// Disassemble this backpack artifact
 			for(const auto & ci : parts)
 			{
 				if(ci.getArtifact()->getTypeId() != elem)
-					cb->giveHeroNewArtifact(h, ci.getArtifact()->getTypeId(), ArtifactPosition::BACKPACK_START);
+					gameEvents.giveHeroNewArtifact(h, ci.getArtifact()->getTypeId(), ArtifactPosition::BACKPACK_START);
 			}
 
 			continue;
@@ -153,8 +154,8 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h, bool all
 		logGlobal->error("Failed to find artifact %s in inventory of hero %s", elem.toEntity(LIBRARY)->getJsonKey(), h->getHeroTypeID());
 	}
 
-	cb->takeCreatures(h->id, mission.creatures, allowFullArmyRemoval);
-	cb->giveResources(h->getOwner(), -mission.resources);
+	gameEvents.takeCreatures(h->id, mission.creatures, allowFullArmyRemoval);
+	gameEvents.giveResources(h->getOwner(), -mission.resources);
 }
 
 void CQuest::addTextReplacements(const CGameInfoCallback * cb, MetaString & text, std::vector<Component> & components) const
@@ -550,16 +551,16 @@ void CGSeerHut::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
 	}
 }
 
-void CGSeerHut::newTurn(vstd::RNG & rand) const
+void CGSeerHut::newTurn(IGameEventCallback & gameEvents) const
 {
-	CRewardableObject::newTurn(rand);
+	CRewardableObject::newTurn(gameEvents);
 	if(getQuest().lastDay >= 0 && getQuest().lastDay <= cb->getDate() - 1) //time is up
 	{
-		cb->setObjPropertyValue(id, ObjProperty::SEERHUT_COMPLETE, true);
+		gameEvents.setObjPropertyValue(id, ObjProperty::SEERHUT_COMPLETE, true);
 	}
 }
 
-void CGSeerHut::onHeroVisit(const CGHeroInstance * h) const
+void CGSeerHut::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	InfoWindow iw;
 	iw.player = h->getOwner();
@@ -570,23 +571,23 @@ void CGSeerHut::onHeroVisit(const CGHeroInstance * h) const
 
 		if(firstVisit)
 		{
-			cb->setObjPropertyID(id, ObjProperty::SEERHUT_VISITED, h->getOwner());
+			gameEvents.setObjPropertyID(id, ObjProperty::SEERHUT_VISITED, h->getOwner());
 
 			AddQuest aq;
 			aq.quest = QuestInfo(id);
 			aq.player = h->tempOwner;
-			cb->sendAndApply(aq); //TODO: merge with setObjProperty?
+			gameEvents.sendAndApply(aq); //TODO: merge with setObjProperty?
 		}
 
 		if(firstVisit || failRequirements)
 		{
 			getVisitText (iw.text, iw.components, firstVisit, h);
 
-			cb->showInfoDialog(&iw);
+			gameEvents.showInfoDialog(&iw);
 		}
 		if(!failRequirements) // propose completion, also on first visit
 		{
-			CRewardableObject::onHeroVisit(h);
+			CRewardableObject::onHeroVisit(gameEvents, h);
 			return;
 		}
 	}
@@ -595,7 +596,7 @@ void CGSeerHut::onHeroVisit(const CGHeroInstance * h) const
 		iw.text.appendRawString(LIBRARY->generaltexth->seerEmpty[getQuest().completedOption]);
 		if (ID == Obj::SEER_HUT)
 			iw.text.replaceRawString(seerName);
-		cb->showInfoDialog(&iw);
+		gameEvents.showInfoDialog(&iw);
 	}
 }
 
@@ -654,14 +655,14 @@ bool CGSeerHut::allowsFullArmyRemoval() const
 	return seerGivesUnits || h3BugSettingEnabled;
 }
 
-void CGSeerHut::blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const
+void CGSeerHut::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const
 {
 	if(answer)
 	{
-		getQuest().completeQuest(cb, hero, allowsFullArmyRemoval());
-		cb->setObjPropertyValue(id, ObjProperty::SEERHUT_COMPLETE, !getQuest().repeatedQuest); //mission complete
+		getQuest().completeQuest(gameEvents, hero, allowsFullArmyRemoval());
+		gameEvents.setObjPropertyValue(id, ObjProperty::SEERHUT_COMPLETE, !getQuest().repeatedQuest); //mission complete
 	}
-	CRewardableObject::blockingDialogAnswered(hero, answer);
+	CRewardableObject::blockingDialogAnswered(gameEvents, hero, answer);
 }
 
 void CGSeerHut::serializeJsonOptions(JsonSerializeFormat & handler)
@@ -753,12 +754,12 @@ void CGQuestGuard::init(vstd::RNG & rand)
 	configuration.canRefuse = true;
 }
 
-void CGQuestGuard::onHeroVisit(const CGHeroInstance * h) const
+void CGQuestGuard::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	if(!getQuest().isCompleted)
-		CGSeerHut::onHeroVisit(h);
+		CGSeerHut::onHeroVisit(gameEvents, h);
 	else
-		cb->setObjPropertyValue(id, ObjProperty::SEERHUT_COMPLETE, false);
+		gameEvents.setObjPropertyValue(id, ObjProperty::SEERHUT_COMPLETE, false);
 }
 
 bool CGQuestGuard::passableFor(PlayerColor color) const
@@ -797,7 +798,7 @@ bool CGKeymasterTent::wasVisited (PlayerColor player) const
 	return wasMyColorVisited (player);
 }
 
-void CGKeymasterTent::onHeroVisit( const CGHeroInstance * h ) const
+void CGKeymasterTent::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	int txt_id;
 	if (!wasMyColorVisited (h->getOwner()) )
@@ -806,12 +807,12 @@ void CGKeymasterTent::onHeroVisit( const CGHeroInstance * h ) const
 		cow.mode = ChangeObjectVisitors::VISITOR_ADD_PLAYER;
 		cow.hero = h->id;
 		cow.object = id;
-		cb->sendAndApply(cow);
+		gameEvents.sendAndApply(cow);
 		txt_id=19;
 	}
 	else
 		txt_id=20;
-	h->showInfoDialog(txt_id);
+	h->showInfoDialog(gameEvents, txt_id);
 }
 
 void CGBorderGuard::initObj(vstd::RNG & rand)
@@ -839,43 +840,43 @@ bool CGBorderGuard::checkQuest(const CGHeroInstance * h) const
 	return wasMyColorVisited (h->tempOwner);
 }
 
-void CGBorderGuard::onHeroVisit(const CGHeroInstance * h) const
+void CGBorderGuard::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	if (wasMyColorVisited (h->getOwner()) )
 	{
 		BlockingDialog bd (true, false);
 		bd.player = h->getOwner();
 		bd.text.appendLocalString (EMetaText::ADVOB_TXT, 17);
-		cb->showBlockingDialog (this, &bd);
+		gameEvents.showBlockingDialog (this, &bd);
 	}
 	else
 	{
-		h->showInfoDialog(18);
+		h->showInfoDialog(gameEvents, 18);
 
 		AddQuest aq;
 		aq.quest = QuestInfo(id);
 		aq.player = h->tempOwner;
-		cb->sendAndApply(aq);
+		gameEvents.sendAndApply(aq);
 		//TODO: add this quest only once OR check for multiple instances later
 	}
 }
 
-void CGBorderGuard::blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const
+void CGBorderGuard::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const
 {
 	if (answer)
-		cb->removeObject(this, hero->getOwner());
+		gameEvents.removeObject(this, hero->getOwner());
 }
 
-void CGBorderGate::onHeroVisit(const CGHeroInstance * h) const //TODO: passability
+void CGBorderGate::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const //TODO: passability
 {
 	if (!wasMyColorVisited (h->getOwner()) )
 	{
-		h->showInfoDialog(18);
+		h->showInfoDialog(gameEvents, 18);
 
 		AddQuest aq;
 		aq.quest = QuestInfo(id);
 		aq.player = h->tempOwner;
-		cb->sendAndApply(aq);
+		gameEvents.sendAndApply(aq);
 	}
 }
 

+ 9 - 9
lib/mapObjects/CQuest.h

@@ -80,7 +80,7 @@ public:
 	void getVisitText(const CGameInfoCallback * cb, MetaString &text, std::vector<Component> & components, bool FirstVisit, const CGHeroInstance * h = nullptr) const;
 	void getCompletionText(const CGameInfoCallback * cb, MetaString &text) const;
 	void getRolloverText (const CGameInfoCallback * cb, MetaString &text, bool onHover) const; //hover or quest log entry
-	void completeQuest(IGameCallback *, const CGHeroInstance * h, bool allowFullArmyRemoval) const;
+	void completeQuest(IGameEventCallback & gameEvents, const CGHeroInstance * h, bool allowFullArmyRemoval) const;
 	void addTextReplacements(const CGameInfoCallback * cb, MetaString &out, std::vector<Component> & components) const;
 	void addKillTargetReplacements(MetaString &out) const;
 	void defineQuestName();
@@ -147,9 +147,9 @@ public:
 	std::string getPopupText(const CGHeroInstance * hero) const override;
 	std::vector<Component> getPopupComponents(PlayerColor player) const override;
 	std::vector<Component> getPopupComponents(const CGHeroInstance * hero) const override;
-	void newTurn(vstd::RNG & rand) const override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
-	void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
+	void newTurn(IGameEventCallback & gameEvents) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
+	void blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const override;
 	void getVisitText (MetaString &text, std::vector<Component> &components, bool FirstVisit, const CGHeroInstance * h = nullptr) const override;
 
 	virtual void init(vstd::RNG & rand);
@@ -179,7 +179,7 @@ public:
 
 	void init(vstd::RNG & rand) override;
 	
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	bool passableFor(PlayerColor color) const override;
 
 	template <typename Handler> void serialize(Handler &h)
@@ -213,7 +213,7 @@ public:
 	using CGKeys::CGKeys;
 
 	bool wasVisited (PlayerColor player) const override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -228,8 +228,8 @@ public:
 	using CGKeys::CGKeys;
 
 	void initObj(vstd::RNG & rand) override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
-	void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
+	void blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const override;
 
 	void getVisitText (MetaString &text, std::vector<Component> &components, bool FirstVisit, const CGHeroInstance * h = nullptr) const override;
 	void getRolloverText (MetaString &text, bool onHover) const;
@@ -247,7 +247,7 @@ class DLL_LINKAGE CGBorderGate : public CGBorderGuard
 public:
 	using CGBorderGuard::CGBorderGuard;
 
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 
 	bool passableFor(PlayerColor color) const override;
 };

+ 34 - 33
lib/mapObjects/CRewardableObject.cpp

@@ -14,7 +14,8 @@
 #include "../CPlayerState.h"
 #include "../IGameSettings.h"
 #include "../battle/BattleLayout.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../gameState/CGameState.h"
 #include "../mapObjectConstructors/AObjectTypeHandler.h"
 #include "../mapObjectConstructors/CRewardableConstructor.h"
@@ -33,10 +34,10 @@ const IObjectInterface * CRewardableObject::getObject() const
 	return this;
 }
 
-void CRewardableObject::markAsScouted(const CGHeroInstance * hero) const
+void CRewardableObject::markAsScouted(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const
 {
 	ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_ADD_PLAYER, id, hero->id);
-	cb->sendAndApply(cov);
+	gameEvents.sendAndApply(cov);
 }
 
 bool CRewardableObject::isGuarded() const
@@ -44,21 +45,21 @@ bool CRewardableObject::isGuarded() const
 	return stacksCount() > 0;
 }
 
-void CRewardableObject::onHeroVisit(const CGHeroInstance *hero) const
+void CRewardableObject::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const
 {
 	if(!wasScouted(hero->getOwner()))
 	{
 		ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_SCOUTED, id, hero->id);
-		cb->sendAndApply(cov);
+		gameEvents.sendAndApply(cov);
 	}
 
 	if (!isGuarded())
 	{
-		doHeroVisit(hero);
+		doHeroVisit(gameEvents, hero);
 	}
 	else if (configuration.forceCombat)
 	{
-		doStartBattle(hero);
+		doStartBattle(gameEvents, hero);
 	}
 	else
 	{
@@ -71,67 +72,67 @@ void CRewardableObject::onHeroVisit(const CGHeroInstance *hero) const
 		bd.text = guardedReward.message;
 		bd.components = getPopupComponents(hero->getOwner());
 
-		cb->showBlockingDialog(this, &bd);
+		gameEvents.showBlockingDialog(this, &bd);
 	}
 }
 
-void CRewardableObject::heroLevelUpDone(const CGHeroInstance *hero) const
+void CRewardableObject::heroLevelUpDone(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const
 {
-	grantRewardAfterLevelup(configuration.info.at(selectedReward), this, hero);
+	grantRewardAfterLevelup(gameEvents, configuration.info.at(selectedReward), this, hero);
 }
 
-void CRewardableObject::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
+void CRewardableObject::battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const
 {
 	if (result.winner == BattleSide::ATTACKER)
 	{
-		doHeroVisit(hero);
+		doHeroVisit(gameEvents, hero);
 	}
 }
 
-void CRewardableObject::garrisonDialogClosed(const CGHeroInstance *hero) const
+void CRewardableObject::garrisonDialogClosed(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const
 {
 	// if visitor received creatures as rewards, but does not have free slots, he will leave some units
 	// inside rewardable object, which might get treated as guards later
 	while(!stacks.empty())
-		cb->eraseStack(StackLocation(id, stacks.begin()->first));
+		gameEvents.eraseStack(StackLocation(id, stacks.begin()->first));
 }
 
-void CRewardableObject::doStartBattle(const CGHeroInstance * hero) const
+void CRewardableObject::doStartBattle(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const
 {
 	auto layout = BattleLayout::createLayout(cb, configuration.guardsLayout, hero, this);
-	cb->startBattle(hero, this, visitablePos(), hero, nullptr, layout, nullptr);
+	gameEvents.startBattle(hero, this, visitablePos(), hero, nullptr, layout, nullptr);
 }
 
-void CRewardableObject::blockingDialogAnswered(const CGHeroInstance * hero, int32_t answer) const
+void CRewardableObject::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance * hero, int32_t answer) const
 {
 	if(isGuarded())
 	{
 		if (answer)
-			doStartBattle(hero);
+			doStartBattle(gameEvents, hero);
 	}
 	else
 	{
-		onBlockingDialogAnswered(hero, answer);
+		onBlockingDialogAnswered(gameEvents, hero, answer);
 	}
 }
 
-void CRewardableObject::markAsVisited(const CGHeroInstance * hero) const
+void CRewardableObject::markAsVisited(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const
 {
-	cb->setObjPropertyValue(id, ObjProperty::REWARD_CLEARED, true);
+	gameEvents.setObjPropertyValue(id, ObjProperty::REWARD_CLEARED, true);
 
 	ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_ADD_HERO, id, hero->id);
-	cb->sendAndApply(cov);
+	gameEvents.sendAndApply(cov);
 }
 
-void CRewardableObject::grantReward(ui32 rewardID, const CGHeroInstance * hero) const
+void CRewardableObject::grantReward(IGameEventCallback & gameEvents, ui32 rewardID, const CGHeroInstance * hero) const
 {
-	cb->setObjPropertyValue(id, ObjProperty::REWARD_SELECT, rewardID);
-	grantRewardBeforeLevelup(configuration.info.at(rewardID), hero);
+	gameEvents.setObjPropertyValue(id, ObjProperty::REWARD_SELECT, rewardID);
+	grantRewardBeforeLevelup(gameEvents, configuration.info.at(rewardID), hero);
 	
 	// hero is not blocked by levelup dialog - grant remainder immediately
-	if(!cb->isVisitCoveredByAnotherQuery(this, hero))
+	if(!gameEvents.isVisitCoveredByAnotherQuery(this, hero))
 	{
-		grantRewardAfterLevelup(configuration.info.at(rewardID), this, hero);
+		grantRewardAfterLevelup(gameEvents, configuration.info.at(rewardID), this, hero);
 	}
 }
 
@@ -330,21 +331,21 @@ void CRewardableObject::setPropertyDer(ObjProperty what, ObjPropertyID identifie
 	}
 }
 
-void CRewardableObject::newTurn(vstd::RNG & rand) const
+void CRewardableObject::newTurn(IGameEventCallback & gameEvents) const
 {
 	if (configuration.resetParameters.period != 0 && cb->getDate(Date::DAY) > 1 && ((cb->getDate(Date::DAY)-1) % configuration.resetParameters.period) == 0)
 	{
 		if (configuration.resetParameters.rewards)
 		{
 			auto handler = std::dynamic_pointer_cast<const CRewardableConstructor>(getObjectHandler());
-			auto newConfiguration = handler->generateConfiguration(cb, rand, ID, configuration.variables.preset);
-			cb->setRewardableObjectConfiguration(id, newConfiguration);
+			auto newConfiguration = handler->generateConfiguration(cb, gameEvents.getRandomGenerator(), ID, configuration.variables.preset);
+			gameEvents.setRewardableObjectConfiguration(id, newConfiguration);
 		}
 		if (configuration.resetParameters.visitors)
 		{
-			cb->setObjPropertyValue(id, ObjProperty::REWARD_CLEARED, false);
+			gameEvents.setObjPropertyValue(id, ObjProperty::REWARD_CLEARED, false);
 			ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_CLEAR, id);
-			cb->sendAndApply(cov);
+			gameEvents.sendAndApply(cov);
 		}
 	}
 }
@@ -354,7 +355,7 @@ void CRewardableObject::initObj(vstd::RNG & rand)
 	getObjectHandler()->configureObject(this, rand);
 }
 
-CRewardableObject::CRewardableObject(IGameCallback *cb)
+CRewardableObject::CRewardableObject(CPrivilegedInfoCallback *cb)
 	:CArmedInstance(cb)
 {}
 

+ 11 - 11
lib/mapObjects/CRewardableObject.h

@@ -25,13 +25,13 @@ protected:
 	/// reward selected by player, no serialize
 	ui16 selectedReward = 0;
 	
-	void doStartBattle(const CGHeroInstance * hero) const;
+	void doStartBattle(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const;
 
-	void grantReward(ui32 rewardID, const CGHeroInstance * hero) const override;
-	void markAsVisited(const CGHeroInstance * hero) const override;
+	void grantReward(IGameEventCallback & gameEvents, ui32 rewardID, const CGHeroInstance * hero) const override;
+	void markAsVisited(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const override;
 
 	const IObjectInterface * getObject() const override;
-	void markAsScouted(const CGHeroInstance * hero) const override;
+	void markAsScouted(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const override;
 	
 	/// return true if this object was "cleared" before and no longer has rewards applicable to selected hero
 	/// unlike wasVisited, this method uses information not available to player owner, for example, if object was cleared by another player before
@@ -55,19 +55,19 @@ public:
 	bool wasScouted(PlayerColor player) const;
 	
 	/// gives reward to player or ask for choice in case of multiple rewards
-	void onHeroVisit(const CGHeroInstance *h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance *h) const override;
 
-	void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
-	void garrisonDialogClosed(const CGHeroInstance *hero) const override;
+	void battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const override;
+	void garrisonDialogClosed(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const override;
 
 	///possibly resets object state
-	void newTurn(vstd::RNG & rand) const override;
+	void newTurn(IGameEventCallback & gameEvents) const override;
 
 	/// gives second part of reward after hero level-ups for proper granting of spells/mana
-	void heroLevelUpDone(const CGHeroInstance *hero) const override;
+	void heroLevelUpDone(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const override;
 
 	/// applies player selection of reward
-	void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
+	void blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const override;
 
 	void initObj(vstd::RNG & rand) override;
 
@@ -77,7 +77,7 @@ public:
 	
 	void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
 
-	CRewardableObject(IGameCallback *cb);
+	CRewardableObject(CPrivilegedInfoCallback *cb);
 	
 	std::string getHoverText(PlayerColor player) const override;
 	std::string getHoverText(const CGHeroInstance * hero) const override;

+ 18 - 17
lib/mapObjects/FlaggableMapObject.cpp

@@ -12,7 +12,8 @@
 #include "FlaggableMapObject.h"
 
 #include "CGHeroInstance.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../networkPacks/PacksForClient.h"
 #include "../mapObjectConstructors/FlaggableInstanceConstructor.h"
 #include "../gameState/GameStatePackVisitor.h"
@@ -34,37 +35,37 @@ std::vector<CreatureID> FlaggableMapObject::providedCreatures() const
 	return {};
 }
 
-void FlaggableMapObject::onHeroVisit( const CGHeroInstance * h ) const
+void FlaggableMapObject::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	if (cb->getPlayerRelations(h->getOwner(), getOwner()) != PlayerRelations::ENEMIES)
 		return; // H3 behavior - revisiting owned Lighthouse is a no-op
 
 	if (getOwner().isValidPlayer())
-		takeBonusFrom(getOwner());
+		takeBonusFrom(gameEvents, getOwner());
 
-	cb->setOwner(this, h->getOwner()); //not ours? flag it!
+	gameEvents.setOwner(this, h->getOwner()); //not ours? flag it!
 
 	InfoWindow iw;
 	iw.player = h->getOwner();
 	iw.text.appendTextID(getFlaggableHandler()->getVisitMessageTextID());
-	cb->showInfoDialog(&iw);
+	gameEvents.showInfoDialog(&iw);
 
-	giveBonusTo(h->getOwner());
+	giveBonusTo(gameEvents, h->getOwner());
 }
 
 void FlaggableMapObject::markAsDeleted() const
 {
-	if(getOwner().isValidPlayer())
-		takeBonusFrom(getOwner());
+//	if(getOwner().isValidPlayer())
+//		takeBonusFrom(gameEvents, getOwner());
 }
 
 void FlaggableMapObject::initObj(vstd::RNG & rand)
 {
-	if(getOwner().isValidPlayer())
-	{
-		// FIXME: This is dirty hack
-		giveBonusTo(getOwner(), true);
-	}
+//	if(getOwner().isValidPlayer())
+//	{
+//		// FIXME: This is dirty hack
+//		giveBonusTo(gameEvents, getOwner(), true);
+//	}
 }
 
 std::shared_ptr<FlaggableInstanceConstructor> FlaggableMapObject::getFlaggableHandler() const
@@ -72,7 +73,7 @@ std::shared_ptr<FlaggableInstanceConstructor> FlaggableMapObject::getFlaggableHa
 	return std::dynamic_pointer_cast<FlaggableInstanceConstructor>(getObjectHandler());
 }
 
-void FlaggableMapObject::giveBonusTo(const PlayerColor & player, bool onInit) const
+void FlaggableMapObject::giveBonusTo(IGameEventCallback & gameEvents, const PlayerColor & player, bool onInit) const
 {
 	for (auto const & bonus : getFlaggableHandler()->getProvidedBonuses())
 	{
@@ -94,17 +95,17 @@ void FlaggableMapObject::giveBonusTo(const PlayerColor & player, bool onInit) co
 			gb.visit(visitor);
 		}
 		else
-			cb->sendAndApply(gb);
+			gameEvents.sendAndApply(gb);
 	}
 }
 
-void FlaggableMapObject::takeBonusFrom(const PlayerColor & player) const
+void FlaggableMapObject::takeBonusFrom(IGameEventCallback & gameEvents, const PlayerColor & player) const
 {
 	RemoveBonus rb(GiveBonus::ETarget::PLAYER);
 	rb.whoID = player;
 	rb.source = BonusSource::OBJECT_INSTANCE;
 	rb.id = BonusSourceID(id);
-	cb->sendAndApply(rb);
+	gameEvents.sendAndApply(rb);
 }
 
 void FlaggableMapObject::serializeJsonOptions(JsonSerializeFormat& handler)

+ 3 - 3
lib/mapObjects/FlaggableMapObject.h

@@ -21,13 +21,13 @@ class DLL_LINKAGE FlaggableMapObject : public CGObjectInstance, public IOwnableO
 {
 	std::shared_ptr<FlaggableInstanceConstructor> getFlaggableHandler() const;
 
-	void giveBonusTo(const PlayerColor & player, bool onInit = false) const;
-	void takeBonusFrom(const PlayerColor & player) const;
+	void giveBonusTo(IGameEventCallback & gameEvents, const PlayerColor & player, bool onInit = false) const;
+	void takeBonusFrom(IGameEventCallback & gameEvents, const PlayerColor & player) const;
 
 public:
 	using CGObjectInstance::CGObjectInstance;
 
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	void markAsDeleted() const;
 	void initObj(vstd::RNG & rand) override;
 

+ 1 - 1
lib/mapObjects/IMarket.cpp

@@ -140,7 +140,7 @@ int IMarket::availableUnits(const EMarketMode mode, const int marketItemSerial)
 	}
 }
 
-IMarket::IMarket(IGameCallback *cb)
+IMarket::IMarket(CPrivilegedInfoCallback *cb)
 	:altarArtifactsStorage(std::make_unique<CArtifactSetAltar>(cb))
 {
 }

+ 4 - 4
lib/mapObjects/IMarket.h

@@ -18,19 +18,19 @@ VCMI_LIB_NAMESPACE_BEGIN
 class DLL_LINKAGE IMarket : public virtual Serializeable, boost::noncopyable
 {
 public:
-	explicit IMarket(IGameCallback *cb);
+	explicit IMarket(CPrivilegedInfoCallback *cb);
 	~IMarket();
 
 	class CArtifactSetAltar : public CArtifactSet
 	{
-		IGameCallback *cb;
+		CPrivilegedInfoCallback *cb;
 	public:
-		CArtifactSetAltar(IGameCallback *cb)
+		CArtifactSetAltar(CPrivilegedInfoCallback *cb)
 			: CArtifactSet(cb)
 			, cb(cb)
 		{}
 
-		IGameCallback * getCallback() const override {return cb;};
+		CPrivilegedInfoCallback * getCallback() const override {return cb;};
 		ArtBearer bearerType() const override {return ArtBearer::ALTAR;};
 	};
 

+ 11 - 10
lib/mapObjects/IObjectInterface.cpp

@@ -15,30 +15,31 @@
 #include "MiscObjects.h"
 
 #include "../TerrainHandler.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../networkPacks/PacksForClient.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-void IObjectInterface::showInfoDialog(const ui32 txtID, const ui16 soundID, EInfoWindowMode mode) const
+void IObjectInterface::showInfoDialog(IGameEventCallback & gameEvents, const ui32 txtID, const ui16 soundID, EInfoWindowMode mode) const
 {
 	InfoWindow iw;
 	iw.soundID = soundID;
 	iw.player = getOwner();
 	iw.type = mode;
 	iw.text.appendLocalString(EMetaText::ADVOB_TXT,txtID);
-	cb->sendAndApply(iw);
+	gameEvents.sendAndApply(iw);
 }
 
 ///IObjectInterface
-void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
+void IObjectInterface::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {}
 
-void IObjectInterface::onHeroLeave(const CGHeroInstance * h) const
+void IObjectInterface::onHeroLeave(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {}
 
-void IObjectInterface::newTurn(vstd::RNG & rand) const
+void IObjectInterface::newTurn(IGameEventCallback & gameEvents) const
 {}
 
 void IObjectInterface::initObj(vstd::RNG & rand)
@@ -65,16 +66,16 @@ void IObjectInterface::postInit()
 void IObjectInterface::preInit()
 {}
 
-void IObjectInterface::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
+void IObjectInterface::battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const
 {}
 
-void IObjectInterface::blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const
+void IObjectInterface::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const
 {}
 
-void IObjectInterface::garrisonDialogClosed(const CGHeroInstance *hero) const
+void IObjectInterface::garrisonDialogClosed(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const
 {}
 
-void IObjectInterface::heroLevelUpDone(const CGHeroInstance *hero) const
+void IObjectInterface::heroLevelUpDone(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const
 {}
 
 int3 IBoatGenerator::bestLocation() const

+ 10 - 9
lib/mapObjects/IObjectInterface.h

@@ -28,7 +28,8 @@ class BoatId;
 class CGObjectInstance;
 class CStackInstance;
 class CGHeroInstance;
-class IGameCallback;
+class CPrivilegedInfoCallback;
+class IGameEventCallback;
 class ResourceSet;
 class int3;
 class MetaString;
@@ -49,25 +50,25 @@ public:
 	virtual int3 visitablePos() const = 0;
 	virtual int3 anchorPos() const = 0;
 
-	virtual void onHeroVisit(const CGHeroInstance * h) const;
-	virtual void onHeroLeave(const CGHeroInstance * h) const;
+	virtual void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const;
+	virtual void onHeroLeave(IGameEventCallback & gameEvents, const CGHeroInstance * h) const;
 
 	/// Called on new turn by server. This method can not modify object state on its own
 	/// Instead all changes must be propagated via netpacks
-	virtual void newTurn(vstd::RNG & rand) const;
+	virtual void newTurn(IGameEventCallback & gameEvents) const;
 	virtual void initObj(vstd::RNG & rand); //synchr
 	virtual void pickRandomObject(vstd::RNG & rand);
 	virtual void setProperty(ObjProperty what, ObjPropertyID identifier);//synchr
 
 	//Called when queries created DURING HERO VISIT are resolved
 	//First parameter is always hero that visited object and triggered the query
-	virtual void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const;
-	virtual void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const;
-	virtual void garrisonDialogClosed(const CGHeroInstance *hero) const;
-	virtual void heroLevelUpDone(const CGHeroInstance *hero) const;
+	virtual void battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const;
+	virtual void blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const;
+	virtual void garrisonDialogClosed(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const;
+	virtual void heroLevelUpDone(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const;
 
 	//unified helper to show info dialog for object owner
-	virtual void showInfoDialog(const ui32 txtID, const ui16 soundID = 0, EInfoWindowMode mode = EInfoWindowMode::AUTO) const;
+	virtual void showInfoDialog(IGameEventCallback & gameEvents, const ui32 txtID, const ui16 soundID = 0, EInfoWindowMode mode = EInfoWindowMode::AUTO) const;
 
 	virtual const IOwnableObject * asOwnable() const = 0;
 

+ 85 - 84
lib/mapObjects/MiscObjects.cpp

@@ -12,7 +12,8 @@
 #include "MiscObjects.h"
 
 #include "../bonuses/Propagators.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../constants/StringConstants.h"
 #include "../entities/artifact/ArtifactUtils.h"
 #include "../entities/artifact/CArtifact.h"
@@ -73,13 +74,13 @@ bool CTeamVisited::wasVisited(const TeamID & team) const
 }
 
 //CGMine
-void CGMine::onHeroVisit( const CGHeroInstance * h ) const
+void CGMine::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	auto relations = cb->gameState().getPlayerRelations(h->tempOwner, tempOwner);
 
 	if(relations == PlayerRelations::SAME_PLAYER) //we're visiting our mine
 	{
-		cb->showGarrisonDialog(id,h->id,true);
+		gameEvents.showGarrisonDialog(id,h->id,true);
 		return;
 	}
 	else if (relations == PlayerRelations::ALLIES)//ally
@@ -90,11 +91,11 @@ void CGMine::onHeroVisit( const CGHeroInstance * h ) const
 		BlockingDialog ynd(true,false);
 		ynd.player = h->tempOwner;
 		ynd.text.appendLocalString(EMetaText::ADVOB_TXT, isAbandoned() ? 84 : 187);
-		cb->showBlockingDialog(this, &ynd);
+		gameEvents.showBlockingDialog(this, &ynd);
 		return;
 	}
 
-	flagMine(h->tempOwner);
+	flagMine(gameEvents, h->tempOwner);
 }
 
 void CGMine::initObj(vstd::RNG & rand)
@@ -172,17 +173,17 @@ std::string CGMine::getHoverText(PlayerColor player) const
 	return hoverName;
 }
 
-void CGMine::flagMine(const PlayerColor & player) const
+void CGMine::flagMine(IGameEventCallback & gameEvents, const PlayerColor & player) const
 {
 	assert(tempOwner != player);
-	cb->setOwner(this, player); //not ours? flag it!
+	gameEvents.setOwner(this, player); //not ours? flag it!
 
 	InfoWindow iw;
 	iw.type = EInfoWindowMode::AUTO;
 	iw.text.appendTextID(TextIdentifier("core.mineevnt", producedResource.getNum()).get()); //not use subID, abandoned mines uses default mine texts
 	iw.player = player;
 	iw.components.emplace_back(ComponentType::RESOURCE_PER_DAY, producedResource, getProducedQuantity());
-	cb->showInfoDialog(&iw);
+	gameEvents.showInfoDialog(&iw);
 }
 
 ui32 CGMine::defaultResProduction() const
@@ -206,22 +207,22 @@ ui32 CGMine::getProducedQuantity() const
 	return vstd::divideAndCeil(producedQuantity * playerSettings->handicap.percentIncome, 100);
 }
 
-void CGMine::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
+void CGMine::battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const
 {
 	if(result.winner == BattleSide::ATTACKER) //attacker won
 	{
 		if(isAbandoned())
 		{
-			hero->showInfoDialog(85);
+			hero->showInfoDialog(gameEvents, 85);
 		}
-		flagMine(hero->tempOwner);
+		flagMine(gameEvents, hero->tempOwner);
 	}
 }
 
-void CGMine::blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const
+void CGMine::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const
 {
 	if(answer)
-		cb->startBattle(hero, this);
+		gameEvents.startBattle(hero, this);
 }
 
 void CGMine::serializeJsonOptions(JsonSerializeFormat & handler)
@@ -295,11 +296,11 @@ std::vector<ObjectInstanceID> CGTeleport::getAllExits(bool excludeCurrent) const
 	return ret;
 }
 
-ObjectInstanceID CGTeleport::getRandomExit(const CGHeroInstance * h) const
+ObjectInstanceID CGTeleport::getRandomExit(IGameEventCallback & gameEvents, 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, gameEvents.getRandomGenerator());
 
 	return ObjectInstanceID();
 }
@@ -385,7 +386,7 @@ TeleportChannelID CGMonolith::findMeChannel(const std::vector<Obj> & IDs, MapObj
 	return TeleportChannelID();
 }
 
-void CGMonolith::onHeroVisit( const CGHeroInstance * h ) const
+void CGMonolith::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	TeleportDialog td(h->id, channel);
 	if(isEntrance())
@@ -404,19 +405,19 @@ void CGMonolith::onHeroVisit( const CGHeroInstance * h ) const
 			logGlobal->debug("Cannot find corresponding exit monolith for %d at %s", id.getNum(), anchorPos().toString());
 			td.impassable = true;
 		}
-		else if(getRandomExit(h) == ObjectInstanceID())
+		else if(getRandomExit(gameEvents, h) == ObjectInstanceID())
 			logGlobal->debug("All exits blocked for monolith %d at %s", id.getNum(), anchorPos().toString());
 	}
 	else
-		h->showInfoDialog(70);
+		h->showInfoDialog(gameEvents, 70);
 
-	cb->showTeleportDialog(&td);
+	gameEvents.showTeleportDialog(&td);
 }
 
-void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const
+void CGMonolith::teleportDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const
 {
 	int3 dPos;
-	auto randomExit = getRandomExit(hero);
+	auto randomExit = getRandomExit(gameEvents, hero);
 	auto realExits = getAllExits(true);
 	if(!isEntrance() // Do nothing if hero visited exit only object
 		|| (exits.empty() && realExits.empty()) // Do nothing if there no exits on this channel
@@ -429,7 +430,7 @@ void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer,
 	else
 		dPos = cb->getObj(randomExit)->visitablePos();
 
-	cb->moveHero(hero->id, hero->convertFromVisitablePos(dPos), EMovementMode::MONOLITH);
+	gameEvents.moveHero(hero->id, hero->convertFromVisitablePos(dPos), EMovementMode::MONOLITH);
 }
 
 void CGMonolith::initObj(vstd::RNG & rand)
@@ -459,22 +460,22 @@ void CGMonolith::initObj(vstd::RNG & rand)
 	addToChannel(cb->gameState().getMap().teleportChannels, this);
 }
 
-void CGSubterraneanGate::onHeroVisit( const CGHeroInstance * h ) const
+void CGSubterraneanGate::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	TeleportDialog td(h->id, channel);
 	if(cb->isTeleportChannelImpassable(channel))
 	{
-		h->showInfoDialog(153);//Just inside the entrance you find a large pile of rubble blocking the tunnel. You leave discouraged.
+		h->showInfoDialog(gameEvents, 153);//Just inside the entrance you find a large pile of rubble blocking the tunnel. You leave discouraged.
 		logGlobal->debug("Cannot find exit subterranean gate for  %d at %s", id.getNum(), anchorPos().toString());
 		td.impassable = true;
 	}
 	else
 	{
-		auto exit = getRandomExit(h);
+		auto exit = getRandomExit(gameEvents, h);
 		td.exits.push_back(std::make_pair(exit, cb->getObj(exit)->visitablePos()));
 	}
 
-	cb->showTeleportDialog(&td);
+	gameEvents.showTeleportDialog(&td);
 }
 
 void CGSubterraneanGate::initObj(vstd::RNG & rand)
@@ -482,7 +483,7 @@ void CGSubterraneanGate::initObj(vstd::RNG & rand)
 	type = BOTH;
 }
 
-void CGSubterraneanGate::postInit(IGameCallback * cb) //matches subterranean gates into pairs
+void CGSubterraneanGate::postInit(CPrivilegedInfoCallback * cb) //matches subterranean gates into pairs
 {
 	//split on underground and surface gates
 	std::vector<CGSubterraneanGate *> gatesSplit[2]; //surface and underground gates
@@ -538,7 +539,7 @@ void CGSubterraneanGate::postInit(IGameCallback * cb) //matches subterranean gat
 		assignToChannel(i);
 }
 
-void CGWhirlpool::onHeroVisit( const CGHeroInstance * h ) const
+void CGWhirlpool::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	TeleportDialog td(h->id, channel);
 	if(cb->isTeleportChannelImpassable(channel))
@@ -546,7 +547,7 @@ void CGWhirlpool::onHeroVisit( const CGHeroInstance * h ) const
 		logGlobal->debug("Cannot find exit whirlpool for %d at %s", id.getNum(), anchorPos().toString());
 		td.impassable = true;
 	}
-	else if(getRandomExit(h) == ObjectInstanceID())
+	else if(getRandomExit(gameEvents, h) == ObjectInstanceID())
 		logGlobal->debug("All exits are blocked for whirlpool  %d at %s", id.getNum(), anchorPos().toString());
 
 	if(!isProtected(h))
@@ -566,8 +567,8 @@ void CGWhirlpool::onHeroVisit( const CGHeroInstance * h ) const
 		iw.player = h->tempOwner;
 		iw.text.appendLocalString(EMetaText::ADVOB_TXT, 168);
 		iw.components.emplace_back(ComponentType::CREATURE, h->getCreature(targetstack)->getId(), -countToTake);
-		cb->showInfoDialog(&iw);
-		cb->changeStackCount(StackLocation(h->id, targetstack), -countToTake);
+		gameEvents.showInfoDialog(&iw);
+		gameEvents.changeStackCount(StackLocation(h->id, targetstack), -countToTake);
 	}
 	else
 	{
@@ -580,10 +581,10 @@ void CGWhirlpool::onHeroVisit( const CGHeroInstance * h ) const
 		}
 	}
 
-	cb->showTeleportDialog(&td);
+	gameEvents.showTeleportDialog(&td);
 }
 
-void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const
+void CGWhirlpool::teleportDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const
 {
 	int3 dPos;
 	auto realExits = getAllExits();
@@ -593,17 +594,17 @@ void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer
 		dPos = exits[answer].second;
 	else
 	{
-		auto exit = getRandomExit(hero);
+		auto exit = getRandomExit(gameEvents, hero);
 
 		if(exit == ObjectInstanceID())
 			return;
 
 		const auto * obj = cb->getObj(exit);
 		std::set<int3> tiles = obj->getBlockedPos();
-		dPos = *RandomGeneratorUtil::nextItem(tiles, cb->gameState().getRandomGenerator());
+		dPos = *RandomGeneratorUtil::nextItem(tiles, gameEvents.getRandomGenerator());
 	}
 
-	cb->moveHero(hero->id, hero->convertFromVisitablePos(dPos), EMovementMode::MONOLITH);
+	gameEvents.moveHero(hero->id, hero->convertFromVisitablePos(dPos), EMovementMode::MONOLITH);
 }
 
 bool CGWhirlpool::isProtected(const CGHeroInstance * h)
@@ -708,7 +709,7 @@ std::vector<Component> CGArtifact::getPopupComponents(PlayerColor player) const
 	};
 }
 
-void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
+void CGArtifact::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	if(!stacksCount())
 	{
@@ -748,8 +749,8 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
 		{
 			iw.text.appendLocalString(EMetaText::ADVOB_TXT, 2);
 		}
-		cb->showInfoDialog(&iw);
-		pick(h);
+		gameEvents.showInfoDialog(&iw);
+		pick(gameEvents, h);
 	}
 	else
 	{
@@ -769,7 +770,7 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
 					ynd.text.replaceRawString(getArmyDescription());
 					ynd.text.replaceLocalString(EMetaText::GENERAL_TXT, 43); // creatures
 				}
-				cb->showBlockingDialog(this, &ynd);
+				gameEvents.showBlockingDialog(this, &ynd);
 			}
 			break;
 		case Obj::SPELL_SCROLL:
@@ -779,20 +780,20 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
 					BlockingDialog ynd(true,false);
 					ynd.player = h->getOwner();
 					ynd.text = message;
-					cb->showBlockingDialog(this, &ynd);
+					gameEvents.showBlockingDialog(this, &ynd);
 				}
 				else
-					blockingDialogAnswered(h, true);
+					blockingDialogAnswered(gameEvents, h, true);
 			}
 			break;
 		}
 	}
 }
 
-void CGArtifact::pick(const CGHeroInstance * h) const
+void CGArtifact::pick(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
-	if(cb->putArtifact(ArtifactLocation(h->id, ArtifactPosition::FIRST_AVAILABLE), getArtifactInstance()->getId()))
-		cb->removeObject(this, h->getOwner());
+	if(gameEvents.putArtifact(ArtifactLocation(h->id, ArtifactPosition::FIRST_AVAILABLE), getArtifactInstance()->getId()))
+		gameEvents.removeObject(this, h->getOwner());
 }
 
 BattleField CGArtifact::getBattlefield() const
@@ -800,16 +801,16 @@ BattleField CGArtifact::getBattlefield() const
 	return BattleField::NONE;
 }
 
-void CGArtifact::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
+void CGArtifact::battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const
 {
 	if(result.winner == BattleSide::ATTACKER) //attacker won
-		pick(hero);
+		pick(gameEvents, hero);
 }
 
-void CGArtifact::blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const
+void CGArtifact::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const
 {
 	if(answer)
-		cb->startBattle(hero, this);
+		gameEvents.startBattle(hero, this);
 }
 
 void CGArtifact::serializeJsonOptions(JsonSerializeFormat& handler)
@@ -844,15 +845,15 @@ void CGSignBottle::initObj(vstd::RNG & rand)
 	}
 }
 
-void CGSignBottle::onHeroVisit( const CGHeroInstance * h ) const
+void CGSignBottle::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	InfoWindow iw;
 	iw.player = h->getOwner();
 	iw.text = message;
-	cb->showInfoDialog(&iw);
+	gameEvents.showInfoDialog(&iw);
 
 	if(ID == Obj::OCEAN_BOTTLE)
-		cb->removeObject(this, h->getOwner());
+		gameEvents.removeObject(this, h->getOwner());
 }
 
 void CGSignBottle::serializeJsonOptions(JsonSerializeFormat& handler)
@@ -875,20 +876,20 @@ std::vector<CreatureID> CGGarrison::providedCreatures() const
 	return {};
 }
 
-void CGGarrison::onHeroVisit (const CGHeroInstance *h) const
+void CGGarrison::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	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);
+		gameEvents.startBattle(h, this);
 		return;
 	}
 
 	//New owner.
 	if (relations == PlayerRelations::ENEMIES)
-		cb->setOwner(this, h->tempOwner);
+		gameEvents.setOwner(this, h->tempOwner);
 
-	cb->showGarrisonDialog(id, h->id, removableUnits);
+	gameEvents.showGarrisonDialog(id, h->id, removableUnits);
 }
 
 bool CGGarrison::passableFor(PlayerColor player) const
@@ -905,10 +906,10 @@ bool CGGarrison::passableFor(PlayerColor player) const
 	return false;
 }
 
-void CGGarrison::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
+void CGGarrison::battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const
 {
 	if (result.winner == BattleSide::ATTACKER)
-		onHeroVisit(hero);
+		onHeroVisit(gameEvents, hero);
 }
 
 void CGGarrison::serializeJsonOptions(JsonSerializeFormat& handler)
@@ -941,11 +942,11 @@ void CGMagi::initObj(vstd::RNG & rand)
 		blockVisit = true;
 }
 
-void CGMagi::onHeroVisit(const CGHeroInstance * h) const
+void CGMagi::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	if (ID == Obj::HUT_OF_MAGI)
 	{
-		h->showInfoDialog(61);
+		h->showInfoDialog(gameEvents, 61);
 
 		std::vector<const CGObjectInstance *> eyes;
 
@@ -969,23 +970,23 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const
 			for(const auto & eye : eyes)
 			{
 				cb->getTilesInRange (fw.tiles, eye->visitablePos(), 10, ETileVisibility::HIDDEN, h->tempOwner);
-				cb->sendAndApply(fw);
+				gameEvents.sendAndApply(fw);
 				cv.pos = eye->visitablePos();
 
-				cb->sendAndApply(cv);
+				gameEvents.sendAndApply(cv);
 			}
 			cv.pos = h->visitablePos();
 			cv.focusTime = 0;
-			cb->sendAndApply(cv);
+			gameEvents.sendAndApply(cv);
 		}
 	}
 	else if (ID == Obj::EYE_OF_MAGI)
 	{
-		h->showInfoDialog(48);
+		h->showInfoDialog(gameEvents, 48);
 	}
 }
 
-CGBoat::CGBoat(IGameCallback * cb)
+CGBoat::CGBoat(CPrivilegedInfoCallback * cb)
 	: CGObjectInstance(cb)
 {
 	direction = 4;
@@ -1023,7 +1024,7 @@ std::string CGSirens::getHoverText(const CGHeroInstance * hero) const
 	return getObjectName() + " " + visitedTxt(hero->hasBonusFrom(BonusSource::OBJECT_TYPE, BonusSourceID(ID)));
 }
 
-void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
+void CGSirens::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	InfoWindow iw;
 	iw.player = h->tempOwner;
@@ -1034,7 +1035,7 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
 	}
 	else
 	{
-		giveDummyBonus(h->id, BonusDuration::ONE_BATTLE);
+		giveDummyBonus(gameEvents, h->id, BonusDuration::ONE_BATTLE);
 		TExpType xp = 0;
 
 		for (auto i = h->Slots().begin(); i != h->Slots().end(); i++)
@@ -1048,7 +1049,7 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
 
 			if(drown)
 			{
-				cb->changeStackCount(StackLocation(h->id, i->first), -drown);
+				gameEvents.changeStackCount(StackLocation(h->id, i->first), -drown);
 				xp += drown * i->second->getType()->getMaxHealth();
 			}
 		}
@@ -1058,14 +1059,14 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
 			xp = h->calculateXp(static_cast<int>(xp));
 			iw.text.appendLocalString(EMetaText::ADVOB_TXT,132);
 			iw.text.replaceNumber(static_cast<int>(xp));
-			cb->giveExperience(h, xp);
+			gameEvents.giveExperience(h, xp);
 		}
 		else
 		{
 			iw.text.appendLocalString(EMetaText::ADVOB_TXT,134);
 		}
 	}
-	cb->showInfoDialog(&iw);
+	gameEvents.showInfoDialog(&iw);
 }
 
 void CGShipyard::getOutOffsets( std::vector<int3> &offsets ) const
@@ -1094,10 +1095,10 @@ const IObjectInterface * CGShipyard::getObject() const
 	return this;
 }
 
-void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
+void CGShipyard::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	if(cb->gameState().getPlayerRelations(tempOwner, h->tempOwner) == PlayerRelations::ENEMIES)
-		cb->setOwner(this, h->tempOwner);
+		gameEvents.setOwner(this, h->tempOwner);
 
 	if(shipyardStatus() != IBoatGenerator::GOOD)
 	{
@@ -1105,11 +1106,11 @@ void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
 		iw.type = EInfoWindowMode::AUTO;
 		iw.player = tempOwner;
 		getProblemText(iw.text, h);
-		cb->showInfoDialog(&iw);
+		gameEvents.showInfoDialog(&iw);
 	}
 	else
 	{
-		cb->showObjectWindow(this, EOpenWindowMode::SHIPYARD_WINDOW, h, false);
+		gameEvents.showObjectWindow(this, EOpenWindowMode::SHIPYARD_WINDOW, h, false);
 	}
 }
 
@@ -1138,12 +1139,12 @@ std::vector<CreatureID> CGShipyard::providedCreatures() const
 	return {};
 }
 
-void CGDenOfthieves::onHeroVisit (const CGHeroInstance * h) const
+void CGDenOfthieves::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
-	cb->showObjectWindow(this, EOpenWindowMode::THIEVES_GUILD, h, false);
+	gameEvents.showObjectWindow(this, EOpenWindowMode::THIEVES_GUILD, h, false);
 }
 
-void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
+void CGObelisk::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	InfoWindow iw;
 	iw.type = EInfoWindowMode::AUTO;
@@ -1155,22 +1156,22 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
 	if(!wasVisited(team))
 	{
 		iw.text.appendLocalString(EMetaText::ADVOB_TXT, 96);
-		cb->sendAndApply(iw);
+		gameEvents.sendAndApply(iw);
 
 		// increment general visited obelisks counter
-		cb->setObjPropertyID(id, ObjProperty::OBELISK_VISITED, team);
-		cb->showObjectWindow(this, EOpenWindowMode::PUZZLE_MAP, h, false);
+		gameEvents.setObjPropertyID(id, ObjProperty::OBELISK_VISITED, team);
+		gameEvents.showObjectWindow(this, EOpenWindowMode::PUZZLE_MAP, h, false);
 
 		// mark that particular obelisk as visited for all players in the team
 		for(const auto & color : ts->players)
 		{
-			cb->setObjPropertyID(id, ObjProperty::VISITED, color);
+			gameEvents.setObjPropertyID(id, ObjProperty::VISITED, color);
 		}
 	}
 	else
 	{
 		iw.text.appendLocalString(EMetaText::ADVOB_TXT, 97);
-		cb->sendAndApply(iw);
+		gameEvents.sendAndApply(iw);
 	}
 
 }
@@ -1213,9 +1214,9 @@ void CGObelisk::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
 	}
 }
 
-void HillFort::onHeroVisit(const CGHeroInstance * h) const
+void HillFort::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
-	cb->showObjectWindow(this, EOpenWindowMode::HILL_FORT_WINDOW, h, false);
+	gameEvents.showObjectWindow(this, EOpenWindowMode::HILL_FORT_WINDOW, h, false);
 }
 
 void HillFort::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const

+ 26 - 26
lib/mapObjects/MiscObjects.h

@@ -49,7 +49,7 @@ public:
 
 	MetaString message;
 
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	void initObj(vstd::RNG & rand) override;
 
 	template <typename Handler> void serialize(Handler &h)
@@ -70,8 +70,8 @@ public:
 
 	void initObj(vstd::RNG &rand) override;
 	bool passableFor(PlayerColor color) const override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
-	void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
+	void battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const override;
 
 	const IOwnableObject * asOwnable() const final;
 	ResourceSet dailyIncome() const override;
@@ -96,16 +96,16 @@ public:
 
 	MetaString message;
 
-	void onHeroVisit(const CGHeroInstance * h) const override;
-	void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
-	void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
+	void battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const override;
+	void blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const override;
 
 	std::string getObjectName() const override;
 	std::string getPopupText(PlayerColor player) const override;
 	std::string getPopupText(const CGHeroInstance * hero) const override;
 	std::vector<Component> getPopupComponents(PlayerColor player) const override;
 
-	void pick( const CGHeroInstance * h ) const;
+	void pick(IGameEventCallback & gameEvents, const CGHeroInstance * h) const;
 	void initObj(vstd::RNG & rand) override;
 	void pickRandomObject(vstd::RNG & rand) override;
 
@@ -146,11 +146,11 @@ public:
 private:
 	using CArmedInstance::CArmedInstance;
 
-	void onHeroVisit(const CGHeroInstance * h) const override;
-	void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
-	void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
+	void battleFinished(IGameEventCallback & gameEvents, const CGHeroInstance *hero, const BattleResult &result) const override;
+	void blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const override;
 
-	void flagMine(const PlayerColor & player) const;
+	void flagMine(IGameEventCallback & gameEvents, const PlayerColor & player) const;
 	void initObj(vstd::RNG & rand) override;
 
 	std::string getObjectName() const override;
@@ -200,7 +200,7 @@ protected:
 	enum EType {UNKNOWN, ENTRANCE, EXIT, BOTH};
 	EType type = EType::UNKNOWN;
 
-	ObjectInstanceID getRandomExit(const CGHeroInstance * h) const;
+	ObjectInstanceID getRandomExit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const;
 
 
 public:
@@ -214,7 +214,7 @@ public:
 	std::vector<ObjectInstanceID> getAllEntrances(bool excludeCurrent = false) const;
 	std::vector<ObjectInstanceID> getAllExits(bool excludeCurrent = false) const;
 
-	virtual void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const = 0;
+	virtual void teleportDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const = 0;
 
 	static bool isTeleport(const CGObjectInstance * dst);
 	static bool isConnected(const CGTeleport * src, const CGTeleport * dst);
@@ -236,8 +236,8 @@ class DLL_LINKAGE CGMonolith : public CGTeleport
 	TeleportChannelID findMeChannel(const std::vector<Obj> & IDs, MapObjectSubID SubID) const;
 
 protected:
-	void onHeroVisit(const CGHeroInstance * h) const override;
-	void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
+	void teleportDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const override;
 	void initObj(vstd::RNG & rand) override;
 
 public:
@@ -251,13 +251,13 @@ public:
 
 class DLL_LINKAGE CGSubterraneanGate : public CGMonolith
 {
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	void initObj(vstd::RNG & rand) override;
 
 public:
 	using CGMonolith::CGMonolith;
 
-	static void postInit(IGameCallback * cb);
+	static void postInit(CPrivilegedInfoCallback * cb);
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -267,8 +267,8 @@ public:
 
 class DLL_LINKAGE CGWhirlpool : public CGMonolith
 {
-	void onHeroVisit(const CGHeroInstance * h) const override;
-	void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
+	void teleportDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const override;
 	static bool isProtected( const CGHeroInstance * h );
 
 public:
@@ -285,7 +285,7 @@ class DLL_LINKAGE CGSirens : public CGObjectInstance
 public:
 	using CGObjectInstance::CGObjectInstance;
 
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	std::string getHoverText(const CGHeroInstance * hero) const override;
 	void initObj(vstd::RNG & rand) override;
 
@@ -312,7 +312,7 @@ public:
 	AnimationPath overlayAnimation; //waves animations
 	std::array<AnimationPath, PlayerColor::PLAYER_LIMIT_I> flagAnimations;
 
-	CGBoat(IGameCallback * cb);
+	CGBoat(CPrivilegedInfoCallback * cb);
 	bool isCoastVisitable() const override;
 
 	void setBoardedHero(const CGHeroInstance * hero);
@@ -351,7 +351,7 @@ class DLL_LINKAGE CGShipyard : public CGObjectInstance, public IShipyard, public
 
 protected:
 	void getOutOffsets(std::vector<int3> & offsets) const override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	const IObjectInterface * getObject() const override;
 	BoatId getBoatType() const override;
 
@@ -378,7 +378,7 @@ public:
 	using CGObjectInstance::CGObjectInstance;
 
 	void initObj(vstd::RNG & rand) override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -388,7 +388,7 @@ public:
 
 class DLL_LINKAGE CGDenOfthieves : public CGObjectInstance
 {
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 public:
 	using CGObjectInstance::CGObjectInstance;
 };
@@ -398,7 +398,7 @@ class DLL_LINKAGE CGObelisk : public CTeamVisited
 public:
 	using CTeamVisited::CTeamVisited;
 
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	void initObj(vstd::RNG & rand) override;
 	std::string getHoverText(PlayerColor player) const override;
 	std::string getObjectDescription(PlayerColor player) const;
@@ -429,7 +429,7 @@ class DLL_LINKAGE HillFort : public CGObjectInstance, public ICreatureUpgrader
 	std::vector<int> upgradeCostPercentage;
 
 protected:
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	void fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const override;
 
 public:

+ 21 - 20
lib/mapObjects/TownBuildingInstance.cpp

@@ -12,7 +12,8 @@
 #include "TownBuildingInstance.h"
 
 #include "CGTownInstance.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../entities/building/CBuilding.h"
 
@@ -20,7 +21,7 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-TownBuildingInstance::TownBuildingInstance(IGameCallback * cb)
+TownBuildingInstance::TownBuildingInstance(CPrivilegedInfoCallback * cb)
 	: IObjectInterface(cb)
 	, town(nullptr)
 {}
@@ -61,7 +62,7 @@ int3 TownBuildingInstance::anchorPos() const
 	return town->anchorPos();
 }
 
-TownRewardableBuildingInstance::TownRewardableBuildingInstance(IGameCallback *cb)
+TownRewardableBuildingInstance::TownRewardableBuildingInstance(CPrivilegedInfoCallback *cb)
 	: TownBuildingInstance(cb)
 {}
 
@@ -108,16 +109,16 @@ Rewardable::Configuration TownRewardableBuildingInstance::generateConfiguration(
 	return result;
 }
 
-void TownRewardableBuildingInstance::newTurn(vstd::RNG & rand) const
+void TownRewardableBuildingInstance::newTurn(IGameEventCallback & gameEvents) const
 {
 	if (configuration.resetParameters.period != 0 && cb->getDate(Date::DAY) > 1 && ((cb->getDate(Date::DAY)-1) % configuration.resetParameters.period) == 0)
 	{
-		auto newConfiguration = generateConfiguration(rand);
-		cb->setRewardableObjectConfiguration(town->id, getBuildingType(), newConfiguration);
+		auto newConfiguration = generateConfiguration(gameEvents.getRandomGenerator());
+		gameEvents.setRewardableObjectConfiguration(town->id, getBuildingType(), newConfiguration);
 
 		if(configuration.resetParameters.visitors)
 		{
-			cb->setObjPropertyValue(town->id, ObjProperty::STRUCTURE_CLEAR_VISITORS, getBuildingType().getNum());
+			gameEvents.setObjPropertyValue(town->id, ObjProperty::STRUCTURE_CLEAR_VISITORS, getBuildingType().getNum());
 		}
 	}
 }
@@ -138,24 +139,24 @@ void TownRewardableBuildingInstance::setProperty(ObjProperty what, ObjPropertyID
 	}
 }
 
-void TownRewardableBuildingInstance::heroLevelUpDone(const CGHeroInstance *hero) const
+void TownRewardableBuildingInstance::heroLevelUpDone(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const
 {
-	grantRewardAfterLevelup(configuration.info.at(selectedReward), town, hero);
+	grantRewardAfterLevelup(gameEvents, configuration.info.at(selectedReward), town, hero);
 }
 
-void TownRewardableBuildingInstance::blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const
+void TownRewardableBuildingInstance::blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const
 {
-	onBlockingDialogAnswered(hero, answer);
+	onBlockingDialogAnswered(gameEvents, hero, answer);
 }
 
-void TownRewardableBuildingInstance::grantReward(ui32 rewardID, const CGHeroInstance * hero) const
+void TownRewardableBuildingInstance::grantReward(IGameEventCallback & gameEvents, ui32 rewardID, const CGHeroInstance * hero) const
 {
-	grantRewardBeforeLevelup(configuration.info.at(rewardID), hero);
+	grantRewardBeforeLevelup(gameEvents, configuration.info.at(rewardID), hero);
 	
 	// hero is not blocked by levelup dialog - grant remainder immediately
-	if(!cb->isVisitCoveredByAnotherQuery(town, hero))
+	if(!gameEvents.isVisitCoveredByAnotherQuery(town, hero))
 	{
-		grantRewardAfterLevelup(configuration.info.at(rewardID), town, hero);
+		grantRewardAfterLevelup(gameEvents, configuration.info.at(rewardID), town, hero);
 	}
 }
 
@@ -192,12 +193,12 @@ bool TownRewardableBuildingInstance::wasVisitedBefore(const CGHeroInstance * con
 	}
 }
 
-void TownRewardableBuildingInstance::onHeroVisit(const CGHeroInstance *h) const
+void TownRewardableBuildingInstance::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 	assert(town->hasBuilt(getBuildingType()));
 
 	if(town->hasBuilt(getBuildingType()))
-		doHeroVisit(h);
+		doHeroVisit(gameEvents, h);
 }
 
 const IObjectInterface * TownRewardableBuildingInstance::getObject() const
@@ -223,12 +224,12 @@ bool TownRewardableBuildingInstance::wasVisited(PlayerColor player) const
 	}
 }
 
-void TownRewardableBuildingInstance::markAsVisited(const CGHeroInstance * hero) const
+void TownRewardableBuildingInstance::markAsVisited(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const
 {
-	town->addHeroToStructureVisitors(hero, getBuildingType().getNum());
+	town->addHeroToStructureVisitors(gameEvents, hero, getBuildingType().getNum());
 }
 
-void TownRewardableBuildingInstance::markAsScouted(const CGHeroInstance * hero) const
+void TownRewardableBuildingInstance::markAsScouted(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const
 {
 	// no-op - town building is always 'scouted' by owner
 }

+ 9 - 9
lib/mapObjects/TownBuildingInstance.h

@@ -23,7 +23,7 @@ class DLL_LINKAGE TownBuildingInstance : public IObjectInterface
 ///basic class for town structures handled as map objects
 public:
 	TownBuildingInstance(CGTownInstance * town, const BuildingID & index);
-	TownBuildingInstance(IGameCallback *cb);
+	TownBuildingInstance(CPrivilegedInfoCallback *cb);
 
 	CGTownInstance * town;
 
@@ -56,29 +56,29 @@ class DLL_LINKAGE TownRewardableBuildingInstance : public TownBuildingInstance,
 	std::set<ObjectInstanceID> visitors;
 
 	bool wasVisitedBefore(const CGHeroInstance * contextHero) const override;
-	void grantReward(ui32 rewardID, const CGHeroInstance * hero) const override;
+	void grantReward(IGameEventCallback & gameEvents, ui32 rewardID, const CGHeroInstance * hero) const override;
 	Rewardable::Configuration generateConfiguration(vstd::RNG & rand) const;
 	void assignBonuses(std::vector<Bonus> & bonuses) const;
 
 	const IObjectInterface * getObject() const override;
 	bool wasVisited(PlayerColor player) const override;
-	void markAsVisited(const CGHeroInstance * hero) const override;
-	void markAsScouted(const CGHeroInstance * hero) const override;
+	void markAsVisited(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const override;
+	void markAsScouted(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const override;
 public:
 	void setProperty(ObjProperty what, ObjPropertyID identifier) override;
-	void onHeroVisit(const CGHeroInstance * h) const override;
+	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override;
 	bool wasVisited(const CGHeroInstance * contextHero) const override;
 	
-	void newTurn(vstd::RNG & rand) const override;
+	void newTurn(IGameEventCallback & gameEvents) const override;
 	
 	/// gives second part of reward after hero level-ups for proper granting of spells/mana
-	void heroLevelUpDone(const CGHeroInstance *hero) const override;
+	void heroLevelUpDone(IGameEventCallback & gameEvents, const CGHeroInstance *hero) const override;
 	
 	/// applies player selection of reward
-	void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
+	void blockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance *hero, int32_t answer) const override;
 	
 	TownRewardableBuildingInstance(CGTownInstance * town, const BuildingID & index, vstd::RNG & rand);
-	TownRewardableBuildingInstance(IGameCallback *cb);
+	TownRewardableBuildingInstance(CPrivilegedInfoCallback *cb);
 	
 	template <typename Handler> void serialize(Handler &h)
 	{

+ 2 - 2
lib/mapping/CMap.cpp

@@ -21,7 +21,7 @@
 #include "../RoadHandler.h"
 #include "../TerrainHandler.h"
 
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
 #include "../entities/artifact/CArtHandler.h"
 #include "../entities/hero/CHeroHandler.h"
 #include "../gameState/CGameState.h"
@@ -170,7 +170,7 @@ EDiggingStatus TerrainTile::getDiggingStatus(const bool excludeTop) const
 		return EDiggingStatus::CAN_DIG;
 }
 
-CMap::CMap(IGameCallback * cb)
+CMap::CMap(CPrivilegedInfoCallback * cb)
 	: GameCallbackHolder(cb)
 	, grailPos(-1, -1, -1)
 	, grailRadius(0)

+ 1 - 1
lib/mapping/CMap.h

@@ -80,7 +80,7 @@ public:
 	/// TODO: make private
 	std::vector<std::shared_ptr<CGObjectInstance>> objects;
 
-	explicit CMap(IGameCallback *cb);
+	explicit CMap(CPrivilegedInfoCallback *cb);
 	~CMap();
 	void initTerrain();
 

+ 2 - 2
lib/mapping/CMapService.cpp

@@ -30,7 +30,7 @@
 VCMI_LIB_NAMESPACE_BEGIN
 
 
-std::unique_ptr<CMap> CMapService::loadMap(const ResourcePath & name, IGameCallback * cb) const
+std::unique_ptr<CMap> CMapService::loadMap(const ResourcePath & name, CPrivilegedInfoCallback * cb) const
 {
 	std::string modName = LIBRARY->modh->findResourceOrigin(name);
 	std::string encoding = LIBRARY->modh->findResourceEncoding(name);
@@ -48,7 +48,7 @@ std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const ResourcePath & name
 	return getMapLoader(stream, name.getName(), modName, encoding)->loadMapHeader();
 }
 
-std::unique_ptr<CMap> CMapService::loadMap(const uint8_t * buffer, int size, const std::string & name,  const std::string & modName, const std::string & encoding, IGameCallback * cb) const
+std::unique_ptr<CMap> CMapService::loadMap(const uint8_t * buffer, int size, const std::string & name,  const std::string & modName, const std::string & encoding, CPrivilegedInfoCallback * cb) const
 {
 	auto stream = getStreamFromMem(buffer, size);
 	std::unique_ptr<CMap> map(getMapLoader(stream, name, modName, encoding)->loadMap(cb));

+ 6 - 6
lib/mapping/CMapService.h

@@ -22,7 +22,7 @@ class CInputStream;
 
 class IMapLoader;
 class IMapPatcher;
-class IGameCallback;
+class CPrivilegedInfoCallback;
 
 /**
  * The map service provides loading of VCMI/H3 map files. It can
@@ -39,7 +39,7 @@ public:
 	 * @param name the name of the map
 	 * @return a unique ptr to the loaded map class
 	 */
-	virtual std::unique_ptr<CMap> loadMap(const ResourcePath & name, IGameCallback * cb) const = 0;
+	virtual std::unique_ptr<CMap> loadMap(const ResourcePath & name, CPrivilegedInfoCallback * cb) const = 0;
 
 	/**
 	 * Loads the VCMI/H3 map header specified by the name.
@@ -56,7 +56,7 @@ public:
 	 * @param name indicates name of file that will be used during map header patching
 	 * @return a unique ptr to the loaded map class
 	 */
-	virtual std::unique_ptr<CMap> loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding, IGameCallback * cb) const = 0;
+	virtual std::unique_ptr<CMap> loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding, CPrivilegedInfoCallback * cb) const = 0;
 
 	/**
 	 * Loads the VCMI/H3 map header from a buffer. This method is temporarily
@@ -81,9 +81,9 @@ public:
 	CMapService() = default;
 	virtual ~CMapService() = default;
 
-	std::unique_ptr<CMap> loadMap(const ResourcePath & name, IGameCallback * cb) const override;
+	std::unique_ptr<CMap> loadMap(const ResourcePath & name, CPrivilegedInfoCallback * cb) const override;
 	std::unique_ptr<CMapHeader> loadMapHeader(const ResourcePath & name) const override;
-	std::unique_ptr<CMap> loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding, IGameCallback * cb) const override;
+	std::unique_ptr<CMap> loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding, CPrivilegedInfoCallback * cb) const override;
 	std::unique_ptr<CMapHeader> loadMapHeader(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override;
 	void saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath) const override;
 	
@@ -141,7 +141,7 @@ public:
 	 *
 	 * @return a unique ptr of the loaded map class
 	 */
-	virtual std::unique_ptr<CMap> loadMap(IGameCallback * cb) = 0;
+	virtual std::unique_ptr<CMap> loadMap(CPrivilegedInfoCallback * cb) = 0;
 
 	/**
 	 * Loads the VCMI/H3 map header.

+ 1 - 1
lib/mapping/MapFormatH3M.cpp

@@ -72,7 +72,7 @@ CMapLoaderH3M::CMapLoaderH3M(const std::string & mapName, const std::string & mo
 //must be instantiated in .cpp file for access to complete types of all member fields
 CMapLoaderH3M::~CMapLoaderH3M() = default;
 
-std::unique_ptr<CMap> CMapLoaderH3M::loadMap(IGameCallback * cb)
+std::unique_ptr<CMap> CMapLoaderH3M::loadMap(CPrivilegedInfoCallback * cb)
 {
 	// Init map object by parsing the input buffer
 	map = new CMap(cb);

+ 1 - 1
lib/mapping/MapFormatH3M.h

@@ -86,7 +86,7 @@ public:
 	 *
 	 * @return a unique ptr of the loaded map class
 	 */
-	std::unique_ptr<CMap> loadMap(IGameCallback * cb) override;
+	std::unique_ptr<CMap> loadMap(CPrivilegedInfoCallback * cb) override;
 
 	/**
 	 * Loads the VCMI/H3 map header.

+ 1 - 1
lib/mapping/MapFormatJson.cpp

@@ -767,7 +767,7 @@ CMapLoaderJson::CMapLoaderJson(CInputStream * stream)
 {
 }
 
-std::unique_ptr<CMap> CMapLoaderJson::loadMap(IGameCallback * cb)
+std::unique_ptr<CMap> CMapLoaderJson::loadMap(CPrivilegedInfoCallback * cb)
 {
 	LOG_TRACE(logGlobal);
 	auto result = std::make_unique<CMap>(cb);

+ 1 - 1
lib/mapping/MapFormatJson.h

@@ -167,7 +167,7 @@ public:
 	 *
 	 * @return a unique ptr of the loaded map class
 	 */
-	std::unique_ptr<CMap> loadMap(IGameCallback * cb) override;
+	std::unique_ptr<CMap> loadMap(CPrivilegedInfoCallback * cb) override;
 
 	/**
 	 * Loads the VCMI/Json map header.

+ 2 - 2
lib/mapping/ObstacleProxy.cpp

@@ -230,7 +230,7 @@ bool ObstacleProxy::isProhibited(const rmg::Area& objArea) const
 	return false;
 };
 
-int ObstacleProxy::getWeightedObjects(const int3 & tile, vstd::RNG & rand, IGameCallback * cb, std::list<rmg::Object> & allObjects, std::vector<std::pair<rmg::Object*, int3>> & weightedObjects)
+int ObstacleProxy::getWeightedObjects(const int3 & tile, vstd::RNG & rand, CPrivilegedInfoCallback * cb, std::list<rmg::Object> & allObjects, std::vector<std::pair<rmg::Object*, int3>> & weightedObjects)
 {
 	int maxWeight = std::numeric_limits<int>::min();
 	for(auto & possibleObstacle : possibleObstacles)
@@ -311,7 +311,7 @@ int ObstacleProxy::getWeightedObjects(const int3 & tile, vstd::RNG & rand, IGame
 	return maxWeight;
 }
 
-std::set<std::shared_ptr<CGObjectInstance>> ObstacleProxy::createObstacles(vstd::RNG & rand, IGameCallback * cb)
+std::set<std::shared_ptr<CGObjectInstance>> ObstacleProxy::createObstacles(vstd::RNG & rand, CPrivilegedInfoCallback * cb)
 {
 	//reverse order, since obstacles begin in bottom-right corner, while the map coordinates begin in top-left
 	auto blockedTiles = blockedArea.getTilesVector();

+ 3 - 3
lib/mapping/ObstacleProxy.h

@@ -18,7 +18,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 class CMapEditManager;
 class CGObjectInstance;
 class ObjectTemplate;
-class IGameCallback;
+class CPrivilegedInfoCallback;
 class ObstacleSetFilter;
 
 class DLL_LINKAGE ObstacleProxy
@@ -43,7 +43,7 @@ public:
 
 	virtual void placeObject(rmg::Object & object, std::set<std::shared_ptr<CGObjectInstance>> & instances);
 
-	virtual std::set<std::shared_ptr<CGObjectInstance>> createObstacles(vstd::RNG & rand, IGameCallback * cb);
+	virtual std::set<std::shared_ptr<CGObjectInstance>> createObstacles(vstd::RNG & rand, CPrivilegedInfoCallback * cb);
 
 	virtual bool isInTheMap(const int3& tile) = 0;
 	
@@ -52,7 +52,7 @@ public:
 	virtual void postProcess(const rmg::Object& object) {};
 
 protected:
-	int getWeightedObjects(const int3& tile, vstd::RNG& rand, IGameCallback * cb, std::list<rmg::Object>& allObjects, std::vector<std::pair<rmg::Object*, int3>>& weightedObjects);
+	int getWeightedObjects(const int3& tile, vstd::RNG& rand, CPrivilegedInfoCallback * cb, std::list<rmg::Object>& allObjects, std::vector<std::pair<rmg::Object*, int3>>& weightedObjects);
 	void sortObstacles();
 
 	rmg::Area blockedArea;

+ 1 - 1
lib/pathfinder/CPathfinder.cpp

@@ -20,7 +20,7 @@
 #include "../CPlayerState.h"
 #include "../TerrainHandler.h"
 #include "../RoadHandler.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../mapObjects/CGTownInstance.h"
 #include "../mapObjects/MiscObjects.h"

+ 1 - 1
lib/pathfinder/TurnInfo.cpp

@@ -14,7 +14,7 @@
 #include "../TerrainHandler.h"
 #include "../GameLibrary.h"
 #include "../bonuses/BonusList.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
 #include "../json/JsonNode.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../mapObjects/MiscObjects.h"

+ 6 - 6
lib/rewardable/Info.cpp

@@ -108,7 +108,7 @@ void Rewardable::Info::init(const JsonNode & objectConfig, const std::string & o
 	loadString(parameters["onGuardedMessage"], TextIdentifier(objectName, "onGuarded"));
 }
 
-Rewardable::LimitersList Rewardable::Info::configureSublimiters(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb, const JsonNode & source) const
+Rewardable::LimitersList Rewardable::Info::configureSublimiters(Rewardable::Configuration & object, vstd::RNG & rng, CPrivilegedInfoCallback * cb, const JsonNode & source) const
 {
 	Rewardable::LimitersList result;
 	for (const auto & input : source.Vector())
@@ -123,7 +123,7 @@ Rewardable::LimitersList Rewardable::Info::configureSublimiters(Rewardable::Conf
 	return result;
 }
 
-void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb, Rewardable::Limiter & limiter, const JsonNode & source) const
+void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, vstd::RNG & rng, CPrivilegedInfoCallback * cb, Rewardable::Limiter & limiter, const JsonNode & source) const
 {
 	auto const & variables = object.variables.values;
 	JsonRandom randomizer(cb);
@@ -160,7 +160,7 @@ void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, vstd
 	limiter.noneOf = configureSublimiters(object, rng, cb, source["noneOf"] );
 }
 
-void Rewardable::Info::configureReward(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb, Rewardable::Reward & reward, const JsonNode & source) const
+void Rewardable::Info::configureReward(Rewardable::Configuration & object, vstd::RNG & rng, CPrivilegedInfoCallback * cb, Rewardable::Reward & reward, const JsonNode & source) const
 {
 	auto const & variables = object.variables.values;
 	JsonRandom randomizer(cb);
@@ -233,7 +233,7 @@ void Rewardable::Info::configureResetInfo(Rewardable::Configuration & object, vs
 	resetParameters.rewards  = source["rewards"].Bool();
 }
 
-void Rewardable::Info::configureVariables(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb, const JsonNode & source) const
+void Rewardable::Info::configureVariables(Rewardable::Configuration & object, vstd::RNG & rng, CPrivilegedInfoCallback * cb, const JsonNode & source) const
 {
 	JsonRandom randomizer(cb);
 
@@ -351,7 +351,7 @@ void Rewardable::Info::replaceTextPlaceholders(MetaString & target, const Variab
 void Rewardable::Info::configureRewards(
 		Rewardable::Configuration & object,
 		vstd::RNG & rng,
-		IGameCallback * cb,
+		CPrivilegedInfoCallback * cb,
 		const JsonNode & source,
 		Rewardable::EEventType event,
 		const std::string & modeName) const
@@ -408,7 +408,7 @@ void Rewardable::Info::configureRewards(
 	}
 }
 
-void Rewardable::Info::configureObject(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb) const
+void Rewardable::Info::configureObject(Rewardable::Configuration & object, vstd::RNG & rng, CPrivilegedInfoCallback * cb) const
 {
 	object.info.clear();
 	object.variables.values.clear();

+ 7 - 7
lib/rewardable/Info.h

@@ -21,7 +21,7 @@ class RNG;
 }
 
 class MetaString;
-class IGameCallback;
+class CPrivilegedInfoCallback;
 
 namespace Rewardable
 {
@@ -42,13 +42,13 @@ class DLL_LINKAGE Info : public IObjectInfo
 	void replaceTextPlaceholders(MetaString & target, const Variables & variables) const;
 	void replaceTextPlaceholders(MetaString & target, const Variables & variables, const VisitInfo & info) const;
 
-	void configureVariables(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb, const JsonNode & source) const;
-	void configureRewards(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb, const JsonNode & source, Rewardable::EEventType mode, const std::string & textPrefix) const;
+	void configureVariables(Rewardable::Configuration & object, vstd::RNG & rng, CPrivilegedInfoCallback * cb, const JsonNode & source) const;
+	void configureRewards(Rewardable::Configuration & object, vstd::RNG & rng, CPrivilegedInfoCallback * cb, const JsonNode & source, Rewardable::EEventType mode, const std::string & textPrefix) const;
 
-	void configureLimiter(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb, Rewardable::Limiter & limiter, const JsonNode & source) const;
-	Rewardable::LimitersList configureSublimiters(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb, const JsonNode & source) const;
+	void configureLimiter(Rewardable::Configuration & object, vstd::RNG & rng, CPrivilegedInfoCallback * cb, Rewardable::Limiter & limiter, const JsonNode & source) const;
+	Rewardable::LimitersList configureSublimiters(Rewardable::Configuration & object, vstd::RNG & rng, CPrivilegedInfoCallback * cb, const JsonNode & source) const;
 
-	void configureReward(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb, Rewardable::Reward & info, const JsonNode & source) const;
+	void configureReward(Rewardable::Configuration & object, vstd::RNG & rng, CPrivilegedInfoCallback * cb, Rewardable::Reward & info, const JsonNode & source) const;
 	void configureResetInfo(Rewardable::Configuration & object, vstd::RNG & rng, Rewardable::ResetInfo & info, const JsonNode & source) const;
 public:
 	const JsonNode & getParameters() const;
@@ -70,7 +70,7 @@ public:
 
 	bool hasGuards() const override;
 
-	void configureObject(Rewardable::Configuration & object, vstd::RNG & rng, IGameCallback * cb) const;
+	void configureObject(Rewardable::Configuration & object, vstd::RNG & rng, CPrivilegedInfoCallback * cb) const;
 
 	void init(const JsonNode & objectConfig, const std::string & objectTextID);
 

+ 53 - 52
lib/rewardable/Interface.cpp

@@ -14,7 +14,8 @@
 #include "../TerrainHandler.h"
 #include "../CPlayerState.h"
 #include "../CSoundBase.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
+#include "../callback/IGameEventCallback.h"
 #include "../entities/hero/CHeroHandler.h"
 #include "../gameState/CGameState.h"
 #include "../spells/CSpellHandler.h"
@@ -43,7 +44,7 @@ std::vector<ui32> Rewardable::Interface::getAvailableRewards(const CGHeroInstanc
 	return ret;
 }
 
-void Rewardable::Interface::grantRewardBeforeLevelup(const Rewardable::VisitInfo & info, const CGHeroInstance * hero) const
+void Rewardable::Interface::grantRewardBeforeLevelup(IGameEventCallback & gameEvents, const Rewardable::VisitInfo & info, const CGHeroInstance * hero) const
 {
 	auto cb = getObject()->cb;
 
@@ -51,7 +52,7 @@ void Rewardable::Interface::grantRewardBeforeLevelup(const Rewardable::VisitInfo
 	assert(hero->tempOwner.isValidPlayer());
 	assert(info.reward.creatures.size() <= GameConstants::ARMY_SIZE);
 
-	cb->giveResources(hero->tempOwner, info.reward.resources);
+	gameEvents.giveResources(hero->tempOwner, info.reward.resources);
 
 	if (info.reward.revealTiles)
 	{
@@ -96,12 +97,12 @@ void Rewardable::Interface::grantRewardBeforeLevelup(const Rewardable::VisitInfo
 			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);
+					gameEvents.changeFogOfWar(tiles, player.first, ETileVisibility::HIDDEN);
 			}
 		}
 		else
 		{
-			cb->changeFogOfWar(tiles, hero->getOwner(), ETileVisibility::REVEALED);
+			gameEvents.changeFogOfWar(tiles, hero->getOwner(), ETileVisibility::REVEALED);
 		}
 	}
 
@@ -112,12 +113,12 @@ void Rewardable::Interface::grantRewardBeforeLevelup(const Rewardable::VisitInfo
 			continue;
 
 		if(currentLevel != MasteryLevel::NONE || hero->canLearnSkill())
-			cb->changeSecSkill(hero, entry.first, entry.second, false);
+			gameEvents.changeSecSkill(hero, entry.first, entry.second, false);
 	}
 
 	for(int i=0; i< info.reward.primary.size(); i++)
 		if (info.reward.primary[i] != 0)
-			cb->changePrimSkill(hero, static_cast<PrimarySkill>(i), info.reward.primary[i], false);
+			gameEvents.changePrimSkill(hero, static_cast<PrimarySkill>(i), info.reward.primary[i], false);
 
 	TExpType expToGive = 0;
 
@@ -128,15 +129,15 @@ void Rewardable::Interface::grantRewardBeforeLevelup(const Rewardable::VisitInfo
 		expToGive += hero->calculateXp(info.reward.heroExperience);
 
 	if(expToGive)
-		cb->giveExperience(hero, expToGive);
+		gameEvents.giveExperience(hero, expToGive);
 }
 
-void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo & info, const CArmedInstance * army, const CGHeroInstance * hero) const
+void Rewardable::Interface::grantRewardAfterLevelup(IGameEventCallback & gameEvents, const Rewardable::VisitInfo & info, const CArmedInstance * army, const CGHeroInstance * hero) const
 {
 	auto cb = getObject()->cb;
 
 	if(info.reward.manaDiff || info.reward.manaPercentage >= 0)
-		cb->setManaPoints(hero->id, info.reward.calculateManaPoints(hero));
+		gameEvents.setManaPoints(hero->id, info.reward.calculateManaPoints(hero));
 
 	if(info.reward.movePoints || info.reward.movePercentage >= 0)
 	{
@@ -148,13 +149,13 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 			smp.val = hero->movementPointsLimit(hero->inBoat() && hero->getBoat()->layer == EPathfindingLayer::SAIL) * info.reward.movePercentage / 100;
 		smp.val = std::max<si32>(0, smp.val + info.reward.movePoints);
 
-		cb->setMovePoints(&smp);
+		gameEvents.setMovePoints(&smp);
 	}
 
 	for(const Bonus & bonus : info.reward.heroBonuses)
 	{
 		GiveBonus gb(GiveBonus::ETarget::OBJECT, hero->id, bonus);
-		cb->giveHeroBonus(&gb);
+		gameEvents.giveHeroBonus(&gb);
 	}
 
 	if (hero->getCommander())
@@ -162,14 +163,14 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 		for(const Bonus & bonus : info.reward.commanderBonuses)
 		{
 			GiveBonus gb(GiveBonus::ETarget::HERO_COMMANDER, hero->id, bonus);
-			cb->giveHeroBonus(&gb);
+			gameEvents.giveHeroBonus(&gb);
 		}
 	}
 
 	for(const Bonus & bonus : info.reward.playerBonuses)
 	{
 		GiveBonus gb(GiveBonus::ETarget::PLAYER, hero->getOwner(), bonus);
-		cb->giveHeroBonus(&gb);
+		gameEvents.giveHeroBonus(&gb);
 	}
 
 	for(const ArtifactID & art : info.reward.takenArtifacts)
@@ -182,12 +183,12 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 			{
 				DisassembledArtifact da;
 				da.al = ArtifactLocation(hero->id, hero->getArtPos(assembly));
-				cb->sendAndApply(da);
+				gameEvents.sendAndApply(da);
 			}
 		}
 
 		if(hero->hasArt(art))
-			cb->removeArtifact(ArtifactLocation(hero->id, hero->getArtPos(art, false)));
+			gameEvents.removeArtifact(ArtifactLocation(hero->id, hero->getArtPos(art, false)));
 	}
 
 	for(const ArtifactPosition & slot : info.reward.takenArtifactSlots)
@@ -195,7 +196,7 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 		const auto & slotContent = hero->getSlot(slot);
 
 		if (!slotContent->locked && slotContent->artifactID.hasValue())
-			cb->removeArtifact(ArtifactLocation(hero->id, slot));
+			gameEvents.removeArtifact(ArtifactLocation(hero->id, slot));
 
 		// TODO: handle locked slots?
 	}
@@ -203,14 +204,14 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 	for(const SpellID & spell : info.reward.takenScrolls)
 	{
 		if(hero->hasScroll(spell, false))
-			cb->removeArtifact(ArtifactLocation(hero->id, hero->getScrollPos(spell, false)));
+			gameEvents.removeArtifact(ArtifactLocation(hero->id, hero->getScrollPos(spell, false)));
 	}
 
 	for(const ArtifactID & art : info.reward.grantedArtifacts)
-		cb->giveHeroNewArtifact(hero, art, ArtifactPosition::FIRST_AVAILABLE);
+		gameEvents.giveHeroNewArtifact(hero, art, ArtifactPosition::FIRST_AVAILABLE);
 
 	for(const SpellID & spell : info.reward.grantedScrolls)
-		cb->giveHeroNewScroll(hero, spell, ArtifactPosition::FIRST_AVAILABLE);
+		gameEvents.giveHeroNewScroll(hero, spell, ArtifactPosition::FIRST_AVAILABLE);
 
 	if(!info.reward.spells.empty())
 	{
@@ -221,12 +222,12 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 				spellsToGive.insert(spell);
 
 		if (!spellsToGive.empty())
-			cb->changeSpells(hero, true, spellsToGive);
+			gameEvents.changeSpells(hero, true, spellsToGive);
 	}
 
 	if (!info.reward.takenCreatures.empty())
 	{
-		cb->takeCreatures(hero->id, info.reward.takenCreatures, !info.reward.creatures.empty());
+		gameEvents.takeCreatures(hero->id, info.reward.takenCreatures, !info.reward.creatures.empty());
 	}
 
 	if(!info.reward.creaturesChange.empty())
@@ -240,7 +241,7 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 				if (heroStack->getId() == change.first)
 				{
 					StackLocation location(hero->id, slot.first);
-					cb->changeStackType(location, change.second.toCreature());
+					gameEvents.changeStackType(location, change.second.toCreature());
 					break;
 				}
 			}
@@ -254,19 +255,19 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
 			creatures.addToSlot(creatures.getFreeSlot(), std::make_unique<CStackInstance>(cb, crea.getId(), crea.getCount()));
 
 		if(auto * army = dynamic_cast<const CArmedInstance*>(this)) //TODO: to fix that, CArmedInstance must be split on map instance part and interface part
-			cb->giveCreatures(army, hero, creatures, false);
+			gameEvents.giveCreatures(army, hero, creatures, false);
 	}
 	
 	if(info.reward.spellCast.first != SpellID::NONE)
 	{
 		caster.setActualCaster(hero);
 		caster.setSpellSchoolLevel(info.reward.spellCast.second);
-		cb->castSpell(&caster, info.reward.spellCast.first, int3{-1, -1, -1});
+		gameEvents.castSpell(&caster, info.reward.spellCast.first, int3{-1, -1, -1});
 	}
 
 	if(info.reward.removeObject)
 		if(auto * instance = dynamic_cast<const CGObjectInstance*>(this))
-			cb->removeAfterVisit(instance->id);
+			gameEvents.removeAfterVisit(instance->id);
 }
 
 void Rewardable::Interface::serializeJson(JsonSerializeFormat & handler)
@@ -274,7 +275,7 @@ void Rewardable::Interface::serializeJson(JsonSerializeFormat & handler)
 	configuration.serializeJson(handler);
 }
 
-void Rewardable::Interface::grantRewardWithMessage(const CGHeroInstance * contextHero, int index, bool markAsVisit) const
+void Rewardable::Interface::grantRewardWithMessage(IGameEventCallback & gameEvents, const CGHeroInstance * contextHero, int index, bool markAsVisit) const
 {
 	auto vi = configuration.info.at(index);
 	logGlobal->debug("Granting reward %d. Message says: %s", index, vi.message.toString());
@@ -287,21 +288,21 @@ void Rewardable::Interface::grantRewardWithMessage(const CGHeroInstance * contex
 		vi.reward.loadComponents(iw.components, contextHero);
 		iw.type = configuration.infoWindowType;
 		if(!iw.components.empty() || !iw.text.toString().empty())
-			getObject()->cb->showInfoDialog(&iw);
+			gameEvents.showInfoDialog(&iw);
 	}
 	// grant reward afterwards. Note that it may remove object
 	if(markAsVisit)
-		markAsVisited(contextHero);
-	grantReward(index, contextHero);
+		markAsVisited(gameEvents, contextHero);
+	grantReward(gameEvents, index, contextHero);
 }
 
-void Rewardable::Interface::selectRewardWithMessage(const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices, const MetaString & dialog) const
+void Rewardable::Interface::selectRewardWithMessage(IGameEventCallback & gameEvents, const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices, const MetaString & dialog) const
 {
 	BlockingDialog sd(configuration.canRefuse, rewardIndices.size() > 1);
 	sd.player = contextHero->tempOwner;
 	sd.text = dialog;
 	sd.components = loadComponents(contextHero, rewardIndices);
-	getObject()->cb->showBlockingDialog(getObject(), &sd);
+	gameEvents.showBlockingDialog(getObject(), &sd);
 }
 
 std::vector<Component> Rewardable::Interface::loadComponents(const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices) const
@@ -324,7 +325,7 @@ std::vector<Component> Rewardable::Interface::loadComponents(const CGHeroInstanc
 	return result;
 }
 
-void Rewardable::Interface::grantAllRewardsWithMessage(const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices, bool markAsVisit) const
+void Rewardable::Interface::grantAllRewardsWithMessage(IGameEventCallback & gameEvents, const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices, bool markAsVisit) const
 {
 	if (rewardIndices.empty())
 		return;
@@ -332,14 +333,14 @@ void Rewardable::Interface::grantAllRewardsWithMessage(const CGHeroInstance * co
 	for (auto index : rewardIndices)
 	{
 		// TODO: Merge all rewards of same type, with single message?
-		grantRewardWithMessage(contextHero, index, false);
+		grantRewardWithMessage(gameEvents, contextHero, index, false);
 	}
 	// Mark visited only after all rewards were processed
 	if(markAsVisit)
-		markAsVisited(contextHero);
+		markAsVisited(gameEvents, contextHero);
 }
 
-void Rewardable::Interface::doHeroVisit(const CGHeroInstance *h) const
+void Rewardable::Interface::doHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance *h) const
 {
 	if(!wasVisitedBefore(h))
 	{
@@ -358,7 +359,7 @@ void Rewardable::Interface::doHeroVisit(const CGHeroInstance *h) const
 			{
 				auto emptyRewards = getAvailableRewards(h, Rewardable::EEventType::EVENT_NOT_AVAILABLE);
 				if (!emptyRewards.empty())
-					grantRewardWithMessage(h, emptyRewards[0], false);
+					grantRewardWithMessage(gameEvents, h, emptyRewards[0], false);
 				else
 					logMod->warn("No applicable message for visiting empty object!");
 				break;
@@ -366,34 +367,34 @@ void Rewardable::Interface::doHeroVisit(const CGHeroInstance *h) const
 			case 1: // one reward. Just give it with message
 			{
 				if (configuration.canRefuse)
-					selectRewardWithMessage(h, rewards, configuration.info.at(rewards.front()).message);
+					selectRewardWithMessage(gameEvents, h, rewards, configuration.info.at(rewards.front()).message);
 				else
-					grantRewardWithMessage(h, rewards.front(), true);
+					grantRewardWithMessage(gameEvents, h, rewards.front(), true);
 				break;
 			}
 			default: // multiple rewards. Act according to select mode
 			{
 				switch (configuration.selectMode) {
 					case Rewardable::SELECT_PLAYER: // player must select
-						selectRewardWithMessage(h, rewards, configuration.onSelect);
+						selectRewardWithMessage(gameEvents, h, rewards, configuration.onSelect);
 						break;
 					case Rewardable::SELECT_FIRST: // give first available
 						if (configuration.canRefuse)
-							selectRewardWithMessage(h, { rewards.front() }, configuration.info.at(rewards.front()).message);
+							selectRewardWithMessage(gameEvents, h, { rewards.front() }, configuration.info.at(rewards.front()).message);
 						else
-							grantRewardWithMessage(h, rewards.front(), true);
+							grantRewardWithMessage(gameEvents, h, rewards.front(), true);
 						break;
 					case Rewardable::SELECT_RANDOM: // give random
 					{
-						ui32 rewardIndex = *RandomGeneratorUtil::nextItem(rewards, getObject()->cb->getRandomGenerator());
+						ui32 rewardIndex = *RandomGeneratorUtil::nextItem(rewards, gameEvents.getRandomGenerator());
 						if (configuration.canRefuse)
-							selectRewardWithMessage(h, { rewardIndex }, configuration.info.at(rewardIndex).message);
+							selectRewardWithMessage(gameEvents, h, { rewardIndex }, configuration.info.at(rewardIndex).message);
 						else
-							grantRewardWithMessage(h, rewardIndex, true);
+							grantRewardWithMessage(gameEvents, h, rewardIndex, true);
 						break;
 					}
 					case Rewardable::SELECT_ALL: // grant all possible
-						grantAllRewardsWithMessage(h, rewards, true);
+						grantAllRewardsWithMessage(gameEvents, h, rewards, true);
 						break;
 				}
 				break;
@@ -401,24 +402,24 @@ void Rewardable::Interface::doHeroVisit(const CGHeroInstance *h) const
 		}
 
 		if(!objectRemovalPossible && getAvailableRewards(h, Rewardable::EEventType::EVENT_FIRST_VISIT).empty())
-			markAsScouted(h);
+			markAsScouted(gameEvents, h);
 	}
 	else
 	{
 		logGlobal->debug("Revisiting already visited object");
 
 		if (!wasVisited(h->getOwner()))
-			markAsScouted(h);
+			markAsScouted(gameEvents, h);
 
 		auto visitedRewards = getAvailableRewards(h, Rewardable::EEventType::EVENT_ALREADY_VISITED);
 		if (!visitedRewards.empty())
-			grantRewardWithMessage(h, visitedRewards[0], false);
+			grantRewardWithMessage(gameEvents, h, visitedRewards[0], false);
 		else
 			logMod->warn("No applicable message for visiting already visited object!");
 	}
 }
 
-void Rewardable::Interface::onBlockingDialogAnswered(const CGHeroInstance * hero, int32_t answer) const
+void Rewardable::Interface::onBlockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance * hero, int32_t answer) const
 {
 	if (answer == 0)
 		return; //Player refused
@@ -426,8 +427,8 @@ void Rewardable::Interface::onBlockingDialogAnswered(const CGHeroInstance * hero
 	if(answer > 0 && answer - 1 < configuration.info.size())
 	{
 		auto list = getAvailableRewards(hero, Rewardable::EEventType::EVENT_FIRST_VISIT);
-		markAsVisited(hero);
-		grantReward(list[answer - 1], hero);
+		markAsVisited(gameEvents, hero);
+		grantReward(gameEvents, list[answer - 1], hero);
 	}
 	else
 	{

+ 10 - 10
lib/rewardable/Interface.h

@@ -30,26 +30,26 @@ private:
 protected:
 	
 	/// function that must be called if hero got level-up during grantReward call
-	void grantRewardAfterLevelup(const Rewardable::VisitInfo & reward, const CArmedInstance * army, const CGHeroInstance * hero) const;
+	void grantRewardAfterLevelup(IGameEventCallback & gameEvents, const Rewardable::VisitInfo & reward, const CArmedInstance * army, const CGHeroInstance * hero) const;
 
 	/// grants reward to hero
-	void grantRewardBeforeLevelup(const Rewardable::VisitInfo & reward, const CGHeroInstance * hero) const;
+	void grantRewardBeforeLevelup(IGameEventCallback & gameEvents, const Rewardable::VisitInfo & reward, const CGHeroInstance * hero) const;
 	
-	virtual void grantRewardWithMessage(const CGHeroInstance * contextHero, int rewardIndex, bool markAsVisit) const;
-	void selectRewardWithMessage(const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices, const MetaString & dialog) const;
-	void grantAllRewardsWithMessage(const CGHeroInstance * contextHero, const std::vector<ui32>& rewardIndices, bool markAsVisit) const;
+	virtual void grantRewardWithMessage(IGameEventCallback & gameEvents, const CGHeroInstance * contextHero, int rewardIndex, bool markAsVisit) const;
+	void selectRewardWithMessage(IGameEventCallback & gameEvents, const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices, const MetaString & dialog) const;
+	void grantAllRewardsWithMessage(IGameEventCallback & gameEvents, const CGHeroInstance * contextHero, const std::vector<ui32>& rewardIndices, bool markAsVisit) const;
 	std::vector<Component> loadComponents(const CGHeroInstance * contextHero, const std::vector<ui32> & rewardIndices) const;
 
-	void doHeroVisit(const CGHeroInstance *h) const;
+	void doHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance *h) const;
 
 	virtual const IObjectInterface * getObject() const = 0;
 	virtual bool wasVisitedBefore(const CGHeroInstance * hero) const = 0;
 	virtual bool wasVisited(PlayerColor player) const = 0;
-	virtual void markAsVisited(const CGHeroInstance * hero) const = 0;
-	virtual void markAsScouted(const CGHeroInstance * hero) const = 0;
-	virtual void grantReward(ui32 rewardID, const CGHeroInstance * hero) const = 0;
+	virtual void markAsVisited(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const = 0;
+	virtual void markAsScouted(IGameEventCallback & gameEvents, const CGHeroInstance * hero) const = 0;
+	virtual void grantReward(IGameEventCallback & gameEvents, ui32 rewardID, const CGHeroInstance * hero) const = 0;
 
-	void onBlockingDialogAnswered(const CGHeroInstance * hero, int32_t answer) const;
+	void onBlockingDialogAnswered(IGameEventCallback & gameEvents, const CGHeroInstance * hero, int32_t answer) const;
 public:
 
 	/// filters list of visit info and returns rewards that can be granted to current hero

+ 1 - 1
lib/rewardable/Limiter.cpp

@@ -13,7 +13,7 @@
 
 #include "../CPlayerState.h"
 #include "../CSkillHandler.h"
-#include "../callback/IGameCallback.h"
+#include "../callback/CPrivilegedInfoCallback.h"
 #include "../constants/StringConstants.h"
 #include "../entities/artifact/ArtifactUtils.h"
 #include "../mapObjects/CGHeroInstance.h"

+ 1 - 1
lib/rmg/CMapGenerator.cpp

@@ -40,7 +40,7 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-CMapGenerator::CMapGenerator(CMapGenOptions& mapGenOptions, IGameCallback * cb, int RandomSeed) :
+CMapGenerator::CMapGenerator(CMapGenOptions& mapGenOptions, CPrivilegedInfoCallback * cb, int RandomSeed) :
 	mapGenOptions(mapGenOptions), randomSeed(RandomSeed),
 	monolithIndex(0),
 	rand(std::make_unique<CRandomGenerator>(RandomSeed))

+ 2 - 2
lib/rmg/CMapGenerator.h

@@ -23,7 +23,7 @@ class RmgMap;
 class CMap;
 class Zone;
 class CZonePlacer;
-class IGameCallback;
+class CPrivilegedInfoCallback;
 
 using JsonVector = std::vector<JsonNode>;
 
@@ -54,7 +54,7 @@ public:
 		bool singleThread;
 	};
 	
-	explicit CMapGenerator(CMapGenOptions& mapGenOptions, IGameCallback * cb, int RandomSeed);
+	explicit CMapGenerator(CMapGenOptions& mapGenOptions, CPrivilegedInfoCallback * cb, int RandomSeed);
 	~CMapGenerator(); // required due to std::unique_ptr
 	
 	const Config & getConfig() const;

+ 1 - 1
lib/rmg/RmgMap.cpp

@@ -39,7 +39,7 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-RmgMap::RmgMap(const CMapGenOptions& mapGenOptions, IGameCallback * cb) :
+RmgMap::RmgMap(const CMapGenOptions& mapGenOptions, CPrivilegedInfoCallback * cb) :
 	mapGenOptions(mapGenOptions), zonesTotal(0)
 {
 	mapInstance = std::make_unique<CMap>(cb);

+ 1 - 1
lib/rmg/RmgMap.h

@@ -38,7 +38,7 @@ public:
 	std::shared_ptr<MapProxy> getMapProxy() const;
 	CMap & getMap(const CMapGenerator *) const; //limited access
 	
-	RmgMap(const CMapGenOptions& mapGenOptions, IGameCallback * cb);
+	RmgMap(const CMapGenOptions& mapGenOptions, CPrivilegedInfoCallback * cb);
 	~RmgMap() = default;
 
 	CMapEditManager* getEditManager() const;

+ 1 - 1
lib/serializer/BinaryDeserializer.h

@@ -23,7 +23,7 @@ public:
 	using Version = ESerializationVersion;
 	static constexpr bool saving = false;
 
-	IGameCallback * cb = nullptr;
+	CPrivilegedInfoCallback * cb = nullptr;
 	Version version = Version::NONE;
 	bool loadingGamestate = false;
 	bool reverseEndianness = false; //if source has different endianness than us, we reverse bytes

+ 1 - 1
lib/serializer/CLoadFile.cpp

@@ -19,7 +19,7 @@ struct static_caster
 };
 
 
-CLoadFile::CLoadFile(const boost::filesystem::path & fname, IGameCallback * cb)
+CLoadFile::CLoadFile(const boost::filesystem::path & fname, CPrivilegedInfoCallback * cb)
 	: serializer(this)
 	, sfile(fname.c_str(), std::ios::in | std::ios::binary)
 {

+ 1 - 1
lib/serializer/CLoadFile.h

@@ -21,7 +21,7 @@ class DLL_LINKAGE CLoadFile : public IBinaryReader
 	int read(std::byte * data, unsigned size) override; //throws!
 
 public:
-	CLoadFile(const boost::filesystem::path & fname, IGameCallback * cb); //throws!
+	CLoadFile(const boost::filesystem::path & fname, CPrivilegedInfoCallback * cb); //throws!
 
 	template<class T>
 	void load(T & data)

+ 1 - 1
lib/serializer/Connection.cpp

@@ -124,7 +124,7 @@ void CConnection::enterLobbyConnectionMode()
 	serializer->clear();
 }
 
-void CConnection::setCallback(IGameCallback * cb)
+void CConnection::setCallback(CPrivilegedInfoCallback * cb)
 {
 	deserializer->cb = cb;
 }

+ 2 - 2
lib/serializer/Connection.h

@@ -20,7 +20,7 @@ class INetworkConnection;
 class ConnectionPackReader;
 class ConnectionPackWriter;
 class CGameState;
-class IGameCallback;
+class CPrivilegedInfoCallback;
 
 /// Wrapper class for game connection
 /// Handles serialization and deserialization of data received from network
@@ -50,7 +50,7 @@ public:
 	std::unique_ptr<CPack> retrievePack(const std::vector<std::byte> & data);
 
 	void enterLobbyConnectionMode();
-	void setCallback(IGameCallback * cb);
+	void setCallback(CPrivilegedInfoCallback * cb);
 	void enterGameplayConnectionMode(CGameState & gs);
 	void setSerializationVersion(ESerializationVersion version);
 };

+ 3 - 3
lib/serializer/SerializerReflection.cpp

@@ -30,12 +30,12 @@ template<typename Type>
 class SerializerReflection final : public ISerializerReflection
 {
 public:
-	Serializeable * createPtr(BinaryDeserializer &ar, IGameCallback * cb) const override
+	Serializeable * createPtr(BinaryDeserializer &ar, CPrivilegedInfoCallback * cb) const override
 	{
 		return ClassObjectCreator<Type>::invoke(cb);
 	}
 
-	void loadPtr(BinaryDeserializer &ar, IGameCallback * cb, Serializeable * data) const override
+	void loadPtr(BinaryDeserializer &ar, CPrivilegedInfoCallback * cb, Serializeable * data) const override
 	{
 		auto * realPtr = dynamic_cast<Type *>(data);
 		realPtr->serialize(ar);
@@ -52,7 +52,7 @@ template<typename Type, ESerializationVersion maxVersion>
 class SerializerCompatibility : public ISerializerReflection
 {
 public:
-	Serializeable * createPtr(BinaryDeserializer &ar, IGameCallback * cb) const override
+	Serializeable * createPtr(BinaryDeserializer &ar, CPrivilegedInfoCallback * cb) const override
 	{
 		return ClassObjectCreator<Type>::invoke(cb);
 	}

+ 5 - 5
lib/serializer/SerializerReflection.h

@@ -11,7 +11,7 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-class IGameCallback;
+class CPrivilegedInfoCallback;
 class Serializeable;
 class GameCallbackHolder;
 class BinaryDeserializer;
@@ -21,7 +21,7 @@ class GameCallbackHolder;
 template <typename T, typename Enable = void>
 struct ClassObjectCreator
 {
-	static T *invoke(IGameCallback *cb)
+	static T *invoke(CPrivilegedInfoCallback *cb)
 	{
 		static_assert(!std::is_base_of_v<GameCallbackHolder, T>, "Cannot call new upon map objects!");
 		static_assert(!std::is_abstract_v<T>, "Cannot call new upon abstract classes!");
@@ -32,7 +32,7 @@ struct ClassObjectCreator
 template<typename T>
 struct ClassObjectCreator<T, typename std::enable_if_t<std::is_base_of_v<GameCallbackHolder, T>>>
 {
-	static T *invoke(IGameCallback *cb)
+	static T *invoke(CPrivilegedInfoCallback *cb)
 	{
 		static_assert(!std::is_abstract_v<T>, "Cannot call new upon abstract classes!");
 		return new T(cb);
@@ -42,8 +42,8 @@ struct ClassObjectCreator<T, typename std::enable_if_t<std::is_base_of_v<GameCal
 class ISerializerReflection
 {
 public:
-	virtual Serializeable * createPtr(BinaryDeserializer &ar, IGameCallback * cb) const =0;
-	virtual void loadPtr(BinaryDeserializer &ar, IGameCallback * cb, Serializeable * data) const =0;
+	virtual Serializeable * createPtr(BinaryDeserializer &ar, CPrivilegedInfoCallback * cb) const =0;
+	virtual void loadPtr(BinaryDeserializer &ar, CPrivilegedInfoCallback * cb, Serializeable * data) const =0;
 	virtual void savePtr(BinarySerializer &ar, const Serializeable *data) const =0;
 	virtual ~ISerializerReflection() = default;
 };

+ 6 - 6
server/CGameHandler.cpp

@@ -549,7 +549,7 @@ void CGameHandler::init(StartInfo *si, Load::ProgressAccumulator & progressTrack
 	gs = std::make_shared<CGameState>(this);
 	gs->preInit(LIBRARY);
 	logGlobal->info("Gamestate created!");
-	gs->init(&mapService, si, progressTracking);
+	gs->init(&mapService, si, getRandomGenerator(), progressTracking);
 	logGlobal->info("Gamestate initialized!");
 
 	for (const auto & elem : gameState().players)
@@ -703,7 +703,7 @@ void CGameHandler::onNewTurn()
 	for (auto & elem : gameState().getMap().getObjects())
 	{
 		if (elem)
-			elem->newTurn(getRandomGenerator());
+			elem->newTurn(*this);
 	}
 
 	synchronizeArtifactHandlerLists(); //new day events may have changed them. TODO better of managing that
@@ -914,7 +914,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
 	auto leaveTile = [&]()
 	{
 		for(const auto & objID : gameState().getMap().getTile(h->visitablePos()).visitableObjects)
-			gameState().getObjInstance(objID)->onHeroLeave(h);
+			gameState().getObjInstance(objID)->onHeroLeave(*this, h);
 
 		this->getTilesInRange(tmh.fowRevealed, h->getSightCenter()+(tmh.end-tmh.start), h->getSightRadius(), ETileVisibility::HIDDEN, h->tempOwner);
 	};
@@ -2539,7 +2539,7 @@ bool CGameHandler::swapGarrisonOnSiege(ObjectInstanceID tid)
 	else //visiting -> garrison
 	{
 		if(town->armedGarrison())
-			town->mergeGarrisonOnSiege();
+			town->mergeGarrisonOnSiege(*this);
 
 		intown.visiting = ObjectInstanceID();
 		intown.garrison = town->getVisitingHero()->id;
@@ -3448,7 +3448,7 @@ void CGameHandler::objectVisited(const CGObjectInstance * obj, const CGHeroInsta
 		hv.starting = true;
 		sendAndApply(hv);
 
-		obj->onHeroVisit(h);
+		obj->onHeroVisit(*this, h);
 	};
 
 	ObjectVisitStarted::defaultExecute(serverEventBus.get(), startVisit, h->tempOwner, h->id, obj->id);
@@ -4323,7 +4323,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(getRandomGenerator());
 
 	NewObject no;
 	no.newObject = object;

Some files were not shown because too many files changed in this diff