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

@ -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<const CCreature*, int> 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<Res::ERes>(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<std::vector<int3> > tiles; //tiles[distance_to_fow]
tiles.resize(radius);
@ -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)
@ -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))

View File

@ -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<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!";
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<std::string>(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<CLoadFile> loader;
unique_ptr<CLoadFile> 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<std::string>(settings["server"]["port"].Float());
port = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
verbose = true;
#ifndef VCMI_ANDROID

View File

@ -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;
}

View File

@ -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

View File

@ -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::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.
@ -484,7 +485,7 @@ std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, Ty
}
}
}
std::vector<TypeInfoPtr> ret;
if(!previous.count(from))
@ -512,21 +513,21 @@ 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())
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<CGObjectInstance, ObjectInstanceID>(&gs->map->objects,
registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->map->objects,
[](const CGObjectInstance &obj){ return obj.id; });
registerVectoredType<CHero, HeroTypeID>(&lib->heroh->heroes,
registerVectoredType<CHero, HeroTypeID>(&lib->heroh->heroes,
[](const CHero &h){ return h.ID; });
registerVectoredType<CGHeroInstance, HeroTypeID>(&gs->map->allHeroes,
[](const CGHeroInstance &h){ return h.type->ID; });
registerVectoredType<CCreature, CreatureID>(&lib->creh->creatures,
registerVectoredType<CCreature, CreatureID>(&lib->creh->creatures,
[](const CCreature &cre){ return cre.idNumber; });
registerVectoredType<CArtifact, ArtifactID>(&lib->arth->artifacts,
[](const CArtifact &art){ return art.id; });
registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->map->artInstances,
registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->map->artInstances,
[](const CArtifactInstance &artInst){ return artInst.id; });
registerVectoredType<CQuest, si32>(&gs->map->quests,
registerVectoredType<CQuest, si32>(&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);
}

View File

@ -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<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);
@ -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<Ser, CStackInstance *>
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<bool> &data)
@ -629,7 +638,7 @@ public:
s.saveEnum(data);
}
};
template<typename T>
struct SavePointer
{
@ -638,7 +647,7 @@ public:
s.savePointer(data);
}
};
template<typename T>
struct SaveArray
{
@ -655,22 +664,21 @@ public:
{
throw std::runtime_error("Wrong save serialization call!");
}
};
template <typename T>
class CPointerSaver : public CBasicPointerSaver
};
template <typename T>
class CPointerSaver : public CBasicPointerSaver
{
public:
void savePtr(CSaverBase &ar, const void *data) const override
{
{
COSer &s = static_cast<COSer&>(ar);
const T *ptr = static_cast<const T*>(data);
const T *ptr = static_cast<const T*>(data);
//T is most derived known type, it's time to call actual serialize
const_cast<T&>(*ptr).serialize(s,version);
const_cast<T*>(ptr)->serialize(s,version);
}
};
};
bool saving;
std::map<ui16,CBasicPointerSaver*> savers; // typeID => CPointerSaver<serializer,type>
@ -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<bool> &data)
{
s.loadBooleanVector(data);
}
};
};
template<typename T>
struct LoadEnum
{
@ -1040,7 +1048,7 @@ public:
{
s.loadPrimitive(data);
}
};
};
template<typename T>
struct LoadPointer
@ -1049,8 +1057,8 @@ public:
{
s.loadPointer(data);
}
};
};
template<typename T>
struct LoadArray
{
@ -1076,8 +1084,8 @@ public:
{
throw std::runtime_error("Wrong load serialization call!");
}
};
};
template <typename T> class CPointerLoader : public CBasicPointerLoader
{
public:
@ -1094,8 +1102,8 @@ public:
ptr->serialize(s,version);
return &typeid(T);
}
};
};
bool saving;
std::map<ui16,CBasicPointerLoader*> loaders; // typeID => CPointerSaver<serializer,type>
si32 fileVersion;
@ -1539,9 +1547,9 @@ class DLL_LINKAGE CSaveFile
:public IBinaryWriter
{
public:
COSer serializer;
std::string fName;
unique_ptr<std::ofstream> sfile;
@ -1554,13 +1562,13 @@ public:
void reportState(CLogger * out) override;
void putMagicBytes(const std::string &text);
template<class T>
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<boost::filesystem::ifstream> sfile;
@ -1581,20 +1589,20 @@ public:
void reportState(CLogger * out) override;
void checkMagicBytes(const std::string & text);
template<class T>
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<CLoadFile> 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<class T>
CConnection & operator>>(T &t)
{
iser >> t;
return * this;
}
}
template<class T>
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;

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

@ -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<bool> battleMadeAction;
@ -102,7 +102,7 @@ public:
}
};
template <>
template <>
class CApplyOnGH<CPack> : 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<const CStack*> 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<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);
@ -1026,7 +1026,7 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
int v = path.first.size()-1;
bool stackIsMoving = true;
while(stackIsMoving)
{
if(v<tilesToMove)
@ -1079,10 +1079,10 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
if(obs->stopsMovement() || !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<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)));
}
@ -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);
}

View File

@ -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<shared_ptr<CQuery>> 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<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)
@ -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<ObjectInstanceID> ourIds;
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,24 +290,24 @@ 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);
}
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<const CGTeleport *>(objectVisit.visitedObject);
auto obj = dynamic_ptr_cast<const CGTeleport>(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<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);
@ -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; i<clients; i++)
{
if(!i)
if(!i)
{
cc = &c;
}
@ -508,7 +508,7 @@ void CVCMIServer::loadGame()
continue;
}
cc = new CConnection(s,NAME);
}
}
gh.conns.insert(cc);
}
@ -531,7 +531,7 @@ static void handleCommandOptions(int argc, char *argv[])
{
po::store(po::parse_command_line(argc, argv, opts), cmdLineOptions);
}
catch(std::exception &e)
catch(std::exception &e)
{
std::cerr << "Failure during parsing command-line options:\n" << e.what() << std::endl;
}

View File

@ -89,7 +89,7 @@ bool MoveHero::applyGh( CGameHandler *gh )
bool CastleTeleportHero::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(hid);
return gh->teleportHero(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<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!");
@ -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);

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
}