From ce0205fd929e5fb1446f8c52fcab344884d82569 Mon Sep 17 00:00:00 2001 From: hgn Date: Wed, 4 Oct 2023 09:38:31 +0100 Subject: [PATCH] network oneshots --- network.c | 3 +- network_common.h | 2 ++ network_msg.h | 2 +- player.c | 51 +++++++++++++++++++++++++++++ player.h | 22 +++++++++++-- player_dead.c | 9 +++++ player_dead.h | 2 ++ player_remote.c | 85 +++++++++++++++++++++++++++++++----------------- player_remote.h | 7 +++- player_skate.c | 71 ++++++++++++++++++++++++++++------------ player_skate.h | 14 ++++++-- player_walk.c | 2 +- 12 files changed, 211 insertions(+), 59 deletions(-) diff --git a/network.c b/network.c index 3878ef2..838653c 100644 --- a/network.c +++ b/network.c @@ -379,9 +379,10 @@ static void network_update(void){ poll_remote_connection(); f64 frame_delta = vg.time_real - network_client.last_frame; - if( frame_delta > 0.1 ){ + if( frame_delta > NETWORK_FRAMERATE ){ network_client.last_frame = vg.time_real; remote_player_send_playerframe(); + player__clear_sfx_buffer(); } remote_player_debug_update(); diff --git a/network_common.h b/network_common.h index 988afb2..ad5fb56 100644 --- a/network_common.h +++ b/network_common.h @@ -6,6 +6,8 @@ #define NETWORK_USERNAME_MAX 32 #define NETWORK_MAX_PLAYERS 20 +#define NETWORK_FRAMERATE 0.1 +#define NETWORK_BUFFERFRAMES 6 #include "addon_types.h" diff --git a/network_msg.h b/network_msg.h index ba1fefe..c28f5b3 100644 --- a/network_msg.h +++ b/network_msg.h @@ -87,7 +87,7 @@ struct netmsg_playerframe{ f64 timestamp; u8 client, subsystem, - instance_id; + instance_id, sound_effects; u16 boundary_hash; /* used for animating correctly through gates, teleport.. msb is a flip flop for teleporting second msb is flip flop for gate diff --git a/player.c b/player.c index 78449ad..9938de6 100644 --- a/player.c +++ b/player.c @@ -9,6 +9,7 @@ #include "audio.h" #include "player_replay.h" #include "network.h" +#include "network_common.h" static int localplayer_cmd_respawn( int argc, const char *argv[] ){ ent_spawn *rp = NULL, *r; @@ -268,6 +269,56 @@ static void player__begin_holdout(void){ localplayer.holdout_time = 1.0f; } +static void net_sfx_exchange( bitpack_ctx *ctx, struct net_sfx *sfx ){ + bitpack_bytes( ctx, 1, &sfx->system ); + bitpack_bytes( ctx, 1, &sfx->priority ); + bitpack_bytes( ctx, 1, &sfx->id ); + bitpack_qf32( ctx, 8, 0.0f, 1.0f, &sfx->subframe ); + bitpack_qf32( ctx, 8, 0.0f, 1.0f, &sfx->volume ); + bitpack_qv3f( ctx, 16, -1024.0f, 1024.0f, sfx->location ); +} + +static void net_sfx_play( struct net_sfx *sfx ){ + if( sfx->system < k_player_subsystem_max ){ + struct player_subsystem_interface *sys = player_subsystems[sfx->system]; + if( sys->sfx_oneshot ){ + sys->sfx_oneshot( sfx->id, sfx->location, sfx->volume ); + } + } +}; + +static void player__networked_sfx( u8 system, u8 priority, u8 id, + v3f pos, f32 volume ){ + struct net_sfx null, *sfx = &null; + + if( localplayer.sfx_buffer_count < vg_list_size(localplayer.sfx_buffer) ) + sfx = &localplayer.sfx_buffer[ localplayer.sfx_buffer_count ++ ]; + else { + for( u32 i=0; ipriority < priority ){ + sfx = a; + break; + } + } + } + + sfx->id = id; + sfx->priority = priority; + sfx->volume = volume; + v3_copy( pos, sfx->location ); + sfx->system = system; + + f32 t = (vg.time_real - network_client.last_frame) / NETWORK_FRAMERATE; + sfx->subframe = vg_clampf( t, 0.0f, 1.0f ); + + net_sfx_play( sfx ); +} + +static void player__clear_sfx_buffer(void){ + localplayer.sfx_buffer_count = 0; +} + /* implementation */ #include "player_common.c" #include "player_walk.c" diff --git a/player.h b/player.h index bb87028..6ee3112 100644 --- a/player.h +++ b/player.h @@ -45,6 +45,7 @@ struct player_subsystem_interface{ void(*pose)( void *animator, player_pose *pose ); void(*post_animate)(void); void(*network_animator_exchange)( bitpack_ctx *ctx, void *data ); + void(*sfx_oneshot)( u8 id, v3f pos, f32 volume ); void *animator_data; u32 animator_size; @@ -94,10 +95,21 @@ struct { v3f cam_land_punch, cam_land_punch_v; ent_gate *gate_waiting; - u16 boundary_hash; - int immobile; + /* + * Network + * -------------------------------------------------- + */ + u16 boundary_hash; + struct net_sfx { + u8 system, priority, id; + f32 subframe, volume; + v3f location; + } + sfx_buffer[4]; + u32 sfx_buffer_count; + /* * Animation * -------------------------------------------------- @@ -166,4 +178,10 @@ static void player__begin_holdout(void); static int localplayer_cmd_respawn( int argc, const char *argv[] ); static void player_apply_transport_to_cam( m4x3f transport ); +static void player__clear_sfx_buffer(void); +static void player__networked_sfx( u8 system, u8 priority, u8 id, + v3f pos, f32 volume ); +static void net_sfx_exchange( bitpack_ctx *ctx, struct net_sfx *sfx ); +static void net_sfx_play( struct net_sfx *sfx ); + #endif /* PLAYER_H */ diff --git a/player_dead.c b/player_dead.c index 957f38d..8c558ee 100644 --- a/player_dead.c +++ b/player_dead.c @@ -136,4 +136,13 @@ static void player__dead_transition(void){ v3_copy( part->obj.rb.w, player_dead.w_lpf ); } +static void player__dead_animator_exchange( bitpack_ctx *ctx, void *data ){ + struct player_dead_animator *animator = data; + + for( u32 i=0; isk.bone_count; i ++ ){ + bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->transforms[i].co ); + bitpack_qquat( ctx, animator->transforms[i].q ); + } +} + #endif /* PLAYER_DEAD_C */ diff --git a/player_dead.h b/player_dead.h index 0c1de41..19d6e59 100644 --- a/player_dead.h +++ b/player_dead.h @@ -25,6 +25,7 @@ static void player__dead_pose (void *animator, player_pose *pose); static void player__dead_post_animate(void); static void player__dead_im_gui (void); static void player__dead_transition (void); +static void player__dead_animator_exchange( bitpack_ctx *ctx, void *data ); struct player_subsystem_interface static player_subsystem_dead = { .update = player__dead_update, @@ -36,6 +37,7 @@ struct player_subsystem_interface static player_subsystem_dead = { .animator_data = &player_dead.animator, .animator_size = sizeof(player_dead.animator), + .network_animator_exchange = player__dead_animator_exchange, .name = "Dead" }; diff --git a/player_remote.c b/player_remote.c index a818be1..3e78d50 100644 --- a/player_remote.c +++ b/player_remote.c @@ -151,29 +151,43 @@ static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){ } dest->active = 1; - dest->timestamp = frame->timestamp; dest->subsystem = frame->subsystem; dest->instance_id = frame->instance_id; + + bitpack_ctx ctx = { + .mode = k_bitpack_decompress, + .buffer = frame->animdata, + .buffer_len = datasize, + .bytes = 0, + }; + + + /* sfx + * -------------------------------------------------------------*/ + + for( u32 i=0; isound_effects; i ++ ){ + /* CHEATING for now */ + struct net_sfx sfx; + net_sfx_exchange( &ctx, &sfx ); + net_sfx_play( &sfx ); + } + + /* 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 ){ - bitpack_ctx ctx = { - .mode = k_bitpack_decompress, - .buffer = frame->animdata, - .buffer_len = datasize, - .bytes = 0, - }; - memset( &dest->data, 0, sys->animator_size ); sys->network_animator_exchange( &ctx, &dest->data ); } else { - memcpy( &dest->data, frame->animdata, datasize ); + bitpack_bytes( &ctx, sys->animator_size, sys->animator_data ); } player->subsystem = frame->subsystem; @@ -236,35 +250,46 @@ static void remote_player_send_playerframe(void){ struct player_subsystem_interface *sys = player_subsystems[sysid]; if( sys->animator_size ){ - u32 size = sizeof(netmsg_playerframe)+sys->animator_size; - netmsg_playerframe *frame = alloca(size); + u32 max_buf_size = sys->animator_size + sizeof(localplayer.sfx_buffer), + base_size = sizeof(struct netmsg_playerframe), + max_packet = base_size + max_buf_size; + + netmsg_playerframe *frame = alloca( max_packet ); frame->inetmsg_id = k_inetmsg_playerframe; frame->client = 0xff; frame->subsystem = localplayer.subsystem; - frame->timestamp = vg.time_real; - frame->boundary_hash = localplayer.boundary_hash; frame->instance_id = world_static.active_instance; - if( sys->network_animator_exchange ){ - bitpack_ctx ctx = { - .mode = k_bitpack_compress, - .buffer = frame->animdata, - .buffer_len = sys->animator_size, - .bytes = 0, - }; - + bitpack_ctx ctx = { + .mode = k_bitpack_compress, + .buffer = frame->animdata, + .buffer_len = max_buf_size, + .bytes = 0 + }; + + /* sfx + * ---------------------------------------------*/ + + frame->sound_effects = localplayer.sfx_buffer_count; + for( u32 i=0; itimestamp = vg.time_real; + frame->boundary_hash = localplayer.boundary_hash; + if( sys->network_animator_exchange ) sys->network_animator_exchange( &ctx, sys->animator_data ); - size = sizeof(netmsg_playerframe)+ctx.bytes; - } - else{ - memcpy( frame->animdata, sys->animator_data, sys->animator_size ); - } + else + bitpack_bytes( &ctx, sys->animator_size, sys->animator_data ); - netplayers.up_bytes += size; + u32 wire_size = base_size + ctx.bytes; + netplayers.up_bytes += wire_size; SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( hSteamNetworkingSockets, network_client.remote, - frame, size, + frame, wire_size, k_nSteamNetworkingSend_Unreliable, NULL ); } } @@ -336,7 +361,7 @@ static void remote_player_network_imgui( m4x4f pv ){ if( network_client.state == k_ESteamNetworkingConnectionState_Connected ){ ui_info( panel, "#-1: localplayer" ); - snprintf( buf, 512, "U%.1f/D%.1fkbs", + snprintf( buf, 512, "U%.3f/D%.3fkbs", netplayers.up_kbs, netplayers.down_kbs ); ui_info( panel, buf ); diff --git a/player_remote.h b/player_remote.h index afef269..a35e22c 100644 --- a/player_remote.h +++ b/player_remote.h @@ -5,6 +5,8 @@ #include "network.h" #include "network_common.h" +#define NETWORK_SFX_QUEUE_LENGTH 12 + struct { struct network_player { int active; @@ -41,12 +43,15 @@ struct { } data; } - frames[6]; + frames[ NETWORK_BUFFERFRAMES ]; f64 t; } interp_data[ NETWORK_MAX_PLAYERS ]; + struct net_sfx sfx_queue[ NETWORK_SFX_QUEUE_LENGTH ]; + u8 sfx_availible[ NETWORK_SFX_QUEUE_LENGTH ]; + m4x3f *final_mtx; struct player_board_pose board_poses[ NETWORK_MAX_PLAYERS ]; diff --git a/player_skate.c b/player_skate.c index 4bad1de..b39b016 100644 --- a/player_skate.c +++ b/player_skate.c @@ -974,11 +974,9 @@ static void skate_apply_jump_model(void){ v3_muladds( localplayer.rb.v, jumpdir, force, localplayer.rb.v ); state->jump_charge = 0.0f; state->jump_time = vg.time; - - audio_lock(); - audio_oneshot_3d( &audio_jumps[vg_randu32()%2], - localplayer.rb.co,40.0f,1.0f); - audio_unlock(); + player__networked_sfx( k_player_subsystem_skate, 32, + k_player_skate_soundeffect_jump, + localplayer.rb.co, 1.0f ); } } @@ -2039,7 +2037,11 @@ static void player__skate_update(void){ if( world->water.enabled ){ if( localplayer.rb.co[1]+0.25f < world->water.height ){ - audio_oneshot_3d( &audio_splash, localplayer.rb.co, 40.0f, 1.0f ); +#if 0 + player__networked_sfx( k_player_subsystem_walk, 32, + k_player_walk_soundeffect_splash, + localplayer.rb.co, 1.0f ); +#endif player__skate_kill_audio(); player__dead_transition(); return; @@ -2160,15 +2162,15 @@ static void player__skate_update(void){ } if( (prev_contacts[0]+prev_contacts[1] == 1) && (contact_count == 2) ){ - audio_lock(); for( int i=0; i<2; i++ ){ if( !prev_contacts[i] ){ v3f co; m4x3_mulv( localplayer.rb.to_world, wheels[i].pos, co ); - audio_oneshot_3d( &audio_taps[vg_randu32()%4], co, 40.0f, 0.75f ); + player__networked_sfx( k_player_subsystem_skate, 32, + k_player_skate_soundeffect_tap, + localplayer.rb.co, 0.75f ); } } - audio_unlock(); } if( contact_count ){ @@ -2558,28 +2560,30 @@ begin_collision:; if( stick_frames > 5 ) stick_frames = 5; if( stick_frames == 4 ){ - audio_lock(); - if( state->activity == k_skate_activity_ground ){ if( (fabsf(state->slip) > 0.75f) ){ - audio_oneshot_3d( &audio_lands[vg_randu32()%2+3], localplayer.rb.co, - 40.0f, 1.0f ); + player__networked_sfx( k_player_subsystem_skate, 128, + k_player_skate_soundeffect_land_bad, + localplayer.rb.co, 0.6f ); } else{ - audio_oneshot_3d( &audio_lands[vg_randu32()%3], localplayer.rb.co, - 40.0f, 1.0f ); + player__networked_sfx( k_player_subsystem_skate, 128, + k_player_skate_soundeffect_land_good, + localplayer.rb.co, 1.0f ); } } else if( player_skate.surface == k_surface_prop_metal ){ - audio_oneshot_3d( &audio_board[3], localplayer.rb.co, 40.0f, 1.0f ); + player__networked_sfx( k_player_subsystem_skate, 128, + k_player_skate_soundeffect_grind_metal, + localplayer.rb.co, 1.0f ); } else{ - audio_oneshot_3d( &audio_board[8], localplayer.rb.co, 40.0f, 1.0f ); + player__networked_sfx( k_player_subsystem_skate, 128, + k_player_skate_soundeffect_grind_wood, + localplayer.rb.co, 1.0f ); } - - audio_unlock(); } else if( stick_frames == 0 ){ - + /* TODO: EXIT SOUNDS */ } } @@ -3190,7 +3194,7 @@ static void player__skate_reset( ent_spawn *rp ){ static void player__skate_animator_exchange( bitpack_ctx *ctx, void *data ){ struct player_skate_animator *animator = data; - bitpack_qv3f( ctx, 16, -1024.0f, 1024.0f, animator->root_co ); + bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->root_co ); bitpack_qquat( ctx, animator->root_q ); bitpack_qv3f( ctx, 8, -1.0f, 1.0f, animator->offset ); @@ -3236,4 +3240,29 @@ static void player__skate_animator_exchange( bitpack_ctx *ctx, void *data ){ bitpack_qf32( ctx, 16, 0.0f, 120.0f, &animator->jump_time ); } +static void player__skate_sfx_oneshot( u8 id, v3f pos, f32 volume ){ + audio_lock(); + + if( id == k_player_skate_soundeffect_jump ){ + audio_oneshot_3d( &audio_jumps[vg_randu32()%2], pos, 40.0f, volume ); + } + else if( id == k_player_skate_soundeffect_tap ){ + audio_oneshot_3d( &audio_taps[vg_randu32()%4], pos, 40.0f, volume ); + } + else if( id == k_player_skate_soundeffect_land_good ){ + audio_oneshot_3d( &audio_lands[vg_randu32()%3], pos, 40.0f, volume ); + } + else if( id == k_player_skate_soundeffect_land_bad ){ + audio_oneshot_3d( &audio_lands[vg_randu32()%2+3], pos, 40.0f, volume ); + } + else if( id == k_player_skate_soundeffect_grind_metal ){ + audio_oneshot_3d( &audio_board[3], pos, 40.0f, volume ); + } + else if( id == k_player_skate_soundeffect_grind_wood ){ + audio_oneshot_3d( &audio_board[8], pos, 40.0f, volume ); + } + + audio_unlock(); +} + #endif /* PLAYER_SKATE_C */ diff --git a/player_skate.h b/player_skate.h index e5cc42f..0f5c70c 100644 --- a/player_skate.h +++ b/player_skate.h @@ -196,6 +196,15 @@ struct player_skate{ } static player_skate; +enum player_skate_soundeffect { + k_player_skate_soundeffect_jump, + k_player_skate_soundeffect_tap, + k_player_skate_soundeffect_land_good, + k_player_skate_soundeffect_land_bad, + k_player_skate_soundeffect_grind_metal, + k_player_skate_soundeffect_grind_wood, +}; + static float k_friction_lat = 12.0f, k_friction_resistance = 0.01f, @@ -248,8 +257,7 @@ static float k_grind_balance = -40.0f; -static void player__skate_register(void) -{ +static void player__skate_register(void){ VG_VAR_F32( k_grind_dampener, flags=VG_VAR_CHEAT ); VG_VAR_F32( k_grind_spring, flags=VG_VAR_CHEAT ); VG_VAR_F32( k_grind_aligment, flags=VG_VAR_CHEAT ); @@ -288,6 +296,7 @@ static void player__skate_pose (void *animator, player_pose *pose); static void player__skate_post_animate (void); static void player__skate_reset (ent_spawn *rp); static void player__skate_animator_exchange( bitpack_ctx *ctx, void *data ); +static void player__skate_sfx_oneshot ( u8 id, v3f pos, f32 volume ); static void player__skate_clear_mechanics(void); static void player__skate_reset_animator(void); @@ -305,6 +314,7 @@ struct player_subsystem_interface static player_subsystem_skate = { .pose = player__skate_pose, .post_animate = player__skate_post_animate, .network_animator_exchange = player__skate_animator_exchange, + .sfx_oneshot = player__skate_sfx_oneshot, .animator_data = &player_skate.animator, .animator_size = sizeof(player_skate.animator), diff --git a/player_walk.c b/player_walk.c index 4619c2e..8b493a8 100644 --- a/player_walk.c +++ b/player_walk.c @@ -965,7 +965,7 @@ static void player__walk_reset( ent_spawn *rp ){ static void player__walk_animator_exchange( bitpack_ctx *ctx, void *data ){ struct player_walk_animator *animator = data; - bitpack_qv3f( ctx, 16, -1024.0f, 1024.0f, animator->root_co ); + bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->root_co ); bitpack_qquat( ctx, animator->root_q ); bitpack_qf32( ctx, 8, 0.0f, 1.0f, &animator->fly ); bitpack_qf32( ctx, 8, 0.0f, 1.0f, &animator->run ); -- 2.25.1