2025-12-07 17:35:27 +03:00
# pragma once
# include "Helpers/Networking/NetLibrary.hpp"
# include "NetObjPtr.hpp"
2025-12-08 14:28:01 +03:00
# include "NetObjID.hpp"
2025-12-07 17:35:27 +03:00
# 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 :
2025-12-08 20:51:11 +03:00
// Don't use this function unless you're sure that class T isn't a base class
template < typename . . . Args > NetObjPtr < T > emplace_back_direct ( const NetObjPtr < NetObjOrderedList < T > > & l , Args & & . . . items ) {
NetObjPtr < T > newObj = l . get_obj_man ( ) - > template make_obj_direct < T > ( items . . . ) ;
l - > push_back ( l , newObj ) ;
return newObj ;
2025-12-07 17:35:27 +03:00
}
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 ;
2025-12-08 20:51:11 +03:00
virtual ~ NetObjOrderedList ( ) { }
2025-12-07 17:35:27 +03:00
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 ;
2025-12-07 23:09:17 +03:00
virtual void read_constructor_post_allocation ( const NetObjPtr < NetObjOrderedList < T > > & l , cereal : : PortableBinaryInputArchive & a , const std : : shared_ptr < NetServer : : ClientData > & ) = 0 ;
2025-12-07 17:35:27 +03:00
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 ) ;
}
2025-12-07 23:09:17 +03:00
static NetObjPtr < void > read_constructor_func ( NetObjManager & objMan , cereal : : PortableBinaryInputArchive & a , const std : : shared_ptr < NetServer : : ClientData > & c ) ;
2025-12-07 17:35:27 +03:00
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 :
2025-12-08 20:51:11 +03:00
NetObjOrderedListServer ( ) { }
2025-12-07 17:35:27 +03:00
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 {
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 ) ;
} ) ;
2025-12-07 23:09:17 +03:00
uint32_t iToErase = p - > pos ; // We only have a reference to the pointer, so erasing it might destroy the pointer object. Save the index before erasing
data . erase ( data . begin ( ) + iToErase ) ;
set_positions_for_object_info_vector < T > ( data , iToErase ) ;
2025-12-07 17:35:27 +03:00
}
virtual void write_constructor ( const NetObjPtr < NetObjOrderedList < T > > & l , cereal : : PortableBinaryOutputArchive & a ) override {
2025-12-08 14:28:01 +03:00
a ( static_cast < uint32_t > ( data . size ( ) ) ) ;
for ( size_t i = 0 ; i < data . size ( ) ; i + + )
data [ i ] - > obj . write_create_message ( a ) ;
2025-12-07 17:35:27 +03:00
}
2025-12-07 23:09:17 +03:00
virtual void read_constructor_post_allocation ( const NetObjPtr < NetObjOrderedList < T > > & l , cereal : : PortableBinaryInputArchive & a , const std : : shared_ptr < NetServer : : ClientData > & c ) override {
2025-12-08 14:28:01 +03:00
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
2025-12-07 17:35:27 +03:00
}
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 ) {
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 ) ;
2025-12-07 23:09:17 +03:00
std : : erase_if ( data , [ & ] ( NetObjOrderedListObjectInfoPtr < T > & o ) {
if ( o - > obj . get_net_id ( ) = = idToErase ) {
erase_by_ptr ( l , o ) ;
return true ;
}
return false ;
} ) ;
2025-12-07 17:35:27 +03:00
break ;
}
}
private :
std : : vector < NetObjOrderedListObjectInfoPtr < T > > data ;
} ;
template < typename T > class NetObjOrderedListClient : public NetObjOrderedList < T > {
public :
2025-12-08 20:51:11 +03:00
NetObjOrderedListClient ( ) { }
2025-12-07 17:35:27 +03:00
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 ) ) ;
2025-12-08 14:28:01 +03:00
l . send_client_update ( RELIABLE_COMMAND_CHANNEL , [ & newObjInfoPtr ] ( const NetObjPtr < NetObjOrderedList < T > > & , cereal : : PortableBinaryOutputArchive & a ) {
2025-12-07 17:35:27 +03:00
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 ) {
2025-12-08 14:28:01 +03:00
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 ) ;
} ) ;
2025-12-07 17:35:27 +03:00
}
virtual void erase_by_index ( const NetObjPtr < NetObjOrderedList < T > > & l , uint32_t indexToErase ) override {
2025-12-07 23:09:17 +03:00
indexToErase = std : : min < uint32_t > ( indexToErase , clientData . size ( ) ) ;
auto & newObjInfoPtr = clientData [ indexToErase ] ;
2025-12-08 14:28:01 +03:00
l . send_client_update ( RELIABLE_COMMAND_CHANNEL , [ & newObjInfoPtr ] ( const NetObjPtr < NetObjOrderedList < T > > & , cereal : : PortableBinaryOutputArchive & a ) {
2025-12-07 23:09:17 +03:00
a ( ObjPtrOrderedListCommand_CtoS : : ERASE_SINGLE , newObjInfoPtr - > obj . get_net_id ( ) ) ;
} ) ;
clientData . erase ( clientData . begin ( ) + indexToErase ) ;
set_positions_for_object_info_vector < T > ( clientData , indexToErase ) ;
2025-12-07 17:35:27 +03:00
}
virtual void erase_by_ptr ( const NetObjPtr < NetObjOrderedList < T > > & l , const NetObjOrderedListObjectInfoPtr < T > & p ) override {
2025-12-08 14:28:01 +03:00
l . send_client_update ( RELIABLE_COMMAND_CHANNEL , [ & p ] ( const NetObjPtr < NetObjOrderedList < T > > & , cereal : : PortableBinaryOutputArchive & a ) {
2025-12-07 23:09:17 +03:00
a ( ObjPtrOrderedListCommand_CtoS : : ERASE_SINGLE , p - > obj . get_net_id ( ) ) ;
} ) ;
uint32_t iToErase = p - > pos ;
clientData . erase ( clientData . begin ( ) + iToErase ) ;
set_positions_for_object_info_vector < T > ( clientData , iToErase ) ;
2025-12-07 17:35:27 +03:00
}
virtual void write_constructor ( const NetObjPtr < NetObjOrderedList < T > > & l , cereal : : PortableBinaryOutputArchive & a ) override {
2025-12-08 14:28:01 +03:00
a ( static_cast < uint32_t > ( clientData . size ( ) ) ) ;
for ( size_t i = 0 ; i < clientData . size ( ) ; i + + )
clientData [ i ] - > obj . write_create_message ( a ) ;
2025-12-07 17:35:27 +03:00
}
2025-12-07 23:09:17 +03:00
virtual void read_constructor_post_allocation ( const NetObjPtr < NetObjOrderedList < T > > & l , cereal : : PortableBinaryInputArchive & a , const std : : shared_ptr < NetServer : : ClientData > & ) override {
2025-12-08 14:28:01 +03:00
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 ;
2025-12-07 17:35:27 +03:00
}
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 :
2025-12-07 23:09:17 +03:00
uint32_t newPos ;
a ( newPos ) ;
serverData . insert ( serverData . begin ( ) + newPos , std : : make_shared < NetObjOrderedListObjectInfo < T > > ( l . get_obj_man ( ) - > template read_create_message < T > ( a , nullptr ) , newPos , false ) ) ;
2025-12-07 17:35:27 +03:00
break ;
case ObjPtrOrderedListCommand_StoC : : ERASE_SINGLE :
2025-12-07 23:09:17 +03:00
uint32_t posToErase ;
a ( posToErase ) ;
serverData . erase ( serverData . begin ( ) + posToErase ) ;
2025-12-07 17:35:27 +03:00
break ;
}
}
private :
std : : vector < NetObjOrderedListObjectInfoPtr < T > > serverData ;
std : : vector < NetObjOrderedListObjectInfoPtr < T > > clientData ;
} ;
2025-12-07 23:09:17 +03:00
template < typename T > NetObjPtr < void > NetObjOrderedList < T > : : read_constructor_func ( NetObjManager & objMan , cereal : : PortableBinaryInputArchive & a , const std : : shared_ptr < NetServer : : ClientData > & c ) {
2025-12-08 20:51:11 +03:00
NetObjPtr < NetObjOrderedList < T > > allocatedPtr = objMan . make_obj < NetObjOrderedList < T > > ( ) ;
2025-12-07 23:09:17 +03:00
allocatedPtr - > read_constructor_post_allocation ( allocatedPtr , a , c ) ;
return allocatedPtr . template cast < void > ( ) ;
}
2025-12-07 17:35:27 +03:00
template < typename S > void register_ordered_list_class ( NetObjManagerTypeList & t ) {
2025-12-08 20:51:11 +03:00
t . register_class < NetObjOrderedList < S > , NetObjOrderedList < S > , NetObjOrderedListClient < S > , NetObjOrderedListServer < S > > ( {
2025-12-07 17:35:27 +03:00
. 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 ,
} ) ;
}
}