فهرست منبع

Split IGameCallback to reduce memory required to debug compilation.

O01eg 11 سال پیش
والد
کامیت
927eb33c11
10فایلهای تغییر یافته به همراه1235 افزوده شده و 1131 حذف شده
  1. 1 1
      CCallback.h
  2. 2 2
      lib/CGameState.h
  3. 1 0
      lib/CMakeLists.txt
  4. 2 2
      lib/CScriptingModule.h
  5. 6 919
      lib/IGameCallback.cpp
  6. 8 206
      lib/IGameCallback.h
  7. 951 0
      lib/IGameCallback2.cpp
  8. 262 0
      lib/IGameCallback2.h
  9. 1 1
      lib/filesystem/CFileInputStream.cpp
  10. 1 0
      scripting/erm/ERMInterpreter.cpp

+ 1 - 1
CCallback.h

@@ -1,7 +1,7 @@
 #pragma once
 
 
-#include "lib/IGameCallback.h"
+#include "lib/IGameCallback2.h"
 
 /*
  * CCallback.h, part of VCMI engine

+ 2 - 2
lib/CGameState.h

@@ -11,11 +11,11 @@
 #include "HeroBonus.h"
 #include "CCreatureSet.h"
 #include "ConstTransitivePtr.h"
-#include "IGameCallback.h"
+#include "IGameCallback2.h"
 #include "ResourceSet.h"
 #include "int3.h"
 #include "CObjectHandler.h"
-#include "IGameCallback.h"
+//#include "IGameCallback.h"
 #include "CRandomGenerator.h"
 
 /*

+ 1 - 0
lib/CMakeLists.txt

@@ -7,6 +7,7 @@ include_directories(${Boost_INCLUDE_DIRS} ${SDL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}
 set(lib_SRCS
 		StdInc.cpp
 		IGameCallback.cpp
+		IGameCallback2.cpp
 		CGameState.cpp
 		CObjectHandler.cpp
 		Connection.cpp

+ 2 - 2
lib/CScriptingModule.h

@@ -2,7 +2,7 @@
 
 
 #include "IGameEventsReceiver.h"
-#include "IGameCallback.h"
+#include "IGameCallback2.h"
 
 /*
  * CScriptingModule.h, part of VCMI engine
@@ -24,4 +24,4 @@ public:
 
 	CScriptingModule(){}
 	virtual ~CScriptingModule(){}
-};
+};

+ 6 - 919
lib/IGameCallback.cpp

@@ -11,7 +11,7 @@
 #include "StdInc.h"
 #include "IGameCallback.h"
 
-#include "CGameState.h"
+/*#include "CGameState.h"
 #include "mapping/CMap.h"
 #include "CObjectHandler.h"
 #include "CHeroHandler.h"
@@ -20,934 +20,21 @@
 #include "CSpellHandler.h"
 #include "VCMI_Lib.h"
 #include "CTownHandler.h"
-#include "BattleState.h"
+#include "BattleState.h"*/
 #include "NetPacks.h"
-#include "CBuildingHandler.h"
+/*#include "CBuildingHandler.h"
 #include "GameConstants.h"
 #include "CModHandler.h"
 #include "CDefObjInfoHandler.h"
 #include "CBonusTypeHandler.h"
 
-#include "Connection.h"
+#include "Connection.h"*/
 
 //TODO make clean
