From 15c0b8cb57ed5d10814103eaa0b5c06e8ae117e4 Mon Sep 17 00:00:00 2001 From: hgn Date: Thu, 23 Nov 2023 12:32:34 +0000 Subject: [PATCH] gameserver optimisations --- gameserver.c | 114 ++++++++++++++++++++++++++++++++++++--- gameserver.h | 16 +++++- network_common.h | 10 ++++ player.c | 3 ++ player.h | 14 ++--- player_basic_info.c | 22 ++++++++ player_basic_info.h | 25 +++++++++ player_remote.c | 63 +++++++++++----------- player_remote.h | 9 ++-- shaders/scene_override.h | 6 ++- 10 files changed, 232 insertions(+), 50 deletions(-) create mode 100644 player_basic_info.c create mode 100644 player_basic_info.h diff --git a/gameserver.c b/gameserver.c index cd1678a..e641256 100644 --- a/gameserver.c +++ b/gameserver.c @@ -116,7 +116,7 @@ static void gameserver_player_join( int index ){ /* items */ for( int j=0; jitems[j], item->uid, ADDON_UID_MAX, + chs = vg_strncpy( client->items[j].uid, item->uid, ADDON_UID_MAX, k_strncpy_always_add_null ); item->type_index = j; item->client = i; @@ -145,6 +145,8 @@ static void gameserver_player_leave( int index ){ k_nSteamNetworkingSend_Reliable ); } +static void gameserver_update_all_knowledge( int client, int clear ); + /* * Deletes client at index and disconnects the connection handle if it was * set. @@ -160,6 +162,7 @@ static void remove_client( int index ){ NULL, 1 ); } memset( client, 0, sizeof(struct gameserver_client) ); + gameserver_update_all_knowledge( index, 1 ); } /* @@ -432,6 +435,103 @@ static void gameserver_update_db_username( db_request *db_req ){ db_updateuser( inf->steamid, inf->username, admin ); } +static int gameserver_item_eq( struct gameserver_item *ia, + struct gameserver_item *ib ){ + if( ia->hash == ib->hash ) + if( !strcmp(ia->uid,ib->uid) ) + return 1; + + return 0; +} + +/* + * Match addons between two player IDs. if clear is set, then the flags between + * those two IDs will all be set to 0. + */ +static void gameserver_update_knowledge_table( int client0, int client1, + int clear ){ + u32 idx = network_pair_index( client0, client1 ); + + struct gameserver_client *c0 = &gameserver.clients[client0], + *c1 = &gameserver.clients[client1]; + + u8 flags = 0x00; + + if( !clear ){ + if( gameserver_item_eq(&c0->items[k_netmsg_playeritem_world0], + &c1->items[k_netmsg_playeritem_world0])) + flags |= CLIENT_KNOWLEDGE_SAME_WORLD0; + + if( gameserver_item_eq(&c0->items[k_netmsg_playeritem_world1], + &c1->items[k_netmsg_playeritem_world1])) + flags |= CLIENT_KNOWLEDGE_SAME_WORLD1; + } + + gameserver.client_knowledge_mask[idx] = flags; +} + +/* + * If a change has been made on this client, then it will adjust the entire + * table of other players. if clear is set, all references to client will be set + * to 0. + */ +static void gameserver_update_all_knowledge( int client, int clear ){ + for( int i=0; isteamid ) + gameserver_update_knowledge_table( client, i, clear ); + } +} + +static void gameserver_propogate_player_frame( int client_id, + netmsg_playerframe *frame, + u32 size ){ + u32 basic_size = sizeof(netmsg_playerframe) + ((24*3)/8); + netmsg_playerframe *full = alloca(size), + *basic= alloca(basic_size); + + memcpy( full, frame, size ); + memcpy( basic, frame, basic_size ); + + full->client = client_id; + basic->client = client_id; + basic->subsystem = 4; /* (.._basic_info: 24f*3 animator ) */ + basic->sound_effects = 0; + + struct gameserver_client *c0 = &gameserver.clients[client_id]; + c0->instance = frame->instance_id; + + for( int i=0; iinstance == ci->instance ){ + u32 k_index = network_pair_index( client_id, i ); + u8 k_mask = gameserver.client_knowledge_mask[ k_index ]; + + if( (k_mask & (CLIENT_KNOWLEDGE_SAME_WORLD0<instance)) ) + send_full = 1; + } + + if( send_full ){ + gameserver_send_to_client( i, full, size, + k_nSteamNetworkingSend_Unreliable ); + } + else { + gameserver_send_to_client( i, basic, basic_size, + k_nSteamNetworkingSend_Unreliable ); + } + } +} + static void gameserver_rx_200_300( SteamNetworkingMessage_t *msg ){ netmsg_blank *tmp = msg->m_pData; @@ -477,12 +577,8 @@ static void gameserver_rx_200_300( SteamNetworkingMessage_t *msg ){ db_send_request( call ); } else if( tmp->inetmsg_id == k_inetmsg_playerframe ){ - /* propogate */ - netmsg_playerframe *frame = alloca(msg->m_cbSize); - memcpy( frame, msg->m_pData, msg->m_cbSize ); - frame->client = client_id; - gameserver_send_to_all( client_id, frame, msg->m_cbSize, - k_nSteamNetworkingSend_Unreliable ); + gameserver_propogate_player_frame( client_id, + msg->m_pData, msg->m_cbSize ); } else if( tmp->inetmsg_id == k_inetmsg_playeritem ){ netmsg_playeritem *item = msg->m_pData; @@ -495,7 +591,7 @@ static void gameserver_rx_200_300( SteamNetworkingMessage_t *msg ){ return; } - char *dest = client->items[ item->type_index ]; + char *dest = client->items[ item->type_index ].uid; network_msgstring( item->uid, msg->m_cbSize, sizeof(netmsg_playeritem), dest, ADDON_UID_MAX ); @@ -507,6 +603,8 @@ static void gameserver_rx_200_300( SteamNetworkingMessage_t *msg ){ [k_netmsg_playeritem_world0]="world0", [k_netmsg_playeritem_world1]="world1" }[item->type_index], item->uid ); + + gameserver_update_all_knowledge( client_id, 0 ); /* propogate */ netmsg_playeritem *prop = alloca(msg->m_cbSize); diff --git a/gameserver.h b/gameserver.h index fa856ce..ac1c491 100644 --- a/gameserver.h +++ b/gameserver.h @@ -13,6 +13,10 @@ #include "highscores.h" #include +#define CLIENT_KNOWLEDGE_SAME_WORLD0 0x1 +#define CLIENT_KNOWLEDGE_SAME_WORLD1 0x2 +#define CLIENT_KNOWLEDGE_FRIENDS 0x4 /* TODO? */ + struct { HSteamNetPollGroup client_group; EServerMode auth_mode; @@ -23,13 +27,23 @@ struct { int authenticated; HSteamNetConnection connection; char username[ NETWORK_USERNAME_MAX ]; - char items[k_netmsg_playeritem_max][ADDON_UID_MAX]; + + u8 instance; + + struct gameserver_item { + char uid[ADDON_UID_MAX]; + u32 hash; + } + items[k_netmsg_playeritem_max]; + u64 steamid; } clients[ NETWORK_MAX_PLAYERS ]; + u8 client_knowledge_mask[ (NETWORK_MAX_PLAYERS*(NETWORK_MAX_PLAYERS-1))/2 ]; u8 app_symmetric_key[ k_nSteamEncryptedAppTicketSymmetricKeyLen ]; + /* TODO: Consider removing this */ int monitor_fd; int monitor_clients[ 4 ]; } diff --git a/network_common.h b/network_common.h index b3abade..7b6f81d 100644 --- a/network_common.h +++ b/network_common.h @@ -29,4 +29,14 @@ static u32 network_msgstring( const char *src, return vg_strncpy( src, buf, string_len, k_strncpy_always_add_null ); } +static u32 network_pair_index( u32 _a, u32 _b ){ + const u32 N = NETWORK_MAX_PLAYERS; + assert( (_a != _b) && (_aroot_co ); +} + +static void player__basic_info_pose( void *_animator, player_pose *pose ){ + struct player_basic_info_animator *animator = _animator; + v3_copy( animator->root_co, pose->root_co ); + q_identity( pose->root_q ); + pose->type = k_player_pose_type_fk_2; + pose->board.lean = 0.0f; + + for( int i=0; ikeyframes[i].co); + q_identity(pose->keyframes[i].q); + v3_fill(pose->keyframes[i].s,1.0f); + } +} diff --git a/player_basic_info.h b/player_basic_info.h new file mode 100644 index 0000000..12f46c9 --- /dev/null +++ b/player_basic_info.h @@ -0,0 +1,25 @@ +#ifndef PLAYER_BASIC_INFO_H +#define PLAYER_BASIC_INFO_H + +#include "player.h" +#include "player_api.h" + +struct player_basic_info { + struct player_basic_info_animator { + v3f root_co; + } + animator; +} +static player_basic_info; +static void player__basic_info_animator_exchange(bitpack_ctx *ctx, void *data); +static void player__basic_info_pose( void *_animator, player_pose *pose ); + +struct player_subsystem_interface static player_subsystem_basic_info = { + .pose = player__basic_info_pose, + .network_animator_exchange = player__basic_info_animator_exchange, + .animator_data = &player_basic_info.animator, + .animator_size = sizeof(player_basic_info.animator), + .name = "Basic Info" +}; + +#endif /* PLAYER_BASIC_INFO_H */ diff --git a/player_remote.c b/player_remote.c index d9f0065..82bc3da 100644 --- a/player_remote.c +++ b/player_remote.c @@ -5,6 +5,7 @@ #include "addon.h" #include "font.h" #include "gui.h" +#include "ent_miniworld.h" static i32 k_show_own_name = 0; @@ -175,7 +176,24 @@ static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){ .buffer_len = datasize, .bytes = 0, }; - + + /* animation + * -------------------------------------------------------------*/ + + dest->timestamp = frame->timestamp; + dest->boundary_hash = frame->boundary_hash; + + struct network_player *player = &netplayers.list[ frame->client ]; + struct player_subsystem_interface *sys = + player_subsystems[ frame->subsystem ]; + + if( sys->network_animator_exchange ){ + memset( &dest->data, 0, sys->animator_size ); + sys->network_animator_exchange( &ctx, &dest->data ); + } + else { + bitpack_bytes( &ctx, sys->animator_size, sys->animator_data ); + } /* sfx * -------------------------------------------------------------*/ @@ -209,24 +227,6 @@ static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){ dst->subframe = remaining; } } - - /* animation - * -------------------------------------------------------------*/ - - dest->timestamp = frame->timestamp; - dest->boundary_hash = frame->boundary_hash; - - struct network_player *player = &netplayers.list[ frame->client ]; - struct player_subsystem_interface *sys = - player_subsystems[ frame->subsystem ]; - - if( sys->network_animator_exchange ){ - memset( &dest->data, 0, sys->animator_size ); - sys->network_animator_exchange( &ctx, &dest->data ); - } - else { - bitpack_bytes( &ctx, sys->animator_size, sys->animator_data ); - } player->subsystem = frame->subsystem; player->down_bytes += msg->m_cbSize; @@ -314,13 +314,6 @@ static void remote_player_send_playerframe(void){ .bytes = 0 }; - /* sfx - * ---------------------------------------------*/ - - frame->sound_effects = localplayer.sfx_buffer_count; - for( u32 i=0; ianimator_size, sys->animator_data ); + /* sfx + * ---------------------------------------------*/ + + frame->sound_effects = localplayer.sfx_buffer_count; + for( u32 i=0; iactive_world != world ){ + if( !player->active_world ) continue; + + /* their in our active subworld */ + if( player->active_world != world ){ + m4x3_mulv( global_miniworld.mmdl, co, co ); + co[1] -= 2.0f; /* HACK lol */ } f32 d2 = v3_dist2( co, localplayer.rb.co ); @@ -878,9 +883,7 @@ static void remote_players_imgui_world( world_instance *world, m4x4f pv, player->opacity = vg_lerpf( player->opacity, opacity, vg.time_frame_delta * 2.0f ); - remote_player_world_gui( - pv, netplayers.final_mtx[localplayer.skeleton.bone_count*i][3], - player ); + remote_player_world_gui( pv, co, player ); vg_ui.colour[3] = player->opacity; ui_flush( k_ui_shader_colour ); diff --git a/player_remote.h b/player_remote.h index d29ffa3..5ba0105 100644 --- a/player_remote.h +++ b/player_remote.h @@ -45,9 +45,12 @@ struct { u16 boundary_hash; union interp_animdata { - struct player_skate_animator _skate; - struct player_walk_animator _walk; - struct player_dead_animator _dead; + /* these aren't accessed directly, just used to take the + * max(sizeof) all systems */ + struct player_skate_animator __skate; + struct player_walk_animator __walk; + struct player_dead_animator __dead; + struct player_basic_info_animator __basic; } data; } diff --git a/shaders/scene_override.h b/shaders/scene_override.h index 602cda4..0d7515b 100644 --- a/shaders/scene_override.h +++ b/shaders/scene_override.h @@ -479,7 +479,11 @@ static struct vg_shader _shader_scene_override = { " float dither = fract( vDither.g / 71.0 ) - 0.5;\n" "\n" " float dcam = (-8.0+distance( aCo, uCamera ))/4.0;\n" -" if( min(aCo.y*0.5 + dither, dcam + dither) < 0.51 ) discard;\n" +" float dy0 = aCo.y - uMapInfo.x;\n" +" float dy1 = uMapInfo.y - aCo.y;\n" +"\n" +" if( min(min(dy0,dy1)*0.5, dcam) + dither < 0.51 ) \n" +" discard;\n" "\n" " compute_motion_vectors();\n" "\n" -- 2.25.1