Added generic serialized class and changed to random 128 bit IDs for objects
This commit is contained in:
parent
35b46d9d2b
commit
5d24b34200
11 changed files with 113 additions and 69 deletions
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
#include "NetObjPtr.hpp"
|
||||
|
||||
namespace NetworkingObjects {
|
||||
template <typename T> void register_generic_serialized_class(NetObjManagerTypeList& t) {
|
||||
t.register_class<T, T>({
|
||||
.writeConstructorFuncClient = [](const NetObjPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(*o);
|
||||
},
|
||||
.readConstructorFuncClient = [](NetObjManager& m, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) {
|
||||
NetObjPtr<T> o = m.make_obj<T>();
|
||||
a(*o);
|
||||
return o.template cast<void>();
|
||||
},
|
||||
.readUpdateFuncClient = [](const NetObjPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) {
|
||||
a(*o);
|
||||
},
|
||||
.writeConstructorFuncServer = [](const NetObjPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(*o);
|
||||
},
|
||||
.readConstructorFuncServer = [](NetObjManager& m, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) {
|
||||
NetObjPtr<T> o = m.make_obj<T>();
|
||||
a(*o);
|
||||
return o.template cast<void>();
|
||||
},
|
||||
.readUpdateFuncServer = [](const NetObjPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) {
|
||||
a(*o);
|
||||
o.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [](const NetObjPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(*o);
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
10
include/Helpers/NetworkingObjects/NetObjID.cpp
Normal file
10
include/Helpers/NetworkingObjects/NetObjID.cpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#include "NetObjID.hpp"
|
||||
|
||||
namespace NetworkingObjects {
|
||||
|
||||
|
||||
NetObjID NetObjID::random_gen() {
|
||||
return NetObjID{.data = {Random::get().randGen(), Random::get().randGen()}};
|
||||
}
|
||||
|
||||
}
|
||||
26
include/Helpers/NetworkingObjects/NetObjID.hpp
Normal file
26
include/Helpers/NetworkingObjects/NetObjID.hpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <Helpers/Random.hpp>
|
||||
#include <Helpers/Hashes.hpp>
|
||||
|
||||
namespace NetworkingObjects {
|
||||
struct NetObjID {
|
||||
std::array<uint64_t, 2> data;
|
||||
template <typename Archive> void serialize(Archive& a) {
|
||||
a(data[1], data[0]);
|
||||
}
|
||||
NetObjID& operator=(const NetObjID&) = default;
|
||||
bool operator==(const NetObjID&) const = default;
|
||||
static NetObjID random_gen();
|
||||
};
|
||||
};
|
||||
|
||||
template <> struct std::hash<NetworkingObjects::NetObjID> {
|
||||
size_t operator()(const NetworkingObjects::NetObjID& v) const
|
||||
{
|
||||
uint64_t h = 0;
|
||||
hash_combine(h, v.data[1], v.data[0]);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#include "NetObjIDGenerator.hpp"
|
||||
|
||||
namespace NetworkingObjects {
|
||||
|
||||
void NetObjIDGenerator::set_starting_id(NetObjID c) {
|
||||
currentID = c;
|
||||
}
|
||||
|
||||
NetObjID NetObjIDGenerator::gen() {
|
||||
currentID.clientID++;
|
||||
return currentID;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include "../Hashes.hpp"
|
||||
|
||||
namespace NetworkingObjects {
|
||||
|
||||
struct NetObjID {
|
||||
typedef uint16_t ClientPortion;
|
||||
typedef uint64_t ObjectPortion;
|
||||
ClientPortion clientID = 0;
|
||||
ObjectPortion objID = 0;
|
||||
bool operator==(const NetObjID&) const = default;
|
||||
template <typename Archive> void serialize(Archive& a) {
|
||||
a(clientID, objID);
|
||||
}
|
||||
};
|
||||
|
||||
class NetObjIDGenerator {
|
||||
public:
|
||||
void set_starting_id(NetObjID c);
|
||||
NetObjID gen();
|
||||
private:
|
||||
NetObjID currentID;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <> struct std::hash<NetworkingObjects::NetObjID> {
|
||||
size_t operator()(const NetworkingObjects::NetObjID& v) const
|
||||
{
|
||||
uint64_t h = 0;
|
||||
hash_combine(h, v.clientID, v.objID);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
|
@ -2,9 +2,8 @@
|
|||
#include "NetObjPtr.hpp"
|
||||
|
||||
namespace NetworkingObjects {
|
||||
NetObjManager::NetObjManager(std::shared_ptr<NetObjIDGenerator> initIDGen, std::shared_ptr<NetObjManagerTypeList> initTypeList, bool initIsServer):
|
||||
NetObjManager::NetObjManager(std::shared_ptr<NetObjManagerTypeList> initTypeList, bool initIsServer):
|
||||
isServer(initIsServer),
|
||||
idGen(initIDGen),
|
||||
typeList(initTypeList),
|
||||
nextTypeID(0)
|
||||
{}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@
|
|||
#include <cereal/archives/portable_binary.hpp>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <Helpers/Random.hpp>
|
||||
#include "../Networking/NetClient.hpp"
|
||||
#include "../Networking/NetServer.hpp"
|
||||
#include "../Networking/NetLibrary.hpp"
|
||||
#include "NetObjIDGenerator.hpp"
|
||||
#include "Helpers/NetworkingObjects/NetObjID.hpp"
|
||||
#include "NetObjManagerTypeList.hpp"
|
||||
#include "NetObjPtr.decl.hpp"
|
||||
#include "../Networking/NetServer.hpp"
|
||||
|
|
@ -17,7 +18,7 @@
|
|||
namespace NetworkingObjects {
|
||||
class NetObjManager {
|
||||
public:
|
||||
NetObjManager(std::shared_ptr<NetObjIDGenerator> initIDGen, std::shared_ptr<NetObjManagerTypeList> initTypeList, bool initIsServer);
|
||||
NetObjManager(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);
|
||||
|
|
@ -43,14 +44,14 @@ namespace NetworkingObjects {
|
|||
}
|
||||
template <typename T, typename... Args> NetObjPtr<T> make_obj(Args&&... items) {
|
||||
auto sharedPtr = std::make_shared<T>(items...);
|
||||
NetObjID newID = idGen->gen();
|
||||
NetObjID newID = NetObjID::random_gen();
|
||||
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>(this, newID, sharedPtr);
|
||||
}
|
||||
template <typename T> NetObjPtr<T> obj_from_ptr(T* p) {
|
||||
std::shared_ptr<T> sharedPtr(p);
|
||||
NetObjID newID = idGen->gen();
|
||||
NetObjID newID = NetObjID::random_gen();
|
||||
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>(this, newID, sharedPtr);
|
||||
|
|
@ -73,7 +74,6 @@ namespace NetworkingObjects {
|
|||
std::shared_ptr<NetServer> server;
|
||||
MessageCommandType updateCommandID;
|
||||
std::unordered_map<NetObjID, SingleObjectData> objectData;
|
||||
std::shared_ptr<NetObjIDGenerator> idGen;
|
||||
std::shared_ptr<NetObjManagerTypeList> typeList;
|
||||
NetTypeIDType nextTypeID;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "Helpers/Networking/NetLibrary.hpp"
|
||||
#include "NetObjPtr.hpp"
|
||||
#include "NetObjID.hpp"
|
||||
#include "cereal/archives/portable_binary.hpp"
|
||||
#include "NetObjManagerTypeList.hpp"
|
||||
|
||||
|
|
@ -124,8 +125,18 @@ namespace NetworkingObjects {
|
|||
set_positions_for_object_info_vector<T>(data, iToErase);
|
||||
}
|
||||
virtual void write_constructor(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryOutputArchive& a) override {
|
||||
a(static_cast<uint32_t>(data.size()));
|
||||
for(size_t i = 0; i < data.size(); i++)
|
||||
data[i]->obj.write_create_message(a);
|
||||
}
|
||||
virtual void read_constructor_post_allocation(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) override {
|
||||
uint32_t constructedSize;
|
||||
a(constructedSize);
|
||||
data.clear();
|
||||
for(uint32_t i = 0; i < constructedSize; i++)
|
||||
data.emplace_back(std::make_shared<NetObjOrderedListObjectInfo<T>>(l.get_obj_man()->template read_create_message<T>(a, c), static_cast<uint32_t>(data.size()), false));
|
||||
// Dont send the object data to all clients in the constructor, as the function that called read_create_message is also the one that will decide where to send the data of the constructed object
|
||||
// Example: the INSERT_SINGLE command in read_update, if it was inserting another NetObjOrderedList, would first construct the list using read_create_message, then it will call insert() to send it to clients
|
||||
}
|
||||
virtual void read_update(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) override {
|
||||
ObjPtrOrderedListCommand_CtoS command;
|
||||
|
|
@ -164,24 +175,30 @@ namespace NetworkingObjects {
|
|||
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) {
|
||||
l.send_client_update(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) {
|
||||
posToInsertAt = std::min<uint32_t>(posToInsertAt, clientData.size());
|
||||
auto& newObjInfoPtr = *clientData.insert(clientData.begin() + posToInsertAt, std::make_shared<NetObjOrderedListObjectInfo<T>>(newObj, posToInsertAt, true));
|
||||
l.send_client_update(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 erase_by_index(const NetObjPtr<NetObjOrderedList<T>>& l, uint32_t indexToErase) override {
|
||||
indexToErase = std::min<uint32_t>(indexToErase, clientData.size());
|
||||
auto& newObjInfoPtr = clientData[indexToErase];
|
||||
l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr](const NetObjPtr<NetObjOrderedList<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr](const NetObjPtr<NetObjOrderedList<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(ObjPtrOrderedListCommand_CtoS::ERASE_SINGLE, newObjInfoPtr->obj.get_net_id());
|
||||
});
|
||||
clientData.erase(clientData.begin() + indexToErase);
|
||||
set_positions_for_object_info_vector<T>(clientData, 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, [&p](const NetObjPtr<NetObjOrderedList<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&p](const NetObjPtr<NetObjOrderedList<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(ObjPtrOrderedListCommand_CtoS::ERASE_SINGLE, p->obj.get_net_id());
|
||||
});
|
||||
uint32_t iToErase = p->pos;
|
||||
|
|
@ -189,8 +206,18 @@ namespace NetworkingObjects {
|
|||
set_positions_for_object_info_vector<T>(clientData, iToErase);
|
||||
}
|
||||
virtual void write_constructor(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryOutputArchive& a) override {
|
||||
a(static_cast<uint32_t>(clientData.size()));
|
||||
for(size_t i = 0; i < clientData.size(); i++)
|
||||
clientData[i]->obj.write_create_message(a);
|
||||
}
|
||||
virtual void read_constructor_post_allocation(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) override {
|
||||
uint32_t constructedSize;
|
||||
a(constructedSize);
|
||||
clientData.clear();
|
||||
serverData.clear();
|
||||
for(uint32_t i = 0; i < constructedSize; i++)
|
||||
serverData.emplace_back(std::make_shared<NetObjOrderedListObjectInfo<T>>(l.get_obj_man()->template read_create_message<T>(a, nullptr), static_cast<uint32_t>(serverData.size()), false));
|
||||
clientData = serverData;
|
||||
}
|
||||
virtual void read_update(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) override {
|
||||
ObjPtrOrderedListCommand_StoC c;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "NetObjIDGenerator.hpp"
|
||||
#include "NetObjID.hpp"
|
||||
#include <type_traits>
|
||||
#include <cereal/archives/portable_binary.hpp>
|
||||
|
||||
namespace NetworkingObjects {
|
||||
class NetObjManager;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue