From 074fa69f479724f9800849430bad5caf730b01ef Mon Sep 17 00:00:00 2001 From: hgn Date: Mon, 2 Oct 2023 17:05:34 +0100 Subject: [PATCH] network items, interp boundaries --- addon.c | 46 +++++++++++++++++++-- addon.h | 3 ++ ent_skateshop.c | 6 +-- gameserver.c | 58 ++++++++++++-------------- gameserver.h | 3 +- network.c | 77 +++++++++++++++++++++++------------ network.h | 2 +- network_msg.h | 71 +++++++++++++++++++------------- player.c | 16 ++++++-- player.h | 3 +- player_remote.c | 106 ++++++++++++++++++++++++++++++++++++++++++++---- player_remote.h | 13 +++++- player_skate.c | 9 ++-- player_walk.c | 8 ++-- world_gate.c | 21 ++++------ world_gate.h | 3 +- world_load.c | 2 + 17 files changed, 315 insertions(+), 132 deletions(-) diff --git a/addon.c b/addon.c index 09cb43b..fcec0b9 100644 --- a/addon.c +++ b/addon.c @@ -43,7 +43,11 @@ static u32 get_index_from_addon( enum addon_type type, addon_reg *a ){ } static u32 addon_match( addon_alias *alias ){ - u32 foldername_djb2 = vg_strdjb2( alias->foldername ); + if( alias->type == k_addon_type_none ) return 0xffffffff; + + u32 foldername_djb2 = 0; + if( !alias->workshop_id ) + foldername_djb2 = vg_strdjb2( alias->foldername ); u32 count = 0; for( u32 i=0; counttype]; i++ ){ @@ -83,6 +87,32 @@ static void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] ){ } } +/* + * equality check + */ +static int addon_alias_eq( addon_alias *a, addon_alias *b ){ + if( a->type == b->type ){ + if( a->workshop_id == b->workshop_id ){ + if( a->workshop_id ) + return 1; + else + return !strcmp( a->foldername, b->foldername ); + } + else + return 0; + } + else return 0; +} + +/* + * make alias represent NULL. + */ +static void invalidate_addon_alias( addon_alias *alias ){ + alias->type = k_addon_type_none; + alias->workshop_id = 0; + alias->foldername[0] = '\0'; +} + /* * parse uid to alias. returns 1 if successful */ @@ -95,8 +125,14 @@ static int addon_uid_to_alias( char uid[ADDON_UID_MAX], addon_alias *alias ){ * | * location */ - if( strlen(uid) < 13 ) return 0; - if( !((uid[0] == 's') && (uid[1] == 'r')) ) return 0; + if( strlen(uid) < 13 ){ + invalidate_addon_alias( alias ); + return 0; + } + if( !((uid[0] == 's') && (uid[1] == 'r')) ){ + invalidate_addon_alias( alias ); + return 0; + } char type[4]; memcpy( type, uid+2, 3 ); @@ -113,8 +149,10 @@ static int addon_uid_to_alias( char uid[ADDON_UID_MAX], addon_alias *alias ){ alias->workshop_id = 0; vg_strncpy( uid+12, alias->foldername, 64, k_strncpy_always_add_null ); } - else + else{ + invalidate_addon_alias( alias ); return 0; + } return 1; } diff --git a/addon.h b/addon.h index 384c9d7..f63566e 100644 --- a/addon.h +++ b/addon.h @@ -74,7 +74,10 @@ static int addon_get_content_folder( addon_reg *reg, vg_str *folder ); /* scanning routines */ static u32 addon_match( addon_alias *alias ); +static int addon_alias_eq( addon_alias *a, addon_alias *b ); static void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] ); +static int addon_uid_to_alias( char uid[ADDON_UID_MAX], addon_alias *alias ); +static void invalidate_addon_alias( addon_alias *alias ); static void addon_mount_content_folder( enum addon_type type, const char *base_folder, const char *content_ext ); diff --git a/ent_skateshop.c b/ent_skateshop.c index 957c250..f471f42 100644 --- a/ent_skateshop.c +++ b/ent_skateshop.c @@ -261,7 +261,7 @@ static void ent_skateshop_preupdate( ent_skateshop *shop, int active ){ addon_cache_unwatch( k_addon_type_board, localplayer.board_view_slot ); addon_cache_watch( k_addon_type_board, cache_id ); localplayer.board_view_slot = cache_id; - network_send_item( k_addon_type_board ); + network_send_item( k_netmsg_playeritem_board ); world_entity_unfocus(); skaterift_autosave(1); @@ -307,7 +307,7 @@ static void ent_skateshop_preupdate( ent_skateshop *shop, int active ){ } if( button_down( k_srbind_maccept ) ){ - network_send_item( k_addon_type_player ); + network_send_item( k_netmsg_playeritem_player ); world_entity_unfocus(); } } @@ -390,7 +390,7 @@ static void ent_skateshop_preupdate( ent_skateshop *shop, int active ){ if( button_down( k_srbind_mback ) ){ if( shop->type == k_skateshop_type_charshop ) - network_send_item( k_addon_type_player ); + network_send_item( k_netmsg_playeritem_player ); world_entity_unfocus(); return; diff --git a/gameserver.c b/gameserver.c index 6965eea..c0eca67 100644 --- a/gameserver.c +++ b/gameserver.c @@ -92,23 +92,16 @@ static void gameserver_player_join( int index ){ username, size, k_nSteamNetworkingSend_Reliable, NULL ); /* items */ - chs = vg_strncpy( client->item_player, item->uid, ADDON_UID_MAX, - k_strncpy_always_add_null ); - item->type = k_addon_type_player; - item->client = i; - size = sizeof(netmsg_playeritem) + chs + 1; - SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( - hSteamNetworkingSockets, joiner->connection, - item, size, k_nSteamNetworkingSend_Reliable, NULL ); - - chs = vg_strncpy( client->item_board, item->uid, ADDON_UID_MAX, - k_strncpy_always_add_null ); - item->type = k_addon_type_board; - item->client = i; - size = sizeof(netmsg_playeritem) + chs + 1; - SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( - hSteamNetworkingSockets, joiner->connection, - item, size, k_nSteamNetworkingSend_Reliable, NULL ); + for( int j=0; jitems[j], item->uid, ADDON_UID_MAX, + k_strncpy_always_add_null ); + item->type_index = j; + item->client = i; + size = sizeof(netmsg_playeritem) + chs + 1; + SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( + hSteamNetworkingSockets, joiner->connection, + item, size, k_nSteamNetworkingSend_Reliable, NULL ); + } } } @@ -146,6 +139,7 @@ static void new_client_connecting( HSteamNetConnection client ){ hSteamNetworkingSockets, client ); if( accept_status == k_EResultOK ){ vg_success( "Accepted client (id: %u, index: %d)\n", client, index ); + memset( &gameserver.clients[index], 0, sizeof(struct gameserver_client) ); gameserver.clients[index].active = 1; gameserver.clients[index].connection = client; @@ -351,8 +345,7 @@ static void gameserver_rx_200_300( SteamNetworkingMessage_t *msg ){ u32 chs = vg_strncpy( client->username, prop->name, NETWORK_USERNAME_MAX, k_strncpy_always_add_null ); - vg_info( "client #%d changed name to: %s [%s]\n", client_id, - client->username, prop->name ); + vg_info( "client #%d changed name to: %s\n", client_id, prop->name ); u32 propsize = sizeof(netmsg_playerusername) + chs + 1; gameserver_send_to_all( client_id, prop, propsize, @@ -372,21 +365,24 @@ static void gameserver_rx_200_300( SteamNetworkingMessage_t *msg ){ /* record */ struct gameserver_client *client = &gameserver.clients[ client_id ]; - if( item->type == k_addon_type_board ){ - network_msgstring( item->uid, msg->m_cbSize, sizeof(netmsg_playeritem), - client->item_board, ADDON_UID_MAX ); - } - else if( item->type == k_addon_type_player ){ - network_msgstring( item->uid, msg->m_cbSize, sizeof(netmsg_playeritem), - client->item_player, ADDON_UID_MAX ); - } - else { + if( item->type_index >= k_netmsg_playeritem_max ){ vg_warn( "Client #%d invalid equip type %u\n", - client_id, (u32)item->type ); + client_id, (u32)item->type_index ); return; } - vg_info( "Client #%d equiped: [%u] %s\n", - item->client, item->type, item->uid ); + + char *dest = client->items[ item->type_index ]; + + network_msgstring( item->uid, msg->m_cbSize, sizeof(netmsg_playeritem), + dest, ADDON_UID_MAX ); + + vg_info( "Client #%d equiped: [%s] %s\n", + item->client, + (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 ); /* propogate */ netmsg_playeritem *prop = alloca(msg->m_cbSize); diff --git a/gameserver.h b/gameserver.h index 646457e..2f5cfd4 100644 --- a/gameserver.h +++ b/gameserver.h @@ -21,8 +21,7 @@ struct { int authenticated; HSteamNetConnection connection; char username[ NETWORK_USERNAME_MAX ]; - - char item_board[ ADDON_UID_MAX ], item_player[ ADDON_UID_MAX ]; + char items[k_netmsg_playeritem_max][ADDON_UID_MAX]; } clients[ NETWORK_MAX_PLAYERS ]; diff --git a/network.c b/network.c index 4768ece..3878ef2 100644 --- a/network.c +++ b/network.c @@ -135,7 +135,7 @@ static void network_send_username(void){ netmsg_playerusername *update = alloca( sizeof(netmsg_playerusername)+ NETWORK_USERNAME_MAX ); update->inetmsg_id = k_inetmsg_playerusername; - update->index = 0xffffffff; + update->index = 0xff; ISteamFriends *hSteamFriends = SteamAPI_SteamFriends(); const char *username = SteamAPI_ISteamFriends_GetPersonaName(hSteamFriends); @@ -147,38 +147,61 @@ static void network_send_username(void){ k_nSteamNetworkingSend_Reliable, NULL ); } -static void network_send_item( enum addon_type type ){ - if( network_client.remote ){ - u16 id = 0; - if( type == k_addon_type_board ) - id = localplayer.board_view_slot; - else if( type == k_addon_type_player ) - id = localplayer.playermodel_view_slot; +static void network_send_item( enum netmsg_playeritem_type type ){ + if( !network_client.remote ) + return; - struct addon_cache *cache = &addon_system.cache[type]; - vg_pool *pool = &cache->pool; + netmsg_playeritem *item = + alloca( sizeof(netmsg_playeritem) + ADDON_UID_MAX ); + item->inetmsg_id = k_inetmsg_playeritem; + item->type_index = type; + item->client = 0; + + if( (type == k_netmsg_playeritem_world0) || + (type == k_netmsg_playeritem_world1) ){ + + addon_reg *reg = world_static.addon_hub; + + if( type == k_netmsg_playeritem_world1 ) + reg = world_static.addon_client; + + if( reg ) + addon_alias_uid( ®->alias, item->uid ); + else + item->uid[0] = '\0'; + } + else{ + u16 view_id = 0; + enum addon_type addon_type = k_addon_type_none; + if( type == k_netmsg_playeritem_board ){ + view_id = localplayer.board_view_slot; + addon_type = k_addon_type_board; + } + else if( type == k_netmsg_playeritem_player ){ + view_id = localplayer.playermodel_view_slot; + addon_type = k_addon_type_player; + } + else + assert(0); - netmsg_playeritem *item = - alloca( sizeof(netmsg_playeritem) + ADDON_UID_MAX ); - item->inetmsg_id = k_inetmsg_playeritem; - item->type = type; - item->client = 0; + struct addon_cache *cache = &addon_system.cache[addon_type]; + vg_pool *pool = &cache->pool; SDL_AtomicLock( &addon_system.sl_cache_using_resources ); - addon_cache_entry *entry = vg_pool_item( pool, id ); + addon_cache_entry *entry = vg_pool_item( pool, view_id ); addon_alias_uid( &entry->reg_ptr->alias, item->uid ); SDL_AtomicUnlock( &addon_system.sl_cache_using_resources ); + } - vg_info( "send equip: [%u] %s\n", - item->type, item->uid ); + vg_info( "send equip: [%u] %s\n", + item->type_index, item->uid ); + u32 chs = strlen(item->uid); - u32 chs = strlen(item->uid); + SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( + hSteamNetworkingSockets, network_client.remote, + item, sizeof(netmsg_playeritem)+chs+1, + k_nSteamNetworkingSend_Reliable, NULL ); - SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( - hSteamNetworkingSockets, network_client.remote, - item, sizeof(netmsg_playeritem)+chs+1, - k_nSteamNetworkingSend_Reliable, NULL ); - } } static void network_disconnect(void){ @@ -219,8 +242,10 @@ static void on_server_connect_status( CallbackMsg_t *msg ){ k_nSteamNetworkingSend_Reliable, NULL ); network_send_username(); - network_send_item( k_addon_type_board ); - network_send_item( k_addon_type_player ); + + for( u32 i=0; im_info.m_eState == k_ESteamNetworkingConnectionState_ClosedByPeer ){ diff --git a/network.h b/network.h index de64d44..e6407eb 100644 --- a/network.h +++ b/network.h @@ -58,6 +58,6 @@ static network_client = { }; static int packet_minsize( SteamNetworkingMessage_t *msg, u32 size ); -static void network_send_item( enum addon_type type ); +static void network_send_item( enum netmsg_playeritem_type type ); #endif /* NETWORK_H */ diff --git a/network_msg.h b/network_msg.h index 4490502..ba1fefe 100644 --- a/network_msg.h +++ b/network_msg.h @@ -13,16 +13,15 @@ #pragma pack(push,1) typedef struct netmsg_blank netmsg_blank; -struct netmsg_blank -{ - u32 inetmsg_id; +struct netmsg_blank{ + u16 inetmsg_id; }; enum{ k_inetmsg_blank = 0 }; typedef struct netmsg_auth netmsg_auth; struct netmsg_auth { - u32 inetmsg_id; + u16 inetmsg_id; u32 ticket_length; u8 ticket[]; @@ -32,14 +31,14 @@ enum{ k_inetmsg_auth = 1 }; typedef struct netmsg_scores_request netmsg_scores_request; struct netmsg_scores_request { - u32 inetmsg_id; + u16 inetmsg_id; }; enum{ k_inetmsg_scores_request = 2 }; typedef struct netmsg_set_score netmsg_set_score; struct netmsg_set_score { - u32 inetmsg_id; + u16 inetmsg_id; u32 record_count; struct netmsg_score_record @@ -54,20 +53,10 @@ enum{ k_inetmsg_set_score = 6 }; /* 31.05.23: k_inetmsg_set_score id changed from ID 3 to ID 6, * 3 is now INVALID */ -typedef struct netmsg_set_nickname netmsg_set_nickname; -struct netmsg_set_nickname -{ - u32 inetmsg_id; - char nickname[16]; -}; -enum{ k_inetmsg_set_nickname = 4 }; - - typedef struct netmsg_scoreboard netmsg_scoreboard; enum{ k_inetmsg_scoreboard = 5 }; -struct netmsg_scoreboard -{ - u32 inetmsg_id; +struct netmsg_scoreboard{ + u16 inetmsg_id; u32 board_count; struct netmsg_board @@ -87,45 +76,69 @@ static scoreboard_client_data = { /* player updates 200 */ +#define NETMSG_BOUNDARY_BIT 0x8000 +#define NETMSG_GATE_BOUNDARY_BIT 0x4000 +#define NETMSG_BOUNDARY_MASK (NETMSG_BOUNDARY_BIT|NETMSG_GATE_BOUNDARY_BIT) + typedef struct netmsg_playerframe netmsg_playerframe; enum{ k_inetmsg_playerframe = 200 }; struct netmsg_playerframe{ - u32 inetmsg_id; + u16 inetmsg_id; f64 timestamp; - u8 client, subsystem; + + u8 client, subsystem, + instance_id; + u16 boundary_hash; /* used for animating correctly through gates, teleport.. + msb is a flip flop for teleporting + second msb is flip flop for gate + +TODO: disable oblique clipping on cam mtx when rendering remote players + also render over the portal stencil? somehow. + + detransform, interp, retransform. render in dest world. */ + u8 animdata[]; }; typedef struct netmsg_playerjoin netmsg_playerjoin; enum{ k_inetmsg_playerjoin = 201 }; struct netmsg_playerjoin{ - u32 inetmsg_id; - u32 index; + u16 inetmsg_id; + u8 index; }; typedef struct netmsg_playerleave netmsg_playerleave; enum{ k_inetmsg_playerleave = 202 }; struct netmsg_playerleave{ - u32 inetmsg_id; - u32 index; + u16 inetmsg_id; + u8 index; }; typedef struct netmsg_playerusername netmsg_playerusername; enum{ k_inetmsg_playerusername = 203 }; struct netmsg_playerusername{ - u32 inetmsg_id; - u32 index; + u16 inetmsg_id; + u8 index; char name[]; }; typedef struct netmsg_playeritem netmsg_playeritem; enum{ k_inetmsg_playeritem = 204 }; struct netmsg_playeritem{ - u32 inetmsg_id; - u32 client; - u8 type; + u16 inetmsg_id; + u8 client; + u8 type_index; char uid[]; }; +typedef enum netmsg_playeritem_type netmsg_playeritem_type; +enum netmsg_playeritem_type { + k_netmsg_playeritem_board = 0, + k_netmsg_playeritem_player, + k_netmsg_playeritem_world0, + k_netmsg_playeritem_world1, + k_netmsg_playeritem_max +}; + #pragma pack(pop) #endif /* NETWORK_MSG_H */ diff --git a/player.c b/player.c index c478305..78449ad 100644 --- a/player.c +++ b/player.c @@ -114,9 +114,17 @@ static void player__post_update(void){ /* * Applies gate transport to a player_interface */ -static void player__pass_gate( ent_gate *gate ){ - world_routes_fracture( world_current_instance(), gate, - localplayer.rb.co, localplayer.rb.v ); +static void player__pass_gate( u32 id ){ + world_instance *world = world_current_instance(); + + /* update boundary hash (network animation) */ + u16 index = mdl_entity_id_id(id) & ~NETMSG_BOUNDARY_MASK; + localplayer.boundary_hash ^= NETMSG_GATE_BOUNDARY_BIT; + localplayer.boundary_hash &= ~NETMSG_BOUNDARY_MASK; + localplayer.boundary_hash |= index; + + ent_gate *gate = mdl_arritm( &world->ent_gate, mdl_entity_id_id(id) ); + world_routes_fracture( world, gate, localplayer.rb.co, localplayer.rb.v ); localplayer.gate_waiting = gate; world_routes_activate_entry_gate( world_current_instance(), gate ); @@ -246,6 +254,8 @@ static void player__spawn( ent_spawn *rp ){ if( player_subsystems[ localplayer.subsystem ]->reset ) player_subsystems[ localplayer.subsystem ]->reset( rp ); + + localplayer.boundary_hash ^= NETMSG_BOUNDARY_BIT; } diff --git a/player.h b/player.h index 029a34e..63e3028 100644 --- a/player.h +++ b/player.h @@ -92,6 +92,7 @@ struct { v3f cam_land_punch, cam_land_punch_v; ent_gate *gate_waiting; + u16 boundary_hash; int immobile; @@ -153,7 +154,7 @@ static void player__pre_update(void); static void player__update(void); static void player__post_update(void); -static void player__pass_gate( ent_gate *gate ); +static void player__pass_gate( u32 id ); static void player__im_gui(void); static void player__setpos( v3f pos ); static void player__spawn( ent_spawn *rp ); diff --git a/player_remote.c b/player_remote.c index 1689063..62eed5a 100644 --- a/player_remote.c +++ b/player_remote.c @@ -16,6 +16,47 @@ static void player_remote_clear( struct network_player *player ){ player->subsystem = k_player_subsystem_invalid; } +/* + * re-attatches addon_reg pointers on the remote client if we have the same + * world loaded. + */ +static void relink_remote_player_worlds( u32 client_id ){ + struct network_player *player = &netplayers.list[client_id]; + + player->hub_match = 0; + player->client_match = 0; + + addon_alias q0,q1; + addon_uid_to_alias( player->items[k_netmsg_playeritem_world0], &q0 ); + addon_uid_to_alias( player->items[k_netmsg_playeritem_world1], &q1 ); + + /* + * currently in 10.23, the hub world will always be the same. + * this might but probably wont change in the future + */ + if( world_static.addon_hub ) + if( addon_alias_eq( &q0, &world_static.addon_hub->alias ) ) + player->hub_match = 1; + + if( world_static.addon_client ) + if( addon_alias_eq( &q1, &world_static.addon_client->alias ) ) + player->client_match = 1; +} + +/* + * re-attatches addon_reg pointers on the remote client if we have the mod + * installed locally. + * + * Run if local worlds change + */ +static void relink_all_remote_player_worlds(void){ + for( u32 i=0; iactive ) + relink_remote_player_worlds(i); + } +} + static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){ netmsg_blank *tmp = msg->m_pData; @@ -115,6 +156,8 @@ 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; + dest->boundary_hash = frame->boundary_hash; struct network_player *player = &netplayers.list[ frame->client ]; memcpy( &dest->data, frame->animdata, datasize ); @@ -130,26 +173,33 @@ static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){ return; } - vg_info( "Client #%u equiped: [%u] %s\n", - item->client, item->type, item->uid ); + if( item->type_index >= k_netmsg_playeritem_max ){ + vg_warn( "Client #%d invalid equip type %u\n", + (i32)item->client, (u32)item->type_index ); + return; + } struct network_player *player = &netplayers.list[ item->client ]; + char *uid = player->items[ item->type_index ]; - char uid[ ADDON_UID_MAX ]; network_msgstring( item->uid, msg->m_cbSize, sizeof(*item), uid, ADDON_UID_MAX ); - if( item->type == k_addon_type_board ){ + if( item->type_index == k_netmsg_playeritem_board ){ addon_cache_unwatch( k_addon_type_board, player->board_view_slot ); player->board_view_slot = addon_cache_create_viewer_from_uid( k_addon_type_board, uid ); } - else if( item->type == k_addon_type_player ){ + else if( item->type_index == k_netmsg_playeritem_player ){ 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) ){ + relink_remote_player_worlds( item->client ); + } } } @@ -166,9 +216,12 @@ static void remote_player_send_playerframe(void){ u32 size = sizeof(netmsg_playerframe)+sys->animator_size; netmsg_playerframe *frame = alloca(size); frame->inetmsg_id = k_inetmsg_playerframe; - frame->client = 0; + 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; + memcpy( frame->animdata, sys->animator_data, sys->animator_size ); netplayers.up_bytes += size; @@ -296,9 +349,10 @@ static void pose_remote_player( u32 index, struct interp_frame *f0, struct interp_frame *f1 ){ + struct network_player *player = &netplayers.list[ index ]; + struct interp_buffer *buf = &netplayers.interp_data[ index ]; struct player_avatar *av = localplayer.playeravatar; - struct skeleton *sk = &localplayer.playeravatar->sk; m4x3f *final_mtx = &netplayers.final_mtx[ av->sk.bone_count*index ]; struct player_board_pose *board_pose = &netplayers.board_poses[index]; @@ -306,9 +360,10 @@ static void pose_remote_player( u32 index, *sys1 = NULL; player_pose pose0, pose1, posed; - sys0->pose( &f0->data, &pose0 ); + u8 instance_id = 0; + if( f1 ){ f32 t = (buf->t - f0->timestamp) / (f1->timestamp - f0->timestamp); t = vg_clampf( t, 0.0f, 1.0f ); @@ -316,14 +371,39 @@ static void pose_remote_player( u32 index, sys1 = player_subsystems[f1->subsystem]; sys1->pose( &f1->data, &pose1 ); + u16 bounds = f0->boundary_hash^f1->boundary_hash; + + if( bounds & NETMSG_BOUNDARY_BIT ) + t = 1.0f; + + if( bounds & NETMSG_GATE_BOUNDARY_BIT ){ + /* TODO: Extra work retransforming the root_co, instance_id.. etc */ + t = 1.0f; + } + + instance_id = f1->instance_id; + lerp_player_pose( &pose0, &pose1, t, &posed ); apply_full_skeleton_pose( &av->sk, &posed, final_mtx ); memcpy( board_pose, &posed.board, sizeof(*board_pose) ); } else { + instance_id = f0->instance_id; + apply_full_skeleton_pose( &av->sk, &pose0, final_mtx ); memcpy( board_pose, &pose0.board, sizeof(*board_pose) ); } + + if( instance_id ){ + if( player->client_match ){ + player->active_world = &world_static.instances[ instance_id ]; + } + } + else{ + if( player->hub_match ){ + player->active_world = &world_static.instances[ instance_id ]; + } + } } /* @@ -362,7 +442,10 @@ static void animate_remote_player( u32 index ){ abs_max_frame = ifr; } } - } + } + + struct network_player *player = &netplayers.list[ index ]; + player->active_world = NULL; if( minframe && maxframe ){ pose_remote_player( index, minframe, maxframe ); @@ -400,6 +483,7 @@ static void render_remote_players( world_instance *world, camera *cam ){ for( u32 i=0; iactive ) continue; + if( player->active_world != world ) continue; struct player_avatar *av = localplayer.playeravatar; m4x3f *final_mtx = &netplayers.final_mtx[ av->sk.bone_count*i ]; @@ -422,3 +506,7 @@ static void render_remote_players( world_instance *world, camera *cam ){ SDL_AtomicUnlock( &addon_system.sl_cache_using_resources ); } + +/* TODO: Which world is the player in + * nametags with occlusion + */ diff --git a/player_remote.h b/player_remote.h index 6cf7ce5..3c795b2 100644 --- a/player_remote.h +++ b/player_remote.h @@ -11,7 +11,14 @@ struct { u16 board_view_slot, playermodel_view_slot; enum player_subsystem subsystem; - char username[32]; + /* this is set IF they exist in a world that we have loaded */ + world_instance *active_world; + int hub_match, client_match; + + /* TODO: Compression with server code */ + char username[ NETWORK_USERNAME_MAX ]; + char items[k_netmsg_playeritem_max][ADDON_UID_MAX]; + u32 down_bytes; f32 down_kbs; } @@ -24,6 +31,9 @@ struct { f64 timestamp; enum player_subsystem subsystem; + u8 instance_id; + u16 boundary_hash; + union interp_animdata { struct player_skate_animator _skate; struct player_walk_animator _walk; @@ -50,5 +60,6 @@ static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ); static void remote_player_debug_update(void); static void remote_player_send_playerframe(void); static void animate_remote_player( u32 index ); +static void render_remote_players( world_instance *world, camera *cam ); #endif /* PLAYER_REMOTE_H */ diff --git a/player_skate.c b/player_skate.c index dbf927b..f8b4166 100644 --- a/player_skate.c +++ b/player_skate.c @@ -2524,10 +2524,11 @@ begin_collision:; skate_integrate(); vg_line_point( state->cog, 0.02f, VG__WHITE ); - ent_gate *gate = - world_intersect_gates(world, localplayer.rb.co, state->prev_pos ); + u32 id = world_intersect_gates( world, localplayer.rb.co, state->prev_pos ); + + if( id ){ + ent_gate *gate = mdl_arritm( &world->ent_gate, mdl_entity_id_id(id) ); - if( gate ){ m4x3_mulv( gate->transport, localplayer.rb.co, localplayer.rb.co ); m3x3_mulv( gate->transport, localplayer.rb.v, localplayer.rb.v ); m4x3_mulv( gate->transport, state->cog, state->cog ); @@ -2543,7 +2544,7 @@ begin_collision:; q_mul( transport_rotation, state->smoothed_rotation, state->smoothed_rotation ); rb_update_transform( &localplayer.rb ); - player__pass_gate( gate ); + player__pass_gate( id ); } /* FIXME: Rate limit */ diff --git a/player_walk.c b/player_walk.c index c43e7bf..ec025a1 100644 --- a/player_walk.c +++ b/player_walk.c @@ -617,9 +617,9 @@ static void player__walk_update(void){ } } - ent_gate *gate = - world_intersect_gates( world, localplayer.rb.co, w->state.prev_pos ); - if( gate ){ + u32 id = world_intersect_gates(world, localplayer.rb.co, w->state.prev_pos); + if( id ){ + ent_gate *gate = mdl_arritm( &world->ent_gate, mdl_entity_id_id(id) ); m4x3_mulv( gate->transport, localplayer.rb.co, localplayer.rb.co ); m3x3_mulv( gate->transport, localplayer.rb.v, localplayer.rb.v ); @@ -628,7 +628,7 @@ static void player__walk_update(void){ q_mul( transport_rotation, localplayer.rb.q, localplayer.rb.q ); rb_update_transform( &localplayer.rb ); - player__pass_gate( gate ); + player__pass_gate( id ); } rb_update_transform( &localplayer.rb ); } diff --git a/world_gate.c b/world_gate.c index b236bc9..bb62e34 100644 --- a/world_gate.c +++ b/world_gate.c @@ -16,6 +16,7 @@ #include "camera.h" #include "world_water.h" +#include "player_remote.h" /* * Update the transform matrices for gate @@ -196,6 +197,7 @@ static int render_gate( world_instance *world, world_instance *world_inside, glDisable( GL_STENCIL_TEST ); } + render_remote_players( world_inside, &world_gates.cam ); return 1; } @@ -247,8 +249,7 @@ static int gate_intersect_plane( ent_gate *gate, /* * Intersect specific gate */ -static int gate_intersect( ent_gate *gate, v3f pos, v3f last ) -{ +static int gate_intersect( ent_gate *gate, v3f pos, v3f last ){ v2f xy; if( gate_intersect_plane( gate, pos, last, xy ) ){ @@ -264,26 +265,22 @@ static int gate_intersect( ent_gate *gate, v3f pos, v3f last ) /* * Intersect all gates in the world */ -static ent_gate *world_intersect_gates( world_instance *world, - v3f pos, v3f last ){ +static u32 world_intersect_gates( world_instance *world, v3f pos, v3f last ){ for( u32 i=0; ient_gate); i++ ){ ent_gate *gate = mdl_arritm( &world->ent_gate, i ); if( !(gate->flags & k_ent_gate_linked) ) continue; if( gate->flags & k_ent_gate_locked ) continue; - if( gate->flags & k_ent_gate_nonlocal ){ - if( world_static.load_state != k_world_loader_none ){ + if( gate->flags & k_ent_gate_nonlocal ) + if( world_static.load_state != k_world_loader_none ) continue; - } - } - if( gate_intersect( gate, pos, last ) ){ - return gate; - } + if( gate_intersect( gate, pos, last ) ) + return mdl_entity_id( k_ent_gate, i ); } - return NULL; + return 0; } /* diff --git a/world_gate.h b/world_gate.h index bf23beb..5663c29 100644 --- a/world_gate.h +++ b/world_gate.h @@ -24,8 +24,7 @@ static int render_gate( world_instance *world, world_instance *world_inside, ent_gate *gate, camera *cam, int layer_depth ); static int gate_intersect( ent_gate *gate, v3f pos, v3f last ); -static ent_gate *world_intersect_gates( world_instance *world, - v3f pos, v3f last ); +static u32 world_intersect_gates( world_instance *world, v3f pos, v3f last ); static void ent_gate_call( world_instance *world, ent_call *call ); static void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl ); diff --git a/world_load.c b/world_load.c index 00be612..e17483f 100644 --- a/world_load.c +++ b/world_load.c @@ -8,6 +8,7 @@ #include "addon.h" #include "save.h" #include "vg/vg_msg.h" +#include "network.h" /* * load the .mdl file located in path as a world instance @@ -291,6 +292,7 @@ static void skaterift_change_world_start( addon_reg *reg ){ } world_static.addon_client = reg; + network_send_item( k_netmsg_playeritem_world1 ); } } -- 2.25.1