mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-27 22:49:25 +02:00
Simplified CTypeList class
This commit is contained in:
@@ -421,14 +421,14 @@ void AIGateway::requestRealized(PackageApplied * pa)
|
|||||||
NET_EVENT_HANDLER;
|
NET_EVENT_HANDLER;
|
||||||
if(status.haveTurn())
|
if(status.haveTurn())
|
||||||
{
|
{
|
||||||
if(pa->packType == typeList.getTypeID<EndTurn>())
|
if(pa->packType == CTypeList::getInstance().getTypeID<EndTurn>(nullptr))
|
||||||
{
|
{
|
||||||
if(pa->result)
|
if(pa->result)
|
||||||
status.madeTurn();
|
status.madeTurn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pa->packType == typeList.getTypeID<QueryReply>())
|
if(pa->packType == CTypeList::getInstance().getTypeID<QueryReply>(nullptr))
|
||||||
{
|
{
|
||||||
status.receivedAnswerConfirmation(pa->requestID, pa->result);
|
status.receivedAnswerConfirmation(pa->requestID, pa->result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -505,14 +505,14 @@ void VCAI::requestRealized(PackageApplied * pa)
|
|||||||
NET_EVENT_HANDLER;
|
NET_EVENT_HANDLER;
|
||||||
if(status.haveTurn())
|
if(status.haveTurn())
|
||||||
{
|
{
|
||||||
if(pa->packType == typeList.getTypeID<EndTurn>())
|
if(pa->packType == CTypeList::getInstance().getTypeID<EndTurn>(nullptr))
|
||||||
{
|
{
|
||||||
if(pa->result)
|
if(pa->result)
|
||||||
status.madeTurn();
|
status.madeTurn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pa->packType == typeList.getTypeID<QueryReply>())
|
if(pa->packType == CTypeList::getInstance().getTypeID<QueryReply>(nullptr))
|
||||||
{
|
{
|
||||||
status.receivedAnswerConfirmation(pa->requestID, pa->result);
|
status.receivedAnswerConfirmation(pa->requestID, pa->result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1243,10 +1243,10 @@ void CPlayerInterface::showArtifactAssemblyDialog(const Artifact * artifact, con
|
|||||||
|
|
||||||
void CPlayerInterface::requestRealized( PackageApplied *pa )
|
void CPlayerInterface::requestRealized( PackageApplied *pa )
|
||||||
{
|
{
|
||||||
if(pa->packType == typeList.getTypeID<MoveHero>())
|
if(pa->packType == CTypeList::getInstance().getTypeID<MoveHero>(nullptr))
|
||||||
movementController->onMoveHeroApplied();
|
movementController->onMoveHeroApplied();
|
||||||
|
|
||||||
if(pa->packType == typeList.getTypeID<QueryReply>())
|
if(pa->packType == CTypeList::getInstance().getTypeID<QueryReply>(nullptr))
|
||||||
movementController->onQueryReplyApplied();
|
movementController->onQueryReplyApplied();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public:
|
|||||||
T * ptr = static_cast<T *>(pack);
|
T * ptr = static_cast<T *>(pack);
|
||||||
ApplyOnLobbyHandlerNetPackVisitor visitor(*handler);
|
ApplyOnLobbyHandlerNetPackVisitor visitor(*handler);
|
||||||
|
|
||||||
logNetwork->trace("\tImmediately apply on lobby: %s", typeList.getTypeInfo(ptr)->name());
|
logNetwork->trace("\tImmediately apply on lobby: %s", typeid(ptr).name());
|
||||||
ptr->visit(visitor);
|
ptr->visit(visitor);
|
||||||
|
|
||||||
return visitor.getResult();
|
return visitor.getResult();
|
||||||
@@ -105,7 +105,7 @@ public:
|
|||||||
T * ptr = static_cast<T *>(pack);
|
T * ptr = static_cast<T *>(pack);
|
||||||
ApplyOnLobbyScreenNetPackVisitor visitor(*handler, lobby);
|
ApplyOnLobbyScreenNetPackVisitor visitor(*handler, lobby);
|
||||||
|
|
||||||
logNetwork->trace("\tApply on lobby from queue: %s", typeList.getTypeInfo(ptr)->name());
|
logNetwork->trace("\tApply on lobby from queue: %s", typeid(ptr).name());
|
||||||
ptr->visit(visitor);
|
ptr->visit(visitor);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -298,7 +298,7 @@ void CServerHandler::applyPacksOnLobbyScreen()
|
|||||||
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
||||||
CPackForLobby * pack = packsForLobbyScreen.front();
|
CPackForLobby * pack = packsForLobbyScreen.front();
|
||||||
packsForLobbyScreen.pop_front();
|
packsForLobbyScreen.pop_front();
|
||||||
CBaseForLobbyApply * apply = applier->getApplier(typeList.getTypeID(pack)); //find the applier
|
CBaseForLobbyApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack)); //find the applier
|
||||||
apply->applyOnLobbyScreen(dynamic_cast<CLobbyScreen *>(SEL), this, pack);
|
apply->applyOnLobbyScreen(dynamic_cast<CLobbyScreen *>(SEL), this, pack);
|
||||||
GH.windows().totalRedraw();
|
GH.windows().totalRedraw();
|
||||||
delete pack;
|
delete pack;
|
||||||
@@ -953,7 +953,7 @@ void CServerHandler::threadHandleConnection()
|
|||||||
|
|
||||||
void CServerHandler::visitForLobby(CPackForLobby & lobbyPack)
|
void CServerHandler::visitForLobby(CPackForLobby & lobbyPack)
|
||||||
{
|
{
|
||||||
if(applier->getApplier(typeList.getTypeID(&lobbyPack))->applyOnLobbyHandler(this, &lobbyPack))
|
if(applier->getApplier(CTypeList::getInstance().getTypeID(&lobbyPack))->applyOnLobbyHandler(this, &lobbyPack))
|
||||||
{
|
{
|
||||||
if(!settings["session"]["headless"].Bool())
|
if(!settings["session"]["headless"].Bool())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -523,20 +523,20 @@ void CClient::installNewBattleInterface(std::shared_ptr<CBattleGameInterface> ba
|
|||||||
|
|
||||||
void CClient::handlePack(CPack * pack)
|
void CClient::handlePack(CPack * pack)
|
||||||
{
|
{
|
||||||
CBaseForCLApply * apply = applier->getApplier(typeList.getTypeID(pack)); //find the applier
|
CBaseForCLApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack)); //find the applier
|
||||||
if(apply)
|
if(apply)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
||||||
apply->applyOnClBefore(this, pack);
|
apply->applyOnClBefore(this, pack);
|
||||||
logNetwork->trace("\tMade first apply on cl: %s", typeList.getTypeInfo(pack)->name());
|
logNetwork->trace("\tMade first apply on cl: %s", typeid(pack).name());
|
||||||
gs->apply(pack);
|
gs->apply(pack);
|
||||||
logNetwork->trace("\tApplied on gs: %s", typeList.getTypeInfo(pack)->name());
|
logNetwork->trace("\tApplied on gs: %s", typeid(pack).name());
|
||||||
apply->applyOnClAfter(this, pack);
|
apply->applyOnClAfter(this, pack);
|
||||||
logNetwork->trace("\tMade second apply on cl: %s", typeList.getTypeInfo(pack)->name());
|
logNetwork->trace("\tMade second apply on cl: %s", typeid(pack).name());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logNetwork->error("Message %s cannot be applied, cannot find applier!", typeList.getTypeInfo(pack)->name());
|
logNetwork->error("Message %s cannot be applied, cannot find applier!", typeid(pack).name());
|
||||||
}
|
}
|
||||||
delete pack;
|
delete pack;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1134,7 +1134,7 @@ PlayerRelations CGameState::getPlayerRelations( PlayerColor color1, PlayerColor
|
|||||||
|
|
||||||
void CGameState::apply(CPack *pack)
|
void CGameState::apply(CPack *pack)
|
||||||
{
|
{
|
||||||
ui16 typ = typeList.getTypeID(pack);
|
ui16 typ = CTypeList::getInstance().getTypeID(pack);
|
||||||
applier->getApplier(typ)->applyOnGS(this, pack);
|
applier->getApplier(typ)->applyOnGS(this, pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
#define DEFINE_EXTERNAL_METHOD(METHODNAME) \
|
#define DEFINE_EXTERNAL_METHOD(METHODNAME) \
|
||||||
extern template DLL_LINKAGE void METHODNAME<BinaryDeserializer>(BinaryDeserializer & s); \
|
extern template DLL_LINKAGE void METHODNAME<BinaryDeserializer>(BinaryDeserializer & s); \
|
||||||
extern template DLL_LINKAGE void METHODNAME<BinarySerializer>(BinarySerializer & s); \
|
extern template DLL_LINKAGE void METHODNAME<BinarySerializer>(BinarySerializer & s);
|
||||||
extern template DLL_LINKAGE void METHODNAME<CTypeList>(CTypeList & s); \
|
|
||||||
|
|
||||||
//DEFINE_EXTERNAL_METHOD(registerTypesMapObjects)
|
//DEFINE_EXTERNAL_METHOD(registerTypesMapObjects)
|
||||||
DEFINE_EXTERNAL_METHOD(registerTypesMapObjects1)
|
DEFINE_EXTERNAL_METHOD(registerTypesMapObjects1)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "../mapObjects/CGCreature.h"
|
#include "../mapObjects/CGCreature.h"
|
||||||
#include "../mapObjects/CGTownBuilding.h"
|
#include "../mapObjects/CGTownBuilding.h"
|
||||||
#include "../mapObjects/ObjectTemplate.h"
|
#include "../mapObjects/ObjectTemplate.h"
|
||||||
|
#include "../battle/BattleInfo.h"
|
||||||
#include "../battle/CObstacleInstance.h"
|
#include "../battle/CObstacleInstance.h"
|
||||||
#include "../bonuses/Limiters.h"
|
#include "../bonuses/Limiters.h"
|
||||||
#include "../bonuses/Updaters.h"
|
#include "../bonuses/Updaters.h"
|
||||||
@@ -351,7 +352,6 @@ void registerTypes(Serializer &s)
|
|||||||
|
|
||||||
extern template DLL_LINKAGE void registerTypes<BinaryDeserializer>(BinaryDeserializer & s);
|
extern template DLL_LINKAGE void registerTypes<BinaryDeserializer>(BinaryDeserializer & s);
|
||||||
extern template DLL_LINKAGE void registerTypes<BinarySerializer>(BinarySerializer & s);
|
extern template DLL_LINKAGE void registerTypes<BinarySerializer>(BinarySerializer & s);
|
||||||
extern template DLL_LINKAGE void registerTypes<CTypeList>(CTypeList & s);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "CSerializer.h"
|
||||||
#include "CTypeList.h"
|
#include "CTypeList.h"
|
||||||
#include "../mapObjects/CGHeroInstance.h"
|
#include "../mapObjects/CGHeroInstance.h"
|
||||||
#include "../../Global.h"
|
#include "../../Global.h"
|
||||||
@@ -100,40 +101,39 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> class CPointerLoader;
|
template <typename Type> class CPointerLoader;
|
||||||
|
|
||||||
class CBasicPointerLoader
|
class IPointerLoader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual const std::type_info * loadPtr(CLoaderBase &ar, void *data, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER
|
virtual void * loadPtr(CLoaderBase &ar, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER
|
||||||
virtual ~CBasicPointerLoader(){}
|
virtual ~IPointerLoader() = default;
|
||||||
|
|
||||||
template<typename T> static CBasicPointerLoader *getApplier(const T * t=nullptr)
|
template<typename Type> static IPointerLoader *getApplier(const Type * t = nullptr)
|
||||||
{
|
{
|
||||||
return new CPointerLoader<T>();
|
return new CPointerLoader<Type>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> class CPointerLoader : public CBasicPointerLoader
|
template <typename Type> class CPointerLoader : public IPointerLoader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const std::type_info * loadPtr(CLoaderBase &ar, void *data, ui32 pid) const override //data is pointer to the ACTUAL POINTER
|
void * loadPtr(CLoaderBase &ar, ui32 pid) const override //data is pointer to the ACTUAL POINTER
|
||||||
{
|
{
|
||||||
auto & s = static_cast<BinaryDeserializer &>(ar);
|
auto & s = static_cast<BinaryDeserializer &>(ar);
|
||||||
T *&ptr = *static_cast<T**>(data);
|
|
||||||
|
|
||||||
//create new object under pointer
|
//create new object under pointer
|
||||||
typedef typename std::remove_pointer<T>::type npT;
|
Type * ptr = ClassObjectCreator<Type>::invoke(); //does new npT or throws for abstract classes
|
||||||
ptr = ClassObjectCreator<npT>::invoke(); //does new npT or throws for abstract classes
|
|
||||||
s.ptrAllocated(ptr, pid);
|
s.ptrAllocated(ptr, pid);
|
||||||
//T is most derived known type, it's time to call actual serialize
|
|
||||||
assert(s.fileVersion != 0);
|
assert(s.fileVersion != 0);
|
||||||
ptr->serialize(s,s.fileVersion);
|
ptr->serialize(s,s.fileVersion);
|
||||||
return &typeid(T);
|
|
||||||
|
return static_cast<void*>(ptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CApplier<CBasicPointerLoader> applier;
|
CApplier<IPointerLoader> applier;
|
||||||
|
|
||||||
int write(const void * data, unsigned size);
|
int write(const void * data, unsigned size);
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ public:
|
|||||||
|
|
||||||
std::map<ui32, void*> loadedPointers;
|
std::map<ui32, void*> loadedPointers;
|
||||||
std::map<ui32, const std::type_info*> loadedPointersTypes;
|
std::map<ui32, const std::type_info*> loadedPointersTypes;
|
||||||
std::map<const void*, std::any> loadedSharedPointers;
|
std::map<const void*, std::shared_ptr<void>> loadedSharedPointers;
|
||||||
bool smartPointerSerialization;
|
bool smartPointerSerialization;
|
||||||
bool saving;
|
bool saving;
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ public:
|
|||||||
// We already got this pointer
|
// We already got this pointer
|
||||||
// Cast it in case we are loading it to a non-first base pointer
|
// Cast it in case we are loading it to a non-first base pointer
|
||||||
assert(loadedPointersTypes.count(pid));
|
assert(loadedPointersTypes.count(pid));
|
||||||
data = reinterpret_cast<T>(typeList.castRaw(i->second, loadedPointersTypes.at(pid), &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type)));
|
data = static_cast<T>(i->second);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,8 +313,7 @@ public:
|
|||||||
data = nullptr;
|
data = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto typeInfo = app->loadPtr(*this,&data, pid);
|
data = static_cast<T>(app->loadPtr(*this, pid));
|
||||||
data = reinterpret_cast<T>(typeList.castRaw((void*)data, typeInfo, &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +339,7 @@ public:
|
|||||||
NonConstT *internalPtr;
|
NonConstT *internalPtr;
|
||||||
load(internalPtr);
|
load(internalPtr);
|
||||||
|
|
||||||
void *internalPtrDerived = typeList.castToMostDerived(internalPtr);
|
void * internalPtrDerived = static_cast<void*>(internalPtr);
|
||||||
|
|
||||||
if(internalPtr)
|
if(internalPtr)
|
||||||
{
|
{
|
||||||
@@ -349,35 +348,13 @@ public:
|
|||||||
{
|
{
|
||||||
// This pointers is already loaded. The "data" needs to be pointed to it,
|
// This pointers is already loaded. The "data" needs to be pointed to it,
|
||||||
// so their shared state is actually shared.
|
// so their shared state is actually shared.
|
||||||
try
|
data = std::static_pointer_cast<T>(itr->second);
|
||||||
{
|
|
||||||
auto actualType = typeList.getTypeInfo(internalPtr);
|
|
||||||
auto typeWeNeedToReturn = typeList.getTypeInfo<T>();
|
|
||||||
if(*actualType == *typeWeNeedToReturn)
|
|
||||||
{
|
|
||||||
// No casting needed, just unpack already stored shared_ptr and return it
|
|
||||||
data = std::any_cast<std::shared_ptr<T>>(itr->second);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We need to perform series of casts
|
|
||||||
auto ret = typeList.castShared(itr->second, actualType, typeWeNeedToReturn);
|
|
||||||
data = std::any_cast<std::shared_ptr<T>>(ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(std::exception &e)
|
|
||||||
{
|
|
||||||
logGlobal->error(e.what());
|
|
||||||
logGlobal->error("Failed to cast stored shared ptr. Real type: %s. Needed type %s. FIXME FIXME FIXME", itr->second.type().name(), typeid(std::shared_ptr<T>).name());
|
|
||||||
//TODO scenario with inheritance -> we can have stored ptr to base and load ptr to derived (or vice versa)
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto hlp = std::shared_ptr<NonConstT>(internalPtr);
|
auto hlp = std::shared_ptr<NonConstT>(internalPtr);
|
||||||
data = hlp;
|
data = hlp;
|
||||||
loadedSharedPointers[internalPtrDerived] = typeList.castSharedToMostDerived(hlp);
|
loadedSharedPointers[internalPtrDerived] = std::static_pointer_cast<void>(hlp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "CSerializer.h"
|
||||||
#include "CTypeList.h"
|
#include "CTypeList.h"
|
||||||
#include "../mapObjects/CArmedInstance.h"
|
#include "../mapObjects/CArmedInstance.h"
|
||||||
|
|
||||||
@@ -194,9 +195,10 @@ public:
|
|||||||
template < typename T, typename std::enable_if < !std::is_base_of_v<Entity, std::remove_pointer_t<T>>, int >::type = 0 >
|
template < typename T, typename std::enable_if < !std::is_base_of_v<Entity, std::remove_pointer_t<T>>, int >::type = 0 >
|
||||||
void savePointerImpl(const T &data)
|
void savePointerImpl(const T &data)
|
||||||
{
|
{
|
||||||
|
typedef typename std::remove_const<typename std::remove_pointer<T>::type>::type TObjectType;
|
||||||
|
|
||||||
if(writer->smartVectorMembersSerialization)
|
if(writer->smartVectorMembersSerialization)
|
||||||
{
|
{
|
||||||
typedef typename std::remove_const<typename std::remove_pointer<T>::type>::type TObjectType;
|
|
||||||
typedef typename VectorizedTypeFor<TObjectType>::type VType;
|
typedef typename VectorizedTypeFor<TObjectType>::type VType;
|
||||||
typedef typename VectorizedIDType<TObjectType>::type IDType;
|
typedef typename VectorizedIDType<TObjectType>::type IDType;
|
||||||
|
|
||||||
@@ -220,7 +222,7 @@ public:
|
|||||||
{
|
{
|
||||||
// We might have an object that has multiple inheritance and store it via the non-first base pointer.
|
// We might have an object that has multiple inheritance and store it via the non-first base pointer.
|
||||||
// Therefore, all pointers need to be normalized to the actual object address.
|
// Therefore, all pointers need to be normalized to the actual object address.
|
||||||
auto actualPointer = typeList.castToMostDerived(data);
|
const void * actualPointer = static_cast<const void*>(data);
|
||||||
auto i = savedPointers.find(actualPointer);
|
auto i = savedPointers.find(actualPointer);
|
||||||
if(i != savedPointers.end())
|
if(i != savedPointers.end())
|
||||||
{
|
{
|
||||||
@@ -236,13 +238,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//write type identifier
|
//write type identifier
|
||||||
ui16 tid = typeList.getTypeID(data);
|
uint16_t tid = CTypeList::getInstance().getTypeID(data);
|
||||||
save(tid);
|
save(tid);
|
||||||
|
|
||||||
if(!tid)
|
if(!tid)
|
||||||
save(*data); //if type is unregistered simply write all data in a standard way
|
save(*data); //if type is unregistered simply write all data in a standard way
|
||||||
else
|
else
|
||||||
applier.getApplier(tid)->savePtr(*this, typeList.castToMostDerived(data)); //call serializer specific for our real type
|
applier.getApplier(tid)->savePtr(*this, static_cast<const void*>(data)); //call serializer specific for our real type
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T, typename std::enable_if < is_serializeable<BinarySerializer, T>::value, int >::type = 0 >
|
template < typename T, typename std::enable_if < is_serializeable<BinarySerializer, T>::value, int >::type = 0 >
|
||||||
|
|||||||
@@ -14,128 +14,9 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
extern template void registerTypes<CTypeList>(CTypeList & s);
|
|
||||||
|
|
||||||
CTypeList typeList;
|
|
||||||
|
|
||||||
CTypeList::CTypeList()
|
CTypeList::CTypeList()
|
||||||
{
|
{
|
||||||
registerTypes(*this);
|
registerTypes(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CTypeList::TypeInfoPtr CTypeList::registerType(const std::type_info *type)
|
|
||||||
{
|
|
||||||
if(auto typeDescr = getTypeDescriptor(type, false))
|
|
||||||
return typeDescr; //type found, return ptr to structure
|
|
||||||
|
|
||||||
//type not found - add it to the list and return given ID
|
|
||||||
auto newType = std::make_shared<TypeDescriptor>();
|
|
||||||
newType->typeID = static_cast<ui16>(typeInfos.size() + 1);
|
|
||||||
newType->name = type->name();
|
|
||||||
typeInfos[type] = newType;
|
|
||||||
|
|
||||||
return newType;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui16 CTypeList::getTypeID(const std::type_info *type, bool throws) const
|
|
||||||
{
|
|
||||||
auto descriptor = getTypeDescriptor(type, throws);
|
|
||||||
if (descriptor == nullptr)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return descriptor->typeID;
|
|
||||||
}
|
|
||||||
|
|
||||||
CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(ui16 typeID) const
|
|
||||||
{
|
|
||||||
auto found = std::find_if(typeInfos.begin(), typeInfos.end(), [typeID](const std::pair<const std::type_info *, TypeInfoPtr> & p) -> bool
|
|
||||||
{
|
|
||||||
return p.second->typeID == typeID;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(found != typeInfos.end())
|
|
||||||
{
|
|
||||||
return found->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TypeInfoPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) const
|
|
||||||
{
|
|
||||||
if(!strcmp(from->name, to->name))
|
|
||||||
return std::vector<CTypeList::TypeInfoPtr>();
|
|
||||||
|
|
||||||
// Perform a simple BFS in the class hierarchy.
|
|
||||||
|
|
||||||
auto BFS = [&](bool upcast)
|
|
||||||
{
|
|
||||||
std::map<TypeInfoPtr, TypeInfoPtr> previous;
|
|
||||||
std::queue<TypeInfoPtr> q;
|
|
||||||
q.push(to);
|
|
||||||
while(!q.empty())
|
|
||||||
{
|
|
||||||
auto typeNode = q.front();
|
|
||||||
q.pop();
|
|
||||||
for(auto & weakNode : (upcast ? typeNode->parents : typeNode->children) )
|
|
||||||
{
|
|
||||||
auto nodeBase = weakNode.lock();
|
|
||||||
if(!previous.count(nodeBase))
|
|
||||||
{
|
|
||||||
previous[nodeBase] = typeNode;
|
|
||||||
q.push(nodeBase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<TypeInfoPtr> ret;
|
|
||||||
|
|
||||||
if(!previous.count(from))
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret.push_back(from);
|
|
||||||
TypeInfoPtr ptr = from;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ptr = previous.at(ptr);
|
|
||||||
ret.push_back(ptr);
|
|
||||||
} while(ptr != to);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Try looking both up and down.
|
|
||||||
auto ret = BFS(true);
|
|
||||||
if(ret.empty())
|
|
||||||
ret = BFS(false);
|
|
||||||
|
|
||||||
if(ret.empty())
|
|
||||||
THROW_FORMAT("Cannot find relation between types %s and %s. Were they (and all classes between them) properly registered?", from->name % to->name);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
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(!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) const
|
|
||||||
{
|
|
||||||
auto i = typeInfos.find(type);
|
|
||||||
if(i != typeInfos.end())
|
|
||||||
return i->second; //type found, return ptr to structure
|
|
||||||
|
|
||||||
if(!throws)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
THROW_FORMAT("Cannot find type descriptor for type %s. Was it registered?", type->name());
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|||||||
@@ -9,199 +9,72 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CSerializer.h"
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
struct IPointerCaster
|
|
||||||
{
|
|
||||||
virtual std::any castRawPtr(const std::any &ptr) const = 0; // takes From*, returns To*
|
|
||||||
virtual std::any castSharedPtr(const std::any &ptr) const = 0; // takes std::shared_ptr<From>, performs dynamic cast, returns std::shared_ptr<To>
|
|
||||||
virtual std::any castWeakPtr(const std::any &ptr) const = 0; // takes std::weak_ptr<From>, performs dynamic cast, returns std::weak_ptr<To>. The object under poitner must live.
|
|
||||||
//virtual std::any castUniquePtr(const std::any &ptr) const = 0; // takes std::unique_ptr<From>, performs dynamic cast, returns std::unique_ptr<To>
|
|
||||||
virtual ~IPointerCaster() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename From, typename To>
|
|
||||||
struct PointerCaster : IPointerCaster
|
|
||||||
{
|
|
||||||
virtual std::any castRawPtr(const std::any &ptr) const override // takes void* pointing to From object, performs dynamic cast, returns void* pointing to To object
|
|
||||||
{
|
|
||||||
From * from = (From*)std::any_cast<void*>(ptr);
|
|
||||||
To * ret = static_cast<To*>(from);
|
|
||||||
return (void*)ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function performing casts between smart pointers
|
|
||||||
template<typename SmartPt>
|
|
||||||
std::any castSmartPtr(const std::any &ptr) const
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto from = std::any_cast<SmartPt>(ptr);
|
|
||||||
auto ret = std::static_pointer_cast<To>(from);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
catch(std::exception &e)
|
|
||||||
{
|
|
||||||
THROW_FORMAT("Failed cast %s -> %s. Given argument was %s. Error message: %s", typeid(From).name() % typeid(To).name() % ptr.type().name() % e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::any castSharedPtr(const std::any &ptr) const override
|
|
||||||
{
|
|
||||||
return castSmartPtr<std::shared_ptr<From>>(ptr);
|
|
||||||
}
|
|
||||||
virtual std::any castWeakPtr(const std::any &ptr) const override
|
|
||||||
{
|
|
||||||
auto from = std::any_cast<std::weak_ptr<From>>(ptr);
|
|
||||||
return castSmartPtr<std::shared_ptr<From>>(from.lock());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Class that implements basic reflection-like mechanisms
|
/// Class that implements basic reflection-like mechanisms
|
||||||
/// For every type registered via registerType() generates inheritance tree
|
/// For every type registered via registerType() generates inheritance tree
|
||||||
/// Rarely used directly - usually used as part of CApplier
|
/// Rarely used directly - usually used as part of CApplier
|
||||||
class DLL_LINKAGE CTypeList: public boost::noncopyable
|
class CTypeList
|
||||||
{
|
{
|
||||||
//public:
|
std::map<std::string, uint16_t> typeInfos;
|
||||||
struct TypeDescriptor;
|
|
||||||
using TypeInfoPtr = std::shared_ptr<TypeDescriptor>;
|
|
||||||
using WeakTypeInfoPtr = std::weak_ptr<TypeDescriptor>;
|
|
||||||
struct TypeDescriptor
|
|
||||||
{
|
|
||||||
ui16 typeID;
|
|
||||||
const char *name;
|
|
||||||
std::vector<WeakTypeInfoPtr> children, parents;
|
|
||||||
};
|
|
||||||
using TMutex = boost::shared_mutex;
|
|
||||||
using TUniqueLock = boost::unique_lock<TMutex>;
|
|
||||||
using TSharedLock = boost::shared_lock<TMutex>;
|
|
||||||
|
|
||||||
private:
|
DLL_LINKAGE CTypeList();
|
||||||
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)
|
|
||||||
|
|
||||||
/// 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;
|
|
||||||
|
|
||||||
template<std::any(IPointerCaster::*CastingFunction)(const std::any &) const>
|
|
||||||
std::any castHelper(std::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg) const
|
|
||||||
{
|
|
||||||
TSharedLock lock(mx);
|
|
||||||
auto typesSequence = castSequence(fromArg, toArg);
|
|
||||||
|
|
||||||
std::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());
|
|
||||||
|
|
||||||
const auto & caster = casters.at(castingPair);
|
|
||||||
ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr not have operator->* ..?
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
CTypeList & operator=(CTypeList &) = delete;
|
|
||||||
|
|
||||||
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 different types.");
|
|
||||||
auto bt = getTypeInfo(b);
|
|
||||||
auto dt = getTypeInfo(d); //obtain std::type_info
|
|
||||||
auto bti = registerType(bt);
|
|
||||||
auto dti = registerType(dt); //obtain our TypeDescriptor
|
|
||||||
|
|
||||||
// register the relation between classes
|
|
||||||
bti->children.push_back(dti);
|
|
||||||
dti->parents.push_back(bti);
|
|
||||||
casters[std::make_pair(bti, dti)] = std::make_unique<const PointerCaster<Base, Derived>>();
|
|
||||||
casters[std::make_pair(dti, bti)] = std::make_unique<const PointerCaster<Derived, Base>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
ui16 getTypeID(const std::type_info *type, bool throws = false) const;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
ui16 getTypeID(const T * t = nullptr, bool throws = false) const
|
const std::type_info & getTypeInfo(const T * t = nullptr) const
|
||||||
{
|
|
||||||
return getTypeID(getTypeInfo(t), throws);
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeInfoPtr getTypeDescriptor(ui16 typeID) const;
|
|
||||||
|
|
||||||
template<typename TInput>
|
|
||||||
void * castToMostDerived(const TInput * inputPtr) const
|
|
||||||
{
|
|
||||||
const auto & baseType = typeid(typename std::remove_cv<TInput>::type);
|
|
||||||
auto derivedType = getTypeInfo(inputPtr);
|
|
||||||
|
|
||||||
if (strcmp(baseType.name(), derivedType->name()) == 0)
|
|
||||||
{
|
|
||||||
return const_cast<void*>(reinterpret_cast<const void*>(inputPtr));
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(
|
|
||||||
const_cast<void*>(reinterpret_cast<const void*>(inputPtr)), &baseType,
|
|
||||||
derivedType));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TInput>
|
|
||||||
std::any castSharedToMostDerived(const std::shared_ptr<TInput> inputPtr) const
|
|
||||||
{
|
|
||||||
const auto & baseType = typeid(typename std::remove_cv<TInput>::type);
|
|
||||||
auto derivedType = getTypeInfo(inputPtr.get());
|
|
||||||
|
|
||||||
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) const
|
|
||||||
{
|
|
||||||
return std::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(inputPtr, from, to));
|
|
||||||
}
|
|
||||||
std::any castShared(std::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) const
|
|
||||||
{
|
{
|
||||||
if(t)
|
if(t)
|
||||||
return &typeid(*t);
|
return typeid(*t);
|
||||||
else
|
else
|
||||||
return &typeid(T);
|
return typeid(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static CTypeList & getInstance()
|
||||||
|
{
|
||||||
|
static CTypeList registry;
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
void registerType()
|
||||||
|
{
|
||||||
|
registerType<T>();
|
||||||
|
registerType<U>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void registerType()
|
||||||
|
{
|
||||||
|
const std::type_info & typeInfo = typeid(T);
|
||||||
|
|
||||||
|
if (typeInfos.count(typeInfo.name()) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
typeInfos[typeInfo.name()] = typeInfos.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
uint16_t getTypeID(T * typePtr)
|
||||||
|
{
|
||||||
|
static_assert(!std::is_pointer_v<T>, "CTypeList does not supports pointers!");
|
||||||
|
static_assert(!std::is_reference_v<T>, "CTypeList does not supports references!");
|
||||||
|
|
||||||
|
const std::type_info & typeInfo = getTypeInfo(typePtr);
|
||||||
|
|
||||||
|
if (typeInfos.count(typeInfo.name()) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return typeInfos.at(typeInfo.name());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern DLL_LINKAGE CTypeList typeList;
|
|
||||||
|
|
||||||
/// Wrapper over CTypeList. Allows execution of templated class T for any type
|
/// Wrapper over CTypeList. Allows execution of templated class T for any type
|
||||||
/// that was resgistered for this applier
|
/// that was resgistered for this applier
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class CApplier : boost::noncopyable
|
class CApplier : boost::noncopyable
|
||||||
{
|
{
|
||||||
std::map<ui16, std::unique_ptr<T>> apps;
|
std::map<int32_t, std::unique_ptr<T>> apps;
|
||||||
|
|
||||||
template<typename RegisteredType>
|
template<typename RegisteredType>
|
||||||
void addApplier(ui16 ID)
|
void addApplier(ui16 ID)
|
||||||
@@ -224,9 +97,8 @@ public:
|
|||||||
template<typename Base, typename Derived>
|
template<typename Base, typename Derived>
|
||||||
void registerType(const Base * b = nullptr, const Derived * d = nullptr)
|
void registerType(const Base * b = nullptr, const Derived * d = nullptr)
|
||||||
{
|
{
|
||||||
typeList.registerType(b, d);
|
addApplier<Base>(CTypeList::getInstance().getTypeID<Base>(nullptr));
|
||||||
addApplier<Base>(typeList.getTypeID(b));
|
addApplier<Derived>(CTypeList::getInstance().getTypeID<Derived>(nullptr));
|
||||||
addApplier<Derived>(typeList.getTypeID(d));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,58 +9,18 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <typeinfo>
|
|
||||||
#include <string>
|
|
||||||
#include "CTypeList.h"
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
template<class T, class F>
|
template<class T, class F>
|
||||||
inline const T * dynamic_ptr_cast(const F * ptr)
|
inline const T * dynamic_ptr_cast(const F * ptr)
|
||||||
{
|
{
|
||||||
#ifndef VCMI_APPLE
|
|
||||||
return dynamic_cast<const T *>(ptr);
|
return dynamic_cast<const T *>(ptr);
|
||||||
#else
|
|
||||||
if(!strcmp(typeid(*ptr).name(), typeid(T).name()))
|
|
||||||
{
|
|
||||||
return static_cast<const T *>(ptr);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto * sourceTypeInfo = typeList.getTypeInfo(ptr);
|
|
||||||
auto * targetTypeInfo = &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type);
|
|
||||||
typeList.castRaw((void *)ptr, sourceTypeInfo, targetTypeInfo);
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return static_cast<const T *>(ptr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, class F>
|
template<class T, class F>
|
||||||
inline T * dynamic_ptr_cast(F * ptr)
|
inline T * dynamic_ptr_cast(F * ptr)
|
||||||
{
|
{
|
||||||
#ifndef VCMI_APPLE
|
|
||||||
return dynamic_cast<T *>(ptr);
|
return dynamic_cast<T *>(ptr);
|
||||||
#else
|
|
||||||
if(!strcmp(typeid(*ptr).name(), typeid(T).name()))
|
|
||||||
{
|
|
||||||
return static_cast<T *>(ptr);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto * sourceTypeInfo = typeList.getTypeInfo(ptr);
|
|
||||||
auto * targetTypeInfo = &typeid(typename std::remove_const<typename std::remove_pointer<T>::type>::type);
|
|
||||||
typeList.castRaw((void *)ptr, sourceTypeInfo, targetTypeInfo);
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return static_cast<T *>(ptr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|||||||
@@ -463,12 +463,12 @@ void CGameHandler::handleReceivedPack(CPackForServer * pack)
|
|||||||
PackageApplied applied;
|
PackageApplied applied;
|
||||||
applied.player = pack->player;
|
applied.player = pack->player;
|
||||||
applied.result = succesfullyApplied;
|
applied.result = succesfullyApplied;
|
||||||
applied.packType = typeList.getTypeID(pack);
|
applied.packType = CTypeList::getInstance().getTypeID(pack);
|
||||||
applied.requestID = pack->requestID;
|
applied.requestID = pack->requestID;
|
||||||
pack->c->sendPack(&applied);
|
pack->c->sendPack(&applied);
|
||||||
};
|
};
|
||||||
|
|
||||||
CBaseForGHApply * apply = applier->getApplier(typeList.getTypeID(pack)); //and appropriate applier object
|
CBaseForGHApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack)); //and appropriate applier object
|
||||||
if(isBlockedByQueries(pack, pack->player))
|
if(isBlockedByQueries(pack, pack->player))
|
||||||
{
|
{
|
||||||
sendPackageResponse(false);
|
sendPackageResponse(false);
|
||||||
|
|||||||
@@ -485,7 +485,7 @@ void CVCMIServer::threadHandleClient(std::shared_ptr<CConnection> c)
|
|||||||
|
|
||||||
void CVCMIServer::handleReceivedPack(std::unique_ptr<CPackForLobby> pack)
|
void CVCMIServer::handleReceivedPack(std::unique_ptr<CPackForLobby> pack)
|
||||||
{
|
{
|
||||||
CBaseForServerApply * apply = applier->getApplier(typeList.getTypeID(pack.get()));
|
CBaseForServerApply * apply = applier->getApplier(CTypeList::getInstance().getTypeID(pack.get()));
|
||||||
if(apply->applyOnServerBefore(this, pack.get()))
|
if(apply->applyOnServerBefore(this, pack.get()))
|
||||||
addToAnnounceQueue(std::move(pack));
|
addToAnnounceQueue(std::move(pack));
|
||||||
}
|
}
|
||||||
@@ -502,7 +502,7 @@ void CVCMIServer::announcePack(std::unique_ptr<CPackForLobby> pack)
|
|||||||
c->sendPack(pack.get());
|
c->sendPack(pack.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
applier->getApplier(typeList.getTypeID(pack.get()))->applyOnServerAfter(this, pack.get());
|
applier->getApplier(CTypeList::getInstance().getTypeID(pack.get()))->applyOnServerAfter(this, pack.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVCMIServer::announceMessage(const std::string & txt)
|
void CVCMIServer::announceMessage(const std::string & txt)
|
||||||
|
|||||||
Reference in New Issue
Block a user