1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Fix possible assertion failure on removing non-owned town

This commit is contained in:
Ivan Savenko 2023-07-04 20:02:41 +03:00
parent 4fd5a2b3ea
commit 1cbc6457ce
9 changed files with 57 additions and 12 deletions

View File

@ -448,6 +448,12 @@ void AIGateway::battleResultsApplied()
status.setBattle(NO_BATTLE);
}
void AIGateway::beforeObjectPropertyChanged(const SetObjectProperty * sop)
{
}
void AIGateway::objectPropertyChanged(const SetObjectProperty * sop)
{
LOG_TRACE(logAi);

View File

@ -161,6 +161,7 @@ public:
void heroManaPointsChanged(const CGHeroInstance * hero) override;
void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) override;
void battleResultsApplied() override;
void beforeObjectPropertyChanged(const SetObjectProperty * sop) override;
void objectPropertyChanged(const SetObjectProperty * sop) override;
void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override;
void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override;

View File

@ -538,6 +538,11 @@ void VCAI::battleResultsApplied()
status.setBattle(NO_BATTLE);
}
void VCAI::beforeObjectPropertyChanged(const SetObjectProperty * sop)
{
}
void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
{
LOG_TRACE(logAi);

View File

@ -194,6 +194,7 @@ public:
void heroManaPointsChanged(const CGHeroInstance * hero) override;
void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) override;
void battleResultsApplied() override;
void beforeObjectPropertyChanged(const SetObjectProperty * sop) override;
void objectPropertyChanged(const SetObjectProperty * sop) override;
void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override;
void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override;

View File

@ -1317,11 +1317,8 @@ void CPlayerInterface::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanc
GH.windows().createAndPushWindow<CExchangeWindow>(hero1, hero2, query);
}
void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
void CPlayerInterface::beforeObjectPropertyChanged(const SetObjectProperty * sop)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
//redraw minimap if owner changed
if (sop->what == ObjProperty::OWNER)
{
const CGObjectInstance * obj = cb->getObj(sop->id);
@ -1331,13 +1328,34 @@ void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
auto town = static_cast<const CGTownInstance *>(obj);
if(obj->tempOwner == playerID)
localState->addOwnedTown(town);
else
{
localState->removeOwnedTown(town);
adventureInt->onTownChanged(town);
}
}
}
}
adventureInt->onTownChanged(town);
void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
if (sop->what == ObjProperty::OWNER)
{
const CGObjectInstance * obj = cb->getObj(sop->id);
if(obj->ID == Obj::TOWN)
{
auto town = static_cast<const CGTownInstance *>(obj);
if(obj->tempOwner == playerID)
{
localState->addOwnedTown(town);
adventureInt->onTownChanged(town);
}
}
//redraw minimap if owner changed
std::set<int3> pos = obj->getBlockedPos();
std::unordered_set<int3> upos(pos.begin(), pos.end());
adventureInt->onMapTilesChanged(upos);

View File

@ -144,6 +144,7 @@ protected: // Call-ins from server, should not be called directly, but only via
void requestRealized(PackageApplied *pa) override;
void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) override;
void centerView (int3 pos, int focusTime) override;
void beforeObjectPropertyChanged(const SetObjectProperty * sop) override;
void objectPropertyChanged(const SetObjectProperty * sop) override;
void objectRemoved(const CGObjectInstance *obj) override;
void objectRemovedAfter() override;

View File

@ -128,4 +128,5 @@ public:
virtual void visitBattleStackMoved(BattleStackMoved & pack) override;
virtual void visitBattleAttack(BattleAttack & pack) override;
virtual void visitStartAction(StartAction & pack) override;
};
virtual void visitSetObjectProperty(SetObjectProperty & pack) override;
};

View File

@ -611,6 +611,20 @@ void ApplyClientNetPackVisitor::visitInfoWindow(InfoWindow & pack)
logNetwork->warn("We received InfoWindow for not our player...");
}
void ApplyFirstClientNetPackVisitor::visitSetObjectProperty(SetObjectProperty & pack)
{
//inform all players that see this object
for(auto it = cl.playerint.cbegin(); it != cl.playerint.cend(); ++it)
{
if(gs.isVisible(gs.getObjInstance(pack.id), it->first))
callInterfaceIfPresent(cl, it->first, &IGameEventsReceiver::beforeObjectPropertyChanged, &pack);
}
// invalidate section of map view with our object and force an update with new flag color
if (pack.what == ObjProperty::OWNER)
CGI->mh->onObjectInstantRemove(gs.getObjInstance(pack.id));
}
void ApplyClientNetPackVisitor::visitSetObjectProperty(SetObjectProperty & pack)
{
//inform all players that see this object
@ -620,12 +634,9 @@ void ApplyClientNetPackVisitor::visitSetObjectProperty(SetObjectProperty & pack)
callInterfaceIfPresent(cl, it->first, &IGameEventsReceiver::objectPropertyChanged, &pack);
}
// invalidate section of map view with our object and force an update with new flag color
if (pack.what == ObjProperty::OWNER)
{
// invalidate section of map view with our object and force an update with new flag color
CGI->mh->onObjectInstantRemove(gs.getObjInstance(pack.id));
CGI->mh->onObjectInstantAdd(gs.getObjInstance(pack.id));
}
}
void ApplyClientNetPackVisitor::visitHeroLevelUp(HeroLevelUp & pack)

View File

@ -127,6 +127,7 @@ public:
virtual void playerBonusChanged(const Bonus &bonus, bool gain){};//if gain hero received bonus, else he lost it
virtual void requestSent(const CPackForServer *pack, int requestID){};
virtual void requestRealized(PackageApplied *pa){};
virtual void beforeObjectPropertyChanged(const SetObjectProperty * sop){}; //eg. mine has been flagged
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 objectRemovedAfter(){}; //eg. collected resource, picked artifact, beaten hero