Started work on generic network ordered list object

This commit is contained in:
Yousef Khadadeh 2025-12-07 17:35:27 +03:00
parent ed4810e6ee
commit 2f7ebfe083
8 changed files with 439 additions and 130 deletions

View file

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

View file

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

View file

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

View 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,
});
}
}

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

View file

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

View 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)
{}
}

View file

@ -1,6 +1,5 @@
#include "MainProgram.hpp"
#include "DrawingProgram/DrawingProgramToolBase.hpp"
#include "Helpers/VersionNumber.hpp"
#include "VersionConstants.hpp"
#include "cereal/archives/portable_binary.hpp"
#include "cereal/details/helpers.hpp"
@ -39,11 +38,23 @@
#include <Helpers/Logger.hpp>
#include <Helpers/Networking/NetLibrary.hpp>
#include <Helpers/NetworkingObjects/NetObjOrderedList.hpp>
#include <Helpers/NetworkingObjects/NetObjIDGenerator.hpp>
#include <Helpers/NetworkingObjects/NetObjManager.hpp>
struct Abc {
int a = 0;
};
MainProgram::MainProgram():
fonts(std::make_shared<FontData>()),
toolbar(*this)
{
auto idGen = std::make_shared<NetworkingObjects::NetObjIDGenerator>();
auto typeList = std::make_shared<NetworkingObjects::NetObjManagerTypeList>();
NetworkingObjects::register_ordered_list_class<Abc>(*typeList);
auto nObjMan = std::make_shared<NetworkingObjects::NetObjManager>(idGen, typeList, false);
displayName = Random::get().alphanumeric_str(10);
Logger::get().add_log("WORLDFATAL", [&](const std::string& text) {