From 68cc86013319148137e1f488826addb90e836160 Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Wed, 28 Oct 2015 23:53:44 +0300 Subject: [PATCH] Fix dynamic_cast on MacOSX in CQuery.cpp --- server/CGameHandler.cpp | 92 ++++++++++++++++++++--------------------- server/CQuery.cpp | 47 +++++++++++---------- server/StdInc.h | 14 +++++++ 3 files changed, 85 insertions(+), 68 deletions(-) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 17b0f7ed6..9a13c3285 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -65,14 +65,14 @@ class ServerSpellCastEnvironment: public SpellCastEnvironment public: ServerSpellCastEnvironment(CGameHandler * gh); ~ServerSpellCastEnvironment(){}; - void sendAndApply(CPackForClient * info) const override; + void sendAndApply(CPackForClient * info) const override; CRandomGenerator & getRandomGenerator() const override; void complain(const std::string & problem) const override; const CMap * getMap() const override; const CGameInfoCallback * getCb() const override; - bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, PlayerColor asker = PlayerColor::NEUTRAL) const override; + bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, PlayerColor asker = PlayerColor::NEUTRAL) const override; private: - mutable CGameHandler * gh; + mutable CGameHandler * gh; }; CondSh battleMadeAction; @@ -102,7 +102,7 @@ public: } }; -template <> +template <> class CApplyOnGH : public CBaseForGHApply { public: @@ -799,15 +799,15 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt const Bonus * bonus = att->getBonusLocalFirst(Selector::type(Bonus::SPELL_LIKE_ATTACK)); if (bonus && (bat.shot())) //TODO: make it work in melee? - { + { //this is need for displaying hit animation bat.flags |= BattleAttack::SPELL_LIKE; bat.spellID = SpellID(bonus->subtype); - + //TODO: should spell override creature`s projectile? - + std::set attackedCreatures = SpellID(bonus->subtype).toSpell()->getAffectedStacks(gs->curB, ECastingMode::SPELL_LIKE_ATTACK, att->owner, bonus->val, targetHex, att); - + //TODO: get exact attacked hex for defender for(const CStack * stack : attackedCreatures) @@ -817,7 +817,7 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt applyBattleEffects(bat, att, stack, distance, true); } } - + //now add effect info for all attacked stacks for(BattleStackAttacked & bsa : bat.bsa) { @@ -828,7 +828,7 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt bsa.spellID = SpellID(bonus->subtype); } } - + } } void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, const CStack *def, int distance, bool secondary) //helper function for prepareAttack @@ -917,7 +917,7 @@ void CGameHandler::handleConnection(std::set players, CConnection & c << &applied; }; - CBaseForGHApply *apply = applier->apps[packType]; //and appropriae applier object + CBaseForGHApply *apply = applier->apps[packType]; //and appropriate applier object if(isBlockedByQueries(pack, player)) { sendPackageResponse(false); @@ -1026,7 +1026,7 @@ int CGameHandler::moveStack(int stack, BattleHex dest) int v = path.first.size()-1; bool stackIsMoving = true; - + while(stackIsMoving) { if(vstopsMovement() || !curStack->alive()) stackIsMoving = false; - obs.reset(); + obs.reset(); } }; - + processObstacle(obstacle); if(curStack->alive()) processObstacle(obstacle2); @@ -1105,14 +1105,14 @@ int CGameHandler::moveStack(int stack, BattleHex dest) if(curStack->alive() && curStack->doubleWide()) { BattleHex otherHex = curStack->occupiedHex(curStack->position); - + if(otherHex.isValid()) if(auto theLastObstacle = battleGetObstacleOnPos(otherHex, false)) { //two hex creature hit obstacle by backside handleDamageFromObstacle(*theLastObstacle, curStack); } - } + } return ret; } @@ -1125,7 +1125,7 @@ CGameHandler::CGameHandler(void) registerTypesServerPacks(*applier); visitObjectAfterVictory = false; queries.gh = this; - + spellEnv = new ServerSpellCastEnvironment(this); } @@ -3907,8 +3907,8 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) complain("That stack can't cast spells!"); else { - const CSpell * spell = SpellID(spellID).toSpell(); - BattleSpellCastParameters parameters(gs->curB, stack, spell); + const CSpell * spell = SpellID(spellID).toSpell(); + BattleSpellCastParameters parameters(gs->curB, stack, spell); parameters.spellLvl = 0; if (spellcaster) vstd::amax(parameters.spellLvl, spellcaster->val); @@ -3940,12 +3940,12 @@ void CGameHandler::playerMessage( PlayerColor player, const std::string &message { SetMana sm; GiveBonus giveBonus(GiveBonus::HERO); - + CGHeroInstance *h = gs->getHero(currObj); if(!h && complain("Cannot realize cheat, no hero selected!")) return; sm.hid = h->id; - + giveBonus.id = h->id.getNum(); //give all spells with bonus (to allow banned spells) @@ -4107,11 +4107,11 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) } const CSpell * s = SpellID(ba.additionalInfo).toSpell(); - + BattleSpellCastParameters parameters(gs->curB, h, s); parameters.aimToHex(ba.destinationTile);//todo: allow multiple destinations parameters.mode = ECastingMode::HERO_CASTING; - parameters.selectedStack = gs->curB->battleGetStackByID(ba.selectedStack, false); + parameters.selectedStack = gs->curB->battleGetStackByID(ba.selectedStack, false); ESpellCastProblem::ESpellCastProblem escp = gs->curB->battleCanCastThisSpell(h, s, ECastingMode::HERO_CASTING);//todo: should we check aimed cast(battleCanCastThisSpellHere)? if(escp != ESpellCastProblem::OK) @@ -4123,9 +4123,9 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) StartAction start_action(ba); sendAndApply(&start_action); //start spell casting - + s->battleCast(spellEnv, parameters); - + sendAndApply(&end_action); if( !gs->curB->battleGetStackByID(gs->curB->activeStack, true)) { @@ -4255,8 +4255,8 @@ void CGameHandler::stackTurnTrigger(const CStack * st) auto bonus = *RandomGeneratorUtil::nextItem(bl, gs->getRandomGenerator()); auto spellID = SpellID(bonus->subtype); const CSpell * spell = SpellID(spellID).toSpell(); - bl.remove_if([&bonus](Bonus * b){return b==bonus;}); - + bl.remove_if([&bonus](Bonus * b){return b==bonus;}); + if (gs->curB->battleCanCastThisSpell(st, spell, ECastingMode::ENCHANTER_CASTING) == ESpellCastProblem::OK) { BattleSpellCastParameters parameters(gs->curB, st, spell); @@ -4265,8 +4265,8 @@ void CGameHandler::stackTurnTrigger(const CStack * st) parameters.aimToHex(BattleHex::INVALID); parameters.mode = ECastingMode::ENCHANTER_CASTING; parameters.selectedStack = nullptr; - - spell->battleCast(spellEnv, parameters); + + spell->battleCast(spellEnv, parameters); //todo: move to mechanics BattleSetStackProperty ssp; @@ -4275,9 +4275,9 @@ void CGameHandler::stackTurnTrigger(const CStack * st) ssp.val = bonus->additionalInfo; //increase cooldown counter ssp.stackID = st->ID; sendAndApply(&ssp); - + cast = true; - } + } }; } bl = *(st->getBonuses(Selector::type(Bonus::ENCHANTED))); @@ -4383,7 +4383,7 @@ void CGameHandler::handleTimeEvents() while(gs->map->events.size() && gs->map->events.front().firstOccurence+1 == gs->day) { CMapEvent ev = gs->map->events.front(); - + for (int player = 0; player < PlayerColor::PLAYER_LIMIT_I; player++) { auto color = PlayerColor(player); @@ -4973,7 +4973,7 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta parameters.mode = ECastingMode::AFTER_ATTACK_CASTING; parameters.selectedStack = nullptr; - spell->battleCast(spellEnv, parameters); + spell->battleCast(spellEnv, parameters); } } } @@ -4990,7 +4990,7 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat ) const CStack * attacker = gs->curB->battleGetStackByID(bat.stackAttacking); if (!attacker) //could be already dead return; - + auto cast = [=](SpellID spellID, int power) { const CSpell * spell = SpellID(spellID).toSpell(); @@ -4999,13 +4999,13 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat ) parameters.spellLvl = 0; parameters.effectLevel = 0; parameters.aimToStack(gs->curB->battleGetStackByID(bat.bsa.at(0).stackAttacked)); - parameters.effectPower = power; + parameters.effectPower = power; parameters.mode = ECastingMode::AFTER_ATTACK_CASTING; parameters.selectedStack = nullptr; - spell->battleCast(this->spellEnv, parameters); - }; - + spell->battleCast(this->spellEnv, parameters); + }; + attackCasting(bat, Bonus::SPELL_AFTER_ATTACK, attacker); if(bat.bsa.at(0).newAmount <= 0) @@ -5056,11 +5056,11 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat ) bool CGameHandler::castSpell(const CGHeroInstance *h, SpellID spellID, const int3 &pos) { const CSpell *s = spellID.toSpell(); - + AdventureSpellCastParameters p; p.caster = h; p.pos = pos; - + return s->adventureCast(spellEnv, p); } @@ -5298,8 +5298,8 @@ void CGameHandler::runBattle() auto h = gs->curB->battleGetFightingHero(i); if(h && h->hasBonusOfType(Bonus::OPENING_BATTLE_SPELL)) { - TBonusListPtr bl = h->getBonuses(Selector::type(Bonus::OPENING_BATTLE_SPELL)); - + TBonusListPtr bl = h->getBonuses(Selector::type(Bonus::OPENING_BATTLE_SPELL)); + for (Bonus *b : *bl) { const CSpell * spell = SpellID(b->subtype).toSpell(); @@ -5308,7 +5308,7 @@ void CGameHandler::runBattle() parameters.effectLevel = 3; parameters.aimToHex(BattleHex::INVALID); parameters.mode = ECastingMode::PASSIVE_CASTING; - parameters.selectedStack = nullptr; + parameters.selectedStack = nullptr; parameters.enchantPower = b->val; spell->battleCast(spellEnv, parameters); } @@ -5347,7 +5347,6 @@ void CGameHandler::runBattle() const CStack *next; while(!battleResult.get() && (next = curB.getNextStack()) && next->willMove()) { - //check for bad morale => freeze int nextStackMorale = next->MoraleVal(); if( nextStackMorale < 0 && @@ -5483,7 +5482,7 @@ void CGameHandler::runBattle() { logGlobal->traceStream() << "Activating " << next->nodeName(); auto nextId = next->ID; - BattleSetActiveStack sas; + BattleSetActiveStack sas; sas.stack = nextId; sendAndApply(&sas); @@ -5900,7 +5899,7 @@ CGameHandler::FinishingBattleHelper::FinishingBattleHelper() ///ServerSpellCastEnvironment ServerSpellCastEnvironment::ServerSpellCastEnvironment(CGameHandler * gh): gh(gh) { - + } void ServerSpellCastEnvironment::sendAndApply(CPackForClient * info) const @@ -5933,4 +5932,3 @@ bool ServerSpellCastEnvironment::moveHero(ObjectInstanceID hid, int3 dst, ui8 te { return gh->moveHero(hid, dst, teleporting, false, asker); } - diff --git a/server/CQuery.cpp b/server/CQuery.cpp index f03e50e63..e3d36b52d 100644 --- a/server/CQuery.cpp +++ b/server/CQuery.cpp @@ -97,11 +97,11 @@ CObjectVisitQuery::CObjectVisitQuery(const CGObjectInstance *Obj, const CGHeroIn addPlayer(Hero->tempOwner); } -bool CObjectVisitQuery::blocksPack(const CPack *pack) const +bool CObjectVisitQuery::blocksPack(const CPack *pack) const { //During the visit itself ALL actions are blocked. //(However, the visit may trigger a query above that'll pass some.) - return true; + return true; } void CObjectVisitQuery::onRemoval(CGameHandler *gh, PlayerColor color) @@ -220,7 +220,7 @@ std::vector> Queries::allQueries() return ret; } -void CBattleQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const +void CBattleQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const { assert(result); objectVisit.visitedObject->battleFinished(objectVisit.visitingHero, *result); @@ -242,9 +242,14 @@ CBattleQuery::CBattleQuery() } -bool CBattleQuery::blocksPack(const CPack *pack) const +bool CBattleQuery::blocksPack(const CPack *pack) const { - return !dynamic_cast(pack) && !dynamic_cast(pack); + #ifndef __APPLE__ + bool dynamic_success = !dynamic_cast(pack) && !dynamic_cast(pack); + #else + const char * name = typeid(*pack).name(); + return strcmp(name, typeid(MakeAction).name()) && strcmp(name, typeid(MakeCustomAction).name()); + #endif } void CBattleQuery::onRemoval(CGameHandler *gh, PlayerColor color) @@ -252,7 +257,7 @@ void CBattleQuery::onRemoval(CGameHandler *gh, PlayerColor color) gh->battleAfterLevelUp(*result); } -void CGarrisonDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const +void CGarrisonDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const { objectVisit.visitedObject->garrisonDialogClosed(objectVisit.visitingHero); } @@ -266,18 +271,18 @@ CGarrisonDialogQuery::CGarrisonDialogQuery(const CArmedInstance *up, const CArme addPlayer(down->tempOwner); } -bool CGarrisonDialogQuery::blocksPack(const CPack *pack) const +bool CGarrisonDialogQuery::blocksPack(const CPack *pack) const { std::set ourIds; ourIds.insert(this->exchangingArmies[0]->id); ourIds.insert(this->exchangingArmies[1]->id); - - if (auto stacks = dynamic_cast(pack)) + if (auto stacks = dynamic_ptr_cast(pack)) { return !vstd::contains(ourIds, stacks->id1) || !vstd::contains(ourIds, stacks->id2); } - if (auto arts = dynamic_cast(pack)) + + if (auto arts = dynamic_ptr_cast(pack)) { if(auto id1 = boost::apply_visitor(GetEngagedHeroIds(), arts->src.artHolder)) if(!vstd::contains(ourIds, *id1)) @@ -288,24 +293,24 @@ bool CGarrisonDialogQuery::blocksPack(const CPack *pack) const return true; return false; } - if (auto dismiss = dynamic_cast(pack)) + if (auto dismiss = dynamic_ptr_cast(pack)) { return !vstd::contains(ourIds, dismiss->id); } - if (auto dismiss = dynamic_cast(pack)) + if (auto dismiss = dynamic_ptr_cast(pack)) { return !vstd::contains(ourIds, dismiss->heroID); } - - if(auto upgrade = dynamic_cast(pack)) + + if(auto upgrade = dynamic_ptr_cast(pack)) { return !vstd::contains(ourIds, upgrade->id); } return CDialogQuery::blocksPack(pack); } -void CBlockingDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const +void CBlockingDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const { assert(answer); objectVisit.visitedObject->blockingDialogAnswered(objectVisit.visitingHero, *answer); @@ -319,7 +324,7 @@ CBlockingDialogQuery::CBlockingDialogQuery(const BlockingDialog &bd) void CTeleportDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const { - auto obj = dynamic_cast(objectVisit.visitedObject); + auto obj = dynamic_ptr_cast(objectVisit.visitedObject); obj->teleportDialogAnswered(objectVisit.visitingHero, *answer, td.exits); } @@ -342,7 +347,7 @@ void CHeroLevelUpDialogQuery::onRemoval(CGameHandler *gh, PlayerColor color) gh->levelUpHero(hlu.hero, hlu.skills[*answer]); } -void CHeroLevelUpDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const +void CHeroLevelUpDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const { objectVisit.visitedObject->heroLevelUpDone(objectVisit.visitingHero); } @@ -360,20 +365,20 @@ void CCommanderLevelUpDialogQuery::onRemoval(CGameHandler *gh, PlayerColor color gh->levelUpCommander(clu.hero->commander, clu.skills[*answer]); } -void CCommanderLevelUpDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const +void CCommanderLevelUpDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const { objectVisit.visitedObject->heroLevelUpDone(objectVisit.visitingHero); } -bool CDialogQuery::endsByPlayerAnswer() const +bool CDialogQuery::endsByPlayerAnswer() const { return true; } -bool CDialogQuery::blocksPack(const CPack *pack) const +bool CDialogQuery::blocksPack(const CPack *pack) const { //We accept only query replies from correct player - if(auto reply = dynamic_cast(pack)) + if(auto reply = dynamic_ptr_cast(pack)) { return !vstd::contains(players, reply->player); } diff --git a/server/StdInc.h b/server/StdInc.h index 7418241e0..e2e51512e 100644 --- a/server/StdInc.h +++ b/server/StdInc.h @@ -8,3 +8,17 @@ #include #include #include + +template +inline const T * dynamic_ptr_cast(const F * ptr) +{ + #ifndef __APPLE__ + return dynamic_cast(ptr); + #else + if (!strcmp(typeid(*ptr).name(), typeid(T).name())) + { + return static_cast(ptr); + } + return nullptr; + #endif +}