-#define ERROR_SILENT_RET_VAL_IF(cond, txt, retVal) do {if(cond){return retVal;}} while(0)
+/*#define ERROR_SILENT_RET_VAL_IF(cond, txt, retVal) do {if(cond){return retVal;}} while(0)
 #define ERROR_VERBOSE_OR_NOT_RET_VAL_IF(cond, verbose, txt, retVal) do {if(cond){if(verbose)logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return retVal;}} while(0)
 #define ERROR_RET_IF(cond, txt) do {if(cond){logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return;}} while(0)
-#define ERROR_RET_VAL_IF(cond, txt, retVal) do {if(cond){logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return retVal;}} while(0)
-
-CGameState * CPrivilagedInfoCallback::gameState ()
-{
-	return gs;
-}
-
-PlayerColor CGameInfoCallback::getOwner(ObjectInstanceID heroID) const
-{
-	const CGObjectInstance *obj = getObj(heroID);
-	ERROR_RET_VAL_IF(!obj, "No such object!", PlayerColor::CANNOT_DETERMINE);
-	return obj->tempOwner;
-}
-
-int CGameInfoCallback::getResource(PlayerColor Player, Res::ERes which) const
-{
-	const PlayerState *p = getPlayer(Player);
-	ERROR_RET_VAL_IF(!p, "No player info!", -1);
-	ERROR_RET_VAL_IF(p->resources.size() <= which || which < 0, "No such resource!", -1);
-	return p->resources[which];
-}
-
-const CGHeroInstance* CGameInfoCallback::getSelectedHero( PlayerColor Player ) const
-{
-	const PlayerState *p = getPlayer(Player);
-	ERROR_RET_VAL_IF(!p, "No player info!", nullptr);
-	return getHero(p->currentSelection);
-}
-
-const CGHeroInstance* CGameInfoCallback::getSelectedHero() const
-{
-	return getSelectedHero(gs->currentPlayer);
-}
-
-const PlayerSettings * CGameInfoCallback::getPlayerSettings(PlayerColor color) const
-{
-	return &gs->scenarioOps->getIthPlayersSettings(color);
-}
-
-void CPrivilagedInfoCallback::getTilesInRange( std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player/*=uninit*/, int mode/*=0*/ ) const
-{
-	if(!!player && *player >= PlayerColor::PLAYER_LIMIT)
-	{
-        logGlobal->errorStream() << "Illegal call to getTilesInRange!";
-		return;
-	}
-	if (radious == -1) //reveal entire map
-		getAllTiles (tiles, player, -1, 0);
-	else
-	{
-		const TeamState * team = !player ? nullptr : gs->getPlayerTeam(*player);
-		for (int xd = std::max<int>(pos.x - radious , 0); xd <= std::min<int>(pos.x + radious, gs->map->width - 1); xd++)
-		{
-			for (int yd = std::max<int>(pos.y - radious, 0); yd <= std::min<int>(pos.y + radious, gs->map->height - 1); yd++)
-			{
-				double distance = pos.dist2d(int3(xd,yd,pos.z)) - 0.5;
-				if(distance <= radious)
-				{
-					if(!player
-						|| (mode == 1  && team->fogOfWarMap[xd][yd][pos.z]==0)
-						|| (mode == -1 && team->fogOfWarMap[xd][yd][pos.z]==1)
-					)
-						tiles.insert(int3(xd,yd,pos.z));
-				}
-			}
-		}
-	}
-}
-
-void CPrivilagedInfoCallback::getAllTiles (std::unordered_set<int3, ShashInt3> &tiles, boost::optional<PlayerColor> Player/*=uninit*/, int level, int surface ) const
-{
-	if(!!Player && *Player >= PlayerColor::PLAYER_LIMIT)
-	{
-        logGlobal->errorStream() << "Illegal call to getAllTiles !";
-		return;
-	}
-	bool water = surface == 0 || surface == 2,
-		land = surface == 0 || surface == 1;
-
-	std::vector<int> floors;
-	if(level == -1)
-	{
-		for(int b = 0; b < (gs->map->twoLevel ? 2 : 1); ++b)
-		{
-			floors.push_back(b);
-		}
-	}
-	else
-		floors.push_back(level);
-
-	for (auto zd : floors)
-	{
-		
-		for (int xd = 0; xd < gs->map->width; xd++)
-		{
-			for (int yd = 0; yd < gs->map->height; yd++)
-			{
-				if ((getTile (int3 (xd,yd,zd))->terType == ETerrainType::WATER && water)
-					|| (getTile (int3 (xd,yd,zd))->terType != ETerrainType::WATER && land))
-					tiles.insert(int3(xd,yd,zd));
-			}
-		}
-	}
-}
-
-void CPrivilagedInfoCallback::getFreeTiles (std::vector<int3> &tiles) const
-{
-	std::vector<int> floors;
-	for (int b = 0; b < (gs->map->twoLevel ? 2 : 1); ++b)
-	{
-		floors.push_back(b);
-	}
-	const TerrainTile *tinfo;
-	for (auto zd : floors)
-	{
-		
-		for (int xd = 0; xd < gs->map->width; xd++)
-		{
-			for (int yd = 0; yd < gs->map->height; yd++)
-			{
-				tinfo = getTile(int3 (xd,yd,zd));
-				if (tinfo->terType != ETerrainType::WATER && !tinfo->blocked) //land and free
-					tiles.push_back (int3 (xd,yd,zd));
-			}
-		}
-	}
-}
-
-bool CGameInfoCallback::isAllowed( int type, int id )
-{
-	switch(type)
-	{
-	case 0:
-		return gs->map->allowedSpell[id];
-	case 1:
-		return gs->map->allowedArtifact[id];
-	case 2:
-		return gs->map->allowedAbilities[id];
-	default:
-		ERROR_RET_VAL_IF(1, "Wrong type!", false);
-	}
-}
-
-void CPrivilagedInfoCallback::pickAllowedArtsSet(std::vector<const CArtifact*> &out)
-{
-	for (int j = 0; j < 3 ; j++)
-		out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_TREASURE)]);
-	for (int j = 0; j < 3 ; j++)
-		out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_MINOR)]);
-
-	out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_MAJOR)]);
-}
-
-void CPrivilagedInfoCallback::getAllowedSpells(std::vector<SpellID> &out, ui16 level)
-{
-	for (ui32 i = 0; i < gs->map->allowedSpell.size(); i++) //spellh size appears to be greater (?)
-	{
-
-		const CSpell *spell = SpellID(i).toSpell();
-		if (isAllowed (0, spell->id) && spell->level == level)
-		{
-			out.push_back(spell->id);
-		}
-	}
-}
-
-
-template<typename Loader>
-void CPrivilagedInfoCallback::loadCommonState(Loader &in)
-{
-    logGlobal->infoStream() << "Loading lib part of game...";
-	in.checkMagicBytes(SAVEGAME_MAGIC);
-
-	CMapHeader dum;
-	StartInfo *si;
-
-    logGlobal->infoStream() <<"\tReading header";
-	in >> dum;
-
-    logGlobal->infoStream() << "\tReading options";
-	in >> si;
-
-    logGlobal->infoStream() <<"\tReading handlers";
-	in >> *VLC;
-
-    logGlobal->infoStream() <<"\tReading gamestate";
-	in >> gs;
-}
-
-template<typename Saver>
-void CPrivilagedInfoCallback::saveCommonState(Saver &out) const
-{
-    logGlobal->infoStream() << "Saving lib part of game...";
-	out.putMagicBytes(SAVEGAME_MAGIC);
-    logGlobal->infoStream() <<"\tSaving header";
-	out << static_cast<CMapHeader&>(*gs->map);
-    logGlobal->infoStream() << "\tSaving options";
-	out << gs->scenarioOps;
-    logGlobal->infoStream() << "\tSaving handlers";
-	out << *VLC;
-    logGlobal->infoStream() << "\tSaving gamestate";
-	out << gs;
-}
-
-template DLL_LINKAGE void CPrivilagedInfoCallback::loadCommonState<CLoadIntegrityValidator>(CLoadIntegrityValidator&);
-template DLL_LINKAGE void CPrivilagedInfoCallback::loadCommonState<CLoadFile>(CLoadFile&);
-template DLL_LINKAGE void CPrivilagedInfoCallback::saveCommonState<CSaveFile>(CSaveFile&) const;
-
-TerrainTile * CNonConstInfoCallback::getTile( int3 pos )
-{
-	if(!gs->map->isInTheMap(pos))
-		return nullptr;
-	return &gs->map->getTile(pos);
-}
-
-const PlayerState * CGameInfoCallback::getPlayer(PlayerColor color, bool verbose) const
-{
-	ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!hasAccess(color), verbose, "Cannot access player " << color << "info!", nullptr);
-	ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!vstd::contains(gs->players,color), verbose, "Cannot find player " << color << "info!", nullptr);
-	return &gs->players[color];
-}
-
-const CTown * CGameInfoCallback::getNativeTown(PlayerColor color) const
-{
-	const PlayerSettings *ps = getPlayerSettings(color);
-	ERROR_RET_VAL_IF(!ps, "There is no such player!", nullptr);
-	return VLC->townh->factions[ps->castle]->town;
-}
-
-const CGObjectInstance * CGameInfoCallback::getObjByQuestIdentifier(int identifier) const
-{
-	ERROR_RET_VAL_IF(!vstd::contains(gs->map->questIdentifierToId, identifier), "There is no object with such quest identifier!", nullptr);
-	return getObj(gs->map->questIdentifierToId[identifier]);
-}
-
-/************************************************************************/
-/*                                                                      */
-/************************************************************************/
-
-const CGObjectInstance* CGameInfoCallback::getObj(ObjectInstanceID objid, bool verbose) const
-{
-	si32 oid = objid.num;
-	if(oid < 0  ||  oid >= gs->map->objects.size())
-	{
-		if(verbose)
-            logGlobal->errorStream() << "Cannot get object with id " << oid;
-		return nullptr;
-	}
-
-	const CGObjectInstance *ret = gs->map->objects[oid];
-	if(!ret)
-	{
-		if(verbose)
-            logGlobal->errorStream() << "Cannot get object with id " << oid << ". Object was removed.";
-		return nullptr;
-	}
-
-	if(!isVisible(ret, player))
-	{
-		if(verbose)
-            logGlobal->errorStream() << "Cannot get object with id " << oid << ". Object is not visible.";
-		return nullptr;
-	}
-
-	return ret;
-}
-
-const CGHeroInstance* CGameInfoCallback::getHero(ObjectInstanceID objid) const
-{
-	const CGObjectInstance *obj = getObj(objid, false);
-	if(obj)
-		return dynamic_cast<const CGHeroInstance*>(obj);
-	else
-		return nullptr;
-}
-const CGTownInstance* CGameInfoCallback::getTown(ObjectInstanceID objid) const
-{
-	const CGObjectInstance *obj = getObj(objid, false);
-	if(obj)
-		return dynamic_cast<const CGTownInstance*>(obj);
-	else
-		return nullptr;
-}
-
-void CGameInfoCallback::getUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out) const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	ERROR_RET_IF(!canGetFullInfo(obj), "Cannot get info about not owned object!");
-	ERROR_RET_IF(!obj->hasStackAtSlot(stackPos), "There is no such stack!");
-	out = gs->getUpgradeInfo(obj->getStack(stackPos));
-	//return gs->getUpgradeInfo(obj->getStack(stackPos));
-}
-
-const StartInfo * CGameInfoCallback::getStartInfo(bool beforeRandomization /*= false*/) const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	if(beforeRandomization)
-		return gs->initialOpts;
-	else
-		return gs->scenarioOps;
-}
-
-int CGameInfoCallback::getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	ERROR_RET_VAL_IF(!canGetFullInfo(caster), "Cannot get info about caster!", -1);
-	//if there is a battle
-	if(gs->curB)
-		return gs->curB->battleGetSpellCost(sp, caster);
-
-	//if there is no battle
-	return caster->getSpellCost(sp);
-}
-
-int CGameInfoCallback::estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-
-	ERROR_RET_VAL_IF(hero && !canGetFullInfo(hero), "Cannot get info about caster!", -1);
-	if(!gs->curB) //no battle
-	{
-		if (hero) //but we see hero's spellbook
-			return gs->curB->calculateSpellDmg(
-				sp, hero, nullptr, hero->getSpellSchoolLevel(sp), hero->getPrimSkillLevel(PrimarySkill::SPELL_POWER));
-		else
-			return 0; //mage guild
-	}
-	//gs->getHero(gs->currentPlayer)
-	//const CGHeroInstance * ourHero = gs->curB->heroes[0]->tempOwner == player ? gs->curB->heroes[0] : gs->curB->heroes[1];
-	const CGHeroInstance * ourHero = hero;
-	return gs->curB->calculateSpellDmg(
-		sp, ourHero, nullptr, ourHero->getSpellSchoolLevel(sp), ourHero->getPrimSkillLevel(PrimarySkill::SPELL_POWER));
-}
-
-void CGameInfoCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj)
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	ERROR_RET_IF(!obj, "No guild object!");
-	ERROR_RET_IF(obj->ID == Obj::TOWN && !canGetFullInfo(obj), "Cannot get info about town guild object!");
-	//TODO: advmap object -> check if they're visited by our hero
-
-	if(obj->ID == Obj::TOWN  ||  obj->ID == Obj::TAVERN)
-	{
-		gs->obtainPlayersStats(thi, gs->players[obj->tempOwner].towns.size());
-	}
-	else if(obj->ID == Obj::DEN_OF_THIEVES)
-	{
-		gs->obtainPlayersStats(thi, 20);
-	}
-}
-
-int CGameInfoCallback::howManyTowns(PlayerColor Player) const
-{
-	ERROR_RET_VAL_IF(!hasAccess(Player), "Access forbidden!", -1);
-	return gs->players[Player].towns.size();
-}
-
-bool CGameInfoCallback::getTownInfo( const CGObjectInstance *town, InfoAboutTown &dest ) const
-{
-	ERROR_RET_VAL_IF(!isVisible(town, player), "Town is not visible!", false);  //it's not a town or it's not visible for layer
-	bool detailed = hasAccess(town->tempOwner);
-
-	//TODO vision support
-	if(town->ID == Obj::TOWN)
-		dest.initFromTown(static_cast<const CGTownInstance *>(town), detailed);
-	else if(town->ID == Obj::GARRISON || town->ID == Obj::GARRISON2)
-		dest.initFromArmy(static_cast<const CArmedInstance *>(town), detailed);
-	else
-		return false;
-	return true;
-}
-
-int3 CGameInfoCallback::guardingCreaturePosition (int3 pos) const //FIXME: redundant?
-{
-	ERROR_RET_VAL_IF(!isVisible(pos), "Tile is not visible!", int3(-1,-1,-1));
-	return gs->guardingCreaturePosition(pos);
-}
-
-std::vector<const CGObjectInstance*> CGameInfoCallback::getGuardingCreatures (int3 pos) const
-{
-	ERROR_RET_VAL_IF(!isVisible(pos), "Tile is not visible!", std::vector<const CGObjectInstance*>());
-	std::vector<const CGObjectInstance*> ret;
-	for(auto cr : gs->guardingCreatures(pos))
-	{
-		ret.push_back(cr);
-	}
-	return ret;
-}
-
-bool CGameInfoCallback::getHeroInfo( const CGObjectInstance *hero, InfoAboutHero &dest ) const
-{
-	const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(hero);
-
-	ERROR_RET_VAL_IF(!h, "That's not a hero!", false);
-	ERROR_RET_VAL_IF(!isVisible(h->getPosition(false)), "That hero is not visible!", false);
-
-	//TODO vision support
-	dest.initFromHero(h, hasAccess(h->tempOwner));
-	return true;
-}
-
-int CGameInfoCallback::getDate(Date::EDateType mode) const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	return gs->getDate(mode);
-}
-std::vector < std::string > CGameInfoCallback::getObjDescriptions(int3 pos) const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	std::vector<std::string> ret;
-	const TerrainTile *t = getTile(pos);
-	ERROR_RET_VAL_IF(!t, "Not a valid tile given!", ret);
-
-
-	for(const CGObjectInstance * obj : t->blockingObjects)
-		ret.push_back(obj->getHoverText());
-	return ret;
-}
-
-bool CGameInfoCallback::isVisible(int3 pos, boost::optional<PlayerColor> Player) const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	return gs->map->isInTheMap(pos) && (!Player || gs->isVisible(pos, *Player));
-}
-
-bool CGameInfoCallback::isVisible(int3 pos) const
-{
-	return isVisible(pos, player);
-}
-
-bool CGameInfoCallback::isVisible( const CGObjectInstance *obj, boost::optional<PlayerColor> Player ) const
-{
-	return gs->isVisible(obj, Player);
-}
-
-bool CGameInfoCallback::isVisible(const CGObjectInstance *obj) const
-{
-	return isVisible(obj, player);
-}
-// const CCreatureSet* CInfoCallback::getGarrison(const CGObjectInstance *obj) const
-// {
-// 	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-// 	if()
-// 	const CArmedInstance *armi = dynamic_cast<const CArmedInstance*>(obj);
-// 	if(!armi)
-// 		return nullptr;
-// 	else
-// 		return armi;
-// }
-
-std::vector < const CGObjectInstance * > CGameInfoCallback::getBlockingObjs( int3 pos ) const
-{
-	std::vector<const CGObjectInstance *> ret;
-	const TerrainTile *t = getTile(pos);
-	ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
-
-	for(const CGObjectInstance * obj : t->blockingObjects)
-		ret.push_back(obj);
-	return ret;
-}
-
-std::vector <const CGObjectInstance * > CGameInfoCallback::getVisitableObjs(int3 pos, bool verbose /*= true*/) const
-{
-	std::vector<const CGObjectInstance *> ret;
-	const TerrainTile *t = getTile(pos, verbose);
-	ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!t, verbose, pos << " is not visible!", ret);
-
-	for(const CGObjectInstance * obj : t->visitableObjects)
-	{
-		if(player < nullptr || obj->ID != Obj::EVENT) //hide events from players
-			ret.push_back(obj);
-	}
-
-	return ret;
-}
-const CGObjectInstance * CGameInfoCallback::getTopObj (int3 pos) const
-{
-	return vstd::backOrNull(getVisitableObjs(pos));
-}
-
-std::vector < const CGObjectInstance * > CGameInfoCallback::getFlaggableObjects(int3 pos) const
-{
-	std::vector<const CGObjectInstance *> ret;
-	const TerrainTile *t = getTile(pos);
-	ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
-	for(const CGObjectInstance *obj : t->blockingObjects)
-		if(obj->tempOwner != PlayerColor::UNFLAGGABLE)
-			ret.push_back(obj);
-// 	const std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > & objs = CGI->mh->ttiles[pos.x][pos.y][pos.z].objects;
-// 	for(size_t b=0; b<objs.size(); ++b)
-// 	{
-// 		if(objs[b].first->tempOwner!=254 && !((objs[b].first->defInfo->blockMap[pos.y - objs[b].first->pos.y + 5] >> (objs[b].first->pos.x - pos.x)) & 1))
-// 			ret.push_back(CGI->mh->ttiles[pos.x][pos.y][pos.z].objects[b].first);
-// 	}
-	return ret;
-}
-
-int3 CGameInfoCallback::getMapSize() const
-{
-	return int3(gs->map->width, gs->map->height, gs->map->twoLevel ? 2 : 1);
-}
-
-std::vector<const CGHeroInstance *> CGameInfoCallback::getAvailableHeroes(const CGObjectInstance * townOrTavern) const
-{
-	ASSERT_IF_CALLED_WITH_PLAYER
-	std::vector<const CGHeroInstance *> ret;
-	//ERROR_RET_VAL_IF(!isOwnedOrVisited(townOrTavern), "Town or tavern must be owned or visited!", ret);
-	//TODO: town needs to be owned, advmap tavern needs to be visited; to be reimplemented when visit tracking is done
-	range::copy(gs->players[*player].availableHeroes, std::back_inserter(ret));
-	vstd::erase_if(ret, [](const CGHeroInstance *h) { return h == nullptr; });
-	return ret;
-}
-
-const TerrainTile * CGameInfoCallback::getTile( int3 tile, bool verbose) const
-{
-	ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!isVisible(tile), verbose, tile << " is not visible!", nullptr);
-
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	return &gs->map->getTile(tile);
-}
-
-EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, BuildingID ID )
-{
-	ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", EBuildingState::TOWN_NOT_OWNED);
-
-	if(!t->town->buildings.count(ID))
-		return EBuildingState::BUILDING_ERROR;
-
-	const CBuilding * building = t->town->buildings.at(ID);
-
-
-	if(t->hasBuilt(ID))	//already built
-		return EBuildingState::ALREADY_PRESENT;
-
-	//can we build it?
-	if(vstd::contains(t->forbiddenBuildings, ID))
-		return EBuildingState::FORBIDDEN; //forbidden
-
-	if(ID == BuildingID::CAPITOL)
-	{
-		const PlayerState *ps = getPlayer(t->tempOwner);
-		if(ps)
-		{
-			for(const CGTownInstance *t : ps->towns)
-			{
-				if(t->hasBuilt(BuildingID::CAPITOL))
-				{
-					return EBuildingState::HAVE_CAPITAL; //no more than one capitol
-				}
-			}
-		}
-	}
-	else if(ID == BuildingID::SHIPYARD)
-	{
-		const TerrainTile *tile = getTile(t->bestLocation(), false);
-
-		if(!tile || tile->terType != ETerrainType::WATER)
-			return EBuildingState::NO_WATER; //lack of water
-	}
-
-	auto buildTest = [&](const BuildingID & id)
-	{
-		return t->hasBuilt(id);
-	};
-
-	if(t->builded >= VLC->modh->settings.MAX_BUILDING_PER_TURN)
-		return EBuildingState::CANT_BUILD_TODAY; //building limit
-
-	if (!building->requirements.test(buildTest))
-		return EBuildingState::PREREQUIRES;
-
-	if (building->upgrade != BuildingID::NONE && !t->hasBuilt(building->upgrade))
-		return EBuildingState::MISSING_BASE;
-
-	//checking resources
-	if(!building->resources.canBeAfforded(getPlayer(t->tempOwner)->resources))
-		return EBuildingState::NO_RESOURCES; //lack of res
-
-	return EBuildingState::ALLOWED;
-}
-
-const CMapHeader * CGameInfoCallback::getMapHeader() const
-{
-	return gs->map;
-}
-
-bool CGameInfoCallback::hasAccess(boost::optional<PlayerColor> playerId) const
-{
-	return !player || gs->getPlayerRelations( *playerId, *player ) != PlayerRelations::ENEMIES;
-}
-
-EPlayerStatus::EStatus CGameInfoCallback::getPlayerStatus(PlayerColor player, bool verbose) const
-{
-	const PlayerState *ps = gs->getPlayer(player, verbose);
-	ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!ps, verbose, "No such player!", EPlayerStatus::WRONG);
-
-	return ps->status;
-}
-
-std::string CGameInfoCallback::getTavernGossip(const CGObjectInstance * townOrTavern) const
-{
-	return "GOSSIP TEST";
-}
-
-PlayerRelations::PlayerRelations CGameInfoCallback::getPlayerRelations( PlayerColor color1, PlayerColor color2 ) const
-{
-	return gs->getPlayerRelations(color1, color2);
-}
-
-bool CGameInfoCallback::canGetFullInfo(const CGObjectInstance *obj) const
-{
-	return !obj || hasAccess(obj->tempOwner);
-}
-
-int CGameInfoCallback::getHeroCount( PlayerColor player, bool includeGarrisoned ) const
-{
-	int ret = 0;
-	const PlayerState *p = gs->getPlayer(player);
-	ERROR_RET_VAL_IF(!p, "No such player!", -1);
-
-	if(includeGarrisoned)
-		return p->heroes.size();
-	else
-		for(auto & elem : p->heroes)
-			if(!elem->inTownGarrison)
-				ret++;
-	return ret;
-}
-
-bool CGameInfoCallback::isOwnedOrVisited(const CGObjectInstance *obj) const
-{
-	if(canGetFullInfo(obj))
-		return true;
-
-	const TerrainTile *t = getTile(obj->visitablePos()); //get entrance tile
-	const CGObjectInstance *visitor = t->visitableObjects.back(); //visitong hero if present or the obejct itself at last
-	return visitor->ID == Obj::HERO && canGetFullInfo(visitor); //owned or allied hero is a visitor
-}
-
-PlayerColor CGameInfoCallback::getCurrentPlayer() const
-{
-	return gs->currentPlayer;
-}
-
-CGameInfoCallback::CGameInfoCallback()
-{
-}
-
-CGameInfoCallback::CGameInfoCallback(CGameState *GS, boost::optional<PlayerColor> Player)
-{
-	gs = GS;
-	player = Player;
-}
-
-const std::vector< std::vector< std::vector<ui8> > > & CPlayerSpecificInfoCallback::getVisibilityMap() const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	return gs->getPlayerTeam(*player)->fogOfWarMap;
-}
-
-int CPlayerSpecificInfoCallback::howManyTowns() const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	ERROR_RET_VAL_IF(!player, "Applicable only for player callbacks", -1);
-	return CGameInfoCallback::howManyTowns(*player);
-}
-
-std::vector < const CGTownInstance *> CPlayerSpecificInfoCallback::getTownsInfo(bool onlyOur) const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	std::vector < const CGTownInstance *> ret = std::vector < const CGTownInstance *>();
-	for(const auto & i : gs->players)
-	{
-		for(const auto & town : i.second.towns)
-		{
-			if (i.first==player || (isVisible(town, player) && !onlyOur))
-			{
-				ret.push_back(town);
-			}
-		}
-	} //	for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
-	return ret;
-}
-std::vector < const CGHeroInstance *> CPlayerSpecificInfoCallback::getHeroesInfo(bool onlyOur) const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	std::vector < const CGHeroInstance *> ret;
-	for(auto hero : gs->map->heroesOnMap)
-	{
-		if( !player || (hero->tempOwner == *player) ||
-			(isVisible(hero->getPosition(false), player) && !onlyOur)	)
-		{
-			ret.push_back(hero);
-		}
-	}
-	return ret;
-}
-
-boost::optional<PlayerColor> CPlayerSpecificInfoCallback::getMyColor() const
-{
-	return player;
-}
-
-int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool includeGarrisoned) const
-{
-	if (hero->inTownGarrison && !includeGarrisoned)
-		return -1;
-
-	size_t index = 0;
-	auto & heroes = gs->players[*player].heroes;
-
-	for (auto & heroe : heroes)
-	{
-		if (includeGarrisoned || !(heroe)->inTownGarrison)
-			index++;
-
-		if (heroe == hero)
-			return index;
-	}
-	return -1;
-}
-
-int3 CPlayerSpecificInfoCallback::getGrailPos( double &outKnownRatio )
-{
-	if (!player || CGObelisk::obeliskCount == 0)
-	{
-		outKnownRatio = 0.0;
-	}
-	else
-	{
-		outKnownRatio = static_cast<double>(CGObelisk::visited[gs->getPlayerTeam(*player)->id]) / CGObelisk::obeliskCount;
-	}
-	return gs->map->grailPos;
-}
-
-std::vector < const CGObjectInstance * > CPlayerSpecificInfoCallback::getMyObjects() const
-{
-	std::vector < const CGObjectInstance * > ret;
-	for(const CGObjectInstance * obj : gs->map->objects)
-	{
-		if(obj && obj->tempOwner == player)
-			ret.push_back(obj);
-	}
-	return ret;
-}
-
-std::vector < const CGDwelling * > CPlayerSpecificInfoCallback::getMyDwellings() const
-{
-	ASSERT_IF_CALLED_WITH_PLAYER
-	std::vector < const CGDwelling * > ret;
-	for(CGDwelling * dw : gs->getPlayer(*player)->dwellings)
-	{
-		ret.push_back(dw);
-	}
-	return ret;
-}
-
-std::vector <QuestInfo> CPlayerSpecificInfoCallback::getMyQuests() const
-{
-	std::vector <QuestInfo> ret;
-	for (auto quest : gs->getPlayer(*player)->quests)
-	{
-		ret.push_back (quest);
-	}
-	return ret;
-}
-
-int CPlayerSpecificInfoCallback::howManyHeroes(bool includeGarrisoned) const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	ERROR_RET_VAL_IF(!player, "Applicable only for player callbacks", -1);
-	return getHeroCount(*player,includeGarrisoned);
-}
-
-const CGHeroInstance* CPlayerSpecificInfoCallback::getHeroBySerial(int serialId, bool includeGarrisoned) const
-{
-	ASSERT_IF_CALLED_WITH_PLAYER
-	const PlayerState *p = getPlayer(*player);
-	ERROR_RET_VAL_IF(!p, "No player info", nullptr);
-
-	if (!includeGarrisoned)
-	{
-		for(ui32 i = 0; i < p->heroes.size() && i<=serialId; i++)
-			if(p->heroes[i]->inTownGarrison)
-				serialId++;
-	}
-	ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->heroes.size(), "No player info", nullptr);
-	return p->heroes[serialId];
-}
-
-const CGTownInstance* CPlayerSpecificInfoCallback::getTownBySerial(int serialId) const
-{
-	ASSERT_IF_CALLED_WITH_PLAYER
-	const PlayerState *p = getPlayer(*player);
-	ERROR_RET_VAL_IF(!p, "No player info", nullptr);
-	ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->towns.size(), "No player info", nullptr);
-	return p->towns[serialId];
-}
-
-int CPlayerSpecificInfoCallback::getResourceAmount(Res::ERes type) const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	ERROR_RET_VAL_IF(!player, "Applicable only for player callbacks", -1);
-	return getResource(*player, type);
-}
-
-TResources CPlayerSpecificInfoCallback::getResourceAmount() const
-{
-	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	ERROR_RET_VAL_IF(!player, "Applicable only for player callbacks", TResources());
-	return gs->players[*player].resources;
-}
-
-CGHeroInstance *CNonConstInfoCallback::getHero(ObjectInstanceID objid)
-{
-	return const_cast<CGHeroInstance*>(CGameInfoCallback::getHero(objid));
-}
-
-CGTownInstance *CNonConstInfoCallback::getTown(ObjectInstanceID objid)
-{
-	return const_cast<CGTownInstance*>(CGameInfoCallback::getTown(objid));
-}
-
-TeamState *CNonConstInfoCallback::getTeam(TeamID teamID)
-{
-	return const_cast<TeamState*>(CGameInfoCallback::getTeam(teamID));
-}
-
-TeamState *CNonConstInfoCallback::getPlayerTeam(PlayerColor color)
-{
-	return const_cast<TeamState*>(CGameInfoCallback::getPlayerTeam(color));
-}
-
-PlayerState * CNonConstInfoCallback::getPlayer( PlayerColor color, bool verbose )
-{
-	return const_cast<PlayerState*>(CGameInfoCallback::getPlayer(color, verbose));
-}
-
-CArtifactInstance * CNonConstInfoCallback::getArtInstance( ArtifactInstanceID aid )
-{
-	return gs->map->artInstances[aid.num];
-}
-
-CGObjectInstance * CNonConstInfoCallback::getObjInstance( ObjectInstanceID oid )
-{
-	return gs->map->objects[oid.num];
-}
-
-const TeamState * CGameInfoCallback::getTeam( TeamID teamID ) const
-{
-	ERROR_RET_VAL_IF(!vstd::contains(gs->teams, teamID), "Cannot find info for team " << teamID, nullptr);
-	const TeamState *ret = &gs->teams[teamID];
-	ERROR_RET_VAL_IF(!!player && !vstd::contains(ret->players, *player), "Illegal attempt to access team data!", nullptr);
-	return ret;
-}
-
-const TeamState * CGameInfoCallback::getPlayerTeam( PlayerColor color ) const
-{
-	const PlayerState * ps = getPlayer(color);
-	if (ps)
-		return getTeam(ps->team);
-	return nullptr;
-}
-
-const CGHeroInstance* CGameInfoCallback::getHeroWithSubid( int subid ) const
-{
-	for(const CGHeroInstance *h : gs->map->heroesOnMap)
-		if(h->subID == subid)
-			return h;
-
-	return nullptr;
-}
-
-PlayerColor CGameInfoCallback::getLocalPlayer() const
-{
-	return getCurrentPlayer();
-}
-
-bool CGameInfoCallback::isInTheMap(const int3 &pos) const
-{
-	return gs->map->isInTheMap(pos);
-}
-
-const CArtifactInstance * CGameInfoCallback::getArtInstance( ArtifactInstanceID aid ) const
-{
-	return gs->map->artInstances[aid.num];
-}
-
-const CGObjectInstance * CGameInfoCallback::getObjInstance( ObjectInstanceID oid ) const
-{
-	return gs->map->objects[oid.num];
-}
-
-void IGameEventRealizer::showInfoDialog( InfoWindow *iw )
-{
-	commitPackage(iw);
-}
-
-void IGameEventRealizer::showInfoDialog(const std::string &msg, PlayerColor player)
-{
-	InfoWindow iw;
-	iw.player = player;
-	iw.text << msg;
-	showInfoDialog(&iw);
-}
-
-void IGameEventRealizer::setObjProperty(ObjectInstanceID objid, int prop, si64 val)
-{
-	SetObjectProperty sob;
-	sob.id = objid;
-	sob.what = prop;
-	sob.val = static_cast<ui32>(val);
-	commitPackage(&sob);
-}
+#define ERROR_RET_VAL_IF(cond, txt, retVal) do {if(cond){logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return retVal;}} while(0)*/
 
 const CGObjectInstance * IGameCallback::putNewObject(Obj ID, int subID, int3 pos)
 {

+ 8 - 206
lib/IGameCallback.h

@@ -1,11 +1,12 @@
 #pragma once
 
+#include "IGameCallback2.h" // for CPrivilagedInfoCallback, IGameEventCallback
 
-#include "BattleHex.h"
+/*#include "BattleHex.h"
 #include "ResourceSet.h"
 #include "int3.h"
 #include "GameConstants.h"
-#include "CBattleCallback.h"
+#include "CBattleCallback.h"*/
 
 /*
  * IGameCallback.h, part of VCMI engine
@@ -17,7 +18,7 @@
  *
  */
 
-struct SetMovePoints;
+/*struct SetMovePoints;
 struct GiveBonus;
 class CGObjectInstance;
 class CGTownInstance;
@@ -55,210 +56,10 @@ class CCreatureSet;
 class CCreature;
 class CStackBasicDescriptor;
 struct TeamState;
-struct QuestInfo;
+struct QuestInfo;*/
 class CGCreature;
-class CSaveFile;
-class CLoadFile;
-
-class DLL_LINKAGE CGameInfoCallback : public virtual CCallbackBase
-{
-protected:
-	CGameInfoCallback();
-	CGameInfoCallback(CGameState *GS, boost::optional<PlayerColor> Player);
-	bool hasAccess(boost::optional<PlayerColor> playerId) const;
-	bool isVisible(int3 pos, boost::optional<PlayerColor> Player) const;
-	bool isVisible(const CGObjectInstance *obj, boost::optional<PlayerColor> Player) const;
-	bool isVisible(const CGObjectInstance *obj) const;
-
-	bool canGetFullInfo(const CGObjectInstance *obj) const; //true we player owns obj or ally owns obj or privileged mode
-	bool isOwnedOrVisited(const CGObjectInstance *obj) const;
-
-public:
-	//various
-	int getDate(Date::EDateType mode=Date::DAY)const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
-	const StartInfo * getStartInfo(bool beforeRandomization = false)const;
-	bool isAllowed(int type, int id); //type: 0 - spell; 1- artifact; 2 - secondary skill
-
-	//player
-	const PlayerState * getPlayer(PlayerColor color, bool verbose = true) const;
-	int getResource(PlayerColor Player, Res::ERes which) const;
-	bool isVisible(int3 pos) const;
-	PlayerRelations::PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2) const;
-	void getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj); //get thieves' guild info obtainable while visiting given object
-	EPlayerStatus::EStatus getPlayerStatus(PlayerColor player, bool verbose = true) const; //-1 if no such player
-	PlayerColor getCurrentPlayer() const; //player that currently makes move // TODO synchronous turns
-	virtual PlayerColor getLocalPlayer() const; //player that is currently owning given client (if not a client, then returns current player)
-	const PlayerSettings * getPlayerSettings(PlayerColor color) const;
-
-
-	//armed object
-	void getUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out)const;
-
-	//hero
-	const CGHeroInstance* getHero(ObjectInstanceID objid) const;
-	const CGHeroInstance* getHeroWithSubid(int subid) const;
-	int getHeroCount(PlayerColor player, bool includeGarrisoned) const;
-	bool getHeroInfo(const CGObjectInstance *hero, InfoAboutHero &dest) const;
-	int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //when called during battle, takes into account creatures' spell cost reduction
-	int estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const; //estimates damage of given spell; returns 0 if spell causes no dmg
-	const CGHeroInstance* getSelectedHero(PlayerColor player) const; //nullptr if no hero is selected
-	const CGHeroInstance* getSelectedHero() const; //of current (active) player
-	const CArtifactInstance * getArtInstance(ArtifactInstanceID aid) const;
-	const CGObjectInstance * getObjInstance(ObjectInstanceID oid) const;
-
-	//objects
-	const CGObjectInstance* getObj(ObjectInstanceID objid, bool verbose = true) const;
-	std::vector <const CGObjectInstance * > getBlockingObjs(int3 pos)const;
-	std::vector <const CGObjectInstance * > getVisitableObjs(int3 pos, bool verbose = true)const;
-	std::vector <const CGObjectInstance * > getFlaggableObjects(int3 pos) const;
-	const CGObjectInstance * getTopObj (int3 pos) const;
-	std::vector <std::string > getObjDescriptions(int3 pos)const; //returns descriptions of objects at pos in order from the lowest to the highest
-	PlayerColor getOwner(ObjectInstanceID heroID) const;
-	const CGObjectInstance *getObjByQuestIdentifier(int identifier) const; //nullptr if object has been removed (eg. killed)
-
-	//map
-	int3 guardingCreaturePosition (int3 pos) const;
-	std::vector<const CGObjectInstance*> getGuardingCreatures (int3 pos) const;
-	const CMapHeader * getMapHeader()const;
-	int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map
-	const TerrainTile * getTile(int3 tile, bool verbose = true) const;
-	bool isInTheMap(const int3 &pos) const;
-
-	//town
-	const CGTownInstance* getTown(ObjectInstanceID objid) const;
-	int howManyTowns(PlayerColor Player) const;
-	const CGTownInstance * getTownInfo(int val, bool mode)const; //mode = 0 -> val = player town serial; mode = 1 -> val = object id (serial)
-	std::vector<const CGHeroInstance *> getAvailableHeroes(const CGObjectInstance * townOrTavern) const; //heroes that can be recruited
-	std::string getTavernGossip(const CGObjectInstance * townOrTavern) const; 
-	EBuildingState::EBuildingState canBuildStructure(const CGTownInstance *t, BuildingID ID);//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
-	virtual bool getTownInfo(const CGObjectInstance *town, InfoAboutTown &dest) const;
-	const CTown *getNativeTown(PlayerColor color) const;
-
-	//from gs
-	const TeamState *getTeam(TeamID teamID) const;
-	const TeamState *getPlayerTeam(PlayerColor color) const;
-	EBuildingState::EBuildingState canBuildStructure(const CGTownInstance *t, BuildingID ID) const;// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
-};
-
-
-class DLL_LINKAGE CPlayerSpecificInfoCallback : public CGameInfoCallback
-{
-public:
-	int howManyTowns() const;
-	int howManyHeroes(bool includeGarrisoned = true) const;
-	int3 getGrailPos(double &outKnownRatio);
-	boost::optional<PlayerColor> getMyColor() const;
-
-	std::vector <const CGTownInstance *> getTownsInfo(bool onlyOur = true) const; //true -> only owned; false -> all visible
-	int getHeroSerial(const CGHeroInstance * hero, bool includeGarrisoned=true) const;
-	const CGTownInstance* getTownBySerial(int serialId) const; // serial id is [0, number of towns)
-	const CGHeroInstance* getHeroBySerial(int serialId, bool includeGarrisoned=true) const; // serial id is [0, number of heroes)
-	std::vector <const CGHeroInstance *> getHeroesInfo(bool onlyOur = true) const; //true -> only owned; false -> all visible
-	std::vector <const CGDwelling *> getMyDwellings() const; //returns all dwellings that belong to player
-	std::vector <const CGObjectInstance * > getMyObjects() const; //returns all objects flagged by belonging player
-	std::vector <QuestInfo> getMyQuests() const;
-
-	int getResourceAmount(Res::ERes type) const;
-	TResources getResourceAmount() const;
-	const std::vector< std::vector< std::vector<ui8> > > & getVisibilityMap()const; //returns visibility map 
-	const PlayerSettings * getPlayerSettings(PlayerColor color) const;
-};
-
-class DLL_LINKAGE CPrivilagedInfoCallback : public CGameInfoCallback
-{
-public:
-	CGameState * gameState();
-	void getFreeTiles (std::vector<int3> &tiles) const; //used for random spawns
-	void getTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int mode=0) const;  //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 -  only unrevealed
-	void getAllTiles (std::unordered_set<int3, ShashInt3> &tiles, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int level=-1, int surface=0) const; //returns all tiles on given level (-1 - both levels, otherwise number of level); surface: 0 - land and water, 1 - only land, 2 - only water
-	void pickAllowedArtsSet(std::vector<const CArtifact*> &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
-	void getAllowedSpells(std::vector<SpellID> &out, ui16 level);
-
-	template<typename Saver>
-	void saveCommonState(Saver &out) const; //stores GS and VLC
-
-	template<typename Loader>
-	void loadCommonState(Loader &in); //loads GS and VLC
-};
-
-class DLL_LINKAGE CNonConstInfoCallback : public CPrivilagedInfoCallback
-{
-public:
-	PlayerState *getPlayer(PlayerColor color, bool verbose = true);
-	TeamState *getTeam(TeamID teamID);//get team by team ID
-	TeamState *getPlayerTeam(PlayerColor color);// get team by player color
-	CGHeroInstance *getHero(ObjectInstanceID objid);
-	CGTownInstance *getTown(ObjectInstanceID objid);
-	TerrainTile * getTile(int3 pos);
-	CArtifactInstance * getArtInstance(ArtifactInstanceID aid);
-	CGObjectInstance * getObjInstance(ObjectInstanceID oid);
-};
-
-class DLL_LINKAGE IGameEventRealizer
-{
-public:
-	virtual void commitPackage(CPackForClient *pack) = 0;
-
-	virtual void showInfoDialog(InfoWindow *iw);
-	virtual void setObjProperty(ObjectInstanceID objid, int prop, si64 val);
-
-
-	virtual void showInfoDialog(const std::string &msg, PlayerColor player);
-};
-
-class DLL_LINKAGE IGameEventCallback : public IGameEventRealizer
-{
-public:
-	virtual void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells)=0;
-	virtual bool removeObject(const CGObjectInstance * obj)=0;
-	virtual void setBlockVis(ObjectInstanceID objid, bool bv)=0;
-	virtual void setOwner(const CGObjectInstance * objid, PlayerColor owner)=0;
-	virtual void setHoverName(const CGObjectInstance * obj, MetaString * name)=0;
-	virtual void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false)=0;
-	virtual void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false)=0; 
-	virtual void showBlockingDialog(BlockingDialog *iw) =0;
-	virtual void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) =0; //cb will be called when player closes garrison window
-	virtual void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) =0;
-	virtual void giveResource(PlayerColor player, Res::ERes which, int val)=0;
-	virtual void giveResources(PlayerColor player, TResources resources)=0;
-
-	virtual void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0;
-	virtual void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) =0;
-	virtual bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) =0;
-	virtual bool changeStackType(const StackLocation &sl, CCreature *c) =0;
-	virtual bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count = -1) =0; //count -1 => moves whole stack
-	virtual bool eraseStack(const StackLocation &sl, bool forceRemoval = false) =0;
-	virtual bool swapStacks(const StackLocation &sl1, const StackLocation &sl2) =0;
-	virtual bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) =0; //makes new stack or increases count of already existing
-	virtual void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) =0; //merges army from src do dst or opens a garrison window
-	virtual bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count) = 0;
-
-	virtual void removeAfterVisit(const CGObjectInstance *object) = 0; //object will be destroyed when interaction is over. Do not call when interaction is not ongoing!
-
-	virtual void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) = 0;
-	virtual void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) = 0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
-	virtual void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) = 0;
-	virtual void removeArtifact(const ArtifactLocation &al) = 0;
-	virtual bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0;
-	virtual void synchronizeArtifactHandlerLists() = 0;
-
-	virtual void showCompInfo(ShowInInfobox * comp)=0;
-	virtual void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
-	virtual void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
-	virtual void startBattlePrimary(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, const CGTownInstance *town = nullptr)=0; //use hero=nullptr for no hero
-	virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank = false)=0; //if any of armies is hero, hero will be used
-	virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank = false)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
-	virtual void setAmount(ObjectInstanceID objid, ui32 val)=0;
-	virtual bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, PlayerColor asker = PlayerColor::NEUTRAL)=0;
-	virtual void giveHeroBonus(GiveBonus * bonus)=0;
-	virtual void setMovePoints(SetMovePoints * smp)=0;
-	virtual void setManaPoints(ObjectInstanceID hid, int val)=0;
-	virtual void giveHero(ObjectInstanceID id, PlayerColor player)=0;
-	virtual void changeObjPos(ObjectInstanceID objid, int3 newPos, ui8 flags)=0;
-	virtual void sendAndApply(CPackForClient * info)=0;
-	virtual void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)=0; //when two heroes meet on adventure map
-	virtual void addQuest(int player, QuestInfo & quest){};
-};
+/*class CSaveFile;
+class CLoadFile;*/
 
 /// Interface class for handling general game logic and actions
 class DLL_LINKAGE IGameCallback : public CPrivilagedInfoCallback, public IGameEventCallback
