Ver código fonte

Set of minor improvements and fixes.

Michał W. Urbańczyk 14 anos atrás
pai
commit
ed056cf0df

+ 7 - 5
CCallback.cpp

@@ -185,6 +185,7 @@ int CBattleCallback::battleMakeAction(BattleAction* action)
 template <typename T>
 void CBattleCallback::sendRequest(const T* request)
 {
+
 	//TODO? should be part of CClient but it would have to be very tricky cause template/serialization issues
 	if(waitTillRealize)
 		cl->waitingRequest.set(true);
@@ -192,7 +193,13 @@ void CBattleCallback::sendRequest(const T* request)
 	*cl->serv << request;
 
 	if(waitTillRealize)
+	{
+		if(unlockGsWhenWaiting)
+			gs->mx->unlock_shared();
 		cl->waitingRequest.waitWhileTrue();
+		if(unlockGsWhenWaiting)
+			gs->mx->lock_shared();
+	}
 }
 
 void CCallback::swapGarrisonHero( const CGTownInstance *town )
@@ -338,11 +345,6 @@ void CCallback::castSpell(const CGHeroInstance *hero, int spellID, const int3 &p
 	sendRequest(&cas);
 }
 
-boost::shared_mutex& CCallback::getGsMutex()
-{
-	return *gs->mx;
-}
-
 void CCallback::unregisterMyInterface()
 {
 	assert(player >= 0); //works only for player callback

+ 1 - 5
CCallback.h

@@ -36,13 +36,11 @@ struct CGPathNode;
 struct CGPath;
 struct CPathsInfo;
 
-namespace boost
-{class shared_mutex;}
-
 class IBattleCallback
 {
 public:
 	bool waitTillRealize; //if true, request functions will return after they are realized by server
+	bool unlockGsWhenWaiting;//if true after sending each request, gs mutex will be unlocked so the changes can be applied; NOTICE caller must have gs mx locked prior to any call to actiob callback!
 	//battle
 	virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack
 	virtual bool battleMakeTacticAction(BattleAction * action) =0; // performs tactic phase actions
@@ -115,8 +113,6 @@ public:
 	virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src = int3(-1,-1,-1), int movement = -1);
 	virtual void recalculatePaths(); //updates main, client pathfinder info (should be called when moving hero is over)
 
-
-	boost::shared_mutex &getGsMutex(); //just return a reference to mutex, does not lock nor anything
 	void unregisterMyInterface(); //stops delivering information about game events to that player's interface -> can be called ONLY after victory/loss
 
 //commands

+ 7 - 0
lib/CGameInterface.cpp

@@ -121,7 +121,9 @@ void CAdventureAI::battleCatapultAttacked(const CatapultAttack & ca)
 void CAdventureAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
 {
 	assert(!battleAI);
+	assert(cbc);
 	battleAI = CDynLibHandler::getNewBattleAI(battleAIName);
+	battleAI->init(cbc);
 	battleAI->battleStart(army1, army2, tile, hero1, hero2, side);
 }
 
@@ -189,4 +191,9 @@ void CAdventureAI::battleEnd(const BattleResult *br)
 void CAdventureAI::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom)
 {
 	battleAI->battleStacksHealedRes(healedStacks, lifeDrain, tentHeal, lifeDrainFrom);
+}
+
+BattleAction CAdventureAI::activeStack(const CStack * stack)
+{
+	return battleAI->activeStack(stack);
 }

+ 4 - 2
lib/CGameInterface.h

@@ -107,13 +107,15 @@ public:
 class DLL_EXPORT CAdventureAI : public CGlobalAI
 {
 public:
-	CAdventureAI() : battleAI(NULL) {};
-	CAdventureAI(const std::string &BattleAIName) : battleAIName(BattleAIName), battleAI(NULL) {};
+	CAdventureAI() : battleAI(NULL), cbc(NULL) {};
+	CAdventureAI(const std::string &BattleAIName) : battleAIName(BattleAIName), battleAI(NULL), cbc(NULL) {};
 
 	std::string battleAIName;
 	CBattleGameInterface *battleAI;
+	CBattleCallback *cbc;
 
 	//battle interface
+	virtual BattleAction activeStack(const CStack * stack);
 	virtual void battleNewRound(int round);
 	virtual void battleCatapultAttacked(const CatapultAttack & ca);
 	virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side);

+ 6 - 1
lib/IGameCallback.cpp

@@ -34,6 +34,11 @@
 
 extern boost::rand48 ran;
 
+boost::shared_mutex& CCallbackBase::getGsMutex()
+{
+	return *gs->mx;
+}
+
 si8 CBattleInfoCallback::battleHasDistancePenalty( const CStack * stack, THex destHex )
 {
 	return gs->curB->hasDistancePenalty(stack, destHex);
@@ -848,7 +853,7 @@ int CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID )
 		return Buildings::ERROR;
 
 	//checking resources
