static i32 k_show_own_name = 0;
-static void player_remote_clear( struct network_player *player )
+static void player_remote_clear( u32 player_index )
{
+ struct network_player *player = &netplayers.list[ player_index ];
addon_cache_unwatch( k_addon_type_player, player->playermodel_view_slot );
addon_cache_unwatch( k_addon_type_board, player->board_view_slot );
+ bool wanted_to_spec_maybe = player->flag_spectate;
+
memset( player, 0, sizeof(*player) );
- strcpy( player->username, "unknown" );
+ strcpy( player->username, "disconnected" );
player->subsystem = k_player_subsystem_invalid;
+ player->flag_spectate = wanted_to_spec_maybe;
+
+ if( skaterift.activity == k_skaterift_spectate )
+ {
+ if( player_index == netplayers.spectate_index )
+ {
+ skaterift.activity = k_skaterift_default;
+ }
+ }
}
static void relink_remote_player_worlds( u32 client_id )
addon_reg *current_world_reg = addon_details( _world.main.addon_id );
if( addon_alias_eq( &q, ¤t_world_reg->alias ) )
player->same_world = 1;
+ else
+ player->same_world = 0;
}
/*
*/
void relink_all_remote_player_worlds(void)
{
+ if( !network_connected() )
+ return;
+
for( u32 i=0; i<VG_ARRAY_LEN(netplayers.list); i++ )
{
struct network_player *player = &netplayers.list[i];
remote->isblocked = SteamAPI_ISteamFriends_HasFriend( hSteamFriends, remote->steamid, k_EFriendFlagBlocked );
}
-void decode_playerframe( netmsg_playerframe *frame, u32 data_length, struct interp_frame *dest, v2f out_angles,
+void decode_playerframe( netmsg_playerframe *frame, u32 data_length, struct interp_frame *dest,
struct net_sfx *sfx_buffer, u32 *inout_sfx_buffer_len )
{
dest->active = 1;
};
/* camera */
- v2f angles = {0,0};
- bitpack_qv2f( &ctx, 8, 0.0f, 1.0f, angles );
- if( out_angles )
- v2_muls( angles, VG_TAUf, out_angles );
+ dest->angles[2] = 0.0f;
+ bitpack_qv2f( &ctx, 8, 0.0f, 1.0f, dest->angles );
+ v2_muls( dest->angles, VG_TAUf, dest->angles );
/* animation
* -------------------------------------------------------------*/
{
netmsg_blank *tmp = msg->m_pData;
- if( tmp->inetmsg_id == k_inetmsg_playerjoin ){
+ if( tmp->inetmsg_id == k_inetmsg_playerjoin )
+ {
netmsg_playerjoin *playerjoin = msg->m_pData;
- if( !packet_minsize( msg, sizeof(*playerjoin) )) return;
+ if( !packet_minsize( msg, sizeof(*playerjoin) ))
+ return;
- if( playerjoin->index < VG_ARRAY_LEN(netplayers.list) ){
+ if( playerjoin->index < VG_ARRAY_LEN(netplayers.list) )
+ {
struct network_player *player = &netplayers.list[ playerjoin->index ];
- player_remote_clear( player );
+ player_remote_clear( playerjoin->index );
player->active = 1;
player->steamid = playerjoin->steamid;
player_remote_update_friendflags( player );
struct interp_buffer *buf = &netplayers.interp_data[playerjoin->index];
buf->t = -99999999.9;
- for( u32 i=0; i<VG_ARRAY_LEN(buf->frames); i ++ ){
+ for( u32 i=0; i<VG_ARRAY_LEN(buf->frames); i ++ )
buf->frames[i].active = 0;
- }
-
- vg_info( "#%u joined friend: %d, blocked: %d\n",
- playerjoin->index, player->isfriend, player->isblocked );
+ vg_info( "#%u joined friend: %d, blocked: %d\n", playerjoin->index, player->isfriend, player->isblocked );
}
- else {
+ else
vg_error( "inetmsg_playerjoin: player index out of range\n" );
- }
}
- else if( tmp->inetmsg_id == k_inetmsg_playerleave ){
+ else if( tmp->inetmsg_id == k_inetmsg_playerleave )
+ {
netmsg_playerleave *playerleave = msg->m_pData;
- if( !packet_minsize( msg, sizeof(*playerleave) )) return;
+ if( !packet_minsize( msg, sizeof(*playerleave) ))
+ return;
- if( playerleave->index < VG_ARRAY_LEN(netplayers.list) ){
+ if( playerleave->index < VG_ARRAY_LEN(netplayers.list) )
+ {
struct network_player *player = &netplayers.list[ playerleave->index ];
- player_remote_clear( player );
+ player_remote_clear( playerleave->index );
player->active = 0;
vg_info( "player leave (%d)\n", playerleave->index );
}
- else {
+ else
vg_error( "inetmsg_playerleave: player index out of range\n" );
- }
}
- else if( tmp->inetmsg_id == k_inetmsg_playerusername ){
+ else if( tmp->inetmsg_id == k_inetmsg_playerusername )
+ {
netmsg_playerusername *update = msg->m_pData;
- if( !packet_minsize( msg, sizeof(*update) )) return;
+ if( !packet_minsize( msg, sizeof(*update) ))
+ return;
- if( update->index < VG_ARRAY_LEN(netplayers.list) ){
+ if( update->index < VG_ARRAY_LEN(netplayers.list) )
+ {
struct network_player *player = &netplayers.list[ update->index ];
-
- network_msgstring( update->name, msg->m_cbSize, sizeof(*update),
- player->username, sizeof(player->username) );
-
- vg_info( "#%u changed username to: %s\n",
- update->index, player->username );
+ network_msgstring( update->name, msg->m_cbSize, sizeof(*update), player->username, sizeof(player->username) );
+ vg_info( "#%u changed username to: %s\n", update->index, player->username );
}
- else {
+ else
vg_error( "inetmsg_playerleave: player index out of range\n" );
- }
}
else if( tmp->inetmsg_id == k_inetmsg_playerframe )
{
}
}
+ // FIXME: Duplicated code?
dest->active = 1;
dest->subsystem = frame->subsystem;
dest->flags = frame->flags;
};
/* camera */
- v2f _null_v2f = {0,0};
- bitpack_qv2f( &ctx, 8, 0.0f, 1.0f, _null_v2f );
+ dest->angles[2] = 0.0f;
+ bitpack_qv2f( &ctx, 8, 0.0f, 1.0f, dest->angles );
+ v2_muls( dest->angles, VG_TAUf, dest->angles );
/* animation
* -------------------------------------------------------------*/
memset( &dest->data_glider, 0, sizeof(struct remote_glider_animator) );
if( dest->flags & (NETMSG_PLAYERFRAME_HAVE_GLIDER|NETMSG_PLAYERFRAME_GLIDER_ORPHAN) )
- {
player_glide_remote_animator_exchange( &ctx, &dest->data_glider );
- }
// FIXME: these frames might be out of order! Not good to set this
player->subsystem = frame->subsystem;
(const char *[]){[k_netmsg_playeritem_board]="board",
[k_netmsg_playeritem_player]="player",
[k_netmsg_playeritem_world0]="world0",
- [k_netmsg_playeritem_world1]="world1"
}[item->type_index], item->uid );
struct network_player *player = &netplayers.list[ item->client ];
addon_cache_unwatch( k_addon_type_player, player->playermodel_view_slot );
player->playermodel_view_slot = addon_cache_create_viewer_from_uid( k_addon_type_player, uid );
}
- else if( (item->type_index == k_netmsg_playeritem_world0) ||
- (item->type_index == k_netmsg_playeritem_world1) )
+ else if( item->type_index == k_netmsg_playeritem_world0 )
{
relink_remote_player_worlds( item->client );
}
/*
* write the remote players final_mtx
*/
-void pose_remote_player( f64 pose_time, struct interp_frame *f0, struct interp_frame *f1, struct player_board *board,
+void pose_remote_player( f64 pose_time, struct interp_frame *i0, struct interp_frame *i1, struct player_board *board,
m4x3f *out_final_mtx, v3f *out_glider_mtx,
struct player_board_pose *out_board_pose,
struct player_effects_data *out_effects,
- bool *out_render_glider )
+ bool *out_render_glider, vg_camera *out_camera )
{
struct skeleton *sk = &localplayer.skeleton;
- struct player_subsystem_interface *sys0 = player_subsystems[f0->subsystem],
+ struct player_subsystem_interface *sys0 = player_subsystems[i0->subsystem],
*sys1 = NULL;
player_pose pose0, pose1, posed;
- sys0->pose( &f0->data, &pose0 );
+ sys0->pose( &i0->data, &pose0 );
f32 t = 0.0f;
- if( f1 )
+ if( i1 )
{
- t = (pose_time - f0->timestamp) / (f1->timestamp - f0->timestamp);
+ t = (pose_time - i0->timestamp) / (i1->timestamp - i0->timestamp);
t = vg_clampf( t, 0.0f, 1.0f );
- sys1 = player_subsystems[f1->subsystem];
- sys1->pose( &f1->data, &pose1 );
+ sys1 = player_subsystems[i1->subsystem];
+ sys1->pose( &i1->data, &pose1 );
- u16 bounds = f0->boundary_hash^f1->boundary_hash;
+ u16 bounds = i0->boundary_hash^i1->boundary_hash;
if( bounds & NETMSG_BOUNDARY_BIT )
t = 1.0f;
if( bounds & NETMSG_GATE_BOUNDARY_BIT )
if( t < 0.5f )
{
if( sys0->effects )
- sys0->effects( &f0->data, out_final_mtx, board, out_effects );
+ sys0->effects( &i0->data, out_final_mtx, board, out_effects );
}
else
{
if( sys1->effects )
- sys1->effects( &f1->data, out_final_mtx, board, out_effects );
+ sys1->effects( &i1->data, out_final_mtx, board, out_effects );
}
memcpy( out_board_pose, &posed.board, sizeof(struct player_board_pose) );
}
effect_blink_apply( &out_effects->blink, &pose0, vg.time_delta );
apply_full_skeleton_pose( sk, &pose0, out_final_mtx );
if( sys0->effects )
- sys0->effects( &f0->data, out_final_mtx, board, out_effects );
+ sys0->effects( &i0->data, out_final_mtx, board, out_effects );
memcpy( out_board_pose, &pose0.board, sizeof(struct player_board_pose) );
}
- if( f0->flags & (NETMSG_PLAYERFRAME_HAVE_GLIDER|NETMSG_PLAYERFRAME_GLIDER_ORPHAN) )
+ if( i0->flags & (NETMSG_PLAYERFRAME_HAVE_GLIDER|NETMSG_PLAYERFRAME_GLIDER_ORPHAN) )
{
*out_render_glider = 1;
v3f co;
v4f q;
f32 s;
- if( f1 )
+ if( i1 )
{
- v3_lerp( f0->data_glider.root_co,f1->data_glider.root_co, t, co );
- q_nlerp( f0->data_glider.root_q, f1->data_glider.root_q, t, q );
- s = vg_lerpf( f0->data_glider.s, f1->data_glider.s, t );
+ v3_lerp( i0->data_glider.root_co,i1->data_glider.root_co, t, co );
+ q_nlerp( i0->data_glider.root_q, i1->data_glider.root_q, t, q );
+ s = vg_lerpf( i0->data_glider.s, i1->data_glider.s, t );
}
else
{
- v3_copy( f0->data_glider.root_co, co );
- v4_copy( f0->data_glider.root_q, q );
- s = f0->data_glider.s;
+ v3_copy( i0->data_glider.root_co, co );
+ v4_copy( i0->data_glider.root_q, q );
+ s = i0->data_glider.s;
}
q_m3x3( q, out_glider_mtx );
}
else
*out_render_glider = 0;
+
+ if( out_camera )
+ {
+ struct player_cam_controller cc = { .camera_mode = k_cam_thirdperson, .camera_type_blend = 0 };
+ v3f angles;
+ compute_cam_controller_offsets( i0->subsystem, &cc );
+
+ if( i1 ) vg_camera_lerp_angles( i0->angles, i1->angles, t, angles );
+ else v3_copy( i0->angles, angles );
+
+ /* position */
+ v3f fpv_pos, fpv_offset;
+ m4x3_mulv( out_final_mtx[ localplayer.id_head-1 ], cc.fpv_viewpoint, fpv_pos );
+ m3x3_mulv( out_final_mtx[0], cc.fpv_offset, fpv_offset ); // NOTE: [0] could be wrong (was rb.to_world)
+ v3_add( fpv_offset, fpv_pos, fpv_pos );
+
+ /* origin */
+ v3f tpv_origin, tpv_offset, tpv_pos;
+ m4x3_mulv( out_final_mtx[0], cc.tpv_offset, tpv_origin );
+
+ /* offset */
+ v3f camera_follow_dir =
+ { -sinf( angles[0] ) * cosf( angles[1] ),
+ sinf( angles[1] ),
+ cosf( angles[0] ) * cosf( angles[1] ) };
+ v3_muls( camera_follow_dir, 1.8f, tpv_offset );
+ //v3_muladds( tpv_offset, cc.cam_velocity_smooth, -0.025f, tpv_offset );
+
+ v3_add( tpv_origin, tpv_offset, tpv_pos );
+ v3_lerp( tpv_pos, fpv_pos, cc.camera_type_blend, out_camera->pos );
+ v3_copy( angles, out_camera->angles );
+
+ f32 fov_skate = vg_lerpf( 97.0f, 135.0f, k_fov ),
+ fov_walk = vg_lerpf( 90.0f, 110.0f, k_fov );
+ out_camera->fov = vg_lerpf( fov_walk, fov_skate, cc.camera_type_blend );
+ }
}
/*
}
}
+ vg_camera *out_camera = NULL;
+ if( skaterift.activity == k_skaterift_spectate )
+ {
+ if( index == netplayers.spectate_index )
+ out_camera = &netplayers.spectate_camera;
+ }
+
struct network_player *player = &netplayers.list[ index ];
struct skeleton *sk = &localplayer.skeleton;
m4x3f *final_mtx = &netplayers.final_mtx[ sk->bone_count*index ];
if( minframe && maxframe )
{
- pose_remote_player( buf->t, minframe, maxframe, board, final_mtx, glider_mtx, board_pose, effects, glider_flag );
+ pose_remote_player( buf->t, minframe, maxframe, board, final_mtx, glider_mtx, board_pose, effects, glider_flag,
+ out_camera );
buf->t += vg.time_frame_delta;
}
else
buf->t = abs_max_time - 0.25;
if( abs_max_frame )
- pose_remote_player( buf->t, abs_max_frame, NULL, board, final_mtx, glider_mtx, board_pose, effects, glider_flag );
+ pose_remote_player( buf->t, abs_max_frame, NULL, board, final_mtx, glider_mtx, board_pose, effects,
+ glider_flag, out_camera );
else
return;
}
}
else
{
- if( (skaterift.activity == k_skaterift_default) &&
- button_down( k_srbind_chat ) ){
+ if( (skaterift.activity == k_skaterift_default) && button_down( k_srbind_chat ) )
+ {
netplayers.chatting = 1;
netplayers.chat_buffer[0] = '\0';
srinput.state = k_input_state_pause;
{
ui_info( ctx, rect, "#-1: localplayer" );
- snprintf( buf, 512, "U%.3f/D%.3fkbs",
- netplayers.up_kbs, netplayers.down_kbs );
+ snprintf( buf, 512, "U%.3f/D%.3fkbs", netplayers.up_kbs, netplayers.down_kbs );
ui_info( ctx, rect, buf );
for( u32 i=0; i<VG_ARRAY_LEN(netplayers.list); i++ )
const char *sysname = "invalid";
if( player->subsystem < k_player_subsystem_max )
- {
sysname = player_subsystems[ player->subsystem ]->name;
- }
- snprintf( buf, 512, "#%u: %s [%s] D%.1fkbs",
- i, player->username, sysname, player->down_kbs );
+
+ snprintf( buf, 512, "#%u: %s [%s] D%.1fkbs", i, player->username, sysname, player->down_kbs );
ui_info( ctx, rect, buf );
}
}
netplayers.sfx_queue[i].system = k_player_subsystem_invalid;
}
+void _network_get_spectate_cam( vg_camera *cam )
+{
+ if( !network_connected() )
+ return;
+
+ struct network_player *player = &netplayers.list[ netplayers.spectate_index ];
+ if( !player->active || !player->same_world )
+ {
+ gui_helper_reset( k_gui_helper_mode_clear );
+ localplayer.immobile = 0;
+ skaterift.activity = k_skaterift_default;
+ return;
+ }
+
+ vg_camera_copy( &netplayers.spectate_camera, cam );
+}
*i1 = &_remote_replay.interp1;
struct player_cam_controller cc = { .camera_mode = k_cam_thirdperson, .camera_type_blend = 0 };
compute_cam_controller_offsets( i0->subsystem, &cc );
- pose_remote_player( frame_time, i0, i1, board, final_mtx, glider_mtx, board_pose, effects, glider_flag );
-
- f32 t = (frame_time - i0->timestamp) / (i1->timestamp - i0->timestamp);
- t = vg_clampf( t, 0.0f, 1.0f );
- u16 bounds = i0->boundary_hash^i1->boundary_hash;
- if( bounds & NETMSG_BOUNDARY_BIT )
- t = 1.0f;
- if( bounds & NETMSG_GATE_BOUNDARY_BIT )
- t = 1.0f;
-
- v3f angles;
- angles[0] = vg_alerpf( _remote_replay.cam0[0], _remote_replay.cam1[0], t );
- angles[1] = vg_lerpf( _remote_replay.cam0[1], _remote_replay.cam1[1], t );
- angles[2] = 0.0f;
-
- /* position */
- v3f fpv_pos, fpv_offset;
- m4x3_mulv( _replay2.final_mtx[ localplayer.id_head-1 ], cc.fpv_viewpoint, fpv_pos );
- m3x3_mulv( _replay2.final_mtx[0], cc.fpv_offset, fpv_offset ); // NOTE: [0] could be wrong (was rb.to_world)
- v3_add( fpv_offset, fpv_pos, fpv_pos );
-
- /* origin */
- v3f tpv_origin, tpv_offset, tpv_pos;
- m4x3_mulv( _replay2.final_mtx[0], cc.tpv_offset, tpv_origin );
-
- /* offset */
- v3f camera_follow_dir =
- { -sinf( angles[0] ) * cosf( angles[1] ),
- sinf( angles[1] ),
- cosf( angles[0] ) * cosf( angles[1] ) };
- v3_muls( camera_follow_dir, 1.8f, tpv_offset );
- //v3_muladds( tpv_offset, cc.cam_velocity_smooth, -0.025f, tpv_offset );
-
- v3_add( tpv_origin, tpv_offset, tpv_pos );
- v3_lerp( tpv_pos, fpv_pos, cc.camera_type_blend, _replay2.playback_cam.pos );
- v2_copy( angles, _replay2.playback_cam.angles );
-
- f32 fov_skate = vg_lerpf( 97.0f, 135.0f, k_fov ),
- fov_walk = vg_lerpf( 90.0f, 110.0f, k_fov );
- _replay2.playback_cam.fov = vg_lerpf( fov_walk, fov_skate, cc.camera_type_blend );
+ pose_remote_player( frame_time, i0, i1, board, final_mtx, glider_mtx, board_pose, effects, glider_flag,
+ &_replay2.playback_cam );
}
else
{
if( _replay2.type == k_replay_type_network )
{
u32 s0 = current_frame->net.frame_size - sizeof(netmsg_playerframe);
- decode_playerframe( ¤t_frame->net.frame, s0, &_remote_replay.interp0, _remote_replay.cam0, NULL, NULL );
+ decode_playerframe( ¤t_frame->net.frame, s0, &_remote_replay.interp0, NULL, NULL );
if( next_frame )
{
u32 len = VG_ARRAY_LEN( _replay2.sfx_queue );
replay2_frame *next_frame = vg_queue_data( buffer, next_offset );
u32 s1 = next_frame->net.frame_size - sizeof(netmsg_playerframe);
- decode_playerframe( &next_frame->net.frame, s1, &_remote_replay.interp1, _remote_replay.cam1,
- _replay2.sfx_queue, &len );
+ decode_playerframe( &next_frame->net.frame, s1, &_remote_replay.interp1, _replay2.sfx_queue, &len );
_replay2.sfx_queue_length = len;
}
else