@@ -277,3 +78,4 @@ public:
 	friend struct CPackForClient;
 	friend struct CPackForServer;
 };
+

+ 951 - 0
lib/IGameCallback2.cpp

@@ -0,0 +1,951 @@
+/*
+ * IGameCallback.cpp, 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
+ *
+ */
+
+#include "StdInc.h"
+#include "IGameCallback2.h"
+
+#include "CGameState.h"
+/*#include "mapping/CMap.h"*/
+#include "CObjectHandler.h"
+#include "CHeroHandler.h"
+#include "StartInfo.h"
+/*#include "CArtHandler.h"*/
+#include "CSpellHandler.h"
+/*#include "VCMI_Lib.h"
+#include "CTownHandler.h"*/
+#include "BattleState.h"
+#include "NetPacks.h"
+/*#include "CBuildingHandler.h"
+#include "GameConstants.h"
+#include "CModHandler.h"
+#include "CDefObjInfoHandler.h"*/
+#include "CBonusTypeHandler.h"
+
+#include "Connection.h"
+
+//TODO make clean
+/*#define ERROR_SILENT_RET_VAL_IF(cond, txt, retVal) do {if(cond){return retVal;}} while(0)*/
+#define ERROR_VERBOSE_OR_NOT_RET_VAL_IF(cond, verbose, txt, retVal) do {if(cond){if(verbose)logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return retVal;}} while(0)
+#define ERROR_RET_IF(cond, txt) do {if(cond){logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return;}} while(0)
+#define ERROR_RET_VAL_IF(cond, txt, retVal) do {if(cond){logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return retVal;}} while(0)
+
+CGameState * CPrivilagedInfoCallback::gameState ()
+{
+	return gs;
+}
+
+PlayerColor CGameInfoCallback::getOwner(ObjectInstanceID heroID) const
+{
+	const CGObjectInstance *obj = getObj(heroID);
+	ERROR_RET_VAL_IF(!obj, "No such object!", PlayerColor::CANNOT_DETERMINE);
+	return obj->tempOwner;
+}
+
+int CGameInfoCallback::getResource(PlayerColor Player, Res::ERes which) const
+{
+	const PlayerState *p = getPlayer(Player);
+	ERROR_RET_VAL_IF(!p, "No player info!", -1);
+	ERROR_RET_VAL_IF(p->resources.size() <= which || which < 0, "No such resource!", -1);
+	return p->resources[which];
+}
+
+const CGHeroInstance* CGameInfoCallback::getSelectedHero( PlayerColor Player ) const
+{
+	const PlayerState *p = getPlayer(Player);
+	ERROR_RET_VAL_IF(!p, "No player info!", nullptr);
+	return getHero(p->currentSelection);
+}
+
+const CGHeroInstance* CGameInfoCallback::getSelectedHero() const
+{
+	return getSelectedHero(gs->currentPlayer);
+}
+
+const PlayerSettings * CGameInfoCallback::getPlayerSettings(PlayerColor color) const
+{
+	return &gs->scenarioOps->getIthPlayersSettings(color);
+}
+
+void CPrivilagedInfoCallback::getTilesInRange( std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player/*=uninit*/, int mode/*=0*/ ) const
+{
+	if(!!player && *player >= PlayerColor::PLAYER_LIMIT)
+	{
+        logGlobal->errorStream() << "Illegal call to getTilesInRange!";
+		return;
+	}
+	if (radious == -1) //reveal entire map
+		getAllTiles (tiles, player, -1, 0);
+	else
+	{
+		const TeamState * team = !player ? nullptr : gs->getPlayerTeam(*player);
+		for (int xd = std::max<int>(pos.x - radious , 0); xd <= std::min<int>(pos.x + radious, gs->map->width - 1); xd++)
+		{
+			for (int yd = std::max<int>(pos.y - radious, 0); yd <= std::min<int>(pos.y + radious, gs->map->height - 1); yd++)
+			{
+				double distance = pos.dist2d(int3(xd,yd,pos.z)) - 0.5;
+				if(distance <= radious)
+				{
+					if(!player
+						|| (mode == 1  && team->fogOfWarMap[xd][yd][pos.z]==0)
+						|| (mode == -1 && team->fogOfWarMap[xd][yd][pos.z]==1)
+					)
+						tiles.insert(int3(xd,yd,pos.z));
+				}
+			}
+		}
+	}
+}
+
+void CPrivilagedInfoCallback::getAllTiles (std::unordered_set<int3, ShashInt3> &tiles, boost::optional<PlayerColor> Player/*=uninit*/, int level, int surface ) const
+{
+	if(!!Player && *Player >= PlayerColor::PLAYER_LIMIT)
+	{
+        logGlobal->errorStream() << "Illegal call to getAllTiles !";
+		return;
+	}
+	bool water = surface == 0 || surface == 2,
+		land = surface == 0 || surface == 1;
+
+	std::vector<int> floors;
+	if(level == -1)
+	{
+		for(int b = 0; b < (gs->map->twoLevel ? 2 : 1); ++b)
+		{
+			floors.push_back(b);
+		}
+	}
+	else
+		floors.push_back(level);
+
+	for (auto zd : floors)
+	{
+		
+		for (int xd = 0; xd < gs->map->width; xd++)
+		{
+			for (int yd = 0; yd < gs->map->height; yd++)
+			{
+				if ((getTile (int3 (xd,yd,zd))->terType == ETerrainType::WATER && water)
+					|| (getTile (int3 (xd,yd,zd))->terType != ETerrainType::WATER && land))
+					tiles.insert(int3(xd,yd,zd));
+			}
+		}
+	}
+}
+
+void CPrivilagedInfoCallback::getFreeTiles (std::vector<int3> &tiles) const
+{
+	std::vector<int> floors;
+	for (int b = 0; b < (gs->map->twoLevel ? 2 : 1); ++b)
+	{
+		floors.push_back(b);
+	}
+	const TerrainTile *tinfo;
+	for (auto zd : floors)
+	{
+		
+		for (int xd = 0; xd < gs->map->width; xd++)
+		{
+			for (int yd = 0; yd < gs->map->height; yd++)
+			{
+				tinfo = getTile(int3 (xd,yd,zd));
+				if (tinfo->terType != ETerrainType::WATER && !tinfo->blocked) //land and free
+					tiles.push_back (int3 (xd,yd,zd));
+			}
+		}
+	}
+}
+
+bool CGameInfoCallback::isAllowed( int type, int id )
+{
+	switch(type)
+	{
+	case 0:
+		return gs->map->allowedSpell[id];
+	case 1:
+		return gs->map->allowedArtifact[id];
+	case 2:
+		return gs->map->allowedAbilities[id];
+	default:
+		ERROR_RET_VAL_IF(1, "Wrong type!", false);
+	}
+}
+
+void CPrivilagedInfoCallback::pickAllowedArtsSet(std::vector<const CArtifact*> &out)
+{
+	for (int j = 0; j < 3 ; j++)
+		out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_TREASURE)]);
+	for (int j = 0; j < 3 ; j++)
+		out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_MINOR)]);
+
+	out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_MAJOR)]);
+}
+
+void CPrivilagedInfoCallback::getAllowedSpells(std::vector<SpellID> &out, ui16 level)
+{
+	for (ui32 i = 0; i < gs->map->allowedSpell.size(); i++) //spellh size appears to be greater (?)
+	{
+
+		const CSpell *spell = SpellID(i).toSpell();
+		if (isAllowed (0, spell->id) && spell->level == level)
+		{
+			out.push_back(spell->id);
+		}
+	}
+}
+
+
+template<typename Loader>
+void CPrivilagedInfoCallback::loadCommonState(Loader &in)
+{
+    logGlobal->infoStream() << "Loading lib part of game...";
+	in.checkMagicBytes(SAVEGAME_MAGIC);
+
+	CMapHeader dum;
+	StartInfo *si;
+
+    logGlobal->infoStream() <<"\tReading header";
+	in >> dum;
+
+    logGlobal->infoStream() << "\tReading options";
+	in >> si;
+
+    logGlobal->infoStream() <<"\tReading handlers";
+	in >> *VLC;
+
+    logGlobal->infoStream() <<"\tReading gamestate";
+	in >> gs;
+}
+
+template<typename Saver>
+void CPrivilagedInfoCallback::saveCommonState(Saver &out) const
+{
+    logGlobal->infoStream() << "Saving lib part of game...";
+	out.putMagicBytes(SAVEGAME_MAGIC);
+    logGlobal->infoStream() <<"\tSaving header";
+	out << static_cast<CMapHeader&>(*gs->map);
+    logGlobal->infoStream() << "\tSaving options";
+	out << gs->scenarioOps;
+    logGlobal->infoStream() << "\tSaving handlers";
+	out << *VLC;
+    logGlobal->infoStream() << "\tSaving gamestate";
+	out << gs;
+}
+
+template DLL_LINKAGE void CPrivilagedInfoCallback::loadCommonState<CLoadIntegrityValidator>(CLoadIntegrityValidator&);
+template DLL_LINKAGE void CPrivilagedInfoCallback::loadCommonState<CLoadFile>(CLoadFile&);
+template DLL_LINKAGE void CPrivilagedInfoCallback::saveCommonState<CSaveFile>(CSaveFile&) const;
+
+TerrainTile * CNonConstInfoCallback::getTile( int3 pos )
+{
+	if(!gs->map->isInTheMap(pos))
+		return nullptr;
+	return &gs->map->getTile(pos);
+}
+
+const PlayerState * CGameInfoCallback::getPlayer(PlayerColor color, bool verbose) const
+{
+	ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!hasAccess(color), verbose, "Cannot access player " << color << "info!", nullptr);
+	ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!vstd::contains(gs->players,color), verbose, "Cannot find player " << color << "info!", nullptr);
+	return &gs->players[color];
+}
+
+const CTown * CGameInfoCallback::getNativeTown(PlayerColor color) const
+{
+	const PlayerSettings *ps = getPlayerSettings(color);
+	ERROR_RET_VAL_IF(!ps, "There is no such player!", nullptr);
+	return VLC->townh->factions[ps->castle]->town;
+}
+
+const CGObjectInstance * CGameInfoCallback::getObjByQuestIdentifier(int identifier) const
+{
+	ERROR_RET_VAL_IF(!vstd::contains(gs->map->questIdentifierToId, identifier), "There is no object with such quest identifier!", nullptr);
+	return getObj(gs->map->questIdentifierToId[identifier]);
+}
+
+/************************************************************************/
+/*                                                                      */
+/************************************************************************/
+
+const CGObjectInstance* CGameInfoCallback::getObj(ObjectInstanceID objid, bool verbose) const
+{
+	si32 oid = objid.num;
+	if(oid < 0  ||  oid >= gs->map->objects.size())
+	{
+		if(verbose)
+            logGlobal->errorStream() << "Cannot get object with id " << oid;
+		return nullptr;
+	}
+
+	const CGObjectInstance *ret = gs->map->objects[oid];
+	if(!ret)
+	{
+		if(verbose)
+            logGlobal->errorStream() << "Cannot get object with id " << oid << ". Object was removed.";
+		return nullptr;
+	}
+
+	if(!isVisible(ret, player))
+	{
+		if(verbose)
+            logGlobal->errorStream() << "Cannot get object with id " << oid << ". Object is not visible.";
+		return nullptr;
+	}
+
+	return ret;
+}
+
+const CGHeroInstance* CGameInfoCallback::getHero(ObjectInstanceID objid) const
+{
+	const CGObjectInstance *obj = getObj(objid, false);
+	if(obj)
+		return dynamic_cast<const CGHeroInstance*>(obj);
+	else
+		return nullptr;
+}
+const CGTownInstance* CGameInfoCallback::getTown(ObjectInstanceID objid) const
+{
+	const CGObjectInstance *obj = getObj(objid, false);
+	if(obj)
+		return dynamic_cast<const CGTownInstance*>(obj);
+	else
+		return nullptr;
+}
+
+void CGameInfoCallback::getUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out) const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	ERROR_RET_IF(!canGetFullInfo(obj), "Cannot get info about not owned object!");
+	ERROR_RET_IF(!obj->hasStackAtSlot(stackPos), "There is no such stack!");
+	out = gs->getUpgradeInfo(obj->getStack(stackPos));
+	//return gs->getUpgradeInfo(obj->getStack(stackPos));
+}
+
+const StartInfo * CGameInfoCallback::getStartInfo(bool beforeRandomization /*= false*/) const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	if(beforeRandomization)
+		return gs->initialOpts;
+	else
+		return gs->scenarioOps;
+}
+
+int CGameInfoCallback::getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	ERROR_RET_VAL_IF(!canGetFullInfo(caster), "Cannot get info about caster!", -1);
+	//if there is a battle
+	if(gs->curB)
+		return gs->curB->battleGetSpellCost(sp, caster);
+
+	//if there is no battle
+	return caster->getSpellCost(sp);
+}
+
+int CGameInfoCallback::estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+
+	ERROR_RET_VAL_IF(hero && !canGetFullInfo(hero), "Cannot get info about caster!", -1);
+	if(!gs->curB) //no battle
+	{
+		if (hero) //but we see hero's spellbook
+			return gs->curB->calculateSpellDmg(
+				sp, hero, nullptr, hero->getSpellSchoolLevel(sp), hero->getPrimSkillLevel(PrimarySkill::SPELL_POWER));
+		else
+			return 0; //mage guild
+	}
+	//gs->getHero(gs->currentPlayer)
+	//const CGHeroInstance * ourHero = gs->curB->heroes[0]->tempOwner == player ? gs->curB->heroes[0] : gs->curB->heroes[1];
+	const CGHeroInstance * ourHero = hero;
+	return gs->curB->calculateSpellDmg(
+		sp, ourHero, nullptr, ourHero->getSpellSchoolLevel(sp), ourHero->getPrimSkillLevel(PrimarySkill::SPELL_POWER));
+}
+
+void CGameInfoCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj)
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	ERROR_RET_IF(!obj, "No guild object!");
+	ERROR_RET_IF(obj->ID == Obj::TOWN && !canGetFullInfo(obj), "Cannot get info about town guild object!");
+	//TODO: advmap object -> check if they're visited by our hero
+
+	if(obj->ID == Obj::TOWN  ||  obj->ID == Obj::TAVERN)
+	{
+		gs->obtainPlayersStats(thi, gs->players[obj->tempOwner].towns.size());
+	}
+	else if(obj->ID == Obj::DEN_OF_THIEVES)
+	{
+		gs->obtainPlayersStats(thi, 20);
+	}
+}
+
+int CGameInfoCallback::howManyTowns(PlayerColor Player) const
+{
+	ERROR_RET_VAL_IF(!hasAccess(Player), "Access forbidden!", -1);
+	return gs->players[Player].towns.size();
+}
+
+bool CGameInfoCallback::getTownInfo( const CGObjectInstance *town, InfoAboutTown &dest ) const
+{
+	ERROR_RET_VAL_IF(!isVisible(town, player), "Town is not visible!", false);  //it's not a town or it's not visible for layer
+	bool detailed = hasAccess(town->tempOwner);
+
+	//TODO vision support
+	if(town->ID == Obj::TOWN)
+		dest.initFromTown(static_cast<const CGTownInstance *>(town), detailed);
+	else if(town->ID == Obj::GARRISON || town->ID == Obj::GARRISON2)
+		dest.initFromArmy(static_cast<const CArmedInstance *>(town), detailed);
+	else
+		return false;
+	return true;
+}
+
+int3 CGameInfoCallback::guardingCreaturePosition (int3 pos) const //FIXME: redundant?
+{
+	ERROR_RET_VAL_IF(!isVisible(pos), "Tile is not visible!", int3(-1,-1,-1));
+	return gs->guardingCreaturePosition(pos);
+}
+
+std::vector<const CGObjectInstance*> CGameInfoCallback::getGuardingCreatures (int3 pos) const
+{
+	ERROR_RET_VAL_IF(!isVisible(pos), "Tile is not visible!", std::vector<const CGObjectInstance*>());
+	std::vector<const CGObjectInstance*> ret;
+	for(auto cr : gs->guardingCreatures(pos))
+	{
+		ret.push_back(cr);
+	}
+	return ret;
+}
+
+bool CGameInfoCallback::getHeroInfo( const CGObjectInstance *hero, InfoAboutHero &dest ) const
+{
+	const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(hero);
+
+	ERROR_RET_VAL_IF(!h, "That's not a hero!", false);
+	ERROR_RET_VAL_IF(!isVisible(h->getPosition(false)), "That hero is not visible!", false);
+
+	//TODO vision support
+	dest.initFromHero(h, hasAccess(h->tempOwner));
+	return true;
+}
+
+int CGameInfoCallback::getDate(Date::EDateType mode) const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	return gs->getDate(mode);
+}
+std::vector < std::string > CGameInfoCallback::getObjDescriptions(int3 pos) const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	std::vector<std::string> ret;
+	const TerrainTile *t = getTile(pos);
+	ERROR_RET_VAL_IF(!t, "Not a valid tile given!", ret);
+
+
+	for(const CGObjectInstance * obj : t->blockingObjects)
+		ret.push_back(obj->getHoverText());
+	return ret;
+}
+
+bool CGameInfoCallback::isVisible(int3 pos, boost::optional<PlayerColor> Player) const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	return gs->map->isInTheMap(pos) && (!Player || gs->isVisible(pos, *Player));
+}
+
+bool CGameInfoCallback::isVisible(int3 pos) const
+{
+	return isVisible(pos, player);
+}
+
+bool CGameInfoCallback::isVisible( const CGObjectInstance *obj, boost::optional<PlayerColor> Player ) const
+{
+	return gs->isVisible(obj, Player);
+}
+
+bool CGameInfoCallback::isVisible(const CGObjectInstance *obj) const
+{
+	return isVisible(obj, player);
+}
+// const CCreatureSet* CInfoCallback::getGarrison(const CGObjectInstance *obj) const
+// {
+// 	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+// 	if()
+// 	const CArmedInstance *armi = dynamic_cast<const CArmedInstance*>(obj);
+// 	if(!armi)
+// 		return nullptr;
+// 	else
+// 		return armi;
+// }
+
+std::vector < const CGObjectInstance * > CGameInfoCallback::getBlockingObjs( int3 pos ) const
+{
+	std::vector<const CGObjectInstance *> ret;
+	const TerrainTile *t = getTile(pos);
+	ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
+
+	for(const CGObjectInstance * obj : t->blockingObjects)
+		ret.push_back(obj);
+	return ret;
+}
+
+std::vector <const CGObjectInstance * > CGameInfoCallback::getVisitableObjs(int3 pos, bool verbose /*= true*/) const
+{
+	std::vector<const CGObjectInstance *> ret;
+	const TerrainTile *t = getTile(pos, verbose);
+	ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!t, verbose, pos << " is not visible!", ret);
+
+	for(const CGObjectInstance * obj : t->visitableObjects)
+	{
+		if(player < nullptr || obj->ID != Obj::EVENT) //hide events from players
+			ret.push_back(obj);
+	}
+
+	return ret;
+}
+const CGObjectInstance * CGameInfoCallback::getTopObj (int3 pos) const
+{
+	return vstd::backOrNull(getVisitableObjs(pos));
+}
+
+std::vector < const CGObjectInstance * > CGameInfoCallback::getFlaggableObjects(int3 pos) const
+{
+	std::vector<const CGObjectInstance *> ret;
+	const TerrainTile *t = getTile(pos);
+	ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
+	for(const CGObjectInstance *obj : t->blockingObjects)
+		if(obj->tempOwner != PlayerColor::UNFLAGGABLE)
+			ret.push_back(obj);
+// 	const std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > & objs = CGI->mh->ttiles[pos.x][pos.y][pos.z].objects;
+// 	for(size_t b=0; b<objs.size(); ++b)
+// 	{
+// 		if(objs[b].first->tempOwner!=254 && !((objs[b].first->defInfo->blockMap[pos.y - objs[b].first->pos.y + 5] >> (objs[b].first->pos.x - pos.x)) & 1))
+// 			ret.push_back(CGI->mh->ttiles[pos.x][pos.y][pos.z].objects[b].first);
+// 	}
+	return ret;
+}
+
+int3 CGameInfoCallback::getMapSize() const
+{
+	return int3(gs->map->width, gs->map->height, gs->map->twoLevel ? 2 : 1);
+}
+
+std::vector<const CGHeroInstance *> CGameInfoCallback::getAvailableHeroes(const CGObjectInstance * townOrTavern) const
+{
+	ASSERT_IF_CALLED_WITH_PLAYER
+	std::vector<const CGHeroInstance *> ret;
+	//ERROR_RET_VAL_IF(!isOwnedOrVisited(townOrTavern), "Town or tavern must be owned or visited!", ret);
+	//TODO: town needs to be owned, advmap tavern needs to be visited; to be reimplemented when visit tracking is done
+	range::copy(gs->players[*player].availableHeroes, std::back_inserter(ret));
+	vstd::erase_if(ret, [](const CGHeroInstance *h) { return h == nullptr; });
+	return ret;
+}
+
+const TerrainTile * CGameInfoCallback::getTile( int3 tile, bool verbose) const
+{
+	ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!isVisible(tile), verbose, tile << " is not visible!", nullptr);
+
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	return &gs->map->getTile(tile);
+}
+
+EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, BuildingID ID )
+{
+	ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", EBuildingState::TOWN_NOT_OWNED);
+
+	if(!t->town->buildings.count(ID))
+		return EBuildingState::BUILDING_ERROR;
+
+	const CBuilding * building = t->town->buildings.at(ID);
+
+
+	if(t->hasBuilt(ID))	//already built
+		return EBuildingState::ALREADY_PRESENT;
+
+	//can we build it?
+	if(vstd::contains(t->forbiddenBuildings, ID))
+		return EBuildingState::FORBIDDEN; //forbidden
+
+	if(ID == BuildingID::CAPITOL)
+	{
+		const PlayerState *ps = getPlayer(t->tempOwner);
+		if(ps)
+		{
+			for(const CGTownInstance *t : ps->towns)
+			{
+				if(t->hasBuilt(BuildingID::CAPITOL))
+				{
+					return EBuildingState::HAVE_CAPITAL; //no more than one capitol
+				}
+			}
+		}
+	}
+	else if(ID == BuildingID::SHIPYARD)
+	{
+		const TerrainTile *tile = getTile(t->bestLocation(), false);
+
+		if(!tile || tile->terType != ETerrainType::WATER)
+			return EBuildingState::NO_WATER; //lack of water
+	}
+
+	auto buildTest = [&](const BuildingID & id)
+	{
+		return t->hasBuilt(id);
+	};
+
+	if(t->builded >= VLC->modh->settings.MAX_BUILDING_PER_TURN)
+		return EBuildingState::CANT_BUILD_TODAY; //building limit
+
+	if (!building->requirements.test(buildTest))
+		return EBuildingState::PREREQUIRES;
+
+	if (building->upgrade != BuildingID::NONE && !t->hasBuilt(building->upgrade))
+		return EBuildingState::MISSING_BASE;
+
+	//checking resources
+	if(!building->resources.canBeAfforded(getPlayer(t->tempOwner)->resources))
+		return EBuildingState::NO_RESOURCES; //lack of res
+
+	return EBuildingState::ALLOWED;
+}
+
+const CMapHeader * CGameInfoCallback::getMapHeader() const
+{
+	return gs->map;
+}
+
+bool CGameInfoCallback::hasAccess(boost::optional<PlayerColor> playerId) const
+{
+	return !player || gs->getPlayerRelations( *playerId, *player ) != PlayerRelations::ENEMIES;
+}
+
+EPlayerStatus::EStatus CGameInfoCallback::getPlayerStatus(PlayerColor player, bool verbose) const
+{
+	const PlayerState *ps = gs->getPlayer(player, verbose);
+	ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!ps, verbose, "No such player!", EPlayerStatus::WRONG);
+
+	return ps->status;
+}
+
+std::string CGameInfoCallback::getTavernGossip(const CGObjectInstance * townOrTavern) const
+{
+	return "GOSSIP TEST";
+}
+
+PlayerRelations::PlayerRelations CGameInfoCallback::getPlayerRelations( PlayerColor color1, PlayerColor color2 ) const
+{
+	return gs->getPlayerRelations(color1, color2);
+}
+
+bool CGameInfoCallback::canGetFullInfo(const CGObjectInstance *obj) const
+{
+	return !obj || hasAccess(obj->tempOwner);
+}
+
+int CGameInfoCallback::getHeroCount( PlayerColor player, bool includeGarrisoned ) const
+{
+	int ret = 0;
+	const PlayerState *p = gs->getPlayer(player);
+	ERROR_RET_VAL_IF(!p, "No such player!", -1);
+
+	if(includeGarrisoned)
+		return p->heroes.size();
+	else
+		for(auto & elem : p->heroes)
+			if(!elem->inTownGarrison)
+				ret++;
+	return ret;
+}
+
+bool CGameInfoCallback::isOwnedOrVisited(const CGObjectInstance *obj) const
+{
+	if(canGetFullInfo(obj))
+		return true;
+
+	const TerrainTile *t = getTile(obj->visitablePos()); //get entrance tile
+	const CGObjectInstance *visitor = t->visitableObjects.back(); //visitong hero if present or the obejct itself at last
+	return visitor->ID == Obj::HERO && canGetFullInfo(visitor); //owned or allied hero is a visitor
+}
+
+PlayerColor CGameInfoCallback::getCurrentPlayer() const
+{
+	return gs->currentPlayer;
+}
+
+CGameInfoCallback::CGameInfoCallback()
+{
+}
+
+CGameInfoCallback::CGameInfoCallback(CGameState *GS, boost::optional<PlayerColor> Player)
+{
+	gs = GS;
+	player = Player;
+}
+
+const std::vector< std::vector< std::vector<ui8> > > & CPlayerSpecificInfoCallback::getVisibilityMap() const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	return gs->getPlayerTeam(*player)->fogOfWarMap;
+}
+
+int CPlayerSpecificInfoCallback::howManyTowns() const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	ERROR_RET_VAL_IF(!player, "Applicable only for player callbacks", -1);
+	return CGameInfoCallback::howManyTowns(*player);
+}
+
+std::vector < const CGTownInstance *> CPlayerSpecificInfoCallback::getTownsInfo(bool onlyOur) const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	std::vector < const CGTownInstance *> ret = std::vector < const CGTownInstance *>();
+	for(const auto & i : gs->players)
+	{
+		for(const auto & town : i.second.towns)
+		{
+			if (i.first==player || (isVisible(town, player) && !onlyOur))
+			{
+				ret.push_back(town);
+			}
+		}
+	} //	for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
+	return ret;
+}
+std::vector < const CGHeroInstance *> CPlayerSpecificInfoCallback::getHeroesInfo(bool onlyOur) const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	std::vector < const CGHeroInstance *> ret;
+	for(auto hero : gs->map->heroesOnMap)
+	{
+		if( !player || (hero->tempOwner == *player) ||
+			(isVisible(hero->getPosition(false), player) && !onlyOur)	)
+		{
+			ret.push_back(hero);
+		}
+	}
+	return ret;
+}
+
+boost::optional<PlayerColor> CPlayerSpecificInfoCallback::getMyColor() const
+{
+	return player;
+}
+
+int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool includeGarrisoned) const
+{
+	if (hero->inTownGarrison && !includeGarrisoned)
+		return -1;
+
+	size_t index = 0;
+	auto & heroes = gs->players[*player].heroes;
+
+	for (auto & heroe : heroes)
+	{
+		if (includeGarrisoned || !(heroe)->inTownGarrison)
+			index++;
+
+		if (heroe == hero)
+			return index;
+	}
+	return -1;
+}
+
+int3 CPlayerSpecificInfoCallback::getGrailPos( double &outKnownRatio )
+{
+	if (!player || CGObelisk::obeliskCount == 0)
+	{
+		outKnownRatio = 0.0;
+	}
+	else
+	{
+		outKnownRatio = static_cast<double>(CGObelisk::visited[gs->getPlayerTeam(*player)->id]) / CGObelisk::obeliskCount;
+	}
+	return gs->map->grailPos;
+}
+
+std::vector < const CGObjectInstance * > CPlayerSpecificInfoCallback::getMyObjects() const
+{
+	std::vector < const CGObjectInstance * > ret;
+	for(const CGObjectInstance * obj : gs->map->objects)
+	{
+		if(obj && obj->tempOwner == player)
+			ret.push_back(obj);
+	}
+	return ret;
+}
+
+std::vector < const CGDwelling * > CPlayerSpecificInfoCallback::getMyDwellings() const
+{
+	ASSERT_IF_CALLED_WITH_PLAYER
+	std::vector < const CGDwelling * > ret;
+	for(CGDwelling * dw : gs->getPlayer(*player)->dwellings)
+	{
+		ret.push_back(dw);
+	}
+	return ret;
+}
+
+std::vector <QuestInfo> CPlayerSpecificInfoCallback::getMyQuests() const
+{
+	std::vector <QuestInfo> ret;
+	for (auto quest : gs->getPlayer(*player)->quests)
+	{
+		ret.push_back (quest);
+	}
+	return ret;
+}
+
+int CPlayerSpecificInfoCallback::howManyHeroes(bool includeGarrisoned) const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	ERROR_RET_VAL_IF(!player, "Applicable only for player callbacks", -1);
+	return getHeroCount(*player,includeGarrisoned);
+}
+
+const CGHeroInstance* CPlayerSpecificInfoCallback::getHeroBySerial(int serialId, bool includeGarrisoned) const
+{
+	ASSERT_IF_CALLED_WITH_PLAYER
+	const PlayerState *p = getPlayer(*player);
+	ERROR_RET_VAL_IF(!p, "No player info", nullptr);
+
+	if (!includeGarrisoned)
+	{
+		for(ui32 i = 0; i < p->heroes.size() && i<=serialId; i++)
+			if(p->heroes[i]->inTownGarrison)
+				serialId++;
+	}
+	ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->heroes.size(), "No player info", nullptr);
+	return p->heroes[serialId];
+}
+
+const CGTownInstance* CPlayerSpecificInfoCallback::getTownBySerial(int serialId) const
+{
+	ASSERT_IF_CALLED_WITH_PLAYER
+	const PlayerState *p = getPlayer(*player);
+	ERROR_RET_VAL_IF(!p, "No player info", nullptr);
+	ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->towns.size(), "No player info", nullptr);
+	return p->towns[serialId];
+}
+
+int CPlayerSpecificInfoCallback::getResourceAmount(Res::ERes type) const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	ERROR_RET_VAL_IF(!player, "Applicable only for player callbacks", -1);
+	return getResource(*player, type);
+}
+
+TResources CPlayerSpecificInfoCallback::getResourceAmount() const
+{
+	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	ERROR_RET_VAL_IF(!player, "Applicable only for player callbacks", TResources());
+	return gs->players[*player].resources;
+}
+
+CGHeroInstance *CNonConstInfoCallback::getHero(ObjectInstanceID objid)
+{
+	return const_cast<CGHeroInstance*>(CGameInfoCallback::getHero(objid));
+}
+
+CGTownInstance *CNonConstInfoCallback::getTown(ObjectInstanceID objid)
+{
+	return const_cast<CGTownInstance*>(CGameInfoCallback::getTown(objid));
+}
+
+TeamState *CNonConstInfoCallback::getTeam(TeamID teamID)
+{
+	return const_cast<TeamState*>(CGameInfoCallback::getTeam(teamID));
+}
+
+TeamState *CNonConstInfoCallback::getPlayerTeam(PlayerColor color)
+{
+	return const_cast<TeamState*>(CGameInfoCallback::getPlayerTeam(color));
+}
+
+PlayerState * CNonConstInfoCallback::getPlayer( PlayerColor color, bool verbose )
+{
+	return const_cast<PlayerState*>(CGameInfoCallback::getPlayer(color, verbose));
+}
+
+CArtifactInstance * CNonConstInfoCallback::getArtInstance( ArtifactInstanceID aid )
+{
+	return gs->map->artInstances[aid.num];
+}
+
+CGObjectInstance * CNonConstInfoCallback::getObjInstance( ObjectInstanceID oid )
+{
+	return gs->map->objects[oid.num];
+}
+
+const TeamState * CGameInfoCallback::getTeam( TeamID teamID ) const
+{
+	ERROR_RET_VAL_IF(!vstd::contains(gs->teams, teamID), "Cannot find info for team " << teamID, nullptr);
+	const TeamState *ret = &gs->teams[teamID];
+	ERROR_RET_VAL_IF(!!player && !vstd::contains(ret->players, *player), "Illegal attempt to access team data!", nullptr);
+	return ret;
+}
+
+const TeamState * CGameInfoCallback::getPlayerTeam( PlayerColor color ) const
+{
+	const PlayerState * ps = getPlayer(color);
+	if (ps)
+		return getTeam(ps->team);
+	return nullptr;
+}
+
+const CGHeroInstance* CGameInfoCallback::getHeroWithSubid( int subid ) const
+{
+	for(const CGHeroInstance *h : gs->map->heroesOnMap)
+		if(h->subID == subid)
+			return h;
+
+	return nullptr;
+}
+
+PlayerColor CGameInfoCallback::getLocalPlayer() const
+{
+	return getCurrentPlayer();
+}
+
+bool CGameInfoCallback::isInTheMap(const int3 &pos) const
+{
+	return gs->map->isInTheMap(pos);
+}
+
+const CArtifactInstance * CGameInfoCallback::getArtInstance( ArtifactInstanceID aid ) const
+{
+	return gs->map->artInstances[aid.num];
+}
+
+const CGObjectInstance * CGameInfoCallback::getObjInstance( ObjectInstanceID oid ) const
+{
+	return gs->map->objects[oid.num];
+}
+
+void IGameEventRealizer::showInfoDialog( InfoWindow *iw )
+{
+	commitPackage(iw);
+}
+
+void IGameEventRealizer::showInfoDialog(const std::string &msg, PlayerColor player)
+{
+	InfoWindow iw;
+	iw.player = player;
+	iw.text << msg;
+	showInfoDialog(&iw);
+}
+
+void IGameEventRealizer::setObjProperty(ObjectInstanceID objid, int prop, si64 val)
+{
+	SetObjectProperty sob;
+	sob.id = objid;
+	sob.what = prop;
+	sob.val = static_cast<ui32>(val);
+	commitPackage(&sob);
+}
+