-	if(pom->resources.canBeAfforded(getPlayer(t->tempOwner)->resources))
+	if(!pom->resources.canBeAfforded(getPlayer(t->tempOwner)->resources))
 		ret = Buildings::NO_RESOURCES; //lack of res
 
 	//checking for requirements

+ 7 - 2
lib/IGameCallback.h

@@ -58,10 +58,12 @@ class CStackBasicDescriptor;
 struct TeamState;
 class CGCreature;
 
-
 typedef std::vector<const CStack*> TStacks;
 
-class CCallbackBase
+namespace boost
+{class shared_mutex;}
+
+class DLL_EXPORT CCallbackBase
 {
 protected:
 	CGameState *gs;
@@ -73,6 +75,9 @@ protected:
 	CCallbackBase()
 	: gs(NULL), player(-1)
 	{}
+
+public:
+	boost::shared_mutex &getGsMutex(); //just return a reference to mutex, does not lock nor anything
 };
 
 class DLL_EXPORT CBattleInfoCallback : public virtual CCallbackBase

+ 2 - 1
lib/ResourceSet.h

@@ -71,7 +71,8 @@ namespace Res
 		{
 			int ret = INT_MAX;
 			for(int i = 0; i < size(); i++)
-				amin(ret, at(i) / rhs[i]);
+				if(rhs[i])
+					amin(ret, at(i) / rhs[i]);
 
 			return ret;
 		}

+ 12 - 12
server/CGameHandler.cpp

@@ -2006,9 +2006,9 @@ void CGameHandler::close()
 
 bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val, ui8 player )
 {
-	CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id1].get()),
+	const CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id1].get()),
 		*s2 = static_cast<CArmedInstance*>(gs->map->objects[id2].get());
-	CCreatureSet &S1 = *s1, &S2 = *s2;
+	const CCreatureSet &S1 = *s1, &S2 = *s2;
 	StackLocation sl1(s1, p1), sl2(s2, p2);
 
 	if(!isAllowedExchange(id1,id2))
@@ -2019,8 +2019,8 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
 
 	if(what==1) //swap
 	{
-		if ( ((s1->tempOwner != player && s1->tempOwner != 254) && S1.stacks[p1]->count) //why 254??
-		  || ((s2->tempOwner != player && s2->tempOwner != 254) && S2.stacks[p2]->count))
+		if ( ((s1->tempOwner != player && s1->tempOwner != 254) && s1->getStackCount(p1)) //why 254??
+		  || ((s2->tempOwner != player && s2->tempOwner != 254) && s2->getStackCount(p2)))
 		{
 			complain("Can't take troops from another player!");
 			return false;
@@ -2030,16 +2030,16 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
 	}
 	else if(what==2)//merge
 	{
-		if (( S1.stacks[p1]->type != S2.stacks[p2]->type && complain("Cannot merge different creatures stacks!"))
-		|| (((s1->tempOwner != player && s1->tempOwner != 254) && S2.stacks[p2]->count) && complain("Can't take troops from another player!")))
+		if (( s1->getCreature(p1) != s2->getCreature(p2) && complain("Cannot merge different creatures stacks!"))
+		|| (((s1->tempOwner != player && s1->tempOwner != 254) && s2->getStackCount(p2)) && complain("Can't take troops from another player!")))
 			return false; 
 
 		moveStack(sl1, sl2);
 	}
 	else if(what==3) //split
 	{
-		if ( (s1->tempOwner != player && S1.stacks[p1]->count < s1->getStackCount(p1) )
-			|| (s2->tempOwner != player && S2.stacks[p2]->count < s2->getStackCount(p2) ) )
+		if ( (s1->tempOwner != player && s1->getStackCount(p1) < s1->getStackCount(p1) )
+			|| (s2->tempOwner != player && s2->getStackCount(p2) < s2->getStackCount(p2) ) )
 		{
 			complain("Can't move troops of another player!");
 			return false;
@@ -2055,21 +2055,21 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
 
 		if(vstd::contains(S2.stacks,p2))	 //dest. slot not free - it must be "rebalancing"...
 		{
-			int total = S1.stacks[p1]->count + S2.stacks[p2]->count;
+			int total = s1->getStackCount(p1) + s2->getStackCount(p2);
 			if( (total < val   &&   complain("Cannot split that stack, not enough creatures!"))
-				|| (S2.stacks[p2]->type != S1.stacks[p1]->type && complain("Cannot rebalance different creatures stacks!"))
+				|| (s1->getCreature(p1) != s2->getCreature(p2) && complain("Cannot rebalance different creatures stacks!"))
 			)
 			{
 				return false; 
 			}
 			
-			moveStack(sl1, sl2, val - S2.stacks[p2]->count);
+			moveStack(sl1, sl2, val - s2->getStackCount(p2));
 			//S2.slots[p2]->count = val;
 			//S1.slots[p1]->count = total - val;
 		}
 		else //split one stack to the two
 		{
-			if(S1.stacks[p1]->count < val)//not enough creatures
+			if(s1->getStackCount(p1) < val)//not enough creatures
 			{
 				complain("Cannot split that stack, not enough creatures!");
 				return false;