Added net ordered list test, and fixed ordering issues with list
This commit is contained in:
parent
8611a2e6bb
commit
6e13c5742e
5 changed files with 137 additions and 17 deletions
|
|
@ -49,9 +49,12 @@ void NetClient::update() {
|
|||
isDisconnected = true;
|
||||
return;
|
||||
}
|
||||
#ifdef NDEBUG
|
||||
try {
|
||||
#endif
|
||||
parse_received_messages();
|
||||
send_queued_messages();
|
||||
#ifdef NDEBUG
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
Logger::get().log("INFO", "[NetClient::update] Exception thrown while parsing and sending messages: " + std::string(e.what()));
|
||||
|
|
@ -61,6 +64,7 @@ void NetClient::update() {
|
|||
Logger::get().log("INFO", "[NetClient::update] Unknown exception thrown while parsing and sending messages.");
|
||||
isDisconnected = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetClient::parse_received_messages() {
|
||||
|
|
|
|||
|
|
@ -26,9 +26,12 @@ void NetServer::update() {
|
|||
if(client->setToDisconnect)
|
||||
disconnectCallback(client);
|
||||
else {
|
||||
#ifdef NDEBUG
|
||||
try {
|
||||
#endif
|
||||
client->parse_received_messages(*this);
|
||||
client->send_queued_messages(*this);
|
||||
#ifdef NDEBUG
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
Logger::get().log("INFO", "[NetServer::update] Exception thrown while parsing and sending messages for a client: " + std::string(e.what()));
|
||||
|
|
@ -40,6 +43,7 @@ void NetServer::update() {
|
|||
client->setToDisconnect = true;
|
||||
disconnectCallback(client);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,14 @@
|
|||
#include <limits>
|
||||
#include <list>
|
||||
|
||||
//#define ENABLE_NETOBJ_ORDERED_LIST_VERBOSE_DEBUG
|
||||
|
||||
#ifdef ENABLE_NETOBJ_ORDERED_LIST_VERBOSE_DEBUG
|
||||
#define NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(data, idMap) netobj_ordered_list_debug_check(data, idMap)
|
||||
#else
|
||||
#define NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(data, idMap)
|
||||
#endif
|
||||
|
||||
namespace NetworkingObjects {
|
||||
enum class ObjPtrOrderedListCommand_StoC : uint8_t {
|
||||
INSERT_LIST_CONSTRUCT,
|
||||
|
|
@ -49,6 +57,37 @@ namespace NetworkingObjects {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_NETOBJ_ORDERED_LIST_VERBOSE_DEBUG
|
||||
template <typename T> void netobj_ordered_list_debug_check(const std::list<NetObjOrderedListObjectInfo<T>>& l, const std::unordered_map<NetObjID, NetObjOrderedListIterator<T>>& idMap) {
|
||||
uint32_t i = 0;
|
||||
std::cout << "[netobj_ordered_list_debug_check] Debug print start\n";
|
||||
for(auto& o : l) {
|
||||
std::cout << "Pos " << o.pos << " with id " << o.obj.get_net_id().to_string() << '\n';
|
||||
if(o.pos != i)
|
||||
throw std::runtime_error("[netobj_ordered_list_debug_check] Position values are incorrect!");
|
||||
++i;
|
||||
auto it = idMap.find(o.obj.get_net_id());
|
||||
if(it == idMap.end())
|
||||
throw std::runtime_error("[netobj_ordered_list_debug_check] Could not find element in ID Map!");
|
||||
if(&(*it->second) != &o)
|
||||
throw std::runtime_error("[netobj_ordered_list_debug_check] ID Map and list point to different objects!");
|
||||
}
|
||||
if(l.size() != idMap.size()) {
|
||||
std::cout << "ID map size: " << idMap.size() << " list size: " << l.size() << '\n';
|
||||
throw std::runtime_error("[netobj_ordered_list_debug_check] ID map and list have different sizes!");
|
||||
}
|
||||
std::cout << "[netobj_ordered_list_debug_check] Debug print end" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T> void refresh_positions_complete(std::list<NetObjOrderedListObjectInfo<T>>& l) {
|
||||
uint32_t i = 0;
|
||||
for(auto& c : l) {
|
||||
c.pos = i;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> class NetObjOrderedList {
|
||||
public:
|
||||
// Don't use this function unless you're sure that class T isn't a base class
|
||||
|
|
@ -301,6 +340,7 @@ namespace NetworkingObjects {
|
|||
a(idPosition, newObjIt->obj.get_net_id());
|
||||
});
|
||||
this->call_insert_callback_list(toRet);
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(data, idToDataMap);
|
||||
return toRet;
|
||||
}
|
||||
virtual void erase_it_list(const NetObjTemporaryPtr<NetObjOrderedList<T>>& l, const std::vector<NetObjOrderedListIterator<T>>& itList, std::vector<NetObjOwnerPtr<T>>* erasedObjects) {
|
||||
|
|
@ -338,11 +378,13 @@ namespace NetworkingObjects {
|
|||
});
|
||||
|
||||
set_position_obj_info_list<T>(smallestPosIt, data.end());
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(data, idToDataMap);
|
||||
}
|
||||
virtual void write_constructor(const NetObjTemporaryPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryOutputArchive& a) override {
|
||||
a(static_cast<uint32_t>(data.size()));
|
||||
for(auto& c : data)
|
||||
c.obj.write_create_message(a);
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(data, idToDataMap);
|
||||
}
|
||||
virtual void read_constructor(const NetObjTemporaryPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) override {
|
||||
uint32_t constructedSize;
|
||||
|
|
@ -353,6 +395,7 @@ namespace NetworkingObjects {
|
|||
auto it = data.emplace(data.end(), l.get_obj_man()->template read_create_message<T>(a, c), i);
|
||||
idToDataMap.emplace(data.back().obj.get_net_id(), it);
|
||||
}
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(data, idToDataMap);
|
||||
// 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
|
||||
}
|
||||
virtual void read_update(const NetObjTemporaryPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) override {
|
||||
|
|
@ -373,17 +416,9 @@ namespace NetworkingObjects {
|
|||
newObjs.emplace_back(NetObjOrderedListIterator<T>(), l.get_obj_man()->template read_create_message<T>(a, c));
|
||||
}
|
||||
|
||||
uint32_t currentIndex = data.size();
|
||||
NetObjOrderedListIterator<T> currentIt = data.end();
|
||||
for(std::pair<std::pair<NetObjOrderedListIterator<T>, NetObjOwnerPtr<T>>&, uint32_t&> elem : (std::views::zip(newObjs, insertIndices) | std::views::reverse)) {
|
||||
uint32_t index = elem.second;
|
||||
auto& it = elem.first.first;
|
||||
while(currentIndex != index) {
|
||||
--currentIndex;
|
||||
--currentIt;
|
||||
}
|
||||
it = currentIt;
|
||||
}
|
||||
std::vector<NetObjOrderedListIterator<T>> itList = this->at_ordered_indices(insertIndices);
|
||||
for(size_t i = 0; i < itList.size(); i++)
|
||||
newObjs[i].first = itList[i];
|
||||
|
||||
insert_ordered_list(l, c, newObjs);
|
||||
break;
|
||||
|
|
@ -445,6 +480,7 @@ namespace NetworkingObjects {
|
|||
}
|
||||
});
|
||||
this->call_insert_callback_list(toRet);
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(clientData, clientIdToDataMap);
|
||||
return toRet;
|
||||
}
|
||||
virtual void erase_it_list(const NetObjTemporaryPtr<NetObjOrderedList<T>>& l, const std::vector<NetObjOrderedListIterator<T>>& itList, std::vector<NetObjOwnerPtr<T>>* erasedObjects) {
|
||||
|
|
@ -481,6 +517,7 @@ namespace NetworkingObjects {
|
|||
});
|
||||
|
||||
set_position_obj_info_list<T>(smallestPosIt, clientData.end());
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(clientData, clientIdToDataMap);
|
||||
}
|
||||
virtual void write_constructor(const NetObjTemporaryPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryOutputArchive& a) override {
|
||||
a(static_cast<uint32_t>(clientData.size()));
|
||||
|
|
@ -491,6 +528,7 @@ namespace NetworkingObjects {
|
|||
auto serverIt = serverData.emplace(serverData.end(), c.obj.get_net_id()); // We are the ones who made this list, so fill up
|
||||
serverIdToDataMap.emplace(c.obj.get_net_id(), serverIt);
|
||||
}
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(clientData, clientIdToDataMap);
|
||||
}
|
||||
virtual void read_constructor(const NetObjTemporaryPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) override {
|
||||
uint32_t constructedSize;
|
||||
|
|
@ -505,6 +543,7 @@ namespace NetworkingObjects {
|
|||
auto serverIt = serverData.emplace(serverData.end(), clientIt->obj.get_net_id());
|
||||
serverIdToDataMap.emplace(clientIt->obj.get_net_id(), serverIt);
|
||||
}
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(clientData, clientIdToDataMap);
|
||||
}
|
||||
virtual void read_update(const NetObjTemporaryPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) override {
|
||||
ObjPtrOrderedListCommand_StoC c;
|
||||
|
|
@ -515,17 +554,18 @@ namespace NetworkingObjects {
|
|||
a(newObjsSize);
|
||||
|
||||
std::vector<NetworkingObjects::NetObjID> idsBeforeElements;
|
||||
std::vector<std::list<NetObjID>::iterator> serverInsertIts;
|
||||
std::vector<std::pair<NetObjOrderedListIterator<T>, NetObjOwnerPtr<T>>> newObjs;
|
||||
|
||||
for(uint32_t i = 0; i < newObjsSize; i++) {
|
||||
auto& idBeforeElement = idsBeforeElements.emplace_back();
|
||||
a(idBeforeElement);
|
||||
newObjs.emplace_back(get_client_iterator_from_server_previous_net_obj_id(idBeforeElement), l.get_obj_man()->template read_create_message<T>(a, nullptr));
|
||||
serverInsertIts.emplace_back(get_server_iterator_from_server_previous_net_obj_id(idBeforeElement));
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < newObjsSize; i++) {
|
||||
auto serverInsertAtIt = get_server_iterator_from_server_previous_net_obj_id(idsBeforeElements[i]);
|
||||
auto serverIt = serverData.emplace(serverInsertAtIt, newObjs[i].second.get_net_id());
|
||||
auto serverIt = serverData.emplace(serverInsertIts[i], newObjs[i].second.get_net_id());
|
||||
serverIdToDataMap.emplace(newObjs[i].second.get_net_id(), serverIt);
|
||||
}
|
||||
|
||||
|
|
@ -539,9 +579,11 @@ namespace NetworkingObjects {
|
|||
if(i == 0)
|
||||
firstInsertedIt = newObjIt;
|
||||
}
|
||||
|
||||
set_position_obj_info_list<T>(firstInsertedIt, clientData.end());
|
||||
this->call_insert_callback_list(insertedIterators);
|
||||
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(clientData, clientIdToDataMap);
|
||||
break;
|
||||
}
|
||||
case ObjPtrOrderedListCommand_StoC::INSERT_LIST_REFERENCE: {
|
||||
|
|
@ -551,6 +593,7 @@ namespace NetworkingObjects {
|
|||
struct PerElementData {
|
||||
NetworkingObjects::NetObjID idBeforeElement;
|
||||
NetworkingObjects::NetObjID refID;
|
||||
std::list<NetObjID>::iterator serverInsertIt;
|
||||
bool foundInClient;
|
||||
NetObjOrderedListIterator<T> clientObjectIt;
|
||||
NetObjOrderedListIterator<T> clientInsertPosIt;
|
||||
|
|
@ -560,6 +603,7 @@ namespace NetworkingObjects {
|
|||
for(uint32_t i = 0; i < newObjsSize; i++) {
|
||||
auto& elemData = receivedElements.emplace_back();
|
||||
a(elemData.idBeforeElement, elemData.refID);
|
||||
elemData.serverInsertIt = get_server_iterator_from_server_previous_net_obj_id(elemData.idBeforeElement);
|
||||
}
|
||||
|
||||
std::list<NetObjOrderedListObjectInfo<T>> referredToObjectData;
|
||||
|
|
@ -577,7 +621,7 @@ namespace NetworkingObjects {
|
|||
if(startRefreshFrom != clientData.end())
|
||||
startRefreshFrom->pos = elemData.clientObjectIt->pos;
|
||||
}
|
||||
referredToObjectData.splice(referredToObjectData.end(), clientData, elemData.clientObjectIt, std::next(elemData.clientObjectIt));
|
||||
referredToObjectData.splice(referredToObjectData.end(), clientData, elemData.clientObjectIt);
|
||||
clientIdToDataMap.erase(clientIdToDataMapIt);
|
||||
elemData.foundInClient = true;
|
||||
}
|
||||
|
|
@ -586,6 +630,7 @@ namespace NetworkingObjects {
|
|||
}
|
||||
|
||||
set_position_obj_info_list<T>(startRefreshFrom, clientData.end());
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(clientData, clientIdToDataMap);
|
||||
|
||||
for(auto& elemData : receivedElements) {
|
||||
if(elemData.foundInClient)
|
||||
|
|
@ -593,8 +638,7 @@ namespace NetworkingObjects {
|
|||
}
|
||||
|
||||
for(auto& elemData : receivedElements) {
|
||||
auto serverInsertAtIt = get_server_iterator_from_server_previous_net_obj_id(elemData.idBeforeElement);
|
||||
auto serverIt = serverData.emplace(serverInsertAtIt, elemData.refID);
|
||||
auto serverIt = serverData.emplace(elemData.serverInsertIt, elemData.refID);
|
||||
serverIdToDataMap.emplace(elemData.refID, serverIt);
|
||||
}
|
||||
|
||||
|
|
@ -607,7 +651,7 @@ namespace NetworkingObjects {
|
|||
firstInsertedActualPos = elemData.clientInsertPosIt->pos;
|
||||
firstInsertedIt = elemData.clientObjectIt;
|
||||
}
|
||||
clientData.splice(elemData.clientInsertPosIt, referredToObjectData, elemData.clientObjectIt, std::next(elemData.clientObjectIt));
|
||||
clientData.splice(elemData.clientInsertPosIt, referredToObjectData, elemData.clientObjectIt);
|
||||
clientIdToDataMap.emplace(elemData.clientObjectIt->obj.get_net_id(), elemData.clientObjectIt);
|
||||
}
|
||||
|
||||
|
|
@ -626,6 +670,7 @@ namespace NetworkingObjects {
|
|||
actualPos++;
|
||||
}
|
||||
}
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(clientData, clientIdToDataMap);
|
||||
break;
|
||||
}
|
||||
case ObjPtrOrderedListCommand_StoC::ERASE_ID_LIST: {
|
||||
|
|
@ -655,6 +700,7 @@ namespace NetworkingObjects {
|
|||
}
|
||||
|
||||
set_position_obj_info_list<T>(smallestPosIt, clientData.end());
|
||||
NETOBJ_ORDERED_LIST_VERBOSE_DEBUG(clientData, clientIdToDataMap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp>
|
||||
#include <cereal/types/unordered_map.hpp>
|
||||
#include "DrawingProgram/Layers/DrawingProgramLayerListItem.hpp"
|
||||
#include "Helpers/NetworkingObjects/NetObjOrderedList.hpp"
|
||||
#include "Helpers/NetworkingObjects/NetObjTemporaryPtr.decl.hpp"
|
||||
#include "Helpers/NetworkingObjects/NetObjUnorderedSet.hpp"
|
||||
#include "CommandList.hpp"
|
||||
|
|
@ -18,6 +19,7 @@
|
|||
#include "VersionConstants.hpp"
|
||||
#include "WorldGrid.hpp"
|
||||
#include <cereal/archives/portable_binary.hpp>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include "FileHelpers.hpp"
|
||||
#include "FontData.hpp"
|
||||
|
|
@ -67,6 +69,9 @@ World::World(MainProgram& initMain, OpenWorldInfo& worldInfo):
|
|||
else
|
||||
load_empty_canvas();
|
||||
set_name(name);
|
||||
#ifdef ENABLE_ORDERED_LIST_TEST
|
||||
listDebugTest = netObjMan.make_obj<NetworkingObjects::NetObjOrderedList<uint16_t>>();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,6 +113,11 @@ void World::init_net_obj_type_list() {
|
|||
canvasTheme.register_class();
|
||||
ClientData::register_class(*this);
|
||||
NetworkingObjects::register_unordered_set_class<ClientData>(netObjMan);
|
||||
|
||||
#ifdef ENABLE_ORDERED_LIST_TEST
|
||||
NetworkingObjects::register_generic_serialized_class<uint16_t>(netObjMan);
|
||||
NetworkingObjects::register_ordered_list_class<uint16_t>(netObjMan);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World::init_client(const std::string& serverFullID) {
|
||||
|
|
@ -135,6 +145,10 @@ void World::init_client(const std::string& serverFullID) {
|
|||
ownClientData = netObjMan.get_obj_temporary_ref_from_id<ClientData>(clientDataObjID);
|
||||
drawData.cam.smooth_move_to(*main.world, ownClientData->get_cam_coords(), ownClientData->get_window_size(), true);
|
||||
|
||||
#ifdef ENABLE_ORDERED_LIST_TEST
|
||||
listDebugTest = netObjMan.read_create_message<NetworkingObjects::NetObjOrderedList<uint16_t>>(message, nullptr);
|
||||
#endif
|
||||
|
||||
clientStillConnecting = false;
|
||||
});
|
||||
netClient->add_recv_callback(CLIENT_UPDATE_NETWORK_OBJECT, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
|
|
@ -165,6 +179,9 @@ void World::focus_update() {
|
|||
}
|
||||
ownClientData->set_cursor_pos(ownClientData, main.input.mouse.pos);
|
||||
drawProg.update();
|
||||
#ifdef ENABLE_ORDERED_LIST_TEST
|
||||
list_debug_test_update();
|
||||
#endif
|
||||
}
|
||||
|
||||
drawData.cam.update_main(*this);
|
||||
|
|
@ -326,6 +343,9 @@ void World::start_hosting(const std::string& initNetSource, const std::string& s
|
|||
drawProg.write_components_server(a);
|
||||
canvasTheme.write_create_message(a);
|
||||
clients.write_create_message(a);
|
||||
#ifdef ENABLE_ORDERED_LIST_TEST
|
||||
listDebugTest.write_create_message(a);
|
||||
#endif
|
||||
}
|
||||
netServer->send_string_stream_to_client(client, RELIABLE_COMMAND_CHANNEL, ss);
|
||||
for(auto& r : rMan.resource_list()) {
|
||||
|
|
@ -484,6 +504,44 @@ void World::scale_up(const WorldScalar& scaleUpAmount) {
|
|||
undo.scale_up(scaleUpAmount);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ORDERED_LIST_TEST
|
||||
void World::list_debug_test_update() {
|
||||
if(std::chrono::steady_clock::now() < (listDebugTestTimeStart + std::chrono::minutes(1))) {
|
||||
bool isInsert;
|
||||
if(listDebugTest->size() > 70)
|
||||
isInsert = false;
|
||||
else if(listDebugTest->size() < 20)
|
||||
isInsert = true;
|
||||
else
|
||||
isInsert = Random::get().real_range(0.0f, 1.0f) > 0.5f;
|
||||
|
||||
using namespace NetworkingObjects;
|
||||
if(isInsert) {
|
||||
std::vector<std::pair<NetObjOrderedListIterator<uint16_t>, NetObjOwnerPtr<uint16_t>>> toInsert;
|
||||
std::vector<uint32_t> randomIndices;
|
||||
uint32_t insertAmount = Random::get().int_range(5, 25);
|
||||
for(uint32_t i = 0; i < insertAmount; i++)
|
||||
randomIndices.emplace_back(Random::get().int_range<uint32_t>(0, listDebugTest->size() + 10));
|
||||
randomIndices[1] = randomIndices[0];
|
||||
std::sort(randomIndices.begin(), randomIndices.end());
|
||||
for(uint32_t index : randomIndices)
|
||||
toInsert.emplace_back(listDebugTest->at(index), netObjMan.make_obj_direct<uint16_t>(Random::get().int_range<uint32_t>(10, 100)));
|
||||
listDebugTest->insert_ordered_list_and_send_create(listDebugTest, toInsert);
|
||||
}
|
||||
else {
|
||||
std::vector<NetObjOrderedListIterator<uint16_t>> toErase;
|
||||
for(uint32_t i = 0; i < listDebugTest->size(); i++) {
|
||||
if(Random::get().real_range(0.0f, 1.0f) > 0.8f)
|
||||
toErase.emplace_back(listDebugTest->at(i));
|
||||
}
|
||||
listDebugTest->erase_list(listDebugTest, toErase);
|
||||
}
|
||||
}
|
||||
if(netServer && netServer->get_client_list().empty())
|
||||
listDebugTestTimeStart = std::chrono::steady_clock::now();
|
||||
}
|
||||
#endif
|
||||
|
||||
void World::draw(SkCanvas* canvas) {
|
||||
drawData.refresh_draw_optimizing_values();
|
||||
if(drawData.drawGrids)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
class MainProgram;
|
||||
|
||||
//#define ENABLE_ORDERED_LIST_TEST
|
||||
|
||||
#define DEFAULT_CANVAS_BACKGROUND_COLOR Vector3f{0.07f, 0.07f, 0.07f}
|
||||
|
||||
class World {
|
||||
|
|
@ -113,4 +115,10 @@ class World {
|
|||
WorldVec mouseWorldMove = {0, 0};
|
||||
|
||||
std::chrono::steady_clock::time_point lastKeepAliveSent;
|
||||
|
||||
#ifdef ENABLE_ORDERED_LIST_TEST
|
||||
NetworkingObjects::NetObjOwnerPtr<NetworkingObjects::NetObjOrderedList<uint16_t>> listDebugTest;
|
||||
void list_debug_test_update();
|
||||
std::chrono::steady_clock::time_point listDebugTestTimeStart = std::chrono::steady_clock::now();
|
||||
#endif
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue