From 687a82886f5c42ee055941a56302312ee44996ec Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Sun, 25 Oct 2015 01:38:30 +0300 Subject: [PATCH 01/13] cleanup CTypeList interface --- lib/Connection.cpp | 8 ++-- lib/Connection.h | 98 +++++++++++++++++++--------------------------- 2 files changed, 45 insertions(+), 61 deletions(-) diff --git a/lib/Connection.cpp b/lib/Connection.cpp index 0f6ca2ee2..4dc857cc1 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -448,7 +448,7 @@ CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type ) return newType; } -ui16 CTypeList::getTypeID( const std::type_info *type ) +ui16 CTypeList::getTypeID(const std::type_info * type) const { auto i = typeInfos.find(type); if(i != typeInfos.end()) @@ -457,7 +457,7 @@ ui16 CTypeList::getTypeID( const std::type_info *type ) return 0; } -std::vector CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) +std::vector CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) const { if(from == to) return std::vector(); @@ -510,7 +510,7 @@ std::vector CTypeList::castSequence(TypeInfoPtr from, Ty return ret; } -std::vector CTypeList::castSequence(const std::type_info *from, const std::type_info *to) +std::vector 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 // (and if casting is not needed, then registereing should no be required) @@ -520,7 +520,7 @@ std::vector CTypeList::castSequence(const std::type_info 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); if(i != typeInfos.end()) diff --git a/lib/Connection.h b/lib/Connection.h index ee07bf9aa..61eb654ad 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -136,7 +136,7 @@ struct PointerCaster : IPointerCaster // } }; -class DLL_LINKAGE CTypeList +class DLL_LINKAGE CTypeList: public boost::noncopyable { public: struct TypeDescriptor; @@ -152,58 +152,14 @@ private: std::map typeInfos; std::map, std::unique_ptr> casters; //for each pair we provide a caster (each registered relations creates a single entry here) - CTypeList(CTypeList &) - { - // This type is non-copyable. - // Unfortunately on Windows it is required for DLL_EXPORT-ed type to provide copy c-tor, so we can't =delete it. - assert(0); - } - CTypeList &operator=(CTypeList &) - { - // As above. - assert(0); - return *this; - } -public: - - CTypeList(); - - TypeInfoPtr registerType(const std::type_info *type); - - - template - void registerType(const Base * b = nullptr, const Derived * d = nullptr) - { - static_assert(std::is_base_of::value, "First registerType template parameter needs to ba a base class of the second one."); - static_assert(std::has_virtual_destructor::value, "Base class needs to have a virtual destructor."); - static_assert(!std::is_same::value, "Parameters of registerTypes should be two diffrenet types."); - auto bt = getTypeInfo(b), dt = getTypeInfo(d); //obtain std::type_info - auto bti = registerType(bt), dti = registerType(dt); //obtain our TypeDescriptor - - // register the relation between classes - bti->children.push_back(dti); - dti->parents.push_back(bti); - casters[std::make_pair(bti, dti)] = make_unique>(); - casters[std::make_pair(dti, bti)] = make_unique>(); - } - - ui16 getTypeID(const std::type_info *type); - TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true); //if not throws, failure returns nullptr - - template - ui16 getTypeID(const T * t = nullptr) - { - return getTypeID(getTypeInfo(t)); - } - - - // 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 castSequence(TypeInfoPtr from, TypeInfoPtr to); - std::vector castSequence(const std::type_info *from, const std::type_info *to); + /// 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 castSequence(TypeInfoPtr from, TypeInfoPtr to) const; + std::vector castSequence(const std::type_info *from, const std::type_info *to) const; + template - boost::any castHelper(boost::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg) + boost::any castHelper(boost::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg) const { auto typesSequence = castSequence(fromArg, toArg); @@ -223,8 +179,37 @@ public: return ptr; } + TypeInfoPtr registerType(const std::type_info *type); +public: + CTypeList(); + + template + void registerType(const Base * b = nullptr, const Derived * d = nullptr) + { + static_assert(std::is_base_of::value, "First registerType template parameter needs to ba a base class of the second one."); + static_assert(std::has_virtual_destructor::value, "Base class needs to have a virtual destructor."); + static_assert(!std::is_same::value, "Parameters of registerTypes should be two diffrenet types."); + auto bt = getTypeInfo(b), dt = getTypeInfo(d); //obtain std::type_info + auto bti = registerType(bt), dti = registerType(dt); //obtain our TypeDescriptor + + // register the relation between classes + bti->children.push_back(dti); + dti->parents.push_back(bti); + casters[std::make_pair(bti, dti)] = make_unique>(); + casters[std::make_pair(dti, bti)] = make_unique>(); + } + + ui16 getTypeID(const std::type_info *type) const; + TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true) const; //if not throws, failure returns nullptr + + template + ui16 getTypeID(const T * t = nullptr) const + { + return getTypeID(getTypeInfo(t)); + } + template - void *castToMostDerived(const TInput *inputPtr) + void * castToMostDerived(const TInput * inputPtr) const { auto &baseType = typeid(typename std::remove_cv::type); auto derivedType = getTypeInfo(inputPtr); @@ -236,7 +221,7 @@ public: } template - boost::any castSharedToMostDerived(const std::shared_ptr inputPtr) + boost::any castSharedToMostDerived(const std::shared_ptr inputPtr) const { auto &baseType = typeid(typename std::remove_cv::type); auto derivedType = getTypeInfo(inputPtr.get()); @@ -247,17 +232,16 @@ public: 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(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); } - - template const std::type_info * getTypeInfo(const T * t = nullptr) + template const std::type_info * getTypeInfo(const T * t = nullptr) const { if(t) return &typeid(*t); From 0f9de1c560fa93591f456f24db027c4a9eacedef Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Sun, 25 Oct 2015 03:26:48 +0300 Subject: [PATCH 02/13] Made CTypeList threadsafe --- lib/Connection.cpp | 1 + lib/Connection.h | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/Connection.cpp b/lib/Connection.cpp index 4dc857cc1..d88326017 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -450,6 +450,7 @@ CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type ) ui16 CTypeList::getTypeID(const std::type_info * type) const { + TSharedLock lock(mx); auto i = typeInfos.find(type); if(i != typeInfos.end()) return i->second->typeID; diff --git a/lib/Connection.h b/lib/Connection.h index 61eb654ad..bf12e07f4 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -147,7 +147,11 @@ public: const char *name; std::vector children, parents; }; + typedef boost::shared_mutex TMutex; + typedef boost::unique_lock TUniqueLock; + typedef boost::shared_lock TSharedLock; private: + mutable TMutex mx; std::map typeInfos; std::map, std::unique_ptr> casters; //for each pair we provide a caster (each registered relations creates a single entry here) @@ -161,6 +165,7 @@ private: template 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; @@ -179,13 +184,16 @@ private: return ptr; } - TypeInfoPtr registerType(const std::type_info *type); + TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true) const; //if not throws, failure returns nullptr + + TypeInfoPtr registerType(const std::type_info *type); public: CTypeList(); template void registerType(const Base * b = nullptr, const Derived * d = nullptr) { + TUniqueLock lock(mx); static_assert(std::is_base_of::value, "First registerType template parameter needs to ba a base class of the second one."); static_assert(std::has_virtual_destructor::value, "Base class needs to have a virtual destructor."); static_assert(!std::is_same::value, "Parameters of registerTypes should be two diffrenet types."); @@ -200,7 +208,6 @@ public: } ui16 getTypeID(const std::type_info *type) const; - TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true) const; //if not throws, failure returns nullptr template ui16 getTypeID(const T * t = nullptr) const From cfb58536891869d4dd7cddb3e6fb12e38e63dd24 Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Sun, 25 Oct 2015 03:29:16 +0300 Subject: [PATCH 03/13] Just a bit of black magic --- lib/NetPacks.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/NetPacks.h b/lib/NetPacks.h index cdbe3ebe9..e788fd9b2 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -331,9 +331,6 @@ struct SetAvailableHeroes : public CPackForClient //113 for (int i = 0; i < GameConstants::AVAILABLE_HEROES_PER_PLAYER; i++) army[i].clear(); } - ~SetAvailableHeroes() - { - } void applyCl(CClient *cl); DLL_LINKAGE void applyGs(CGameState *gs); From 79fb5b0c7bcc7c3b847a65b62df36bd051c90d03 Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Sun, 25 Oct 2015 13:04:21 +0300 Subject: [PATCH 04/13] Fix typeid ordering bug on MacOSX --- lib/Connection.cpp | 49 ++++++++++++----------- lib/Connection.h | 96 ++++++++++++++++++++++++---------------------- 2 files changed, 74 insertions(+), 71 deletions(-) diff --git a/lib/Connection.cpp b/lib/Connection.cpp index d88326017..0fce3d2c3 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -68,7 +68,7 @@ void CConnection::init() } CConnection::CConnection(std::string host, std::string port, std::string Name) -:iser(this), oser(this), io_service(new asio::io_service), name(Name) +:iser(this), oser(this), io_service(new asio::io_service), name(Name) { int i; boost::system::error_code error = asio::error::host_not_found; @@ -119,7 +119,7 @@ connerror1: else logNetwork->errorStream() << "No error info. "; delete io_service; - //delete socket; + //delete socket; throw std::runtime_error("Can't establish connection :("); } CConnection::CConnection(TSocket * Socket, std::string Name ) @@ -134,10 +134,10 @@ CConnection::CConnection(TAcceptor * acceptor, boost::asio::io_service *Io_servi socket = new tcp::socket(*io_service); acceptor->accept(*socket,error); if (error) - { + { logNetwork->errorStream() << "Error on accepting: " << error; - delete socket; - throw std::runtime_error("Can't establish connection :("); + delete socket; + throw std::runtime_error("Can't establish connection :("); } init(); } @@ -238,12 +238,12 @@ void CConnection::sendPackToServer(const CPack &pack, PlayerColor player, ui32 r void CConnection::disableStackSendingByID() { - CSerializer::sendStackInstanceByIds = false; + CSerializer::sendStackInstanceByIds = false; } void CConnection::enableStackSendingByID() { - CSerializer::sendStackInstanceByIds = true; + CSerializer::sendStackInstanceByIds = true; } void CConnection::disableSmartPointerSerialization() @@ -283,7 +283,7 @@ void CConnection::enableSmartVectorMemberSerializatoin() CSerializer::smartVectorMembersSerialization = true; } -CSaveFile::CSaveFile( const std::string &fname ): serializer(this) +CSaveFile::CSaveFile( const std::string &fname ): serializer(this) { registerTypes(serializer); openNextFile(fname); @@ -377,7 +377,7 @@ void CLoadFile::openNextFile(const boost::filesystem::path & fname, int minimalV if(std::memcmp(buffer,"VCMI",4)) THROW_FORMAT("Error: not a VCMI file(%s)!", fName); - serializer >> serializer.fileVersion; + serializer >> serializer.fileVersion; if(serializer.fileVersion < minimalVersion) THROW_FORMAT("Error: too old file format (%s)!", fName); @@ -435,7 +435,7 @@ CTypeList::CTypeList() } CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type ) -{ +{ if(auto typeDescr = getTypeDescriptor(type, false)) return typeDescr; //type found, return ptr to structure @@ -448,14 +448,14 @@ CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type ) return newType; } -ui16 CTypeList::getTypeID(const std::type_info * type) const -{ - TSharedLock lock(mx); - auto i = typeInfos.find(type); - if(i != typeInfos.end()) - return i->second->typeID; - else +ui16 CTypeList::getTypeID( const std::type_info *type, bool throws ) const +{ + auto descriptor = getTypeDescriptor(type, throws); + if (descriptor == nullptr) + { return 0; + } + return descriptor->typeID; } std::vector CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) const @@ -483,7 +483,7 @@ std::vector CTypeList::castSequence(TypeInfoPtr from, Ty } } } - + std::vector ret; if(!previous.count(from)) @@ -525,7 +525,7 @@ CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(const std::type_info *type, { auto i = typeInfos.find(type); if(i != typeInfos.end()) - return i->second; //type found, return ptr to structure + return i->second; //type found, return ptr to structure if(!throws) return nullptr; @@ -552,19 +552,19 @@ CSerializer::CSerializer() void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib) { - registerVectoredType(&gs->map->objects, + registerVectoredType(&gs->map->objects, [](const CGObjectInstance &obj){ return obj.id; }); - registerVectoredType(&lib->heroh->heroes, + registerVectoredType(&lib->heroh->heroes, [](const CHero &h){ return h.ID; }); registerVectoredType(&gs->map->allHeroes, [](const CGHeroInstance &h){ return h.type->ID; }); - registerVectoredType(&lib->creh->creatures, + registerVectoredType(&lib->creh->creatures, [](const CCreature &cre){ return cre.idNumber; }); registerVectoredType(&lib->arth->artifacts, [](const CArtifact &art){ return art.id; }); - registerVectoredType(&gs->map->artInstances, + registerVectoredType(&gs->map->artInstances, [](const CArtifactInstance &artInst){ return artInst.id; }); - registerVectoredType(&gs->map->quests, + registerVectoredType(&gs->map->quests, [](const CQuest &q){ return q.qid; }); smartVectorMembersSerialization = true; @@ -645,4 +645,3 @@ CMemorySerializer::CMemorySerializer(): iser(this), oser(this) registerTypes(iser); registerTypes(oser); } - diff --git a/lib/Connection.h b/lib/Connection.h index bf12e07f4..b27a77c50 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -81,10 +81,14 @@ enum SerializationLvl struct TypeComparer { - bool operator()(const std::type_info *a, const std::type_info *b) const - { - return a->before(*b); - } + bool operator()(const std::type_info *a, const std::type_info *b) const + { + #ifndef __APPLE__ + return a->before(*b); + #else + return std::string(a->name()) < std::string(b->name()); + #endif + } }; struct IPointerCaster @@ -160,7 +164,7 @@ private: /// Throws if there is no link registered. std::vector castSequence(TypeInfoPtr from, TypeInfoPtr to) const; std::vector castSequence(const std::type_info *from, const std::type_info *to) const; - + template boost::any castHelper(boost::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg) const @@ -207,12 +211,12 @@ public: casters[std::make_pair(dti, bti)] = make_unique>(); } - ui16 getTypeID(const std::type_info *type) const; + ui16 getTypeID(const std::type_info *type, bool throws = false) const; template - ui16 getTypeID(const T * t = nullptr) const + ui16 getTypeID(const T * t = nullptr, bool throws = false) const { - return getTypeID(getTypeInfo(t)); + return getTypeID(getTypeInfo(t), throws); } template @@ -435,13 +439,13 @@ public: virtual int write(const void * data, unsigned size) = 0; }; -class DLL_LINKAGE CSaverBase +class DLL_LINKAGE CSaverBase { protected: IBinaryWriter * writer; public: CSaverBase(IBinaryWriter * w): writer(w){}; - + inline int write(const void * data, unsigned size) { return writer->write(data, size); @@ -577,15 +581,15 @@ struct LoadIfStackInstance class DLL_LINKAGE COSer : public CSaverBase { public: - + struct SaveBoolean { static void invoke(COSer &s, const bool &data) { s.saveBoolean(data); } - }; - + }; + struct SaveBooleanVector { static void invoke(COSer &s, const std::vector &data) @@ -620,7 +624,7 @@ public: s.saveEnum(data); } }; - + template struct SavePointer { @@ -629,7 +633,7 @@ public: s.savePointer(data); } }; - + template struct SaveArray { @@ -646,9 +650,9 @@ public: { throw std::runtime_error("Wrong save serialization call!"); } - }; - - template + }; + + template class CPointerSaver : public CBasicPointerSaver { public: @@ -660,8 +664,8 @@ public: //T is most derived known type, it's time to call actual serialize const_cast(*ptr).serialize(s,version); } - }; - + }; + bool saving; std::map savers; // typeID => CPointerSaver @@ -955,13 +959,13 @@ public: virtual int read(void * data, unsigned size) = 0; }; -class DLL_LINKAGE CLoaderBase +class DLL_LINKAGE CLoaderBase { protected: IBinaryReader * reader; public: CLoaderBase(IBinaryReader * r): reader(r){}; - + inline int read(void * data, unsigned size) { return reader->read(data, size); @@ -1006,15 +1010,15 @@ public: s.loadBoolean(data); } }; - + struct LoadBooleanVector { static void invoke(CISer &s, std::vector &data) { s.loadBooleanVector(data); } - }; - + }; + template struct LoadEnum { @@ -1031,7 +1035,7 @@ public: { s.loadPrimitive(data); } - }; + }; template struct LoadPointer @@ -1040,8 +1044,8 @@ public: { s.loadPointer(data); } - }; - + }; + template struct LoadArray { @@ -1067,8 +1071,8 @@ public: { throw std::runtime_error("Wrong load serialization call!"); } - }; - + }; + template class CPointerLoader : public CBasicPointerLoader { public: @@ -1085,8 +1089,8 @@ public: ptr->serialize(s,version); return &typeid(T); } - }; - + }; + bool saving; std::map loaders; // typeID => CPointerSaver si32 fileVersion; @@ -1530,9 +1534,9 @@ class DLL_LINKAGE CSaveFile :public IBinaryWriter { public: - + COSer serializer; - + std::string fName; unique_ptr sfile; @@ -1545,13 +1549,13 @@ public: void reportState(CLogger * out) override; void putMagicBytes(const std::string &text); - + template CSaveFile & operator<<(const T &t) { serializer << t; return * this; - } + } }; class DLL_LINKAGE CLoadFile @@ -1559,7 +1563,7 @@ class DLL_LINKAGE CLoadFile { public: CISer serializer; - + std::string fName; unique_ptr sfile; @@ -1572,20 +1576,20 @@ public: void reportState(CLogger * out) override; void checkMagicBytes(const std::string & text); - + template CLoadFile & operator>>(T &t) { serializer >> t; return * this; - } + } }; -class DLL_LINKAGE CLoadIntegrityValidator +class DLL_LINKAGE CLoadIntegrityValidator : public IBinaryReader { public: - CISer serializer; + CISer serializer; unique_ptr primaryFile, controlFile; bool foundDesync; @@ -1611,7 +1615,7 @@ class DLL_LINKAGE CConnection public: CISer iser; COSer oser; - + boost::mutex *rmx, *wmx; // read/write mutexes TSocket * socket; bool logging; @@ -1649,14 +1653,14 @@ public: void prepareForSendingHeroes(); //disables sending vectorised, enables smart pointer serialization, clears saved/loaded ptr cache void enterPregameConnectionMode(); - + template CConnection & operator>>(T &t) { iser >> t; return * this; - } - + } + template CConnection & operator<<(const T &t) { @@ -1678,7 +1682,7 @@ class DLL_LINKAGE CMemorySerializer public: CISer iser; COSer oser; - + int read(void * data, unsigned size) override; //throws! int write(const void * data, unsigned size) override; From c5ebec0d1fcb182688de33d76d9c870c6ea9b5d1 Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Tue, 27 Oct 2015 09:09:42 +0300 Subject: [PATCH 05/13] Fix the second crash (dynamic_cast failure) --- client/Client.cpp | 53 +++++++++++++++++++++++----------------------- lib/Connection.cpp | 4 ++-- lib/Connection.h | 39 ++++++++++++++++++++++------------ 3 files changed, 54 insertions(+), 42 deletions(-) diff --git a/client/Client.cpp b/client/Client.cpp index dabe2209f..0471204ae 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -59,8 +59,8 @@ template class CApplyOnCL; class CBaseForCLApply { public: - virtual void applyOnClAfter(CClient *cl, void *pack) const =0; - virtual void applyOnClBefore(CClient *cl, void *pack) const =0; + virtual void applyOnClAfter(CClient *cl, void *pack) const =0; + virtual void applyOnClBefore(CClient *cl, void *pack) const =0; virtual ~CBaseForCLApply(){} template static CBaseForCLApply *getApplier(const U * t=nullptr) @@ -144,7 +144,7 @@ void CClient::waitForMoveAndSend(PlayerColor color) { logNetwork->traceStream() << "Send battle action to server: " << ba; MakeAction temp_action(ba); - sendRequest(&temp_action, color); + sendRequest(&temp_action, color); } return; } @@ -169,8 +169,8 @@ void CClient::run() while(!terminate) { CPack *pack = serv->retreivePack(); //get the package from the server - - if (terminate) + + if (terminate) { vstd::clear_pointer(pack); break; @@ -178,10 +178,10 @@ void CClient::run() handlePack(pack); } - } + } //catch only asio exceptions catch (const boost::system::system_error& e) - { + { logNetwork->errorStream() << "Lost connection to server, ending listening thread!"; logNetwork->errorStream() << e.what(); if(!terminate) //rethrow (-> boom!) only if closing connection was unexpected @@ -313,7 +313,7 @@ void CClient::loadGame(const std::string & fname, const bool server, const std:: *serv << ui8(3) << ui8(loadNumPlayers); //load game; one client if single-player *serv << fname; *serv >> pom8; - if(pom8) + if(pom8) throw std::runtime_error("Server cannot open the savegame!"); else logNetwork->infoStream() << "Server opened savegame properly."; @@ -369,7 +369,7 @@ void CClient::newGame( CConnection *con, StartInfo *si ) { enum {SINGLE, HOST, GUEST} networkMode = SINGLE; - if (con == nullptr) + if (con == nullptr) { CServerHandler sh; serv = sh.connectToServer(); @@ -452,7 +452,7 @@ void CClient::newGame( CConnection *con, StartInfo *si ) logNetwork->infoStream() << boost::format("Player %s will be lead by %s") % color % AiToGive; installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), color); } - else + else { installNewPlayerInterface(make_shared(color), color); humanPlayers++; @@ -495,7 +495,7 @@ void CClient::newGame( CConnection *con, StartInfo *si ) // nm->giveActionCB(this); // nm->giveInfoCB(this); // nm->init(); -// +// // erm = nm; //something tells me that there'll at most one module and it'll be ERM // } } @@ -503,7 +503,7 @@ void CClient::newGame( CConnection *con, StartInfo *si ) void CClient::serialize(COSer & h, const int version) { assert(h.saving); - h & hotSeat; + h & hotSeat; { ui8 players = playerint.size(); h & players; @@ -513,7 +513,7 @@ void CClient::serialize(COSer & h, const int version) LOG_TRACE_PARAMS(logGlobal, "Saving player %s interface", i->first); assert(i->first == i->second->playerID); h & i->first & i->second->dllName & i->second->human; - i->second->saveGame(h, version); + i->second->saveGame(h, version); } } } @@ -529,7 +529,7 @@ void CClient::serialize(CISer & h, const int version) for(int i=0; i < players; i++) { std::string dllname; - PlayerColor pid; + PlayerColor pid; bool isHuman = false; h & pid & dllname & isHuman; @@ -541,7 +541,7 @@ void CClient::serialize(CISer & h, const int version) if(pid == PlayerColor::NEUTRAL) { installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid); - //TODO? consider serialization + //TODO? consider serialization continue; } else @@ -582,7 +582,7 @@ void CClient::serialize(COSer & h, const int version, const std::setfirst); assert(i->first == i->second->playerID); h & i->first & i->second->dllName & i->second->human; - i->second->saveGame(h, version); + i->second->saveGame(h, version); } } } @@ -598,7 +598,7 @@ void CClient::serialize(CISer & h, const int version, const std::setloadGame(h, version); + nInt->loadGame(h, version); } if(playerIDs.count(PlayerColor::NEUTRAL)) @@ -707,7 +707,7 @@ void CClient::battleStarted(const BattleInfo * info) { for(auto &battleCb : battleCallbacks) { - if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; }) + if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; }) || battleCb.first >= PlayerColor::PLAYER_LIMIT) { battleCb.second->setBattle(info); @@ -735,7 +735,7 @@ void CClient::battleStarted(const BattleInfo * info) { boost::unique_lock un(*LOCPLINT->pim); auto bi = new CBattleInterface(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, - Rect((screen->w - 800)/2, + Rect((screen->w - 800)/2, (screen->h - 600)/2, 800, 600), att, def); GH.pushInt(bi); @@ -798,7 +798,7 @@ void CClient::commenceTacticPhaseForInt(shared_ptr battleI catch(...) { handleException(); - } + } } void CClient::invalidatePaths() @@ -822,7 +822,6 @@ const CPathsInfo * CClient::getPathsInfo(const CGHeroInstance *h) int CClient::sendRequest(const CPack *request, PlayerColor player) { static ui32 requestCounter = 0; - ui32 requestID = requestCounter++; logNetwork->traceStream() << boost::format("Sending a request \"%s\". It'll have an ID=%d.") % typeid(*request).name() % requestID; @@ -882,7 +881,7 @@ void CClient::installNewBattleInterface(shared_ptr battleI boost::unique_lock un(*LOCPLINT->pim); PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE); - if(!color) + if(!color) privilagedBattleEventReceivers.push_back(battleInterface); battleints[colorUsed] = battleInterface; @@ -954,7 +953,7 @@ CConnection * CServerHandler::connectToServer() #endif th.update(); //put breakpoint here to attach to server before it does something stupid - + CConnection *ret = justConnectToServer(settings["server"]["server"].String(), port); if(verbose) @@ -1015,8 +1014,8 @@ CConnection * CServerHandler::justConnectToServer(const std::string &host, const try { logNetwork->infoStream() << "Establishing connection..."; - ret = new CConnection( host.size() ? host : settings["server"]["server"].String(), - port.size() ? port : boost::lexical_cast(settings["server"]["port"].Float()), + ret = new CConnection( host.size() ? host : settings["server"]["server"].String(), + port.size() ? port : boost::lexical_cast(settings["server"]["port"].Float()), NAME); } catch(...) diff --git a/lib/Connection.cpp b/lib/Connection.cpp index 0fce3d2c3..1fd56c26f 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -460,7 +460,7 @@ ui16 CTypeList::getTypeID( const std::type_info *type, bool throws ) const std::vector CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) const { - if(from == to) + if(!strcmp(from->name, to->name)) return std::vector(); // Perform a simple BFS in the class hierarchy. @@ -515,7 +515,7 @@ std::vector CTypeList::castSequence(const std::type_info { //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) - if(*from == *to) + if(!strcmp(from->name(), to->name())) return std::vector(); return castSequence(getTypeDescriptor(from), getTypeDescriptor(to)); diff --git a/lib/Connection.h b/lib/Connection.h index b27a77c50..73f9a43e7 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -86,7 +86,7 @@ struct TypeComparer #ifndef __APPLE__ return a->before(*b); #else - return std::string(a->name()) < std::string(b->name()); + return strcmp(a->name(), b->name()) < 0; #endif } }; @@ -106,6 +106,11 @@ struct PointerCaster : IPointerCaster { From * from = (From*)boost::any_cast(ptr); To * ret = dynamic_cast(from); + if (ret == nullptr) + { + // Last resort when RTTI goes mad + ret = static_cast(from); + } return (void*)ret; } @@ -117,6 +122,11 @@ struct PointerCaster : IPointerCaster { auto from = boost::any_cast(ptr); auto ret = std::dynamic_pointer_cast(from); + if (!ret) + { + // Last resort when RTTI goes mad + ret = std::static_pointer_cast(from); + } return ret; } catch(std::exception &e) @@ -173,7 +183,7 @@ private: auto typesSequence = castSequence(fromArg, toArg); boost::any ptr = inputPtr; - for(int i = 0; i < (int)typesSequence.size() - 1; i++) + for(int i = 0; i < static_cast(typesSequence.size()) - 1; i++) { auto &from = typesSequence[i]; auto &to = typesSequence[i + 1]; @@ -182,7 +192,7 @@ private: 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->* ..? + ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr not have operator->* ..? } return ptr; @@ -225,10 +235,14 @@ public: auto &baseType = typeid(typename std::remove_cv::type); auto derivedType = getTypeInfo(inputPtr); - if(baseType == *derivedType) - return (void*)inputPtr; + if (!strcmp(baseType.name(), derivedType->name())) + { + return const_cast(reinterpret_cast(inputPtr)); + } - return boost::any_cast(castHelper<&IPointerCaster::castRawPtr>((void*)inputPtr, &baseType, derivedType)); + return boost::any_cast(castHelper<&IPointerCaster::castRawPtr>( + const_cast(reinterpret_cast(inputPtr)), &baseType, + derivedType)); } template @@ -237,7 +251,7 @@ public: auto &baseType = typeid(typename std::remove_cv::type); auto derivedType = getTypeInfo(inputPtr.get()); - if(baseType == *derivedType) + if (!strcmp(baseType.name(), derivedType->name())) return inputPtr; return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, &baseType, derivedType); @@ -653,16 +667,15 @@ public: }; template - class CPointerSaver : public CBasicPointerSaver + class CPointerSaver : public CBasicPointerSaver { public: void savePtr(CSaverBase &ar, const void *data) const override - { + { COSer &s = static_cast(ar); - const T *ptr = static_cast(data); - + const T *ptr = static_cast(data); //T is most derived known type, it's time to call actual serialize - const_cast(*ptr).serialize(s,version); + const_cast(ptr)->serialize(s,version); } }; @@ -772,7 +785,7 @@ public: //write type identifier ui16 tid = typeList.getTypeID(data); - *this << tid; + *this << tid; this->savePointerHlp(tid, data); } From 68cc86013319148137e1f488826addb90e836160 Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Wed, 28 Oct 2015 23:53:44 +0300 Subject: [PATCH 06/13] 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 +} From fa8a2826963b3089a758beea6e61af0a660bdbf6 Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Sat, 31 Oct 2015 18:04:06 +0300 Subject: [PATCH 07/13] Fix pthread_mutex_lock abort() in requestActionASAP impl --- AI/VCAI/VCAI.cpp | 35 ++++++++++++++--------------------- server/CGameHandler.cpp | 4 ++-- server/CVCMIServer.cpp | 32 ++++++++++++++++---------------- server/NetPacksServer.cpp | 16 ++++++++-------- server/StdInc.h | 14 ++++++++++++++ 5 files changed, 54 insertions(+), 47 deletions(-) diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 6048e6487..b42d9eb64 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -822,7 +822,7 @@ void VCAI::makeTurnInternal() { if (h->movement) logAi->warnStream() << boost::format("hero %s has %d MP left") % h->name % h->movement; - } + } } catch(boost::thread_interrupted &e) { @@ -891,7 +891,7 @@ bool VCAI::canGetArmy (const CGHeroInstance * army, const CGHeroInstance * sourc const CArmedInstance *armies[] = {army, source}; - + //we calculate total strength for each creature type available in armies std::map creToPower; for(auto armyPtr : armies) @@ -988,7 +988,7 @@ void VCAI::pickBestCreatures(const CArmedInstance * army, const CArmedInstance * } void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other) -{ +{ auto equipBest = [](const CGHeroInstance * h, const CGHeroInstance * otherh, bool giveStuffToFirstHero) -> void { bool changeMade = false; @@ -2059,7 +2059,7 @@ void VCAI::tryRealize(Goals::CollectRes & g) cb->trade(obj, EMarketMode::RESOURCE_RESOURCE, i, g.resID, toGive); if(cb->getResourceAmount(static_cast(g.resID)) >= g.value) return; - } + } throw cannotFulfillGoalException("I cannot get needed resources by trade!"); } @@ -2277,7 +2277,7 @@ Goals::TSubgoal VCAI::striveToGoalInternal(Goals::TSubgoal ultimateGoal, bool on completeGoal (goal); //completed goal was main goal //TODO: find better condition if (ultimateGoal->fulfillsMe(goal) || maxGoals > searchDepth2) - return sptr(Goals::Invalid()); + return sptr(Goals::Invalid()); } catch(std::exception &e) { @@ -2530,7 +2530,7 @@ int3 VCAI::explorationDesperate(HeroPtr h) //logAi->debugStream() << "Looking for an another place for exploration..."; SectorMap sm(h); int radius = h->getSightRadious(); - + std::vector > tiles; //tiles[distance_to_fow] tiles.resize(radius); @@ -2660,19 +2660,13 @@ void VCAI::finish() void VCAI::requestActionASAP(std::function whatToDo) { -// static boost::mutex m; -// boost::unique_lock mylock(m); - - boost::barrier b(2); - boost::thread newThread([&b,this,whatToDo]() + boost::thread newThread([this, whatToDo]() { - setThreadName("VCAI::requestActionASAP::helper"); + setThreadName("VCAI::requestActionASAP::whatToDo"); SET_GLOBAL_STATE(this); boost::shared_lock gsLock(cb->getGsMutex()); - b.wait(); whatToDo(); }); - b.wait(); } void VCAI::lostHero(HeroPtr h) @@ -2867,8 +2861,8 @@ void AIStatus::heroVisit(const CGObjectInstance *obj, bool started) objectsBeingVisited.push_back(obj); else { - // There can be more than one object visited at the time (eg. hero visits Subterranean Gate - // causing visit to hero on the other side. + // There can be more than one object visited at the time (eg. hero visits Subterranean Gate + // causing visit to hero on the other side. // However, we are guaranteed that start/end visit notification maintain stack order. assert(!objectsBeingVisited.empty()); objectsBeingVisited.pop_back(); @@ -2980,7 +2974,7 @@ void SectorMap::exploreNewSector(crint3 pos, int num, CCallback * cbp) s.embarkmentPoints.push_back(neighPos); } }); - + if(t->visitable) { auto obj = t->visitableObjects.front(); @@ -3036,7 +3030,7 @@ bool isWeeklyRevisitable (const CGObjectInstance * obj) bool shouldVisit(HeroPtr h, const CGObjectInstance * obj) { switch (obj->ID) - { + { case Obj::TOWN: case Obj::HERO: //never visit our heroes at random return obj->tempOwner != h->tempOwner; //do not visit our towns at random @@ -3087,7 +3081,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj) return canRecruitCreatures; } case Obj::HILL_FORT: - { + { for (auto slot : h->Slots()) { if (slot.second->type->upgrades.size()) @@ -3386,7 +3380,7 @@ void SectorMap::makeParentBFS(crint3 source) ui8 &sec = retreiveTile(curPos); assert(sec == mySector); //consider only tiles from the same sector UNUSED(sec); - + foreach_neighbour(curPos, [&](crint3 neighPos) { if(retreiveTile(neighPos) == mySector && !vstd::contains(parent, neighPos)) @@ -3405,4 +3399,3 @@ unsigned char & SectorMap::retreiveTile(crint3 pos) { return retreiveTileN(sector, pos); } - diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 9a13c3285..3529c7d0b 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -5688,7 +5688,7 @@ bool CGameHandler::isValidObject(const CGObjectInstance *obj) const bool CGameHandler::isBlockedByQueries(const CPack *pack, PlayerColor player) { - if(dynamic_cast(pack)) + if(!strcmp(typeid(*pack).name(), typeid(PlayerMessage).name())) return false; auto query = queries.topQuery(player); @@ -5826,7 +5826,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI auto warMachine = VLC->arth->creatureToMachineID(st->type->idNumber); if (warMachine != ArtifactID::NONE) { - auto hero = dynamic_cast (army); + auto hero = dynamic_ptr_cast (army); if (hero) removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true))); } diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 1dc10fe67..cb8b690f8 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -86,8 +86,8 @@ void CPregameServer::handleConnection(CConnection *cpc) logNetwork->infoStream() << "Got package to announce " << typeid(*cpfs).name() << " from " << *cpc; boost::unique_lock queueLock(mx); - bool quitting = dynamic_cast(cpfs), - startingGame = dynamic_cast(cpfs); + bool quitting = dynamic_ptr_cast(cpfs), + startingGame = dynamic_ptr_cast(cpfs); if(quitting || startingGame) //host leaves main menu or wants to start game -> we end { cpc->receivedStop = true; @@ -258,11 +258,11 @@ void CPregameServer::sendPack(CConnection * pc, const CPackForSelectionScreen & *pc << &pack; } - if(dynamic_cast(&pack)) + if(dynamic_ptr_cast(&pack)) { pc->sendStop = true; } - else if(dynamic_cast(&pack)) + else if(dynamic_ptr_cast(&pack)) { pc->sendStop = true; } @@ -270,25 +270,25 @@ void CPregameServer::sendPack(CConnection * pc, const CPackForSelectionScreen & void CPregameServer::processPack(CPackForSelectionScreen * pack) { - if(dynamic_cast(pack)) + if(dynamic_ptr_cast(pack)) { sendPack(host, *pack); } - else if(SelectMap *sm = dynamic_cast(pack)) + else if(SelectMap *sm = dynamic_ptr_cast(pack)) { vstd::clear_pointer(curmap); curmap = sm->mapInfo; sm->free = false; announcePack(*pack); } - else if(UpdateStartOptions *uso = dynamic_cast(pack)) + else if(UpdateStartOptions *uso = dynamic_ptr_cast(pack)) { vstd::clear_pointer(curStartInfo); curStartInfo = uso->options; uso->free = false; announcePack(*pack); } - else if(dynamic_cast(pack)) + else if(dynamic_ptr_cast(pack)) { state = ENDING_AND_STARTING_GAME; announcePack(*pack); @@ -307,7 +307,7 @@ void CPregameServer::initConnection(CConnection *c) } void CPregameServer::startListeningThread(CConnection * pc) -{ +{ listeningThreads++; pc->enterPregameConnectionMode(); pc->handler = new boost::thread(&CPregameServer::handleConnection, this, pc); @@ -355,7 +355,7 @@ void CVCMIServer::newGame() { CConnection &c = *firstConnection; ui8 clients; - c >> clients; //how many clients should be connected + c >> clients; //how many clients should be connected assert(clients == 1); //multi goes now by newPregame, TODO: custom lobbies CGameHandler *gh = initGhFromHostingConnection(c); @@ -469,14 +469,14 @@ void CVCMIServer::loadGame() // char sig[8]; // CMapHeader dum; // StartInfo *si; -// +// // CLoadFile lf(CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::LIB_SAVEGAME))); // lf >> sig >> dum >> si; // logNetwork->infoStream() <<"Reading save signature"; -// +// // lf >> *VLC; // logNetwork->infoStream() <<"Reading handlers"; -// +// // lf >> (gh.gs); // c.addStdVecItems(gh.gs); // logNetwork->infoStream() <<"Reading gamestate"; @@ -493,7 +493,7 @@ void CVCMIServer::loadGame() CConnection* cc; //tcp::socket * ss; for(int i=0; iteleportHero(hid,dest,source,gh->getPlayerAt(c)); } @@ -126,7 +126,7 @@ bool GarrisonHeroSwap::applyGh( CGameHandler *gh ) { const CGTownInstance * town = gh->getTown(tid); if (!PLAYER_OWNS(tid) && !( town->garrisonHero && PLAYER_OWNS(town->garrisonHero->id) ) ) - ERROR_AND_RETURN;//neither town nor garrisoned hero (if present) is ours + ERROR_AND_RETURN;//neither town nor garrisoned hero (if present) is ours return gh->garrisonSwap(tid); } @@ -201,7 +201,7 @@ bool TradeOnMarketplace::applyGh( CGameHandler *gh ) } bool SetFormation::applyGh( CGameHandler *gh ) -{ +{ ERROR_IF_NOT_OWNS(hid); return gh->setFormation(hid,formation); } @@ -209,7 +209,7 @@ bool SetFormation::applyGh( CGameHandler *gh ) bool HireHero::applyGh( CGameHandler *gh ) { const CGObjectInstance *obj = gh->getObj(tid); - const CGTownInstance *town = dynamic_cast(obj); + const CGTownInstance *town = dynamic_ptr_cast(obj); if(town && PlayerRelations::ENEMIES == gh->getPlayerRelations(obj->tempOwner, gh->getPlayerAt(c))) COMPLAIN_AND_RETURN("Can't buy hero in enemy town!"); @@ -240,16 +240,16 @@ bool MakeAction::applyGh( CGameHandler *gh ) { const BattleInfo *b = GS(gh)->curB; if(!b) ERROR_AND_RETURN; - + if(b->tacticDistance) { - if(ba.actionType != Battle::WALK && ba.actionType != Battle::END_TACTIC_PHASE + if(ba.actionType != Battle::WALK && ba.actionType != Battle::END_TACTIC_PHASE && ba.actionType != Battle::RETREAT && ba.actionType != Battle::SURRENDER) ERROR_AND_RETURN; - if(gh->connections[b->sides[b->tacticsSide].color] != c) + if(gh->connections[b->sides[b->tacticsSide].color] != c) ERROR_AND_RETURN; } - else if(gh->connections[b->battleGetStackByID(b->activeStack)->owner] != c) + else if(gh->connections[b->battleGetStackByID(b->activeStack)->owner] != c) ERROR_AND_RETURN; return gh->makeBattleAction(ba); diff --git a/server/StdInc.h b/server/StdInc.h index e2e51512e..08c4b8424 100644 --- a/server/StdInc.h +++ b/server/StdInc.h @@ -22,3 +22,17 @@ inline const T * dynamic_ptr_cast(const F * ptr) return nullptr; #endif } + +template +inline T * dynamic_ptr_cast(F * ptr) +{ + #ifndef __APPLE__ + return dynamic_cast(ptr); + #else + if (!strcmp(typeid(*ptr).name(), typeid(T).name())) + { + return static_cast(ptr); + } + return nullptr; + #endif +} From e6e975e9ef0c1d74db4ccc01a54ebf9634edb649 Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Sat, 31 Oct 2015 20:23:13 +0300 Subject: [PATCH 08/13] Fix adventure map movement segfault in some scenarios --- client/windows/CAdvmapInterface.cpp | 35 +++++++++++++++-------------- lib/CGameState.cpp | 10 ++++----- lib/CGameStateFwd.h | 2 +- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index e1b96e049..92622c738 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -62,9 +62,9 @@ CAdvMapInt *adventureInt; CTerrainRect::CTerrainRect() - : fadeSurface(nullptr), + : fadeSurface(nullptr), fadeAnim(new CFadeAnimation()), - curHoveredTile(-1,-1,-1), + curHoveredTile(-1,-1,-1), currentPath(nullptr) { tilesw=(ADVOPT.advmapW+31)/32; @@ -283,7 +283,7 @@ void CTerrainRect::show(SDL_Surface * to) info.heroAnim = adventureInt->heroAnim; if (ADVOPT.smoothMove) info.movement = int3(moveX, moveY, 0); - + lastRedrawStatus = CGI->mh->drawTerrainRectNew(to, &info); if (fadeAnim->isFading()) { @@ -316,7 +316,7 @@ void CTerrainRect::showAll(SDL_Surface * to) } void CTerrainRect::showAnim(SDL_Surface * to) -{ +{ if (fadeAnim->isFading()) show(to); else if (lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED) @@ -357,7 +357,7 @@ void CTerrainRect::fadeFromCurrentView() return; if (adventureInt->mode == EAdvMapMode::WORLD_VIEW) return; - + if (!fadeSurface) fadeSurface = CSDL_Ext::newSurface(pos.w, pos.h); SDL_BlitSurface(screen, &pos, fadeSurface, nullptr); @@ -502,10 +502,10 @@ CAdvMapInt::CAdvMapInt(): endTurn = makeButton(302, std::bind(&CAdvMapInt::fendTurn,this), ADVOPT.endTurn, SDLK_e); int panelSpaceBottom = screen->h - resdatabar.pos.h - 4; - + panelMain = new CAdvMapPanel(nullptr, Point(0, 0)); // TODO correct drawing position - panelWorldView = new CAdvMapWorldViewPanel(bgWorldView, Point(heroList.pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID); + panelWorldView = new CAdvMapWorldViewPanel(bgWorldView, Point(heroList.pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID); panelMain->addChildColorableButton(kingOverview); panelMain->addChildColorableButton(underground); @@ -593,7 +593,7 @@ CAdvMapInt::CAdvMapInt(): Colors::WHITE, CGI->generaltexth->allTexts[618])); activeMapPanel = panelMain; - + changeMode(EAdvMapMode::NORMAL); underground->block(!CGI->mh->map->twoLevel); @@ -966,7 +966,7 @@ void CAdvMapInt::show(SDL_Surface * to) for(int i=0;i<4;i++) blitAt(gems[i]->ourImages[LOCPLINT->playerID.getNum()].bitmap,ADVOPT.gemX[i],ADVOPT.gemY[i],to); } - + infoBar.show(to); statusbar.showAll(to); } @@ -981,7 +981,7 @@ void CAdvMapInt::selectionChanged() void CAdvMapInt::centerOn(int3 on, bool fade /* = false */) { bool switchedLevels = on.z != position.z; - + if (fade) { terrain.fadeFromCurrentView(); @@ -1534,7 +1534,9 @@ void CAdvMapInt::tileHovered(const int3 &mapPos) } 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; vstd::amin(turns, 3); @@ -1780,9 +1782,9 @@ void CAdvMapInt::changeMode(EAdvMapMode newMode, float newScale /* = 0.4f */) townList.activate(); heroList.activate(); infoBar.activate(); - + worldViewOptions.clear(); - + break; case EAdvMapMode::WORLD_VIEW: panelMain->deactivate(); @@ -1852,14 +1854,13 @@ CAdvMapInt::WorldViewOptions::WorldViewOptions() void CAdvMapInt::WorldViewOptions::clear() { showAllTerrain = false; - + iconPositions.clear(); } void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info) { info.showAllTerrain = showAllTerrain; - - info.additionalIcons = &iconPositions; -} + info.additionalIcons = &iconPositions; +} diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 41b138b08..51f8e8bd5 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -674,8 +674,8 @@ void CGameState::randomizeObject(CGObjectInstance *cur) } else { - cur->setType(ran.first, ran.second); - } + cur->setType(ran.first, ran.second); + } } int CGameState::getDate(Date::EDateType mode) const @@ -2899,11 +2899,11 @@ bool CGPathNode::reachable() const return turns < 255; } -const CGPathNode * CPathsInfo::getPathInfo( int3 tile ) const +const CGPathNode * CPathsInfo::getPathInfo( const int3& tile ) const { boost::unique_lock pathLock(pathMx); - - if (tile.x >= sizes.x || tile.y >= sizes.y || tile.z >= sizes.z) + if (tile.x >= sizes.x || tile.y >= sizes.y || tile.z >= sizes.z || + tile.x < 0 || tile.y < 0 || tile.z < 0) return nullptr; return &nodes[tile.x][tile.y][tile.z]; } diff --git a/lib/CGameStateFwd.h b/lib/CGameStateFwd.h index 5dc1672b6..8e6196ef1 100644 --- a/lib/CGameStateFwd.h +++ b/lib/CGameStateFwd.h @@ -158,7 +158,7 @@ struct DLL_LINKAGE CPathsInfo int3 sizes; CGPathNode ***nodes; //[w][h][level] - const CGPathNode * getPathInfo( int3 tile ) const; + const CGPathNode * getPathInfo( const int3& tile ) const; bool getPath(const int3 &dst, CGPath &out) const; int getDistance( int3 tile ) const; CPathsInfo(const int3 &Sizes); From 5c623868bf814cecb160d7cf92a0ab0c8f54a78c Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Sat, 31 Oct 2015 23:01:22 +0300 Subject: [PATCH 09/13] Fix invalid dynamic_cast replacement --- server/CQuery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CQuery.cpp b/server/CQuery.cpp index e3d36b52d..7e1a53433 100644 --- a/server/CQuery.cpp +++ b/server/CQuery.cpp @@ -324,7 +324,7 @@ CBlockingDialogQuery::CBlockingDialogQuery(const BlockingDialog &bd) void CTeleportDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const { - auto obj = dynamic_ptr_cast(objectVisit.visitedObject); + auto obj = dynamic_cast(objectVisit.visitedObject); obj->teleportDialogAnswered(objectVisit.visitingHero, *answer, td.exits); } From 1bcfa986e4243bb4a17b3d6d632e04011fc7cf93 Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Sun, 1 Nov 2015 01:52:43 +0300 Subject: [PATCH 10/13] Apply fixes to pathfinder --- lib/CPathfinder.cpp | 5 +++-- lib/CPathfinder.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index 2eae0500c..df7fadb53 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -479,11 +479,12 @@ CPathsInfo::~CPathsInfo() delete [] nodes; } -const CGPathNode * CPathsInfo::getPathInfo( int3 tile ) const +const CGPathNode * CPathsInfo::getPathInfo(const int3& tile) const { boost::unique_lock pathLock(pathMx); - if(tile.x >= sizes.x || tile.y >= sizes.y || tile.z >= sizes.z) + if(tile.x >= sizes.x || tile.y >= sizes.y || tile.z >= sizes.z + || tile.x < 0 || tile.y < 0 || tile.z < 0) return nullptr; return &nodes[tile.x][tile.y][tile.z]; } diff --git a/lib/CPathfinder.h b/lib/CPathfinder.h index 38d13821e..43615456d 100644 --- a/lib/CPathfinder.h +++ b/lib/CPathfinder.h @@ -61,7 +61,7 @@ struct DLL_LINKAGE CPathsInfo CPathsInfo(const int3 &Sizes); ~CPathsInfo(); - const CGPathNode * getPathInfo( int3 tile ) const; + const CGPathNode * getPathInfo(const int3& tile) const; bool getPath(const int3 &dst, CGPath &out) const; int getDistance( int3 tile ) const; }; From 0661aa0e6e26b557e5b023e39062511b5f3ec11b Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Sun, 13 Dec 2015 11:04:42 +0300 Subject: [PATCH 11/13] Remove undefined behavior in requestActionASAP --- AI/VCAI/VCAI.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 31915aa57..25e1eb752 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -2705,24 +2705,13 @@ void VCAI::finish() void VCAI::requestActionASAP(std::function whatToDo) { - boost::mutex mutex; - mutex.lock(); - - boost::thread newThread([&mutex,this,whatToDo]() + boost::thread newThread([this,whatToDo]() { setThreadName("VCAI::requestActionASAP::whatToDo"); SET_GLOBAL_STATE(this); boost::shared_lock gsLock(cb->getGsMutex()); - // unlock mutex and allow parent function to exit - mutex.unlock(); 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) From 9a0161e4e23e026d74e23350fb0d9e712d0eb4c9 Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Sun, 13 Dec 2015 15:57:33 +0300 Subject: [PATCH 12/13] Fix and unify CBattleQuery::blocksPack --- server/CQuery.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/server/CQuery.cpp b/server/CQuery.cpp index 0c69bd671..3d07d3af0 100644 --- a/server/CQuery.cpp +++ b/server/CQuery.cpp @@ -245,12 +245,8 @@ CBattleQuery::CBattleQuery() bool CBattleQuery::blocksPack(const CPack *pack) const { - #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) From 5cd4e852d49a988157d04349db6350322de59342 Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Sun, 13 Dec 2015 15:59:48 +0300 Subject: [PATCH 13/13] Use portable cast in CTeleportDialogQuery also --- server/CQuery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CQuery.cpp b/server/CQuery.cpp index 3d07d3af0..aad12a423 100644 --- a/server/CQuery.cpp +++ b/server/CQuery.cpp @@ -321,7 +321,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); }