Started work on generic network ordered list object
This commit is contained in:
parent
ed4810e6ee
commit
2f7ebfe083
8 changed files with 439 additions and 130 deletions
|
|
@ -1,19 +1,24 @@
|
|||
#include "NetObjManager.hpp"
|
||||
#include "NetObjPtr.hpp"
|
||||
|
||||
namespace NetworkingObjects {
|
||||
NetObjManager::NetObjManager(std::shared_ptr<NetObjIDGenerator> initIDGen, std::shared_ptr<NetObjManagerTypeList> initTypeList):
|
||||
NetObjManager::NetObjManager(std::shared_ptr<NetObjIDGenerator> initIDGen, std::shared_ptr<NetObjManagerTypeList> initTypeList, bool initIsServer):
|
||||
isServer(initIsServer),
|
||||
idGen(initIDGen),
|
||||
typeList(initTypeList),
|
||||
nextTypeID(0)
|
||||
{}
|
||||
void NetObjManager::read_update_message(cereal::PortableBinaryInputArchive& a) {
|
||||
void NetObjManager::read_update_message(cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& clientReceivedFrom) {
|
||||
NetObjID id;
|
||||
a(id);
|
||||
auto it = objectData.find(id);
|
||||
if(it == objectData.end())
|
||||
return;
|
||||
auto& netTypeIDData = typeList->netTypeIDData[it->second.netTypeID];
|
||||
netTypeIDData.readUpdateFunc(it->second.p.get(), a);
|
||||
if(isServer)
|
||||
netTypeIDData.readUpdateFuncServer(NetObjPtr<void>(this, id, it->second.p), a, clientReceivedFrom);
|
||||
else
|
||||
netTypeIDData.readUpdateFuncClient(NetObjPtr<void>(this, id, it->second.p), a, clientReceivedFrom);
|
||||
}
|
||||
void NetObjManager::set_client(std::shared_ptr<NetClient> initClient, MessageCommandType initUpdateCommandID) {
|
||||
client = initClient;
|
||||
|
|
|
|||
|
|
@ -11,28 +11,31 @@
|
|||
#include "../Networking/NetLibrary.hpp"
|
||||
#include "NetObjIDGenerator.hpp"
|
||||
#include "NetObjManagerTypeList.hpp"
|
||||
#include "NetObjPtr.decl.hpp"
|
||||
#include "../Networking/NetServer.hpp"
|
||||
|
||||
namespace NetworkingObjects {
|
||||
template <typename T> class NetObjPtr;
|
||||
|
||||
class NetObjManager {
|
||||
public:
|
||||
NetObjManager(std::shared_ptr<NetObjIDGenerator> initIDGen, std::shared_ptr<NetObjManagerTypeList> initTypeList);
|
||||
void read_update_message(cereal::PortableBinaryInputArchive& a);
|
||||
NetObjManager(std::shared_ptr<NetObjIDGenerator> initIDGen, std::shared_ptr<NetObjManagerTypeList> initTypeList, bool initIsServer);
|
||||
void read_update_message(cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& clientReceivedFrom);
|
||||
void set_client(std::shared_ptr<NetClient> initClient, MessageCommandType initUpdateCommandID);
|
||||
void set_server(std::shared_ptr<NetServer> initServer, MessageCommandType initUpdateCommandID);
|
||||
|
||||
template <typename T> NetObjPtr<T> read_create_message(cereal::PortableBinaryInputArchive& a) {
|
||||
template <typename T> NetObjPtr<T> read_create_message(cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& clientReceivedFrom) {
|
||||
NetObjID id;
|
||||
NetTypeIDType typeID;
|
||||
a(id, typeID);
|
||||
auto& netTypeIDData = typeList->netTypeIDData[typeID];
|
||||
std::shared_ptr<void> sharedPtr = netTypeIDData.allocatorFunc();
|
||||
auto [it, placed] = objectData.emplace(id, typeID, sharedPtr);
|
||||
std::shared_ptr<void> sharedPtr = isServer ? netTypeIDData.allocatorFuncServer() : netTypeIDData.allocatorFuncClient();
|
||||
auto [it, placed] = objectData.emplace(id, SingleObjectData{.netTypeID = typeID, .p = sharedPtr});
|
||||
if(!placed)
|
||||
throw std::runtime_error("[NetObjManager::read_create_message] ID Collision on object creation");
|
||||
netTypeIDData.readConstructorFunc(sharedPtr.get(), a);
|
||||
return NetObjPtr<T>(id, std::static_pointer_cast<T>(sharedPtr));
|
||||
if(isServer)
|
||||
netTypeIDData.readConstructorFuncServer(NetObjPtr<void>(this, id, sharedPtr), a, clientReceivedFrom);
|
||||
else
|
||||
netTypeIDData.readConstructorFuncClient(NetObjPtr<void>(this, id, sharedPtr), a, clientReceivedFrom);
|
||||
return NetObjPtr<T>(this, id, std::static_pointer_cast<T>(sharedPtr));
|
||||
}
|
||||
template <typename T> NetObjPtr<T> read_get_obj_from_message(cereal::PortableBinaryInputArchive& a) {
|
||||
NetObjID id;
|
||||
|
|
@ -40,27 +43,27 @@ namespace NetworkingObjects {
|
|||
auto it = objectData.find(id);
|
||||
if(it == objectData.end())
|
||||
return NetObjPtr<T>();
|
||||
return NetObjPtr<T>(id, std::static_pointer_cast<T>(it->second.p));
|
||||
return NetObjPtr<T>(this, id, std::static_pointer_cast<T>(it->second.p));
|
||||
}
|
||||
template <typename T, typename... Args> NetObjPtr<T> make_obj(Args&&... items) {
|
||||
auto sharedPtr = std::make_shared<T>(items...);
|
||||
NetObjID newID = idGen->gen();
|
||||
if(!objectData.emplace(newID, typeList->typeIndexData[std::type_index(typeid(T))].netTypeID, sharedPtr).second)
|
||||
if(!objectData.emplace(newID, SingleObjectData{.netTypeID = isServer ? typeList->typeIndexDataServer[std::type_index(typeid(T))].netTypeID : typeList->typeIndexDataClient[std::type_index(typeid(T))].netTypeID, .p = std::static_pointer_cast<void>(sharedPtr)}).second)
|
||||
throw std::runtime_error("[NetObjManager::make_obj] ID Collision");
|
||||
return NetObjPtr<T>(newID, sharedPtr);
|
||||
return NetObjPtr<T>(this, newID, sharedPtr);
|
||||
}
|
||||
template <typename T> NetObjPtr<T> obj_from_ptr(T* p) {
|
||||
std::shared_ptr<T> sharedPtr(p);
|
||||
NetObjID newID = idGen->gen();
|
||||
if(!objectData.emplace(newID, typeList->typeIndexData[std::type_index(typeid(T))].netTypeID, sharedPtr).second)
|
||||
if(!objectData.emplace(newID, SingleObjectData{.netTypeID = isServer ? typeList->typeIndexDataServer[std::type_index(typeid(T))].netTypeID : typeList->typeIndexDataClient[std::type_index(typeid(T))].netTypeID, .p = std::static_pointer_cast<void>(sharedPtr)}).second)
|
||||
throw std::runtime_error("[NetObjManager::obj_from_ptr] ID Collision");
|
||||
return NetObjPtr<T>(newID, sharedPtr);
|
||||
return NetObjPtr<T>(this, newID, sharedPtr);
|
||||
}
|
||||
template <typename T> NetObjPtr<T> get_obj_from_id(NetObjID id) {
|
||||
auto it = objectData.find(id);
|
||||
if(it == objectData.end())
|
||||
throw std::runtime_error("[NetObjManager::get_obj_from_id] ID doesn't exist");
|
||||
return NetObjPtr<T>(id, std::static_pointer_cast<T>(it->second.p));
|
||||
return NetObjPtr<T>(this, id, std::static_pointer_cast<T>(it->second.p));
|
||||
}
|
||||
private:
|
||||
template <typename T> friend class NetObjPtr;
|
||||
|
|
@ -68,8 +71,8 @@ namespace NetworkingObjects {
|
|||
struct SingleObjectData {
|
||||
NetTypeIDType netTypeID;
|
||||
std::shared_ptr<void> p;
|
||||
std::optional<std::chrono::time_point<std::chrono::steady_clock>> timeSinceNoReference;
|
||||
};
|
||||
bool isServer;
|
||||
std::shared_ptr<NetClient> client;
|
||||
std::shared_ptr<NetServer> server;
|
||||
MessageCommandType updateCommandID;
|
||||
|
|
|
|||
|
|
@ -1,27 +1,59 @@
|
|||
#pragma once
|
||||
#include "../Networking/NetLibrary.hpp"
|
||||
#include <cereal/archives/portable_binary.hpp>
|
||||
#include "NetObjPtr.decl.hpp"
|
||||
#include "../Networking/NetServer.hpp"
|
||||
|
||||
namespace NetworkingObjects {
|
||||
|
||||
class NetObjManagerTypeList {
|
||||
public:
|
||||
template <typename T> void register_class(NetTypeIDType netTypeID, std::function<void(T&, cereal::PortableBinaryOutputArchive&)> writeConstructorFunc, std::function<void(T&, cereal::PortableBinaryInputArchive&)> readConstructorFunc, std::function<void(T&, cereal::PortableBinaryInputArchive&)> readUpdateFunc) {
|
||||
netTypeIDData.emplace(netTypeID, {
|
||||
.readConstructorFunc = [readConstructorFunc](void* obj, cereal::PortableBinaryInputArchive& message) {
|
||||
readConstructorFunc(static_cast<T*>(obj), message);
|
||||
template <typename ClientT, typename ServerT> struct ServerClientClassFunctions {
|
||||
std::function<void(const NetObjPtr<ClientT>&, cereal::PortableBinaryOutputArchive&)> writeConstructorFuncClient;
|
||||
std::function<void(const NetObjPtr<ClientT>&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)> readConstructorFuncClient;
|
||||
std::function<void(const NetObjPtr<ClientT>&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)> readUpdateFuncClient;
|
||||
|
||||
std::function<void(const NetObjPtr<ServerT>&, cereal::PortableBinaryOutputArchive&)> writeConstructorFuncServer;
|
||||
std::function<void(const NetObjPtr<ServerT>&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)> readConstructorFuncServer;
|
||||
std::function<void(const NetObjPtr<ServerT>&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)> readUpdateFuncServer;
|
||||
};
|
||||
template <typename ClientPointerType, typename ServerPointerType, typename ClientActualType, typename ServerActualType> void register_class(const ServerClientClassFunctions<ClientPointerType, ServerPointerType>& funcs) {
|
||||
netTypeIDData[nextNetTypeID] = NetTypeIDContainer {
|
||||
.readConstructorFuncClient = [f = funcs.readConstructorFuncClient](const NetObjPtr<void>& obj, cereal::PortableBinaryInputArchive& message, const std::shared_ptr<NetServer::ClientData>& c) {
|
||||
if(f)
|
||||
f(obj.cast<ClientPointerType>(), message, c);
|
||||
},
|
||||
.readUpdateFunc = [readUpdateFunc](void* obj, cereal::PortableBinaryInputArchive& message) {
|
||||
readUpdateFunc(static_cast<T*>(obj), message);
|
||||
.readUpdateFuncClient = [f = funcs.readUpdateFuncClient](const NetObjPtr<void>& obj, cereal::PortableBinaryInputArchive& message, const std::shared_ptr<NetServer::ClientData>& c) {
|
||||
if(f)
|
||||
f(obj.cast<ClientPointerType>(), message, c);
|
||||
},
|
||||
.allocatorFunc = []() { return std::make_shared<T>(); }
|
||||
});
|
||||
typeIndexData.emplace(std::type_index(typeid(T)), {
|
||||
.netTypeID = netTypeID,
|
||||
.writeConstructorFunc = [writeConstructorFunc](void* obj, cereal::PortableBinaryInputArchive& message) {
|
||||
writeConstructorFunc(static_cast<T*>(obj), message);
|
||||
.allocatorFuncClient = []() { return std::static_pointer_cast<void>(std::make_shared<ClientActualType>()); },
|
||||
|
||||
.readConstructorFuncServer = [f = funcs.readConstructorFuncServer](const NetObjPtr<void>& obj, cereal::PortableBinaryInputArchive& message, const std::shared_ptr<NetServer::ClientData>& c) {
|
||||
if(f)
|
||||
f(obj.cast<ServerPointerType>(), message, c);
|
||||
},
|
||||
});
|
||||
.readUpdateFuncServer = [f = funcs.readUpdateFuncServer](const NetObjPtr<void>& obj, cereal::PortableBinaryInputArchive& message, const std::shared_ptr<NetServer::ClientData>& c) {
|
||||
if(f)
|
||||
f(obj.cast<ServerPointerType>(), message, c);
|
||||
},
|
||||
.allocatorFuncServer = []() { return std::static_pointer_cast<void>(std::make_shared<ServerActualType>()); }
|
||||
};
|
||||
typeIndexDataClient[std::type_index(typeid(ClientActualType))] = TypeIndexContainer{
|
||||
.netTypeID = nextNetTypeID,
|
||||
.writeConstructorFunc = [f = funcs.writeConstructorFuncClient](const NetObjPtr<void>& obj, cereal::PortableBinaryOutputArchive& message) {
|
||||
if(f)
|
||||
f(obj.cast<ClientPointerType>(), message);
|
||||
},
|
||||
};
|
||||
typeIndexDataServer[std::type_index(typeid(ServerActualType))] = TypeIndexContainer{
|
||||
.netTypeID = nextNetTypeID,
|
||||
.writeConstructorFunc = [f = funcs.writeConstructorFuncServer](const NetObjPtr<void>& obj, cereal::PortableBinaryOutputArchive& message) {
|
||||
if(f)
|
||||
f(obj.cast<ServerPointerType>(), message);
|
||||
},
|
||||
};
|
||||
nextNetTypeID++;
|
||||
}
|
||||
private:
|
||||
friend class NetObjManager;
|
||||
|
|
@ -29,16 +61,24 @@ class NetObjManagerTypeList {
|
|||
|
||||
struct TypeIndexContainer {
|
||||
NetTypeIDType netTypeID;
|
||||
std::function<void(void*, cereal::PortableBinaryOutputArchive&)> writeConstructorFunc;
|
||||
std::function<void(const NetObjPtr<void>&, cereal::PortableBinaryOutputArchive&)> writeConstructorFunc;
|
||||
};
|
||||
std::unordered_map<std::type_index, TypeIndexContainer> typeIndexData;
|
||||
|
||||
std::unordered_map<std::type_index, TypeIndexContainer> typeIndexDataClient;
|
||||
std::unordered_map<std::type_index, TypeIndexContainer> typeIndexDataServer;
|
||||
|
||||
struct NetTypeIDContainer {
|
||||
std::function<void(void*, cereal::PortableBinaryInputArchive&)> readConstructorFunc;
|
||||
std::function<void(void*, cereal::PortableBinaryInputArchive&)> readUpdateFunc;
|
||||
std::function<std::shared_ptr<void>()> allocatorFunc;
|
||||
std::function<void(const NetObjPtr<void>&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)> readConstructorFuncClient;
|
||||
std::function<void(const NetObjPtr<void>&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)> readUpdateFuncClient;
|
||||
std::function<std::shared_ptr<void>()> allocatorFuncClient;
|
||||
|
||||
std::function<void(const NetObjPtr<void>&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)> readConstructorFuncServer;
|
||||
std::function<void(const NetObjPtr<void>&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)> readUpdateFuncServer;
|
||||
std::function<std::shared_ptr<void>()> allocatorFuncServer;
|
||||
};
|
||||
std::unordered_map<NetTypeIDType, NetTypeIDContainer> netTypeIDData;
|
||||
|
||||
NetTypeIDType nextNetTypeID = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
204
include/Helpers/NetworkingObjects/NetObjOrderedList.hpp
Normal file
204
include/Helpers/NetworkingObjects/NetObjOrderedList.hpp
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
#pragma once
|
||||
#include "Helpers/Networking/NetLibrary.hpp"
|
||||
#include "NetObjPtr.hpp"
|
||||
#include "cereal/archives/portable_binary.hpp"
|
||||
#include "NetObjManagerTypeList.hpp"
|
||||
|
||||
namespace NetworkingObjects {
|
||||
enum class ObjPtrOrderedListCommand_StoC : uint8_t {
|
||||
INSERT_SINGLE,
|
||||
ERASE_SINGLE
|
||||
};
|
||||
|
||||
enum class ObjPtrOrderedListCommand_CtoS : uint8_t {
|
||||
INSERT_SINGLE,
|
||||
ERASE_SINGLE
|
||||
};
|
||||
|
||||
template <typename T> class NetObjOrderedListObjectInfo {
|
||||
public:
|
||||
NetObjOrderedListObjectInfo(const NetObjPtr<T>& initObj, uint32_t initPos, bool initSyncIgnore):
|
||||
obj(initObj),
|
||||
pos(initPos),
|
||||
syncIgnore(initSyncIgnore)
|
||||
{}
|
||||
uint32_t get_pos() const { return pos; }
|
||||
const NetObjPtr<T>& get_obj() const { return obj; }
|
||||
private:
|
||||
NetObjPtr<T> obj;
|
||||
uint32_t pos;
|
||||
bool syncIgnore;
|
||||
template <typename S> friend class NetObjOrderedList;
|
||||
template <typename S> friend class NetObjOrderedListServer;
|
||||
template <typename S> friend class NetObjOrderedListClient;
|
||||
template <typename S> friend void set_positions_for_object_info_vector(std::vector<std::shared_ptr<NetObjOrderedListObjectInfo<S>>>& v, uint32_t i);
|
||||
};
|
||||
|
||||
template <typename T> using NetObjOrderedListObjectInfoPtr = std::shared_ptr<NetObjOrderedListObjectInfo<T>>;
|
||||
|
||||
template <typename T> void set_positions_for_object_info_vector(std::vector<NetObjOrderedListObjectInfoPtr<T>>& v, uint32_t i = 0) {
|
||||
uint32_t vSize = static_cast<uint32_t>(v.size());
|
||||
for(; i < vSize; i++)
|
||||
v[i]->pos = i;
|
||||
}
|
||||
|
||||
template <typename T> class NetObjOrderedList {
|
||||
public:
|
||||
template <typename... Args> static NetObjPtr<T> emplace_back(const NetObjPtr<NetObjOrderedList<T>>& l, Args&&... args) {
|
||||
NetObjPtr<T> newObj = l.get_obj_man()->template make_obj<T>(args...);
|
||||
return push_back_and_send_create(l, newObj);
|
||||
}
|
||||
static NetObjPtr<T> push_back_and_send_create(const NetObjPtr<NetObjOrderedList<T>>& l, const NetObjPtr<T>& newObj) {
|
||||
l->push_back(l, newObj);
|
||||
return newObj;
|
||||
}
|
||||
static NetObjPtr<T> insert_and_send_create(const NetObjPtr<NetObjOrderedList<T>>& l, uint32_t posToInsertAt, const NetObjPtr<T>& newObj) {
|
||||
l->insert(l, posToInsertAt, newObj);
|
||||
return newObj;
|
||||
}
|
||||
static void erase(const NetObjPtr<NetObjOrderedList<T>>& l, uint32_t indexToErase) {
|
||||
l->erase_by_index(l, indexToErase);
|
||||
}
|
||||
static void erase(const NetObjPtr<NetObjOrderedList<T>>& l, const NetObjOrderedListObjectInfoPtr<T>& p) {
|
||||
l->erase_by_ptr(l, p);
|
||||
}
|
||||
virtual uint32_t size() const = 0;
|
||||
virtual const std::vector<NetObjOrderedListObjectInfoPtr<T>>& get_data() const = 0;
|
||||
protected:
|
||||
virtual void push_back(const NetObjPtr<NetObjOrderedList<T>>& l, const NetObjPtr<T>& newObj) = 0;
|
||||
virtual void insert(const NetObjPtr<NetObjOrderedList<T>>& l, uint32_t posToInsertAt, const NetObjPtr<T>& newObj) = 0;
|
||||
virtual void erase_by_index(const NetObjPtr<NetObjOrderedList<T>>& l, uint32_t indexToErase) = 0;
|
||||
virtual void erase_by_ptr(const NetObjPtr<NetObjOrderedList<T>>& l, const NetObjOrderedListObjectInfoPtr<T>& p) = 0;
|
||||
virtual void write_constructor(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryOutputArchive& a) = 0;
|
||||
virtual void read_update(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) = 0;
|
||||
virtual void read_constructor(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) = 0;
|
||||
private:
|
||||
template <typename S> friend void register_ordered_list_class(NetObjManagerTypeList& t);
|
||||
static void write_constructor_func(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryOutputArchive& a) {
|
||||
l->write_constructor(l, a);
|
||||
}
|
||||
static void read_constructor_func(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
|
||||
l->read_constructor(l, a, c);
|
||||
}
|
||||
static void read_update_func(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
|
||||
l->read_update(l, a, c);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class NetObjOrderedListServer : public NetObjOrderedList<T> {
|
||||
public:
|
||||
virtual uint32_t size() const override {
|
||||
return data.size();
|
||||
}
|
||||
virtual const std::vector<NetObjOrderedListObjectInfoPtr<T>>& get_data() const override {
|
||||
return data;
|
||||
}
|
||||
protected:
|
||||
virtual void push_back(const NetObjPtr<NetObjOrderedList<T>>& l, const NetObjPtr<T>& newObj) override {
|
||||
auto& newObjInfoPtr = data.emplace_back(std::make_shared<NetObjOrderedListObjectInfo<T>>(newObj, static_cast<uint32_t>(data.size()), false));
|
||||
l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr](const NetObjPtr<NetObjOrderedList<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(ObjPtrOrderedListCommand_StoC::INSERT_SINGLE, newObjInfoPtr->pos);
|
||||
newObjInfoPtr->obj.write_create_message(a);
|
||||
});
|
||||
}
|
||||
virtual void insert(const NetObjPtr<NetObjOrderedList<T>>& l, uint32_t posToInsertAt, const NetObjPtr<T>& newObj) override {
|
||||
posToInsertAt = std::min<uint32_t>(posToInsertAt, data.size());
|
||||
auto& newObjInfoPtr = *data.insert(data.begin() + posToInsertAt, std::make_shared<NetObjOrderedListObjectInfo<T>>(newObj, posToInsertAt, false));
|
||||
set_positions_for_object_info_vector<T>(data, posToInsertAt);
|
||||
l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr](const NetObjPtr<NetObjOrderedList<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(ObjPtrOrderedListCommand_StoC::INSERT_SINGLE, newObjInfoPtr->pos);
|
||||
newObjInfoPtr->obj.write_create_message(a);
|
||||
});
|
||||
}
|
||||
virtual void erase_by_index(const NetObjPtr<NetObjOrderedList<T>>& l, uint32_t indexToErase) override {
|
||||
NetObjOrderedListObjectInfoPtr<T>& objToErase = data[indexToErase];
|
||||
l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [indexToErase](const NetObjPtr<NetObjOrderedList<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(ObjPtrOrderedListCommand_StoC::ERASE_SINGLE, indexToErase);
|
||||
});
|
||||
data.erase(data.begin() + indexToErase);
|
||||
set_positions_for_object_info_vector<T>(data, indexToErase);
|
||||
}
|
||||
virtual void erase_by_ptr(const NetObjPtr<NetObjOrderedList<T>>& l, const NetObjOrderedListObjectInfoPtr<T>& p) override {
|
||||
l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [indexToErase = p->pos](const NetObjPtr<NetObjOrderedList<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(ObjPtrOrderedListCommand_StoC::ERASE_SINGLE, indexToErase);
|
||||
});
|
||||
data.erase(data.begin() + p->pos);
|
||||
set_positions_for_object_info_vector<T>(data, p->pos);
|
||||
}
|
||||
virtual void write_constructor(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryOutputArchive& a) override {
|
||||
}
|
||||
virtual void read_constructor(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) override {
|
||||
}
|
||||
virtual void read_update(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) override {
|
||||
ObjPtrOrderedListCommand_CtoS command;
|
||||
a(command);
|
||||
switch(command) {
|
||||
//cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& clientReceivedFrom
|
||||
case ObjPtrOrderedListCommand_CtoS::INSERT_SINGLE:
|
||||
uint32_t newPos;
|
||||
a(newPos);
|
||||
insert(l, newPos, l.get_obj_man()->template read_create_message<T>(a, c));
|
||||
break;
|
||||
case ObjPtrOrderedListCommand_CtoS::ERASE_SINGLE:
|
||||
NetObjID idToErase;
|
||||
a(idToErase);
|
||||
insert(l, newPos, l.get_obj_man()->template read_create_message<T>(a, c));
|
||||
break;
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<NetObjOrderedListObjectInfoPtr<T>> data;
|
||||
};
|
||||
|
||||
template <typename T> class NetObjOrderedListClient : public NetObjOrderedList<T> {
|
||||
public:
|
||||
virtual uint32_t size() const override {
|
||||
return clientData.size();
|
||||
}
|
||||
virtual const std::vector<NetObjOrderedListObjectInfoPtr<T>>& get_data() const override {
|
||||
return clientData;
|
||||
}
|
||||
protected:
|
||||
virtual void push_back(const NetObjPtr<NetObjOrderedList<T>>& l, const NetObjPtr<T>& newObj) override {
|
||||
auto& newObjInfoPtr = clientData.emplace_back(std::make_shared<NetObjOrderedListObjectInfo<T>>(newObj, static_cast<uint32_t>(clientData.size()), true));
|
||||
l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr](const NetObjPtr<NetObjOrderedList<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(ObjPtrOrderedListCommand_CtoS::INSERT_SINGLE, newObjInfoPtr->pos);
|
||||
newObjInfoPtr->obj.write_create_message(a);
|
||||
});
|
||||
}
|
||||
virtual void insert(const NetObjPtr<NetObjOrderedList<T>>& l, uint32_t posToInsertAt, const NetObjPtr<T>& newObj) {
|
||||
}
|
||||
virtual void erase_by_index(const NetObjPtr<NetObjOrderedList<T>>& l, uint32_t indexToErase) override {
|
||||
}
|
||||
virtual void erase_by_ptr(const NetObjPtr<NetObjOrderedList<T>>& l, const NetObjOrderedListObjectInfoPtr<T>& p) override {
|
||||
}
|
||||
virtual void write_constructor(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryOutputArchive& a) override {
|
||||
}
|
||||
virtual void read_constructor(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) override {
|
||||
}
|
||||
virtual void read_update(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) override {
|
||||
ObjPtrOrderedListCommand_StoC c;
|
||||
a(c);
|
||||
switch(c) {
|
||||
case ObjPtrOrderedListCommand_StoC::INSERT_SINGLE:
|
||||
break;
|
||||
case ObjPtrOrderedListCommand_StoC::ERASE_SINGLE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<NetObjOrderedListObjectInfoPtr<T>> serverData;
|
||||
std::vector<NetObjOrderedListObjectInfoPtr<T>> clientData;
|
||||
};
|
||||
|
||||
template <typename S> void register_ordered_list_class(NetObjManagerTypeList& t) {
|
||||
t.register_class<NetObjOrderedList<S>, NetObjOrderedList<S>, NetObjOrderedListClient<S>, NetObjOrderedListServer<S>>({
|
||||
.writeConstructorFuncClient = NetObjOrderedList<S>::write_constructor_func,
|
||||
.readConstructorFuncClient = NetObjOrderedList<S>::read_constructor_func,
|
||||
.readUpdateFuncClient = NetObjOrderedList<S>::read_update_func,
|
||||
.writeConstructorFuncServer = NetObjOrderedList<S>::write_constructor_func,
|
||||
.readConstructorFuncServer = NetObjOrderedList<S>::read_constructor_func,
|
||||
.readUpdateFuncServer = NetObjOrderedList<S>::read_update_func,
|
||||
});
|
||||
}
|
||||
}
|
||||
33
include/Helpers/NetworkingObjects/NetObjPtr.decl.hpp
Normal file
33
include/Helpers/NetworkingObjects/NetObjPtr.decl.hpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
#include "NetObjIDGenerator.hpp"
|
||||
#include <type_traits>
|
||||
|
||||
namespace NetworkingObjects {
|
||||
class NetObjManager;
|
||||
template <typename T> class NetObjPtr {
|
||||
public:
|
||||
NetObjPtr();
|
||||
NetObjPtr(const NetObjPtr& other);
|
||||
NetObjPtr& operator=(const NetObjPtr& other);
|
||||
~NetObjPtr();
|
||||
template <typename S> NetObjPtr<S> cast() const;
|
||||
NetObjManager* get_obj_man() const;
|
||||
NetObjID get_net_id() const;
|
||||
T* get() const;
|
||||
std::add_lvalue_reference_t<T> operator*() const requires(!std::is_void_v<T>);
|
||||
T* operator->() const;
|
||||
operator bool() const;
|
||||
std::strong_ordering operator<=>(const NetObjPtr<T>& rhs) const;
|
||||
void send_client_update(const std::string& channel, std::function<void(const NetObjPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const;
|
||||
void send_server_update_to_all_clients(const std::string& channel, std::function<void(const NetObjPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const;
|
||||
void write_create_message(cereal::PortableBinaryOutputArchive& a) const;
|
||||
private:
|
||||
friend class NetObjManager;
|
||||
template <typename S> friend class NetObjPtr;
|
||||
|
||||
NetObjPtr(NetObjManager* initObjMan, NetObjID initID, const std::shared_ptr<T>& initPtr);
|
||||
NetObjManager* objMan;
|
||||
NetObjID id;
|
||||
std::shared_ptr<T> sharedPtr;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,93 +1,3 @@
|
|||
#pragma once
|
||||
#include "NetObjIDGenerator.hpp"
|
||||
#include <compare>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <cereal/archives/portable_binary.hpp>
|
||||
#include "NetObjManager.hpp"
|
||||
#include "NetObjManagerTypeList.hpp"
|
||||
|
||||
namespace NetworkingObjects {
|
||||
template <typename T> class NetObjPtr {
|
||||
public:
|
||||
NetObjPtr():
|
||||
objMan(nullptr),
|
||||
sharedPtr(nullptr)
|
||||
{}
|
||||
NetObjPtr(const NetObjPtr& other):
|
||||
objMan(other.objMan),
|
||||
id(other.id),
|
||||
sharedPtr(other.sharedPtr)
|
||||
{}
|
||||
NetObjPtr& operator=(const NetObjPtr& other) {
|
||||
if(this != &other) {
|
||||
if(sharedPtr && sharedPtr.unique())
|
||||
objMan->objectData.erase(id);
|
||||
objMan = other.objMan;
|
||||
id = other.id;
|
||||
sharedPtr = other.sharedPtr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~NetObjPtr() {
|
||||
if(sharedPtr && sharedPtr.unique())
|
||||
objMan->objectData.erase(id);
|
||||
}
|
||||
|
||||
NetObjID get_net_id() const {
|
||||
return id;
|
||||
}
|
||||
T* get() const {
|
||||
return sharedPtr.get();
|
||||
}
|
||||
T& operator*() const {
|
||||
return *sharedPtr;
|
||||
}
|
||||
operator bool() const {
|
||||
return sharedPtr != nullptr;
|
||||
}
|
||||
std::strong_ordering operator<=>(const NetObjPtr<T>& rhs) const {
|
||||
return sharedPtr <=> rhs.sharedPtr;
|
||||
}
|
||||
void send_client_update(const std::string& channel, std::function<void(T&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const {
|
||||
if(objMan->client && !objMan->client->is_disconnected()) {
|
||||
auto ss(std::make_shared<std::stringstream>());
|
||||
{
|
||||
cereal::PortableBinaryOutputArchive m(*ss);
|
||||
m(objMan->updateCommandID, id);
|
||||
sendUpdateFunc(*this, m);
|
||||
}
|
||||
objMan->client->send_string_stream_to_server(channel, ss);
|
||||
}
|
||||
}
|
||||
void send_server_update_to_all_clients(const std::string& channel, std::function<void(T&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const {
|
||||
if(objMan->server && !objMan->server->is_disconnected()) {
|
||||
auto ss(std::make_shared<std::stringstream>());
|
||||
{
|
||||
cereal::PortableBinaryOutputArchive m(*ss);
|
||||
m(objMan->updateCommandID, id);
|
||||
sendUpdateFunc(*this, m);
|
||||
}
|
||||
objMan->server->send_string_stream_to_all_clients(channel, ss);
|
||||
}
|
||||
}
|
||||
void write_create_message(cereal::PortableBinaryOutputArchive& a) const {
|
||||
auto& typeIndexData = objMan->typeList->typeIndexData[std::type_index(typeid(T))];
|
||||
a(id, typeIndexData.netTypeID);
|
||||
typeIndexData.writeConstructorFunc(static_cast<void*>(this), a);
|
||||
}
|
||||
private:
|
||||
friend class NetObjManager;
|
||||
|
||||
NetObjPtr(NetObjManager* initObjMan, NetObjID initID, const std::shared_ptr<T>& initPtr):
|
||||
objMan(initObjMan),
|
||||
id(initID),
|
||||
sharedPtr(initPtr)
|
||||
{}
|
||||
|
||||
NetObjManager* objMan;
|
||||
NetObjID id;
|
||||
std::shared_ptr<T> sharedPtr;
|
||||
};
|
||||
|
||||
}
|
||||
#include "NetObjPtr.decl.hpp"
|
||||
#include "NetObjPtr.impl.hpp"
|
||||
|
|
|
|||
103
include/Helpers/NetworkingObjects/NetObjPtr.impl.hpp
Normal file
103
include/Helpers/NetworkingObjects/NetObjPtr.impl.hpp
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#pragma once
|
||||
#include <compare>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <cereal/archives/portable_binary.hpp>
|
||||
#include <type_traits>
|
||||
#include "NetObjPtr.decl.hpp"
|
||||
#include "NetObjManager.hpp"
|
||||
#include "NetObjManagerTypeList.hpp"
|
||||
|
||||
namespace NetworkingObjects {
|
||||
template <typename T> NetObjPtr<T>::NetObjPtr():
|
||||
objMan(nullptr),
|
||||
sharedPtr(nullptr)
|
||||
{}
|
||||
template <typename T> NetObjPtr<T>::NetObjPtr(const NetObjPtr<T>& other):
|
||||
objMan(other.objMan),
|
||||
id(other.id),
|
||||
sharedPtr(other.sharedPtr)
|
||||
{}
|
||||
template <typename T> NetObjPtr<T>& NetObjPtr<T>::operator=(const NetObjPtr<T>& other) {
|
||||
if(this != &other) {
|
||||
if(sharedPtr && sharedPtr.unique())
|
||||
objMan->objectData.erase(id);
|
||||
objMan = other.objMan;
|
||||
id = other.id;
|
||||
sharedPtr = other.sharedPtr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename T> NetObjPtr<T>::~NetObjPtr() {
|
||||
if(sharedPtr && sharedPtr.unique())
|
||||
objMan->objectData.erase(id);
|
||||
}
|
||||
|
||||
template <typename T> template <typename S> NetObjPtr<S> NetObjPtr<T>::cast() const {
|
||||
return NetObjPtr<S>(objMan, id, std::static_pointer_cast<S>(sharedPtr));
|
||||
}
|
||||
|
||||
template <typename T> NetObjManager* NetObjPtr<T>::get_obj_man() const {
|
||||
return objMan;
|
||||
}
|
||||
|
||||
template <typename T> NetObjID NetObjPtr<T>::get_net_id() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
template <typename T> T* NetObjPtr<T>::get() const {
|
||||
return sharedPtr.get();
|
||||
}
|
||||
|
||||
template <typename T> std::add_lvalue_reference_t<T> NetObjPtr<T>::operator*() const requires(!std::is_void_v<T>) {
|
||||
return *sharedPtr;
|
||||
}
|
||||
|
||||
template <typename T> T* NetObjPtr<T>::operator->() const {
|
||||
return sharedPtr.get();
|
||||
}
|
||||
|
||||
template <typename T> NetObjPtr<T>::operator bool() const {
|
||||
return sharedPtr != nullptr;
|
||||
}
|
||||
|
||||
template <typename T> std::strong_ordering NetObjPtr<T>::operator<=>(const NetObjPtr<T>& rhs) const {
|
||||
return sharedPtr <=> rhs.sharedPtr;
|
||||
}
|
||||
|
||||
template <typename T> void NetObjPtr<T>::send_client_update(const std::string& channel, std::function<void(const NetObjPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const {
|
||||
if(objMan->client && !objMan->client->is_disconnected()) {
|
||||
auto ss(std::make_shared<std::stringstream>());
|
||||
{
|
||||
cereal::PortableBinaryOutputArchive m(*ss);
|
||||
m(objMan->updateCommandID, id);
|
||||
sendUpdateFunc(*this, m);
|
||||
}
|
||||
objMan->client->send_string_stream_to_server(channel, ss);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void NetObjPtr<T>::send_server_update_to_all_clients(const std::string& channel, std::function<void(const NetObjPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const {
|
||||
if(objMan->server && !objMan->server->is_disconnected()) {
|
||||
auto ss(std::make_shared<std::stringstream>());
|
||||
{
|
||||
cereal::PortableBinaryOutputArchive m(*ss);
|
||||
m(objMan->updateCommandID, id);
|
||||
sendUpdateFunc(*this, m);
|
||||
}
|
||||
objMan->server->send_string_stream_to_all_clients(channel, ss);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void NetObjPtr<T>::write_create_message(cereal::PortableBinaryOutputArchive& a) const {
|
||||
auto& typeIndexData = objMan->isServer ? objMan->typeList->typeIndexDataServer[std::type_index(typeid(T))] : objMan->typeList->typeIndexDataClient[std::type_index(typeid(T))];
|
||||
a(id, typeIndexData.netTypeID);
|
||||
typeIndexData.writeConstructorFunc(this->cast<void>(), a);
|
||||
}
|
||||
|
||||
template <typename T> NetObjPtr<T>::NetObjPtr(NetObjManager* initObjMan, NetObjID initID, const std::shared_ptr<T>& initPtr):
|
||||
objMan(initObjMan),
|
||||
id(initID),
|
||||
sharedPtr(initPtr)
|
||||
{}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue