1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-15 01:24:45 +02:00

Merge remote-tracking branch 'origin/issue/2306' into develop

This commit is contained in:
Ivan Savenko
2015-12-18 22:21:11 +02:00
12 changed files with 306 additions and 293 deletions

View File

@ -2735,24 +2735,13 @@ void VCAI::finish()
void VCAI::requestActionASAP(std::function<void()> whatToDo) void VCAI::requestActionASAP(std::function<void()> whatToDo)
{ {
boost::mutex mutex; boost::thread newThread([this,whatToDo]()
mutex.lock();
boost::thread newThread([&mutex,this,whatToDo]()
{ {
setThreadName("VCAI::requestActionASAP::helper"); setThreadName("VCAI::requestActionASAP::whatToDo");
SET_GLOBAL_STATE(this); SET_GLOBAL_STATE(this);
boost::shared_lock<boost::shared_mutex> gsLock(cb->getGsMutex()); boost::shared_lock<boost::shared_mutex> gsLock(cb->getGsMutex());
// unlock mutex and allow parent function to exit
mutex.unlock();
whatToDo(); whatToDo();
}); });
// wait for mutex to unlock and for thread to initialize properly
mutex.lock();
// unlock mutex - boost dislikes destruction of locked mutexes
mutex.unlock();
} }
void VCAI::lostHero(HeroPtr h) void VCAI::lostHero(HeroPtr h)

View File

@ -247,21 +247,14 @@ void CClient::endGame( bool closeConnection /*= true*/ )
void CClient::loadGame(const std::string & fname, const bool server, const std::vector<int>& humanplayerindices, const int loadNumPlayers, int player_, const std::string & ipaddr, const std::string & port) void CClient::loadGame(const std::string & fname, const bool server, const std::vector<int>& humanplayerindices, const int loadNumPlayers, int player_, const std::string & ipaddr, const std::string & port)
{ {
PlayerColor player(player_); //intentional shadowing PlayerColor player(player_); //intentional shadowing
logNetwork->infoStream() << "Loading procedure started!";
std::string realPort; logNetwork->infoStream() <<"Loading procedure started!";
if(settings["testing"]["enabled"].Bool())
realPort = settings["testing"]["port"].String();
else if(port.size())
realPort = port;
else
realPort = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
CServerHandler sh; CServerHandler sh;
if(server) if(server)
sh.startServer(); sh.startServer();
else else
serv = sh.justConnectToServer(ipaddr, realPort); serv = sh.justConnectToServer(ipaddr,port=="" ? "3030" : port);
CStopWatch tmh; CStopWatch tmh;
unique_ptr<CLoadFile> loader; unique_ptr<CLoadFile> loader;
@ -974,9 +967,6 @@ CServerHandler::CServerHandler(bool runServer /*= false*/)
{ {
serverThread = nullptr; serverThread = nullptr;
shared = nullptr; shared = nullptr;
if(settings["testing"]["enabled"].Bool())
port = settings["testing"]["port"].String();
else
port = boost::lexical_cast<std::string>(settings["server"]["port"].Float()); port = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
verbose = true; verbose = true;

View File

@ -1538,7 +1538,10 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
} }
else if(const CGHeroInstance * h = curHero()) else if(const CGHeroInstance * h = curHero())
{ {
const CGPathNode * pnode = LOCPLINT->cb->getPathsInfo(h)->getPathInfo(mapPos); int3 mapPosCopy = mapPos;
const CGPathNode * pnode = LOCPLINT->cb->getPathsInfo(h)->getPathInfo(mapPosCopy);
assert(pnode);
int turns = pnode->turns; int turns = pnode->turns;
vstd::amin(turns, 3); vstd::amin(turns, 3);
switch(pnode->action) switch(pnode->action)
@ -1800,4 +1803,3 @@ void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info)
info.additionalIcons = &iconPositions; info.additionalIcons = &iconPositions;
} }

View File

@ -450,18 +450,19 @@ CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type )
return newType; return newType;
} }
ui16 CTypeList::getTypeID( const std::type_info *type ) ui16 CTypeList::getTypeID( const std::type_info *type, bool throws ) const
{
auto descriptor = getTypeDescriptor(type, throws);
if (descriptor == nullptr)
{ {
auto i = typeInfos.find(type);
if(i != typeInfos.end())
return i->second->typeID;
else
return 0; return 0;
} }
return descriptor->typeID;
}
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) const
{ {
if(from == to) if(!strcmp(from->name, to->name))
return std::vector<CTypeList::TypeInfoPtr>(); return std::vector<CTypeList::TypeInfoPtr>();
// Perform a simple BFS in the class hierarchy. // Perform a simple BFS in the class hierarchy.
@ -512,17 +513,17 @@ std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, Ty
return ret; return ret;
} }
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(const std::type_info *from, const std::type_info *to) std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(const std::type_info *from, const std::type_info *to) const
{ {
//This additional if is needed because getTypeDescriptor might fail if type is not registered //This additional if is needed because getTypeDescriptor might fail if type is not registered
// (and if casting is not needed, then registereing should no be required) // (and if casting is not needed, then registereing should no be required)
if(*from == *to) if(!strcmp(from->name(), to->name()))
return std::vector<CTypeList::TypeInfoPtr>(); return std::vector<CTypeList::TypeInfoPtr>();
return castSequence(getTypeDescriptor(from), getTypeDescriptor(to)); return castSequence(getTypeDescriptor(from), getTypeDescriptor(to));
} }
CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(const std::type_info *type, bool throws) CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(const std::type_info *type, bool throws) const
{ {
auto i = typeInfos.find(type); auto i = typeInfos.find(type);
if(i != typeInfos.end()) if(i != typeInfos.end())
@ -646,4 +647,3 @@ CMemorySerializer::CMemorySerializer(): iser(this), oser(this)
registerTypes(iser); registerTypes(iser);
registerTypes(oser); registerTypes(oser);
} }

