#pragma once #include "NetObjWeakPtr.hpp" #include "cereal/archives/portable_binary.hpp" #include namespace NetworkingObjects { class DelayUpdateSerializedClassManager { public: template void register_class(NetObjManagerTypeList& t) { t.register_class({ .writeConstructorFuncClient = [&](const NetObjPtr& o, cereal::PortableBinaryOutputArchive& a){client_write_func(o, a);}, .readConstructorFuncClient = [&](const NetObjPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&){delay_read_func(o, a);}, .readUpdateFuncClient = [&](const NetObjPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&){delay_read_func(o, a);}, .writeConstructorFuncServer = [&](const NetObjPtr& o, cereal::PortableBinaryOutputArchive& a){server_write_func(o, a);}, .readConstructorFuncServer = [&](const NetObjPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&){delay_read_func(o, a);}, .readUpdateFuncServer = [&](const NetObjPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&){server_read_update_func(o, a);} }); } template void send_update_to_all(const NetworkingObjects::NetObjPtr& o) { o.send_update_to_all(RELIABLE_COMMAND_CHANNEL, [&](const NetObjPtr& o, cereal::PortableBinaryOutputArchive& a) { if(o.get_obj_man()->is_server()) server_write_func(o, a); else client_write_func(o, a); }); } void update(); private: template void client_write_func(const NetObjPtr& o, cereal::PortableBinaryOutputArchive& a) { a(*o); auto it = updatingObjs.find(o.get_net_id()); if(it == updatingObjs.end()) { UpdatingObject toAdd; toAdd.objToUpdateCurrentData = std::static_pointer_cast(std::make_shared(*o)); toAdd.lastUpdateTimePoint = std::chrono::steady_clock::now(); toAdd.setDataAfterTimeout = [oWeak = NetObjWeakPtr(o), currentData = toAdd.objToUpdateCurrentData]() { NetObjPtr oLock = oWeak.lock(); if(oLock) *oLock = *std::static_pointer_cast(currentData); }; updatingObjs.emplace(o.get_net_id(), toAdd); } else { auto& [netID, updatingObjData] = *it; updatingObjData.lastUpdateTimePoint = std::chrono::steady_clock::now(); } } template void delay_read_func(const NetObjPtr& o, cereal::PortableBinaryInputArchive& a) { auto it = updatingObjs.find(o.get_net_id()); if(it == updatingObjs.end()) a(*o); else { auto& [netID, updatingObjData] = *it; a(*std::static_pointer_cast(updatingObjData.objToUpdateCurrentData)); } } template void server_write_func(const NetObjPtr& o, cereal::PortableBinaryOutputArchive& a) { a(*o); auto it = updatingObjs.find(o.get_net_id()); if(it == updatingObjs.end()) { UpdatingObject toAdd; toAdd.objToUpdateCurrentData = std::static_pointer_cast(std::make_shared(*o)); toAdd.lastUpdateTimePoint = std::chrono::steady_clock::now(); toAdd.setDataAfterTimeout = [oWeak = NetObjWeakPtr(o), currentData = toAdd.objToUpdateCurrentData]() { NetObjPtr oLock = oWeak.lock(); if(oLock) { *oLock = *std::static_pointer_cast(currentData); oLock.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [](const NetObjPtr& o, cereal::PortableBinaryOutputArchive& a) { a(*o); }); } }; updatingObjs.emplace(o.get_net_id(), toAdd); } else { auto& [netID, updatingObjData] = *it; updatingObjData.lastUpdateTimePoint = std::chrono::steady_clock::now(); *std::static_pointer_cast(updatingObjs[o.get_net_id()].objToUpdateCurrentData) = *o; } } template void server_read_update_func(const NetObjPtr& o, cereal::PortableBinaryInputArchive& a) { auto it = updatingObjs.find(o.get_net_id()); if(it == updatingObjs.end()) { a(*o); o.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [](const NetObjPtr& o, cereal::PortableBinaryOutputArchive& a) { a(*o); }); } else { auto& [netID, updatingObjData] = *it; a(*std::static_pointer_cast(updatingObjData.objToUpdateCurrentData)); } } struct UpdatingObject { std::shared_ptr objToUpdateCurrentData; std::chrono::steady_clock::time_point lastUpdateTimePoint; std::function setDataAfterTimeout; }; std::unordered_map updatingObjs; }; }