mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Fixed at least two #1428 freezes, likely more.
They were occurring when AI hero visited bank that was also guarded by neutral creature nearby,
This commit is contained in:
@@ -493,12 +493,15 @@ void VCAI::showThievesGuildWindow (const CGObjectInstance * obj)
|
||||
NET_EVENT_HANDLER;
|
||||
}
|
||||
|
||||
void VCAI::playerBlocked(int reason)
|
||||
void VCAI::playerBlocked(int reason, bool start)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "reason '%i'", reason);
|
||||
LOG_TRACE_PARAMS(logAi, "reason '%i', start '%i'", reason % start);
|
||||
NET_EVENT_HANDLER;
|
||||
if (reason == PlayerBlocked::UPCOMING_BATTLE)
|
||||
if (start && reason == PlayerBlocked::UPCOMING_BATTLE)
|
||||
status.setBattle(UPCOMING_BATTLE);
|
||||
|
||||
if(reason == PlayerBlocked::ONGOING_MOVEMENT)
|
||||
status.setMove(start);
|
||||
}
|
||||
|
||||
void VCAI::showPuzzleMap()
|
||||
@@ -571,15 +574,17 @@ void VCAI::artifactDisassembled(const ArtifactLocation &al)
|
||||
|
||||
void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "start '%i'", start);
|
||||
LOG_TRACE_PARAMS(logAi, "start '%i'; obj '%s'", start % (visitedObj ? visitedObj->hoverName : std::string("n/a")));
|
||||
NET_EVENT_HANDLER;
|
||||
if (start)
|
||||
if(start)
|
||||
{
|
||||
markObjectVisited (visitedObj);
|
||||
erase_if_present(reservedObjs, visitedObj); //unreserve objects
|
||||
erase_if_present(reservedHeroesMap[visitor], visitedObj);
|
||||
completeGoal (CGoal(GET_OBJ).sethero(visitor)); //we don't need to visit in anymore
|
||||
}
|
||||
|
||||
status.heroVisit(visitedObj, start);
|
||||
}
|
||||
|
||||
void VCAI::availableArtifactsChanged(const CGBlackMarket *bm /*= nullptr*/)
|
||||
@@ -2701,7 +2706,7 @@ void AIStatus::madeTurn()
|
||||
void AIStatus::waitTillFree()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(mx);
|
||||
while(battle != NO_BATTLE || remainingQueries.size())
|
||||
while(battle != NO_BATTLE || remainingQueries.size() || objectsBeingVisited.size() || ongoingHeroMovement)
|
||||
cv.wait(lock);
|
||||
}
|
||||
|
||||
@@ -2738,6 +2743,26 @@ void AIStatus::receivedAnswerConfirmation(int answerRequestID, int result)
|
||||
}
|
||||
}
|
||||
|
||||
void AIStatus::heroVisit(const CGObjectInstance *obj, bool started)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(mx);
|
||||
if(started)
|
||||
objectsBeingVisited.push_back(obj);
|
||||
else
|
||||
{
|
||||
assert(objectsBeingVisited.size() == 1);
|
||||
objectsBeingVisited.clear();
|
||||
}
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void AIStatus::setMove(bool ongoing)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(mx);
|
||||
ongoingHeroMovement = ongoing;
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
int3 whereToExplore(HeroPtr h)
|
||||
{
|
||||
//TODO it's stupid and ineffective, write sth better
|
||||
|
@@ -75,6 +75,8 @@ class AIStatus
|
||||
BattleState battle;
|
||||
std::map<QueryID, std::string> remainingQueries;
|
||||
std::map<int, QueryID> requestToQueryID; //IDs of answer-requests sent to server => query ids (so we can match answer confirmation from server to the query)
|
||||
std::vector<const CGObjectInstance*> objectsBeingVisited;
|
||||
bool ongoingHeroMovement;
|
||||
|
||||
bool havingTurn;
|
||||
|
||||
@@ -82,6 +84,7 @@ public:
|
||||
AIStatus();
|
||||
~AIStatus();
|
||||
void setBattle(BattleState BS);
|
||||
void setMove(bool ongoing);
|
||||
BattleState getBattle();
|
||||
void addQuery(QueryID ID, std::string description);
|
||||
void removeQuery(QueryID ID);
|
||||
@@ -92,6 +95,7 @@ public:
|
||||
bool haveTurn();
|
||||
void attemptedAnsweringQuery(QueryID queryID, int answerRequestID);
|
||||
void receivedAnswerConfirmation(int answerRequestID, int result);
|
||||
void heroVisit(const CGObjectInstance *obj, bool started);
|
||||
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@@ -327,7 +331,7 @@ public:
|
||||
virtual void artifactAssembled(const ArtifactLocation &al) override;
|
||||
virtual void showTavernWindow(const CGObjectInstance *townOrTavern) override;
|
||||
virtual void showThievesGuildWindow (const CGObjectInstance * obj) override;
|
||||
virtual void playerBlocked(int reason) override;
|
||||
virtual void playerBlocked(int reason, bool start) override;
|
||||
virtual void showPuzzleMap() override;
|
||||
virtual void showShipyardDialog(const IShipyard *obj) override;
|
||||
virtual void gameOver(PlayerColor player, bool victory) override;
|
||||
|
@@ -791,7 +791,7 @@ void SystemMessage::applyCl( CClient *cl )
|
||||
|
||||
void PlayerBlocked::applyCl( CClient *cl )
|
||||
{
|
||||
INTERFACE_CALL_IF_PRESENT(player,playerBlocked,reason);
|
||||
INTERFACE_CALL_IF_PRESENT(player,playerBlocked,reason, startOrEnd==BLOCKADE_STARTED);
|
||||
}
|
||||
|
||||
void YourTurn::applyCl( CClient *cl )
|
||||
|
@@ -127,7 +127,7 @@ public:
|
||||
virtual void requestRealized(PackageApplied *pa){};
|
||||
virtual void objectPropertyChanged(const SetObjectProperty * sop){}; //eg. mine has been flagged
|
||||
virtual void objectRemoved(const CGObjectInstance *obj){}; //eg. collected resource, picked artifact, beaten hero
|
||||
virtual void playerBlocked(int reason){}; //reason: 0 - upcoming battle
|
||||
virtual void playerBlocked(int reason, bool start){}; //reason: 0 - upcoming battle
|
||||
virtual void gameOver(PlayerColor player, bool victory){}; //player lost or won the game
|
||||
virtual void playerStartsTurn(PlayerColor player){};
|
||||
virtual void showComp(const Component &comp, std::string message) {}; //display component in the advmapint infobox
|
||||
|
@@ -230,14 +230,16 @@ struct PlayerBlocked : public CPackForClient //96
|
||||
PlayerBlocked(){type = 96;};
|
||||
void applyCl(CClient *cl);
|
||||
|
||||
enum EReason { UPCOMING_BATTLE };
|
||||
|
||||
enum EReason { UPCOMING_BATTLE, ONGOING_MOVEMENT };
|
||||
enum EMode { BLOCKADE_STARTED, BLOCKADE_ENDED };
|
||||
|
||||
EReason reason;
|
||||
EMode startOrEnd;
|
||||
PlayerColor player;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & reason & player;
|
||||
h & reason & startOrEnd & player;
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -5037,6 +5037,7 @@ void CGameHandler::engageIntoBattle( PlayerColor player )
|
||||
PlayerBlocked pb;
|
||||
pb.player = player;
|
||||
pb.reason = PlayerBlocked::UPCOMING_BATTLE;
|
||||
pb.startOrEnd = PlayerBlocked::BLOCKADE_STARTED;
|
||||
sendAndApply(&pb);
|
||||
}
|
||||
|
||||
|
@@ -86,6 +86,11 @@ void CQuery::onExposure(CGameHandler *gh, QueryPtr topQuery)
|
||||
gh->queries.popQuery(*this);
|
||||
}
|
||||
|
||||
void CQuery::onAdding(CGameHandler *gh, PlayerColor color)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CObjectVisitQuery::CObjectVisitQuery(const CGObjectInstance *Obj, const CGHeroInstance *Hero, int3 Tile)
|
||||
: visitedObject(Obj), visitingHero(Hero), tile(Tile), removeObjectAfterVisit(false)
|
||||
{
|
||||
@@ -169,6 +174,7 @@ void Queries::addQuery(QueryPtr query)
|
||||
void Queries::addQuery(PlayerColor player, QueryPtr query)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logGlobal, "player='%s', query='%s'", player % query);
|
||||
query->onAdding(gh, player);
|
||||
queries[player].push_back(query);
|
||||
}
|
||||
|
||||
@@ -372,3 +378,21 @@ void CHeroMovementQuery::onExposure(CGameHandler *gh, QueryPtr topQuery)
|
||||
|
||||
gh->queries.popIfTop(*this);
|
||||
}
|
||||
|
||||
void CHeroMovementQuery::onRemoval(CGameHandler *gh, PlayerColor color)
|
||||
{
|
||||
PlayerBlocked pb;
|
||||
pb.player = color;
|
||||
pb.reason = PlayerBlocked::ONGOING_MOVEMENT;
|
||||
pb.startOrEnd = PlayerBlocked::BLOCKADE_ENDED;
|
||||
gh->sendAndApply(&pb);
|
||||
}
|
||||
|
||||
void CHeroMovementQuery::onAdding(CGameHandler *gh, PlayerColor color)
|
||||
{
|
||||
PlayerBlocked pb;
|
||||
pb.player = color;
|
||||
pb.reason = PlayerBlocked::ONGOING_MOVEMENT;
|
||||
pb.startOrEnd = PlayerBlocked::BLOCKADE_STARTED;
|
||||
gh->sendAndApply(&pb);
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@ public:
|
||||
virtual bool blocksPack(const CPack *pack) const; //query can block attempting actions by player. Eg. he can't move hero during the battle.
|
||||
|
||||
virtual bool endsByPlayerAnswer() const; //query is removed after player gives answer (like dialogs)
|
||||
virtual void onAdding(CGameHandler *gh, PlayerColor color); //called just before query is pushed on stack
|
||||
virtual void onRemoval(CGameHandler *gh, PlayerColor color); //called after query is removed from stack
|
||||
virtual void onExposure(CGameHandler *gh, QueryPtr topQuery);//called when query immediately above is removed and this is exposed (becomes top)
|
||||
virtual std::string toString() const;
|
||||
@@ -98,6 +99,8 @@ public:
|
||||
virtual void onExposure(CGameHandler *gh, QueryPtr topQuery);
|
||||
|
||||
CHeroMovementQuery(const TryMoveHero &Tmh, const CGHeroInstance *Hero, bool VisitDestAfterVictory = false);
|
||||
virtual void onAdding(CGameHandler *gh, PlayerColor color) override;
|
||||
virtual void onRemoval(CGameHandler *gh, PlayerColor color) override;
|
||||
};
|
||||
|
||||
class CDialogQuery : public CQuery
|
||||
|
Reference in New Issue
Block a user