View File

@ -83,7 +83,11 @@ struct TypeComparer
{ {
bool operator()(const std::type_info *a, const std::type_info *b) const bool operator()(const std::type_info *a, const std::type_info *b) const
{ {
#ifndef __APPLE__
return a->before(*b); return a->before(*b);
#else
return strcmp(a->name(), b->name()) < 0;
#endif
} }
}; };
@ -102,6 +106,11 @@ struct PointerCaster : IPointerCaster
{ {
From * from = (From*)boost::any_cast<void*>(ptr); From * from = (From*)boost::any_cast<void*>(ptr);
To * ret = dynamic_cast<To*>(from); To * ret = dynamic_cast<To*>(from);
if (ret == nullptr)
{
// Last resort when RTTI goes mad
ret = static_cast<To*>(from);
}
return (void*)ret; return (void*)ret;
} }
@ -113,6 +122,11 @@ struct PointerCaster : IPointerCaster
{ {
auto from = boost::any_cast<SmartPt>(ptr); auto from = boost::any_cast<SmartPt>(ptr);
auto ret = std::dynamic_pointer_cast<To>(from); auto ret = std::dynamic_pointer_cast<To>(from);
if (!ret)
{
// Last resort when RTTI goes mad
ret = std::static_pointer_cast<To>(from);
}
return ret; return ret;
} }
catch(std::exception &e) catch(std::exception &e)
@ -136,7 +150,7 @@ struct PointerCaster : IPointerCaster
// } // }
}; };
class DLL_LINKAGE CTypeList class DLL_LINKAGE CTypeList: public boost::noncopyable
{ {
public: public:
struct TypeDescriptor; struct TypeDescriptor;
@ -147,33 +161,53 @@ public:
const char *name; const char *name;
std::vector<TypeInfoPtr> children, parents; std::vector<TypeInfoPtr> children, parents;
}; };
typedef boost::shared_mutex TMutex;
typedef boost::unique_lock<TMutex> TUniqueLock;
typedef boost::shared_lock<TMutex> TSharedLock;
private: private:
mutable TMutex mx;
std::map<const std::type_info *, TypeInfoPtr, TypeComparer> typeInfos; std::map<const std::type_info *, TypeInfoPtr, TypeComparer> typeInfos;
std::map<std::pair<TypeInfoPtr, TypeInfoPtr>, std::unique_ptr<const IPointerCaster>> casters; //for each pair <Base, Der> we provide a caster (each registered relations creates a single entry here) std::map<std::pair<TypeInfoPtr, TypeInfoPtr>, std::unique_ptr<const IPointerCaster>> casters; //for each pair <Base, Der> we provide a caster (each registered relations creates a single entry here)
CTypeList(CTypeList &) /// Returns sequence of types starting from "from" and ending on "to". Every next type is derived from the previous.
{ /// Throws if there is no link registered.
// This type is non-copyable. std::vector<TypeInfoPtr> castSequence(TypeInfoPtr from, TypeInfoPtr to) const;
// Unfortunately on Windows it is required for DLL_EXPORT-ed type to provide copy c-tor, so we can't =delete it. std::vector<TypeInfoPtr> castSequence(const std::type_info *from, const std::type_info *to) const;
assert(0);
}
CTypeList &operator=(CTypeList &)
{
// As above.
assert(0);
return *this;
}
public:
CTypeList();
template<boost::any(IPointerCaster::*CastingFunction)(const boost::any &) const>
boost::any castHelper(boost::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg) const
{
TSharedLock lock(mx);
auto typesSequence = castSequence(fromArg, toArg);
boost::any ptr = inputPtr;
for(int i = 0; i < static_cast<int>(typesSequence.size()) - 1; i++)
{
auto &from = typesSequence[i];
auto &to = typesSequence[i + 1];
auto castingPair = std::make_pair(from, to);
if(!casters.count(castingPair))
THROW_FORMAT("Cannot find caster for conversion %s -> %s which is needed to cast %s -> %s", from->name % to->name % fromArg->name() % toArg->name());
auto &caster = casters.at(castingPair);
ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr not have operator->* ..?
}
return ptr;
}
TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true) const; //if not throws, failure returns nullptr
TypeInfoPtr registerType(const std::type_info *type); TypeInfoPtr registerType(const std::type_info *type);
public:
CTypeList();
template <typename Base, typename Derived> template <typename Base, typename Derived>
void registerType(const Base * b = nullptr, const Derived * d = nullptr) void registerType(const Base * b = nullptr, const Derived * d = nullptr)
{ {
TUniqueLock lock(mx);
static_assert(std::is_base_of<Base, Derived>::value, "First registerType template parameter needs to ba a base class of the second one."); static_assert(std::is_base_of<Base, Derived>::value, "First registerType template parameter needs to ba a base class of the second one.");
static_assert(std::has_virtual_destructor<Base>::value, "Base class needs to have a virtual destructor."); static_assert(std::has_virtual_destructor<Base>::value, "Base class needs to have a virtual destructor.");
static_assert(!std::is_same<Base, Derived>::value, "Parameters of registerTypes should be two diffrenet types."); static_assert(!std::is_same<Base, Derived>::value, "Parameters of registerTypes should be two diffrenet types.");
@ -187,77 +221,52 @@ public:
casters[std::make_pair(dti, bti)] = make_unique<const PointerCaster<Derived, Base>>(); casters[std::make_pair(dti, bti)] = make_unique<const PointerCaster<Derived, Base>>();
} }
ui16 getTypeID(const std::type_info *type); ui16 getTypeID(const std::type_info *type, bool throws = false) const;
TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true); //if not throws, failure returns nullptr
template <typename T> template <typename T>
ui16 getTypeID(const T * t = nullptr) ui16 getTypeID(const T * t = nullptr, bool throws = false) const
{ {
return getTypeID(getTypeInfo(t)); return getTypeID(getTypeInfo(t), throws);
}
// Returns sequence of types starting from "from" and ending on "to". Every next type is derived from the previous.
// Throws if there is no link registered.
std::vector<TypeInfoPtr> castSequence(TypeInfoPtr from, TypeInfoPtr to);
std::vector<TypeInfoPtr> castSequence(const std::type_info *from, const std::type_info *to);
template<boost::any(IPointerCaster::*CastingFunction)(const boost::any &) const>
boost::any castHelper(boost::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg)
{
auto typesSequence = castSequence(fromArg, toArg);
boost::any ptr = inputPtr;
for(int i = 0; i < (int)typesSequence.size() - 1; i++)
{
auto &from = typesSequence[i];
auto &to = typesSequence[i + 1];
auto castingPair = std::make_pair(from, to);
if(!casters.count(castingPair))
THROW_FORMAT("Cannot find caster for conversion %s -> %s which is needed to cast %s -> %s", from->name % to->name % fromArg->name() % toArg->name());
auto &caster = casters.at(castingPair);
ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr does not have operator->* ..?
}
return ptr;
} }
template<typename TInput> template<typename TInput>
void *castToMostDerived(const TInput *inputPtr) void * castToMostDerived(const TInput * inputPtr) const
{ {
auto &baseType = typeid(typename std::remove_cv<TInput>::type); auto &baseType = typeid(typename std::remove_cv<TInput>::type);
auto derivedType = getTypeInfo(inputPtr); auto derivedType = getTypeInfo(inputPtr);
if(baseType == *derivedType) if (!strcmp(baseType.name(), derivedType->name()))
return (void*)inputPtr; {
return const_cast<void*>(reinterpret_cast<const void*>(inputPtr));
}
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>((void*)inputPtr, &baseType, derivedType)); return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(
const_cast<void*>(reinterpret_cast<const void*>(inputPtr)), &baseType,
derivedType));
} }
template<typename TInput> template<typename TInput>
boost::any castSharedToMostDerived(const std::shared_ptr<TInput> inputPtr) boost::any castSharedToMostDerived(const std::shared_ptr<TInput> inputPtr) const
{ {
auto &baseType = typeid(typename std::remove_cv<TInput>::type); auto &baseType = typeid(typename std::remove_cv<TInput>::type);
auto derivedType = getTypeInfo(inputPtr.get()); auto derivedType = getTypeInfo(inputPtr.get());
if(baseType == *derivedType) if (!strcmp(baseType.name(), derivedType->name()))
return inputPtr; return inputPtr;
return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, &baseType, derivedType); return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, &baseType, derivedType);
} }
void* castRaw(void *inputPtr, const std::type_info *from, const std::type_info *to) void * castRaw(void *inputPtr, const std::type_info *from, const std::type_info *to) const
{ {
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(inputPtr, from, to)); return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(inputPtr, from, to));
} }
boost::any castShared(boost::any inputPtr, const std::type_info *from, const std::type_info *to) boost::any castShared(boost::any inputPtr, const std::type_info *from, const std::type_info *to) const
{ {
return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, from, to); return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, from, to);
} }
template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr) const
template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr)
{ {
if(t) if(t)
return &typeid(*t); return &typeid(*t);
@ -665,9 +674,8 @@ public:
{ {
COSer &s = static_cast<COSer&>(ar); COSer &s = static_cast<COSer&>(ar);
const T *ptr = static_cast<const T*>(data); const T *ptr = static_cast<const T*>(data);
//T is most derived known type, it's time to call actual serialize //T is most derived known type, it's time to call actual serialize
const_cast<T&>(*ptr).serialize(s,version); const_cast<T*>(ptr)->serialize(s,version);
} }
}; };

