1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

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

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

View File

@ -2735,24 +2735,13 @@ void VCAI::finish()
void VCAI::requestActionASAP(std::function<void()> whatToDo)
{
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<boost::shared_mutex> 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)

View File

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

View File

@ -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)
@ -1800,4 +1803,3 @@ void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info)
info.additionalIcons = &iconPositions;
}

View File

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

View File

@ -83,7 +83,11 @@ struct TypeComparer
{
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
}
};
@ -102,6 +106,11 @@ struct PointerCaster : IPointerCaster
{
From * from = (From*)boost::any_cast<void*>(ptr);
To * ret = dynamic_cast<To*>(from);
if (ret == nullptr)
{
// Last resort when RTTI goes mad
ret = static_cast<To*>(from);
}
return (void*)ret;
}
@ -113,6 +122,11 @@ struct PointerCaster : IPointerCaster
{
auto from = boost::any_cast<SmartPt>(ptr);
auto ret = std::dynamic_pointer_cast<To>(from);
if (!ret)
{
// Last resort when RTTI goes mad
ret = std::static_pointer_cast<To>(from);
}
return ret;
}
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<TypeInfoPtr> children, parents;
};
typedef boost::shared_mutex TMutex;
typedef boost::unique_lock<TMutex> TUniqueLock;
typedef boost::shared_lock<TMutex> TSharedLock;
private:
mutable TMutex mx;
std::map<const std::type_info *, TypeInfoPtr, TypeComparer> typeInfos;
std::map<std::pair<TypeInfoPtr, TypeInfoPtr>, std::unique_ptr<const IPointerCaster>> casters; //for each pair <Base, Der> we provide a caster (each registered relations creates a single entry here)
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<TypeInfoPtr> castSequence(TypeInfoPtr from, TypeInfoPtr to) const;
std::vector<TypeInfoPtr> castSequence(const std::type_info *from, const std::type_info *to) const;
CTypeList();
template<boost::any(IPointerCaster::*CastingFunction)(const boost::any &) const>
boost::any castHelper(boost::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg) const
{
TSharedLock lock(mx);
auto typesSequence = castSequence(fromArg, toArg);
boost::any ptr = inputPtr;
for(int i = 0; i < static_cast<int>(typesSequence.size()) - 1; i++)
{
auto &from = typesSequence[i];
auto &to = typesSequence[i + 1];
auto castingPair = std::make_pair(from, to);
if(!casters.count(castingPair))
THROW_FORMAT("Cannot find caster for conversion %s -> %s which is needed to cast %s -> %s", from->name % to->name % fromArg->name() % toArg->name());
auto &caster = casters.at(castingPair);
ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr not have operator->* ..?
}
return ptr;
}
TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true) const; //if not throws, failure returns nullptr
TypeInfoPtr registerType(const std::type_info *type);
public:
CTypeList();
template <typename Base, typename Derived>
void registerType(const Base * b = nullptr, const Derived * d = nullptr)
{
TUniqueLock lock(mx);
static_assert(std::is_base_of<Base, Derived>::value, "First registerType template parameter needs to ba a base class of the second one.");
static_assert(std::has_virtual_destructor<Base>::value, "Base class needs to have a virtual destructor.");
static_assert(!std::is_same<Base, Derived>::value, "Parameters of registerTypes should be two diffrenet types.");
@ -187,77 +221,52 @@ public:
casters[std::make_pair(dti, bti)] = make_unique<const PointerCaster<Derived, Base>>();
}
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 <typename T>
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<TypeInfoPtr> castSequence(TypeInfoPtr from, TypeInfoPtr to);
std::vector<TypeInfoPtr> castSequence(const std::type_info *from, const std::type_info *to);
template<boost::any(IPointerCaster::*CastingFunction)(const boost::any &) const>
boost::any castHelper(boost::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg)
{
auto typesSequence = castSequence(fromArg, toArg);
boost::any ptr = inputPtr;
for(int i = 0; i < (int)typesSequence.size() - 1; i++)
{
auto &from = typesSequence[i];
auto &to = typesSequence[i + 1];
auto castingPair = std::make_pair(from, to);
if(!casters.count(castingPair))
THROW_FORMAT("Cannot find caster for conversion %s -> %s which is needed to cast %s -> %s", from->name % to->name % fromArg->name() % toArg->name());
auto &caster = casters.at(castingPair);
ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr does not have operator->* ..?
}
return ptr;
return getTypeID(getTypeInfo(t), throws);
}
template<typename TInput>
void *castToMostDerived(const TInput *inputPtr)
void * castToMostDerived(const TInput * inputPtr) const
{
auto &baseType = typeid(typename std::remove_cv<TInput>::type);
auto derivedType = getTypeInfo(inputPtr);
if(baseType == *derivedType)
return (void*)inputPtr;
if (!strcmp(baseType.name(), derivedType->name()))
{
return const_cast<void*>(reinterpret_cast<const void*>(inputPtr));
}
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>((void*)inputPtr, &baseType, derivedType));
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(
const_cast<void*>(reinterpret_cast<const void*>(inputPtr)), &baseType,
derivedType));
}
template<typename TInput>
boost::any castSharedToMostDerived(const std::shared_ptr<TInput> inputPtr)
boost::any castSharedToMostDerived(const std::shared_ptr<TInput> inputPtr) const
{
auto &baseType = typeid(typename std::remove_cv<TInput>::type);
auto 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<void*>(castHelper<&IPointerCaster::castRawPtr>(inputPtr, from, to));
}
boost::any castShared(boost::any inputPtr, const std::type_info *from, const std::type_info *to)
boost::any castShared(boost::any inputPtr, const std::type_info *from, const std::type_info *to) const
{
return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, from, to);
}
template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr)
template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr) const
{
if(t)
return &typeid(*t);
@ -665,9 +674,8 @@ public:
{
COSer &s = static_cast<COSer&>(ar);
const T *ptr = static_cast<const T*>(data);
//T is most derived known type, it's time to call actual serialize
const_cast<T&>(*ptr).serialize(s,version);
const_cast<T*>(ptr)->serialize(s,version);
}
};

View File

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

View File

@ -917,7 +917,7 @@ void CGameHandler::handleConnection(std::set<PlayerColor> 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);
@ -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 &&
@ -5710,7 +5709,7 @@ bool CGameHandler::isValidObject(const CGObjectInstance *obj) const
bool CGameHandler::isBlockedByQueries(const CPack *pack, PlayerColor player)
{
if(dynamic_cast<const PlayerMessage*>(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<const CGHeroInstance*> (army);
auto hero = dynamic_ptr_cast<CGHeroInstance> (army);
if (hero)
removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true)));
}
@ -5955,4 +5954,3 @@ bool ServerSpellCastEnvironment::moveHero(ObjectInstanceID hid, int3 dst, ui8 te
{
return gh->moveHero(hid, dst, teleporting, false, asker);
}

View File

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

View File

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

View File

@ -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<const CGTownInstance *>(obj);
const CGTownInstance *town = dynamic_ptr_cast<CGTownInstance>(obj);
if(town && PlayerRelations::ENEMIES == gh->getPlayerRelations(obj->tempOwner, gh->getPlayerAt(c)))
COMPLAIN_AND_RETURN("Can't buy hero in enemy town!");

View File

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