+ 262 - 0
lib/IGameCallback2.h

@@ -0,0 +1,262 @@
+#pragma once
+
+
+/*#include "BattleHex.h"*/
+#include "ResourceSet.h"
+#include "int3.h"
+/*#include "GameConstants.h"*/
+#include "CBattleCallback.h" //for CCallbackBase
+
+/*
+ * 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
+ *
+ */
+
+struct SetMovePoints;
+struct GiveBonus;
+class CGObjectInstance;
+/*class CGTownInstance;
+class CGHeroInstance;*/
+struct BlockingDialog;
+struct InfoWindow;
+struct MetaString;
+struct ShowInInfobox;
+/*struct BattleResult;
+struct Component;
+class CGameState;*/
+struct PlayerSettings;
+struct CPackForClient;
+/*class CArtHandler;
+class CArtifact;
+class CArmedInstance;*/
+struct TerrainTile;
+struct PlayerState;
+class CTown;
+struct StackLocation;
+struct ArtifactLocation;
+/*class CArtifactInstance;*/
+struct StartInfo;
+struct InfoAboutTown;
+struct UpgradeInfo;
+struct SThievesGuildInfo;
+/*struct CPath;*/
+class CGDwelling;
+/*struct InfoAboutHero;*/
+class CMapHeader;
+/*struct BattleAction;
+class CStack;
+class CSpell;*/
+class CCreatureSet;
+/*class CCreature;*/
+class CStackBasicDescriptor;
+struct TeamState;
+struct QuestInfo;
+/*class CGCreature;
+class CSaveFile;
+class CLoadFile;
+*/
+class DLL_LINKAGE CGameInfoCallback : public virtual CCallbackBase
+{
+protected:
+	CGameInfoCallback();
+	CGameInfoCallback(CGameState *GS, boost::optional<PlayerColor> Player);
+	bool hasAccess(boost::optional<PlayerColor> playerId) const;
+	bool isVisible(int3 pos, boost::optional<PlayerColor> Player) const;
+	bool isVisible(const CGObjectInstance *obj, boost::optional<PlayerColor> Player) const;
+	bool isVisible(const CGObjectInstance *obj) const;
+
+	bool canGetFullInfo(const CGObjectInstance *obj) const; //true we player owns obj or ally owns obj or privileged mode
+	bool isOwnedOrVisited(const CGObjectInstance *obj) const;
+
+public:
+	//various
+	int getDate(Date::EDateType mode=Date::DAY)const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
+	const StartInfo * getStartInfo(bool beforeRandomization = false)const;
+	bool isAllowed(int type, int id); //type: 0 - spell; 1- artifact; 2 - secondary skill
+
+	//player
+	const PlayerState * getPlayer(PlayerColor color, bool verbose = true) const;
+	int getResource(PlayerColor Player, Res::ERes which) const;
+	bool isVisible(int3 pos) const;
+	PlayerRelations::PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2) const;
+	void getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj); //get thieves' guild info obtainable while visiting given object
+	EPlayerStatus::EStatus getPlayerStatus(PlayerColor player, bool verbose = true) const; //-1 if no such player
+	PlayerColor getCurrentPlayer() const; //player that currently makes move // TODO synchronous turns
+	virtual PlayerColor getLocalPlayer() const; //player that is currently owning given client (if not a client, then returns current player)
+	const PlayerSettings * getPlayerSettings(PlayerColor color) const;
+
+
+	//armed object
+	void getUpgradeInfo(const CArmedInstance *obj, SlotID stackPos, UpgradeInfo &out)const;
+
+	//hero
+	const CGHeroInstance* getHero(ObjectInstanceID objid) const;
+	const CGHeroInstance* getHeroWithSubid(int subid) const;
+	int getHeroCount(PlayerColor player, bool includeGarrisoned) const;
+	bool getHeroInfo(const CGObjectInstance *hero, InfoAboutHero &dest) const;
+	int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //when called during battle, takes into account creatures' spell cost reduction
+	int estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const; //estimates damage of given spell; returns 0 if spell causes no dmg
+	const CGHeroInstance* getSelectedHero(PlayerColor player) const; //nullptr if no hero is selected
+	const CGHeroInstance* getSelectedHero() const; //of current (active) player
+	const CArtifactInstance * getArtInstance(ArtifactInstanceID aid) const;
+	const CGObjectInstance * getObjInstance(ObjectInstanceID oid) const;
+
+	//objects
+	const CGObjectInstance* getObj(ObjectInstanceID objid, bool verbose = true) const;
+	std::vector <const CGObjectInstance * > getBlockingObjs(int3 pos)const;
+	std::vector <const CGObjectInstance * > getVisitableObjs(int3 pos, bool verbose = true)const;
+	std::vector <const CGObjectInstance * > getFlaggableObjects(int3 pos) const;
+	const CGObjectInstance * getTopObj (int3 pos) const;
+	std::vector <std::string > getObjDescriptions(int3 pos)const; //returns descriptions of objects at pos in order from the lowest to the highest
+	PlayerColor getOwner(ObjectInstanceID heroID) const;
+	const CGObjectInstance *getObjByQuestIdentifier(int identifier) const; //nullptr if object has been removed (eg. killed)
+
+	//map
+	int3 guardingCreaturePosition (int3 pos) const;
+	std::vector<const CGObjectInstance*> getGuardingCreatures (int3 pos) const;
+	const CMapHeader * getMapHeader()const;
+	int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map
+	const TerrainTile * getTile(int3 tile, bool verbose = true) const;
+	bool isInTheMap(const int3 &pos) const;
+
+	//town
+	const CGTownInstance* getTown(ObjectInstanceID objid) const;
+	int howManyTowns(PlayerColor Player) const;
+	const CGTownInstance * getTownInfo(int val, bool mode)const; //mode = 0 -> val = player town serial; mode = 1 -> val = object id (serial)
+	std::vector<const CGHeroInstance *> getAvailableHeroes(const CGObjectInstance * townOrTavern) const; //heroes that can be recruited
+	std::string getTavernGossip(const CGObjectInstance * townOrTavern) const; 
+	EBuildingState::EBuildingState canBuildStructure(const CGTownInstance *t, BuildingID ID);//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
+	virtual bool getTownInfo(const CGObjectInstance *town, InfoAboutTown &dest) const;
+	const CTown *getNativeTown(PlayerColor color) const;
+
+	//from gs
+	const TeamState *getTeam(TeamID teamID) const;
+	const TeamState *getPlayerTeam(PlayerColor color) const;
+	EBuildingState::EBuildingState canBuildStructure(const CGTownInstance *t, BuildingID ID) const;// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
+};
+
+
+class DLL_LINKAGE CPlayerSpecificInfoCallback : public CGameInfoCallback
+{
+public:
+	int howManyTowns() const;
+	int howManyHeroes(bool includeGarrisoned = true) const;
+	int3 getGrailPos(double &outKnownRatio);
+	boost::optional<PlayerColor> getMyColor() const;
+
+	std::vector <const CGTownInstance *> getTownsInfo(bool onlyOur = true) const; //true -> only owned; false -> all visible
+	int getHeroSerial(const CGHeroInstance * hero, bool includeGarrisoned=true) const;
+	const CGTownInstance* getTownBySerial(int serialId) const; // serial id is [0, number of towns)
+	const CGHeroInstance* getHeroBySerial(int serialId, bool includeGarrisoned=true) const; // serial id is [0, number of heroes)
+	std::vector <const CGHeroInstance *> getHeroesInfo(bool onlyOur = true) const; //true -> only owned; false -> all visible
+	std::vector <const CGDwelling *> getMyDwellings() const; //returns all dwellings that belong to player
+	std::vector <const CGObjectInstance * > getMyObjects() const; //returns all objects flagged by belonging player
+	std::vector <QuestInfo> getMyQuests() const;
+
+	int getResourceAmount(Res::ERes type) const;
+	TResources getResourceAmount() const;
+	const std::vector< std::vector< std::vector<ui8> > > & getVisibilityMap()const; //returns visibility map 
+	const PlayerSettings * getPlayerSettings(PlayerColor color) const;
+};
+
+class DLL_LINKAGE CPrivilagedInfoCallback : public CGameInfoCallback
+{
+public:
+	CGameState * gameState();
+	void getFreeTiles (std::vector<int3> &tiles) const; //used for random spawns
+	void getTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int mode=0) const;  //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 -  only unrevealed
+	void getAllTiles (std::unordered_set<int3, ShashInt3> &tiles, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int level=-1, int surface=0) const; //returns all tiles on given level (-1 - both levels, otherwise number of level); surface: 0 - land and water, 1 - only land, 2 - only water
+	void pickAllowedArtsSet(std::vector<const CArtifact*> &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
+	void getAllowedSpells(std::vector<SpellID> &out, ui16 level);
+
+	template<typename Saver>
+	void saveCommonState(Saver &out) const; //stores GS and VLC
+
+	template<typename Loader>
+	void loadCommonState(Loader &in); //loads GS and VLC
+};
+
+class DLL_LINKAGE CNonConstInfoCallback : public CPrivilagedInfoCallback
+{
+public:
+	PlayerState *getPlayer(PlayerColor color, bool verbose = true);
+	TeamState *getTeam(TeamID teamID);//get team by team ID
+	TeamState *getPlayerTeam(PlayerColor color);// get team by player color
+	CGHeroInstance *getHero(ObjectInstanceID objid);
+	CGTownInstance *getTown(ObjectInstanceID objid);
+	TerrainTile * getTile(int3 pos);
+	CArtifactInstance * getArtInstance(ArtifactInstanceID aid);
+	CGObjectInstance * getObjInstance(ObjectInstanceID oid);
+};
+
+class DLL_LINKAGE IGameEventRealizer
+{
+public:
+	virtual void commitPackage(CPackForClient *pack) = 0;
+
+	virtual void showInfoDialog(InfoWindow *iw);
+	virtual void setObjProperty(ObjectInstanceID objid, int prop, si64 val);
+
+
+	virtual void showInfoDialog(const std::string &msg, PlayerColor player);
+};
+
+class DLL_LINKAGE IGameEventCallback : public IGameEventRealizer
+{
+public:
+	virtual void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells)=0;
+	virtual bool removeObject(const CGObjectInstance * obj)=0;
+	virtual void setBlockVis(ObjectInstanceID objid, bool bv)=0;
+	virtual void setOwner(const CGObjectInstance * objid, PlayerColor owner)=0;
+	virtual void setHoverName(const CGObjectInstance * obj, MetaString * name)=0;
+	virtual void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false)=0;
+	virtual void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false)=0; 
+	virtual void showBlockingDialog(BlockingDialog *iw) =0;
+	virtual void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) =0; //cb will be called when player closes garrison window
+	virtual void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) =0;
+	virtual void giveResource(PlayerColor player, Res::ERes which, int val)=0;
+	virtual void giveResources(PlayerColor player, TResources resources)=0;
+
+	virtual void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0;
+	virtual void takeCreatures(ObjectInstanceID objid, const std::vector<CStackBasicDescriptor> &creatures) =0;
+	virtual bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) =0;
+	virtual bool changeStackType(const StackLocation &sl, CCreature *c) =0;
+	virtual bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count = -1) =0; //count -1 => moves whole stack
+	virtual bool eraseStack(const StackLocation &sl, bool forceRemoval = false) =0;
+	virtual bool swapStacks(const StackLocation &sl1, const StackLocation &sl2) =0;
+	virtual bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) =0; //makes new stack or increases count of already existing
+	virtual void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) =0; //merges army from src do dst or opens a garrison window
+	virtual bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count) = 0;
+
+	virtual void removeAfterVisit(const CGObjectInstance *object) = 0; //object will be destroyed when interaction is over. Do not call when interaction is not ongoing!
+
+	virtual void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, ArtifactPosition pos) = 0;
+	virtual void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) = 0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
+	virtual void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) = 0;
+	virtual void removeArtifact(const ArtifactLocation &al) = 0;
+	virtual bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0;
+	virtual void synchronizeArtifactHandlerLists() = 0;
+
+	virtual void showCompInfo(ShowInInfobox * comp)=0;
+	virtual void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
+	virtual void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
+	virtual void startBattlePrimary(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, const CGTownInstance *town = nullptr)=0; //use hero=nullptr for no hero
+	virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank = false)=0; //if any of armies is hero, hero will be used
+	virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank = false)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
+	virtual void setAmount(ObjectInstanceID objid, ui32 val)=0;
+	virtual bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, PlayerColor asker = PlayerColor::NEUTRAL)=0;
+	virtual void giveHeroBonus(GiveBonus * bonus)=0;
+	virtual void setMovePoints(SetMovePoints * smp)=0;
+	virtual void setManaPoints(ObjectInstanceID hid, int val)=0;
+	virtual void giveHero(ObjectInstanceID id, PlayerColor player)=0;
+	virtual void changeObjPos(ObjectInstanceID objid, int3 newPos, ui8 flags)=0;
+	virtual void sendAndApply(CPackForClient * info)=0;
+	virtual void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)=0; //when two heroes meet on adventure map
+	virtual void addQuest(int player, QuestInfo & quest){};
+};
+

+ 1 - 1
lib/filesystem/CFileInputStream.cpp

@@ -55,7 +55,7 @@ si64 CFileInputStream::seek(si64 position)
 
 si64 CFileInputStream::tell()
 {
-	return fileStream.tellg() - dataStart;
+	return static_cast<si64>(fileStream.tellg()) - dataStart;
 }
 
 si64 CFileInputStream::skip(si64 delta)

+ 1 - 0
scripting/erm/ERMInterpreter.cpp

@@ -547,6 +547,7 @@ bool ERMInterpreter::isATrigger( const ERM::TLine & line )
 		break;
 	}
 	assert(0);
+	return false;
 }
 
 ERM::EVOtions ERMInterpreter::getExpType( const ERM::TVOption & opt )