View File

@ -331,9 +331,6 @@ struct SetAvailableHeroes : public CPackForClient //113
for (int i = 0; i < GameConstants::AVAILABLE_HEROES_PER_PLAYER; i++) for (int i = 0; i < GameConstants::AVAILABLE_HEROES_PER_PLAYER; i++)
army[i].clear(); army[i].clear();
} }
~SetAvailableHeroes()
{
}
void applyCl(CClient *cl); void applyCl(CClient *cl);
DLL_LINKAGE void applyGs(CGameState *gs); DLL_LINKAGE void applyGs(CGameState *gs);

View File

@ -917,7 +917,7 @@ void CGameHandler::handleConnection(std::set<PlayerColor> players, CConnection &
c << &applied; c << &applied;
}; };
CBaseForGHApply *apply = applier->apps[packType]; //and appropriae applier object CBaseForGHApply *apply = applier->apps[packType]; //and appropriate applier object
if(isBlockedByQueries(pack, player)) if(isBlockedByQueries(pack, player))
{ {
sendPackageResponse(false); sendPackageResponse(false);
@ -5368,7 +5368,6 @@ void CGameHandler::runBattle()
const CStack *next; const CStack *next;
while(!battleResult.get() && (next = curB.getNextStack()) && next->willMove()) while(!battleResult.get() && (next = curB.getNextStack()) && next->willMove())
{ {
//check for bad morale => freeze //check for bad morale => freeze
int nextStackMorale = next->MoraleVal(); int nextStackMorale = next->MoraleVal();
if( nextStackMorale < 0 && if( nextStackMorale < 0 &&
@ -5710,7 +5709,7 @@ bool CGameHandler::isValidObject(const CGObjectInstance *obj) const
bool CGameHandler::isBlockedByQueries(const CPack *pack, PlayerColor player) bool CGameHandler::isBlockedByQueries(const CPack *pack, PlayerColor player)
{ {
if(dynamic_cast<const PlayerMessage*>(pack)) if(!strcmp(typeid(*pack).name(), typeid(PlayerMessage).name()))
return false; return false;
auto query = queries.topQuery(player); auto query = queries.topQuery(player);
@ -5849,7 +5848,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI
//catapult artifact remain even if "creature" killed in siege //catapult artifact remain even if "creature" killed in siege
if(warMachine != ArtifactID::NONE && warMachine != ArtifactID::CATAPULT) if(warMachine != ArtifactID::NONE && warMachine != ArtifactID::CATAPULT)
{ {
auto hero = dynamic_cast<const CGHeroInstance*> (army); auto hero = dynamic_ptr_cast<CGHeroInstance> (army);
if (hero) if (hero)
removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true))); removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true)));
} }
@ -5955,4 +5954,3 @@ bool ServerSpellCastEnvironment::moveHero(ObjectInstanceID hid, int3 dst, ui8 te
{ {
return gh->moveHero(hid, dst, teleporting, false, asker); return gh->moveHero(hid, dst, teleporting, false, asker);
} }

View File

@ -245,7 +245,8 @@ CBattleQuery::CBattleQuery()
bool CBattleQuery::blocksPack(const CPack *pack) const bool CBattleQuery::blocksPack(const CPack *pack) const
{ {
return !dynamic_cast<const MakeAction*>(pack) && !dynamic_cast<const MakeCustomAction*>(pack); const char * name = typeid(*pack).name();
return strcmp(name, typeid(MakeAction).name()) && strcmp(name, typeid(MakeCustomAction).name());
} }
void CBattleQuery::onRemoval(CGameHandler *gh, PlayerColor color) void CBattleQuery::onRemoval(CGameHandler *gh, PlayerColor color)
@ -273,12 +274,12 @@ bool CGarrisonDialogQuery::blocksPack(const CPack *pack) const
ourIds.insert(this->exchangingArmies[0]->id); ourIds.insert(this->exchangingArmies[0]->id);
ourIds.insert(this->exchangingArmies[1]->id); ourIds.insert(this->exchangingArmies[1]->id);
if (auto stacks = dynamic_ptr_cast<ArrangeStacks>(pack))
if (auto stacks = dynamic_cast<const ArrangeStacks*>(pack))
{ {
return !vstd::contains(ourIds, stacks->id1) || !vstd::contains(ourIds, stacks->id2); return !vstd::contains(ourIds, stacks->id1) || !vstd::contains(ourIds, stacks->id2);
} }
if (auto arts = dynamic_cast<const ExchangeArtifacts*>(pack))
if (auto arts = dynamic_ptr_cast<ExchangeArtifacts>(pack))
{ {
if(auto id1 = boost::apply_visitor(GetEngagedHeroIds(), arts->src.artHolder)) if(auto id1 = boost::apply_visitor(GetEngagedHeroIds(), arts->src.artHolder))
if(!vstd::contains(ourIds, *id1)) if(!vstd::contains(ourIds, *id1))
@ -289,17 +290,17 @@ bool CGarrisonDialogQuery::blocksPack(const CPack *pack) const
return true; return true;
return false; return false;
} }
if (auto dismiss = dynamic_cast<const DisbandCreature*>(pack)) if (auto dismiss = dynamic_ptr_cast<DisbandCreature>(pack))
{ {
return !vstd::contains(ourIds, dismiss->id); return !vstd::contains(ourIds, dismiss->id);
} }
if (auto dismiss = dynamic_cast<const AssembleArtifacts*>(pack)) if (auto dismiss = dynamic_ptr_cast<AssembleArtifacts>(pack))
{ {
return !vstd::contains(ourIds, dismiss->heroID); return !vstd::contains(ourIds, dismiss->heroID);
} }
if(auto upgrade = dynamic_cast<const UpgradeCreature*>(pack)) if(auto upgrade = dynamic_ptr_cast<UpgradeCreature>(pack))
{ {
return !vstd::contains(ourIds, upgrade->id); return !vstd::contains(ourIds, upgrade->id);
} }
@ -320,7 +321,7 @@ CBlockingDialogQuery::CBlockingDialogQuery(const BlockingDialog &bd)
void CTeleportDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const void CTeleportDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const
{ {
auto obj = dynamic_cast<const CGTeleport *>(objectVisit.visitedObject); auto obj = dynamic_ptr_cast<const CGTeleport>(objectVisit.visitedObject);
obj->teleportDialogAnswered(objectVisit.visitingHero, *answer, td.exits); obj->teleportDialogAnswered(objectVisit.visitingHero, *answer, td.exits);
} }
@ -374,7 +375,7 @@ bool CDialogQuery::endsByPlayerAnswer() const
bool CDialogQuery::blocksPack(const CPack *pack) const bool CDialogQuery::blocksPack(const CPack *pack) const
{ {
//We accept only query replies from correct player //We accept only query replies from correct player
if(auto reply = dynamic_cast<const QueryReply *>(pack)) if(auto reply = dynamic_ptr_cast<QueryReply>(pack))
{ {
return !vstd::contains(players, reply->player); return !vstd::contains(players, reply->player);
} }

View File

@ -86,8 +86,8 @@ void CPregameServer::handleConnection(CConnection *cpc)
logNetwork->infoStream() << "Got package to announce " << typeid(*cpfs).name() << " from " << *cpc; logNetwork->infoStream() << "Got package to announce " << typeid(*cpfs).name() << " from " << *cpc;
boost::unique_lock<boost::recursive_mutex> queueLock(mx); boost::unique_lock<boost::recursive_mutex> queueLock(mx);
bool quitting = dynamic_cast<QuitMenuWithoutStarting*>(cpfs), bool quitting = dynamic_ptr_cast<QuitMenuWithoutStarting>(cpfs),
startingGame = dynamic_cast<StartWithCurrentSettings*>(cpfs); startingGame = dynamic_ptr_cast<StartWithCurrentSettings>(cpfs);
if(quitting || startingGame) //host leaves main menu or wants to start game -> we end if(quitting || startingGame) //host leaves main menu or wants to start game -> we end
{ {
cpc->receivedStop = true; cpc->receivedStop = true;
@ -258,11 +258,11 @@ void CPregameServer::sendPack(CConnection * pc, const CPackForSelectionScreen &
*pc << &pack; *pc << &pack;
} }
if(dynamic_cast<const QuitMenuWithoutStarting*>(&pack)) if(dynamic_ptr_cast<QuitMenuWithoutStarting>(&pack))
{ {
pc->sendStop = true; pc->sendStop = true;
} }
else if(dynamic_cast<const StartWithCurrentSettings*>(&pack)) else if(dynamic_ptr_cast<StartWithCurrentSettings>(&pack))
{ {
pc->sendStop = true; pc->sendStop = true;
} }
@ -270,25 +270,25 @@ void CPregameServer::sendPack(CConnection * pc, const CPackForSelectionScreen &
void CPregameServer::processPack(CPackForSelectionScreen * pack) void CPregameServer::processPack(CPackForSelectionScreen * pack)
{ {
if(dynamic_cast<CPregamePackToHost*>(pack)) if(dynamic_ptr_cast<CPregamePackToHost>(pack))
{ {
sendPack(host, *pack); sendPack(host, *pack);
} }
else if(SelectMap *sm = dynamic_cast<SelectMap*>(pack)) else if(SelectMap *sm = dynamic_ptr_cast<SelectMap>(pack))
{ {
vstd::clear_pointer(curmap); vstd::clear_pointer(curmap);
curmap = sm->mapInfo; curmap = sm->mapInfo;
sm->free = false; sm->free = false;
announcePack(*pack); announcePack(*pack);
} }
else if(UpdateStartOptions *uso = dynamic_cast<UpdateStartOptions*>(pack)) else if(UpdateStartOptions *uso = dynamic_ptr_cast<UpdateStartOptions>(pack))
{ {
vstd::clear_pointer(curStartInfo); vstd::clear_pointer(curStartInfo);
curStartInfo = uso->options; curStartInfo = uso->options;
uso->free = false; uso->free = false;
announcePack(*pack); announcePack(*pack);
} }
else if(dynamic_cast<const StartWithCurrentSettings*>(pack)) else if(dynamic_ptr_cast<StartWithCurrentSettings>(pack))
{ {
state = ENDING_AND_STARTING_GAME; state = ENDING_AND_STARTING_GAME;
announcePack(*pack); announcePack(*pack);

View File

@ -209,7 +209,7 @@ bool SetFormation::applyGh( CGameHandler *gh )
bool HireHero::applyGh( CGameHandler *gh ) bool HireHero::applyGh( CGameHandler *gh )
{ {
const CGObjectInstance *obj = gh->getObj(tid); const CGObjectInstance *obj = gh->getObj(tid);
const CGTownInstance *town = dynamic_cast<const CGTownInstance *>(obj); const CGTownInstance *town = dynamic_ptr_cast<CGTownInstance>(obj);
if(town && PlayerRelations::ENEMIES == gh->getPlayerRelations(obj->tempOwner, gh->getPlayerAt(c))) if(town && PlayerRelations::ENEMIES == gh->getPlayerRelations(obj->tempOwner, gh->getPlayerAt(c)))
COMPLAIN_AND_RETURN("Can't buy hero in enemy town!"); COMPLAIN_AND_RETURN("Can't buy hero in enemy town!");

View File

@ -8,3 +8,31 @@
#include <boost/random/mersenne_twister.hpp> #include <boost/random/mersenne_twister.hpp>
#include <boost/random/variate_generator.hpp> #include <boost/random/variate_generator.hpp>
#include <boost/system/system_error.hpp> #include <boost/system/system_error.hpp>
template<class T, class F>
inline const T * dynamic_ptr_cast(const F * ptr)
{
#ifndef __APPLE__
return dynamic_cast<const T*>(ptr);
#else
if (!strcmp(typeid(*ptr).name(), typeid(T).name()))
{
return static_cast<const T*>(ptr);
}
return nullptr;
#endif
}
template<class T, class F>
inline T * dynamic_ptr_cast(F * ptr)
{
#ifndef __APPLE__
return dynamic_cast<T*>(ptr);
#else
if (!strcmp(typeid(*ptr).name(), typeid(T).name()))
{
return static_cast<T*>(ptr);
}
return nullptr;
#endif
}