Working on moving canvas code to net objects (broken build)

This commit is contained in:
Yousef Khadadeh 2025-12-14 18:57:40 +03:00
parent d2a0bfcda9
commit 45ba26446a
42 changed files with 605 additions and 3186 deletions

View file

@ -7,46 +7,80 @@
namespace NetworkingObjects {
class DelayUpdateSerializedClassManager {
public:
template <typename T> void register_class(NetObjManager& objMan) {
template <typename T> struct CustomConstructors {
std::function<void(const T& o, cereal::PortableBinaryOutputArchive& a)> writeConstructor = [](const T& o, cereal::PortableBinaryOutputArchive& a) {
a(o);
};
std::function<void(T& o, cereal::PortableBinaryOutputArchive& a)> readConstructor = [](T& o, cereal::PortableBinaryOutputArchive& a) {
a(o);
};
std::function<void(const T& o, cereal::PortableBinaryOutputArchive& a)> writeUpdate = [](const T& o, cereal::PortableBinaryOutputArchive& a) {
a(o);
};
std::function<void(T& o, cereal::PortableBinaryOutputArchive& a)> readUpdate = [](T& o, cereal::PortableBinaryOutputArchive& a) {
a(o);
};
std::function<std::shared_ptr<T>(const T& o)> allocateCopy = [](const T& o) {
return std::make_shared<T>();
};
std::function<void(T&, const T&)> assignmentFunc = [](T& o, const T& o2) {
constexpr bool hasDefaultAssignment = requires(T& t, const T& t2) {
t = t2;
};
if constexpr(hasDefaultAssignment)
o = o2;
};
std::function<void(T&)> postUpdateFunc = [](T& o) {};
};
template <typename T> void register_class(NetObjManager& objMan, const CustomConstructors<T>& t = CustomConstructors<T>()) {
objMan.register_class<T, T, T, T>({
.writeConstructorFuncClient = [&](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a){write_constructor_func<T>(o, a);},
.readConstructorFuncClient = [&](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&){read_constructor_func<T>(o, a);},
.readUpdateFuncClient = [&](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&){client_read_update_func<T>(o, a);},
.writeConstructorFuncServer = [&](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a){write_constructor_func<T>(o, a);},
.readConstructorFuncServer = [&](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&){read_constructor_func<T>(o, a);},
.readUpdateFuncServer = [&](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&){server_read_update_func<T>(o, a);}
.writeConstructorFuncClient = t.writeConstructor,
.readConstructorFuncClient = t.readConstructor,
.readUpdateFuncClient = [&, readUpdate = t.readUpdate](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&){client_read_update_func<T>(o, a, readUpdate);},
.writeConstructorFuncServer = t.writeConstructor,
.readConstructorFuncServer = t.readConstructor,
.readUpdateFuncServer = [&, readUpdate = t.readUpdate](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&){server_read_update_func<T>(o, a, readUpdate);}
});
typeIndexFuncs[std::type_index(typeid(T))] = {
.writeUpdateFunc = [writeFunc = t.writeUpdate](const void* o, cereal::PortableBinaryOutputArchive& a) {
writeFunc(*static_cast<const T*>(o), a);
},
.assignmentFunc = [assignFunc = t.assignmentFunc](void* o, const void* o2) {
assignFunc(*static_cast<T*>(o), *static_cast<const T*>(o2));
},
.postUpdateFunc = [postUpdateFunc = t.postUpdateFunc](void* o) {
postUpdateFunc(*static_cast<T*>(o));
},
.allocateCopyFunc = [allocateCopyFunc = t.allocateCopy](const void* o) {
return std::static_pointer_cast<void>(allocateCopyFunc(*static_cast<const T*>(o)));
}
};
}
template <typename T> void send_update_to_all(const NetworkingObjects::NetObjTemporaryPtr<T>& o, const std::function<void(T&)>& postAssignmentFunc, bool finalUpdate) {
template <typename T> void send_update_to_all(const NetworkingObjects::NetObjTemporaryPtr<T>& o, bool finalUpdate) {
o.send_update_to_all(finalUpdate ? RELIABLE_COMMAND_CHANNEL : UNRELIABLE_COMMAND_CHANNEL, [&](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {
if(o.get_obj_man()->is_server())
server_write_func(o, a, postAssignmentFunc);
server_write_func(o, a);
else
client_write_update_func(o, a, postAssignmentFunc, finalUpdate);
client_write_update_func(o, a, finalUpdate);
});
}
void update();
private:
template <typename T> void write_constructor_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {
a(*o);
}
template <typename T> void client_write_update_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a, const std::function<void(T&)>& postAssignmentFunc, bool finalUpdate) {
template <typename T> void client_write_update_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a, bool finalUpdate) {
a(finalUpdate);
a(*o);
typeIndexFuncs[std::type_index(typeid(T))].writeUpdateFunc(static_cast<const void*>(o.get()), a);
auto it = updatingObjs.find(o.get_net_id());
if(it == updatingObjs.end()) {
UpdatingObject toAdd;
toAdd.objToUpdateCurrentData = std::static_pointer_cast<void>(std::make_shared<T>(*o));
toAdd.objToUpdateCurrentData = typeIndexFuncs[std::type_index(typeid(T))].allocateCopyFunc(static_cast<const void*>(o.get()));
toAdd.doLastAssignment = std::make_shared<bool>(true);
toAdd.lastUpdateTimePoint = std::chrono::steady_clock::now();
toAdd.setDataAfterTimeout = [postAssignmentFunc, oWeak = NetObjWeakPtr<T>(o), currentData = toAdd.objToUpdateCurrentData, doLastAssignment = toAdd.doLastAssignment]() {
toAdd.setDataAfterTimeout = [&typeIndexFuncs = typeIndexFuncs, oWeak = NetObjWeakPtr<T>(o), currentData = toAdd.objToUpdateCurrentData, doLastAssignment = toAdd.doLastAssignment]() {
NetObjTemporaryPtr<T> oLock = oWeak.lock();
if(oLock && *doLastAssignment) {
*oLock = *std::static_pointer_cast<T>(currentData);
if(postAssignmentFunc)
postAssignmentFunc(*oLock);
typeIndexFuncs[std::type_index(typeid(T))].assignmentFunc(static_cast<void*>(oLock.get()), static_cast<const void*>(currentData.get()));
typeIndexFuncs[std::type_index(typeid(T))].postUpdateFunc(static_cast<void*>(oLock.get()));
}
};
updatingObjs.emplace(o.get_net_id(), toAdd);
@ -57,38 +91,35 @@ namespace NetworkingObjects {
}
}
template <typename T> void read_constructor_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a) {
a(*o);
}
template <typename T> void client_read_update_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a) {
template <typename T> void client_read_update_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::function<void(T&, cereal::PortableBinaryOutputArchive&)>& readUpdate) {
auto it = updatingObjs.find(o.get_net_id());
if(it == updatingObjs.end())
a(*o);
if(it == updatingObjs.end()) {
readUpdate(*o, a);
typeIndexFuncs[std::type_index(typeid(T))].postUpdateFunc(static_cast<void*>(o.get()));
}
else {
auto& [netID, updatingObjData] = *it;
a(*std::static_pointer_cast<T>(updatingObjData.objToUpdateCurrentData));
readUpdate(*std::static_pointer_cast<T>(updatingObjData.objToUpdateCurrentData), a);
*updatingObjData.doLastAssignment = true;
}
}
template <typename T> void server_write_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a, const std::function<void(T&)>& postAssignmentFunc) {
a(*o);
typeIndexFuncs[std::type_index(typeid(T))].writeUpdateFunc(static_cast<const void*>(o.get()), a);
auto it = updatingObjs.find(o.get_net_id());
if(it == updatingObjs.end()) {
UpdatingObject toAdd;
toAdd.objToUpdateCurrentData = std::static_pointer_cast<void>(std::make_shared<T>(*o));
toAdd.objToUpdateCurrentData = typeIndexFuncs[std::type_index(typeid(T))].allocateCopyFunc(static_cast<const void*>(o.get()));
toAdd.lastUpdateTimePoint = std::chrono::steady_clock::now();
toAdd.doLastAssignment = std::make_shared<bool>(false);
toAdd.setDataAfterTimeout = [postAssignmentFunc, oWeak = NetObjWeakPtr<T>(o), currentData = toAdd.objToUpdateCurrentData, doLastAssignment = toAdd.doLastAssignment]() {
toAdd.setDataAfterTimeout = [&typeIndexFuncs = typeIndexFuncs, postAssignmentFunc, oWeak = NetObjWeakPtr<T>(o), currentData = toAdd.objToUpdateCurrentData, doLastAssignment = toAdd.doLastAssignment]() {
NetObjTemporaryPtr<T> oLock = oWeak.lock();
if(oLock && *doLastAssignment) {
*oLock = *std::static_pointer_cast<T>(currentData);
if(postAssignmentFunc)
postAssignmentFunc(*oLock);
oLock.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {
a(*o);
typeIndexFuncs[std::type_index(typeid(T))].assignmentFunc(static_cast<void*>(oLock.get()), static_cast<const void*>(currentData.get()));
typeIndexFuncs[std::type_index(typeid(T))].postUpdateFunc(static_cast<void*>(oLock.get()));
oLock.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&typeIndexFuncs = typeIndexFuncs](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {
typeIndexFuncs[std::type_index(typeid(T))].writeUpdateFunc(static_cast<const void*>(o.get()), a);
});
}
};
@ -97,23 +128,26 @@ namespace NetworkingObjects {
else {
auto& [netID, updatingObjData] = *it;
updatingObjData.lastUpdateTimePoint = std::chrono::steady_clock::now();
*std::static_pointer_cast<T>(updatingObjs[o.get_net_id()].objToUpdateCurrentData) = *o;
typeIndexFuncs[std::type_index(typeid(T))].assignmentFunc(static_cast<void*>(updatingObjs[o.get_net_id()].objToUpdateCurrentData.get()), static_cast<const void*>(o.get()));
*updatingObjData.doLastAssignment = false;
}
}
template <typename T> void server_read_update_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a) {
template <typename T> void server_read_update_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::function<void(T&, cereal::PortableBinaryOutputArchive&)>& readUpdate) {
auto it = updatingObjs.find(o.get_net_id());
bool finalUpdate;
if(it == updatingObjs.end()) {
a(finalUpdate, *o);
o.send_server_update_to_all_clients(finalUpdate ? RELIABLE_COMMAND_CHANNEL : UNRELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {
a(*o);
a(finalUpdate);
readUpdate(*o, a);
typeIndexFuncs[std::type_index(typeid(T))].postUpdateFunc(static_cast<void*>(o.get()));
o.send_server_update_to_all_clients(finalUpdate ? RELIABLE_COMMAND_CHANNEL : UNRELIABLE_COMMAND_CHANNEL, [&typeIndexFuncs = typeIndexFuncs](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {
typeIndexFuncs[std::type_index(typeid(T))].writeUpdateFunc(static_cast<const void*>(o.get()), a);
});
}
else {
auto& [netID, updatingObjData] = *it;
a(finalUpdate, *std::static_pointer_cast<T>(updatingObjData.objToUpdateCurrentData));
a(finalUpdate);
readUpdate(*std::static_pointer_cast<T>(updatingObjData.objToUpdateCurrentData), a);
*updatingObjData.doLastAssignment = true;
}
}
@ -125,5 +159,13 @@ namespace NetworkingObjects {
std::function<void()> setDataAfterTimeout;
};
std::unordered_map<NetObjID, UpdatingObject> updatingObjs;
struct ExtraFunctions {
std::function<void(const void*, cereal::PortableBinaryOutputArchive&)> writeUpdateFunc;
std::function<void(void*, const void*)> assignmentFunc;
std::function<void(void*)> postUpdateFunc;
std::function<std::shared_ptr<void>(const void*)> allocateCopyFunc;
};
std::unordered_map<std::type_index, ExtraFunctions> typeIndexFuncs;
};
}