diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 915e6ebfe..287805383 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -841,7 +841,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) { @@ -910,7 +910,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) @@ -1007,7 +1007,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; @@ -2131,7 +2131,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!"); } @@ -2349,7 +2349,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) { @@ -2605,7 +2605,7 @@ int3 VCAI::explorationDesperate(HeroPtr h) { auto sm = getCachedSectorMap(h); int radius = h->getSightRadious(); - + std::vector > tiles; //tiles[distance_to_fow] tiles.resize(radius); @@ -2735,24 +2735,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::helper"); + 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) @@ -2963,8 +2952,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(); @@ -3078,7 +3067,7 @@ void SectorMap::exploreNewSector(crint3 pos, int num, CCallback * cbp) s.embarkmentPoints.push_back(neighPos); } }); - + if(t->visitable) { auto obj = t->visitableObjects.front(); @@ -3134,7 +3123,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 @@ -3185,7 +3174,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()) @@ -3498,7 +3487,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)) diff --git a/client/Client.cpp b/client/Client.cpp index bd8b1f695..347cad243 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -246,25 +246,18 @@ void CClient::endGame( bool closeConnection /*= true*/ ) #if 1 void CClient::loadGame(const std::string & fname, const bool server, const std::vector& humanplayerindices, const int loadNumPlayers, int player_, const std::string & ipaddr, const std::string & port) { - PlayerColor player(player_); //intentional shadowing - logNetwork->infoStream() << "Loading procedure started!"; + PlayerColor player(player_); //intentional shadowing - std::string realPort; - if(settings["testing"]["enabled"].Bool()) - realPort = settings["testing"]["port"].String(); - else if(port.size()) - realPort = port; - else - realPort = boost::lexical_cast(settings["server"]["port"].Float()); + logNetwork->infoStream() <<"Loading procedure started!"; CServerHandler sh; - if(server) - sh.startServer(); - else - serv = sh.justConnectToServer(ipaddr, realPort); + if(server) + sh.startServer(); + else + serv = sh.justConnectToServer(ipaddr,port=="" ? "3030" : port); CStopWatch tmh; - unique_ptr loader; + unique_ptr loader; try { std::string clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME)); @@ -974,10 +967,7 @@ CServerHandler::CServerHandler(bool runServer /*= false*/) { serverThread = nullptr; shared = nullptr; - if(settings["testing"]["enabled"].Bool()) - port = settings["testing"]["port"].String(); - else - port = boost::lexical_cast(settings["server"]["port"].Float()); + port = boost::lexical_cast(settings["server"]["port"].Float()); verbose = true; #ifndef VCMI_ANDROID diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index 2ae8f03a9..439523fb3 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); @@ -971,7 +971,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); } @@ -986,7 +986,7 @@ void CAdvMapInt::selectionChanged() void CAdvMapInt::centerOn(int3 on, bool fade /* = false */) { bool switchedLevels = on.z != position.z; - + if (fade) { terrain.fadeFromCurrentView(); @@ -1538,7 +1538,10 @@ 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); switch(pnode->action) @@ -1718,9 +1721,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(); @@ -1790,14 +1793,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 1fb50596d..cb1c0a6fc 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -675,8 +675,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 diff --git a/lib/Connection.cpp b/lib/Connection.cpp index 7bc772093..562fea3f9 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -70,7 +70,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; @@ -121,7 +121,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 ) @@ -136,10 +136,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(); } @@ -240,12 +240,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() @@ -285,7 +285,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); @@ -379,7 +379,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); @@ -437,7 +437,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 @@ -450,18 +450,19 @@ CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type ) return newType; } -ui16 CTypeList::getTypeID( const std::type_info *type ) -{ - 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) +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. @@ -484,7 +485,7 @@ std::vector CTypeList::castSequence(TypeInfoPtr from, Ty } } } - + std::vector ret; if(!previous.count(from)) @@ -512,21 +513,21 @@ 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) - if(*from == *to) + if(!strcmp(from->name(), to->name())) return std::vector(); 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()) - return i->second; //type found, return ptr to structure + return i->second; //type found, return ptr to structure if(!throws) return nullptr; @@ -553,19 +554,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; @@ -646,4 +647,3 @@ CMemorySerializer::CMemorySerializer(): iser(this), oser(this) registerTypes(iser); registerTypes(oser); } - diff --git a/lib/Connection.h b/lib/Connection.h index 07c724af1..c7552ca33 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 strcmp(a->name(), b->name()) < 0; + #endif + } }; struct IPointerCaster @@ -102,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; } @@ -113,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) @@ -136,7 +150,7 @@ struct PointerCaster : IPointerCaster // } }; -class DLL_LINKAGE CTypeList +class DLL_LINKAGE CTypeList: public boost::noncopyable { public: struct TypeDescriptor; @@ -147,33 +161,53 @@ 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) - 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: + /// 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; - CTypeList(); + + 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; + for(int i = 0; i < static_cast(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); - +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."); @@ -187,77 +221,52 @@ public: 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 + ui16 getTypeID(const std::type_info *type, bool throws = false) const; template - ui16 getTypeID(const T * t = nullptr) + ui16 getTypeID(const T * t = nullptr, bool throws = false) const { - 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); - - template - 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; + return getTypeID(getTypeInfo(t), throws); } template - void *castToMostDerived(const TInput *inputPtr) + void * castToMostDerived(const TInput * inputPtr) const { 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 - 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()); - if(baseType == *derivedType) + if (!strcmp(baseType.name(), derivedType->name())) return inputPtr; 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); @@ -444,13 +453,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); @@ -586,15 +595,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) @@ -629,7 +638,7 @@ public: s.saveEnum(data); } }; - + template struct SavePointer { @@ -638,7 +647,7 @@ public: s.savePointer(data); } }; - + template struct SaveArray { @@ -655,22 +664,21 @@ public: { throw std::runtime_error("Wrong save serialization call!"); } - }; - - template - class CPointerSaver : public CBasicPointerSaver + }; + + template + 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); } - }; - + }; + bool saving; std::map savers; // typeID => CPointerSaver @@ -777,7 +785,7 @@ public: //write type identifier ui16 tid = typeList.getTypeID(data); - *this << tid; + *this << tid; this->savePointerHlp(tid, data); } @@ -964,13 +972,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); @@ -1015,15 +1023,15 @@ public: s.loadBoolean(data); } }; - + struct LoadBooleanVector { static void invoke(CISer &s, std::vector &data) { s.loadBooleanVector(data); } - }; - + }; + template struct LoadEnum { @@ -1040,7 +1048,7 @@ public: { s.loadPrimitive(data); } - }; + }; template struct LoadPointer @@ -1049,8 +1057,8 @@ public: { s.loadPointer(data); } - }; - + }; + template struct LoadArray { @@ -1076,8 +1084,8 @@ public: { throw std::runtime_error("Wrong load serialization call!"); } - }; - + }; + template class CPointerLoader : public CBasicPointerLoader { public: @@ -1094,8 +1102,8 @@ public: ptr->serialize(s,version); return &typeid(T); } - }; - + }; + bool saving; std::map loaders; // typeID => CPointerSaver si32 fileVersion; @@ -1539,9 +1547,9 @@ class DLL_LINKAGE CSaveFile :public IBinaryWriter { public: - + COSer serializer; - + std::string fName; unique_ptr sfile; @@ -1554,13 +1562,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 @@ -1568,7 +1576,7 @@ class DLL_LINKAGE CLoadFile { public: CISer serializer; - + std::string fName; unique_ptr sfile; @@ -1581,20 +1589,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; @@ -1620,7 +1628,7 @@ class DLL_LINKAGE CConnection public: CISer iser; COSer oser; - + boost::mutex *rmx, *wmx; // read/write mutexes TSocket * socket; bool logging; @@ -1658,14 +1666,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) { @@ -1687,7 +1695,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; diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 5c564fb4e..06bdbf014 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); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index c383aab68..7bb4c52f0 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); } @@ -3924,8 +3924,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); @@ -3957,12 +3957,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) @@ -4124,11 +4124,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) @@ -4140,9 +4140,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)) { @@ -4272,8 +4272,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); @@ -4282,8 +4282,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; @@ -4292,9 +4292,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))); @@ -4400,7 +4400,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); @@ -4994,7 +4994,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); } } } @@ -5011,7 +5011,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(); @@ -5020,13 +5020,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) @@ -5077,11 +5077,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); } @@ -5319,8 +5319,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(); @@ -5329,7 +5329,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); } @@ -5368,7 +5368,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 && @@ -5504,7 +5503,7 @@ void CGameHandler::runBattle() { logGlobal->traceStream() << "Activating " << next->nodeName(); auto nextId = next->ID; - BattleSetActiveStack sas; + BattleSetActiveStack sas; sas.stack = nextId; sendAndApply(&sas); @@ -5710,7 +5709,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); @@ -5849,7 +5848,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI //catapult artifact remain even if "creature" killed in siege if(warMachine != ArtifactID::NONE && warMachine != ArtifactID::CATAPULT) { - auto hero = dynamic_cast (army); + auto hero = dynamic_ptr_cast (army); if (hero) removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true))); } @@ -5922,7 +5921,7 @@ CGameHandler::FinishingBattleHelper::FinishingBattleHelper() ///ServerSpellCastEnvironment ServerSpellCastEnvironment::ServerSpellCastEnvironment(CGameHandler * gh): gh(gh) { - + } void ServerSpellCastEnvironment::sendAndApply(CPackForClient * info) const @@ -5955,4 +5954,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 badbd2e74..aad12a423 100644 --- a/server/CQuery.cpp +++ b/server/CQuery.cpp @@ -98,11 +98,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) @@ -221,7 +221,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); @@ -243,9 +243,10 @@ CBattleQuery::CBattleQuery() } -bool CBattleQuery::blocksPack(const CPack *pack) const +bool CBattleQuery::blocksPack(const CPack *pack) const { - return !dynamic_cast(pack) && !dynamic_cast(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) @@ -253,7 +254,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); } @@ -267,18 +268,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)) @@ -289,24 +290,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); @@ -320,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); } @@ -343,7 +344,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); } @@ -361,20 +362,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/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 7418241e0..08c4b8424 100644 --- a/server/StdInc.h +++ b/server/StdInc.h @@ -8,3 +8,31 @@ #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 +} + +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 +}