return 0xffffffff;
}
-static void addon_alias_uid( addon_alias *alias, char buf[76] ){
+/*
+ * Create a string version of addon alias in buf
+ */
+static void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] ){
if( alias->workshop_id ){
snprintf( buf, 128, "sr%03d-steam-"PRINTF_U64,
alias->type, alias->workshop_id );
}
}
+/*
+ * parse uid to alias. returns 1 if successful
+ */
+static int addon_uid_to_alias( char uid[ADDON_UID_MAX], addon_alias *alias ){
+/* 1
+ * 01234567890123
+ * sr&&&-@@@@@-#*
+ * | | |
+ * type | id
+ * |
+ * location
+ */
+ if( strlen(uid) < 13 ) return 0;
+ if( !((uid[0] == 's') && (uid[1] == 'r')) ) return 0;
+
+ char type[4];
+ memcpy( type, uid+2, 3 );
+ type[3] = '\0';
+ alias->type = atoi(type);
+
+ char location[6];
+ memcpy( location, uid+6, 5 );
+ location[5] = '\0';
+
+ if( !strcmp(location,"steam") )
+ alias->workshop_id = atoll( uid+12 );
+ else if( !strcmp(location,"local") )
+ vg_strncpy( uid+12, alias->foldername, 64, k_strncpy_always_add_null );
+ else
+ return 0;
+
+ return 1;
+}
+
static void addon_system_init( void ){
u32 reg_size = sizeof(addon_reg)*ADDON_MOUNTED_MAX;
addon_system.registry = vg_linear_alloc( vg_mem.rtmemory, reg_size );
return cache_id;
}
+static u16 addon_cache_create_viewer_from_uid( enum addon_type type,
+ char uid[ADDON_UID_MAX] ){
+ addon_alias q;
+ addon_uid_to_alias( uid, &q );
+ if( q.type != type ) return 0;
+
+ u32 reg_id = addon_match( &q );
+
+ if( reg_id == 0xffffffff ){
+ vg_warn( "We dont have the addon '%s' installed.\n", uid );
+ return 0;
+ }
+ else {
+ return addon_cache_create_viewer( type, reg_id );
+ }
+}
+
static void addon_cache_watch( enum addon_type type, u16 cache_id ){
if( !cache_id ) return;
#ifndef ADDON_H
#define ADDON_H
+#define ADDON_FOLDERNAME_MAX 64
+
+/* total count that we have knowledge of */
+#define ADDON_MOUNTED_MAX 128
+#define ADDON_UID_MAX 76
+
+#ifndef ADDON_DEFINE_ONLY
+
#include "skaterift.h"
#include "vg/vg_steam_ugc.h"
#include "addon_types.h"
#include "world.h"
#include "player.h"
-#define ADDON_FOLDERNAME_MAX 64
-
-/* total count that we have knowledge of */
-#define ADDON_MOUNTED_MAX 128
-
typedef struct addon_reg addon_reg;
typedef struct addon_cache_entry addon_cache_entry;
typedef struct addon_alias addon_alias;
/* scanning routines */
static u32 addon_match( addon_alias *alias );
-static void addon_alias_uid( addon_alias *alias, char buf[76] );
+static void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] );
static void addon_mount_content_folder( enum addon_type type,
const char *base_folder,
const char *content_ext );
static void addon_cache_watch( enum addon_type type, u16 cache_id );
static void addon_cache_unwatch( enum addon_type type, u16 cache_id );
+static u16 addon_cache_create_viewer_from_uid( enum addon_type type,
+ char uid[ADDON_UID_MAX] );
+#endif
#endif /* ADDON_H */
#include "highscores.c"
#include "servermonitor_server.c"
#include "vg/vg_opt.h"
+#include "network_common.h"
static const u64 k_connection_unauthorized = 0xffffffffffffffff;
}
}
-static void gameserver_populate_join_msg( int index, netmsg_playerjoin *msg ){
- memset( msg, 0, sizeof(*msg) );
- msg->inetmsg_id = k_inetmsg_playerjoin;
- msg->index = index;
- vg_strncpy( gameserver.clients[index].username, msg->username,
- sizeof(msg->username), k_strncpy_always_add_null );
-}
-
static void gameserver_player_join( int index ){
struct gameserver_client *joiner = &gameserver.clients[index];
- netmsg_playerjoin join;
- gameserver_populate_join_msg( index, &join );
+ netmsg_playerjoin join = { .inetmsg_id = k_inetmsg_playerjoin,
+ .index = index };
gameserver_send_to_all( index, &join, sizeof(join),
k_nSteamNetworkingSend_Reliable );
/* update the joining user about current connections */
+
+ netmsg_playerusername *username = alloca( sizeof(netmsg_playerusername) +
+ NETWORK_USERNAME_MAX );
+ username->inetmsg_id = k_inetmsg_playerusername;
+
for( int i=0; i<vg_list_size(gameserver.clients); i++ ){
struct gameserver_client *client = &gameserver.clients[i];
if( (i==index) || !client->active )
continue;
- netmsg_playerjoin init;
- gameserver_populate_join_msg( i, &init );
-
+ /* join */
+ netmsg_playerjoin init = { .inetmsg_id = k_inetmsg_playerjoin,
+ .index = i };
SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
hSteamNetworkingSockets, joiner->connection,
&init, sizeof(init), k_nSteamNetworkingSend_Reliable, NULL );
+
+ /* username */
+ username->index = i;
+ u32 chs = vg_strncpy( client->username, username->name,
+ NETWORK_USERNAME_MAX,
+ k_strncpy_always_add_null );
+ u32 size = sizeof(netmsg_playerusername) + chs + 1;
+ SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+ hSteamNetworkingSockets, joiner->connection,
+ username, size, k_nSteamNetworkingSend_Reliable, NULL );
}
}
if( client_id == -1 ) return;
if( tmp->inetmsg_id == k_inetmsg_playerusername ){
- if( !packet_minsize( msg, sizeof(netmsg_playerusername) ))
+ if( !packet_minsize( msg, sizeof(netmsg_playerusername)+1 ))
return;
struct gameserver_client *client = &gameserver.clients[ client_id ];
netmsg_playerusername *src = msg->m_pData;
- vg_info( "%d change name '%s' -> '%s'\n",
- client_id, client->username, src->username );
-
- vg_strncpy( src->username, client->username, sizeof(client->username),
- k_strncpy_always_add_null );
+ u32 name_len = network_msgstring( src->name, msg->m_cbSize,
+ sizeof(netmsg_playerusername),
+ client->username,
+ NETWORK_USERNAME_MAX );
/* update other users about this change */
- netmsg_playerusername msg;
- memset( &msg, 0, sizeof(msg) );
- msg.inetmsg_id = k_inetmsg_playerusername;
- msg.index = client_id;
- vg_strncpy( client->username, msg.username, sizeof(msg.username),
- k_strncpy_always_add_null );
-
- gameserver_send_to_all( client_id, &msg, sizeof(msg),
+ netmsg_playerusername *prop = alloca(sizeof(netmsg_playerusername)+
+ NETWORK_USERNAME_MAX );
+
+ prop->inetmsg_id = k_inetmsg_playerusername;
+ prop->index = client_id;
+ u32 chs = vg_strncpy( client->username, prop->name, name_len,
+ k_strncpy_always_add_null );
+
+ vg_info( "client #%d changed name to: %s\n", client_id,
+ client->username );
+
+ u32 propsize = sizeof(netmsg_playerusername) + chs + 1;
+ gameserver_send_to_all( client_id, prop, propsize,
k_nSteamNetworkingSend_Reliable );
}
else if( tmp->inetmsg_id == k_inetmsg_playerframe ){
#include "vg/vg_steam_http.h"
#include "vg/vg_steam_auth.h"
#include "network_msg.h"
+#include "network_common.h"
#include "highscores.h"
#include <sys/socket.h>
int active;
int authenticated;
HSteamNetConnection connection;
- char username[32];
+ char username[ NETWORK_USERNAME_MAX ];
}
clients[ 32 ];
#include "player.h"
#include "network.h"
#include "network_msg.h"
+#include "network_common.h"
#include "player_remote.h"
static void scores_update(void);
#endif
static void network_send_username(void){
- netmsg_playerusername update;
- memset( &update, 0, sizeof(update) );
- update.inetmsg_id = k_inetmsg_playerusername;
- update.index = 0xffffffff;
+ netmsg_playerusername *update = alloca( sizeof(netmsg_playerusername)+
+ NETWORK_USERNAME_MAX );
+ update->inetmsg_id = k_inetmsg_playerusername;
+ update->index = 0xffffffff;
ISteamFriends *hSteamFriends = SteamAPI_SteamFriends();
const char *username = SteamAPI_ISteamFriends_GetPersonaName(hSteamFriends);
- str_utf8_collapse( username, update.username, sizeof(update.username) );
+ u32 chs = str_utf8_collapse( username, update->name, NETWORK_USERNAME_MAX );
SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
hSteamNetworkingSockets, network_client.remote,
- &update, sizeof(update),
+ update, sizeof(netmsg_playerusername)+chs+1,
k_nSteamNetworkingSend_Reliable, NULL );
}
--- /dev/null
+#ifndef NETWORK_COMMON_H
+#define NETWORK_COMMON_H
+
+#include "vg/vg_stdint.h"
+#include "vg/vg_platform.h"
+
+#define NETWORK_USERNAME_MAX 32
+
+#define ADDON_DEFINE_ONLY
+ #include "addon.h"
+#undef ADDON_DEFINE_ONLY
+
+static u32 network_msgstring( const char *src,
+ u32 m_cbSize, u32 base_size,
+ char *buf, u32 buf_size ){
+
+ u32 string_len = VG_MIN( m_cbSize - base_size, buf_size );
+ return vg_strncpy( src, buf, string_len, k_strncpy_always_add_null );
+}
+
+#endif /* NETWORK_COMMON_H */
/* player updates 200 */
-/* client -> remote */
typedef struct netmsg_playerframe netmsg_playerframe;
enum{ k_inetmsg_playerframe = 200 };
struct netmsg_playerframe{
u8 animdata[];
};
-/* remote -> client */
typedef struct netmsg_playerjoin netmsg_playerjoin;
enum{ k_inetmsg_playerjoin = 201 };
struct netmsg_playerjoin{
u32 inetmsg_id;
-
u32 index;
- char username[32]; /* UNUSED */
- char playermodel_uid[76]; /* UNUSED */
- char board_uid[76]; /* UNUSED */
};
-
-/* remote -> client */
typedef struct netmsg_playerleave netmsg_playerleave;
enum{ k_inetmsg_playerleave = 202 };
struct netmsg_playerleave{
u32 index;
};
-/* client <-> remote */
typedef struct netmsg_playerusername netmsg_playerusername;
enum{ k_inetmsg_playerusername = 203 };
struct netmsg_playerusername{
u32 inetmsg_id;
u32 index;
- char username[32];
+ char name[];
+};
+
+typedef struct netmsg_playeritem netmsg_playeritem;
+enum{ k_inetmsg_playeritem = 204 };
+struct netmsg_playeritem{
+ u32 inetmsg_id;
+ u32 index;
+ u8 type;
+ char uid[];
};
#pragma pack(pop)
#include "player_remote.h"
#include "skeleton.h"
#include "player_render.h"
+#include "network_common.h"
static void player_remote_unwatch( struct network_player *player ){
addon_cache_unwatch( k_addon_type_player, player->playermodel_view_slot );
player->subsystem = k_player_subsystem_invalid;
}
-static void player_remote_clear_interp( u32 index ){
- struct interp_buffer *buf = &netplayers.interp_data[ index ];
- buf->t = -99999999.9;
- for( u32 i=0; i<vg_list_size(buf->frames); i ++ ){
- buf->frames[i].active = 0;
- }
-}
-
static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){
netmsg_blank *tmp = msg->m_pData;
/* TODO: interpret the uids */
player->board_view_slot = 0;
player->playermodel_view_slot = 0;
- player_remote_clear_interp( playerjoin->index );
-
- vg_strncpy( playerjoin->username, player->username,
- sizeof(player->username), k_strncpy_always_add_null );
+#if 0
+ addon_cache_create_viewer_from_uid( k_addon_type_board,
+ playerjoin->board_uid );
+ player->playermodel_view_slot =
+ addon_cache_create_viewer_from_uid( k_addon_type_player,
+ playerjoin->playermodel_uid );
+#endif
+
+ struct interp_buffer *buf = &netplayers.interp_data[playerjoin->index];
+ buf->t = -99999999.9;
+ for( u32 i=0; i<vg_list_size(buf->frames); i ++ ){
+ buf->frames[i].active = 0;
+ }
- vg_info( "#%u joined with name: %s\n",
- playerjoin->index, player->username );
+ vg_info( "#%u joined\n", playerjoin->index );
}
else {
vg_error( "inetmsg_playerjoin: player index out of range\n" );
if( update->index < vg_list_size(netplayers.list) ){
struct network_player *player = &netplayers.list[ update->index ];
- vg_strncpy( update->username, player->username,
- sizeof(player->username), k_strncpy_always_add_null );
- vg_info( "#%u changed username: %s\n", player->username );
+ network_msgstring( update->name, msg->m_cbSize, sizeof(*update),
+ player->username, sizeof(player->username) );
+
+ vg_info( "#%u changed username to: %s\n", player->username );
}
else {
vg_error( "inetmsg_playerleave: player index out of range\n" );
}
}
+/*
+ * Write localplayer pose to network
+ */
static void remote_player_send_playerframe(void){
u8 sysid = localplayer.subsystem;
if( sysid >= k_player_subsystem_max ) return;
}
}
+/*
+ * Updates network traffic stats
+ */
static void remote_player_debug_update(void){
if( (vg.time_real - netplayers.last_data_measurement) > 1.0 ){
netplayers.last_data_measurement = vg.time_real;
}
}
+/*
+ * Debugging information
+ */
static void remote_player_network_imgui( m4x4f pv ){
if( !network_client.network_info )
return;
}
}
+/*
+ * write the remote players final_mtx
+ */
static void pose_remote_player( u32 index,
struct interp_frame *f0,
struct interp_frame *f1 ){
sys1 = player_subsystems[f1->subsystem];
sys1->pose( &f1->data, &pose1 );
- if( pose0.type != pose1.type ){
- /* it would be nice to apply IK pass in-keyframes. TOO BAD! */
- skeleton_copy_pose( sk, pose0.keyframes, posed.keyframes );
- }
- else {
- skeleton_lerp_pose( sk, pose0.keyframes, pose1.keyframes, t,
- posed.keyframes );
- }
-
- v3_lerp( pose0.root_co, pose1.root_co, t, posed.root_co );
- q_nlerp( pose0.root_q, pose1.root_q, t, posed.root_q );
- posed.type = pose0.type;
- posed.board.lean = vg_lerpf( pose0.board.lean, pose1.board.lean, t );
-
+ lerp_player_pose( &pose0, &pose1, t, &posed );
apply_full_skeleton_pose( &av->sk, &posed, final_mtx );
}
else {
}
}
+/*
+ * animate remote player and store in final_mtx
+ */
static void animate_remote_player( u32 index ){
+ /*
+ * Trys to keep the cursor inside the buffer
+ */
f64 min_time = -999999999.9,
max_time = 999999999.9,
abs_max_time = -999999999.9;
return;
}
}
+
+/*
+ * Update full final_mtx for all remote players
+ */
+static void animate_remote_players(void){
+ for( u32 i=0; i<vg_list_size(netplayers.list); i ++ ){
+ struct network_player *player = &netplayers.list[i];
+ if( !player->active ) continue;
+
+ animate_remote_player( i );
+ }
+}
+
+/*
+ * Draw remote players
+ */
+static void render_remote_players( world_instance *world, camera *cam ){
+ for( u32 i=0; i<vg_list_size(netplayers.list); i ++ ){
+ struct network_player *player = &netplayers.list[i];
+ if( !player->active ) continue;
+
+ struct player_avatar *av = localplayer.playeravatar;
+
+ struct player_model *model = &localplayer.fallback_model;
+ render_playermodel( cam, world, 0, model, &av->sk,
+ &netplayers.final_mtx[ av->sk.bone_count*i ] );
+ }
+}
}
}
+static void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t,
+ player_pose *posed ){
+ struct skeleton *sk = &localplayer.playeravatar->sk;
+
+ v3_lerp( pose0->root_co, pose1->root_co, t, posed->root_co );
+ q_nlerp( pose0->root_q, pose1->root_q, t, posed->root_q );
+ posed->type = pose0->type;
+ posed->board.lean = vg_lerpf( pose0->board.lean, pose1->board.lean, t );
+
+ if( pose0->type != pose1->type ){
+ /* it would be nice to apply IK pass in-keyframes. TOO BAD! */
+ skeleton_copy_pose( sk, pose0->keyframes, posed->keyframes );
+ }
+ else {
+ skeleton_lerp_pose( sk, pose0->keyframes, pose1->keyframes, t,
+ posed->keyframes );
+ }
+}
+
static void player__animate_from_replay( replay_buffer *replay ){
replay_frame *frame = replay->cursor_frame,
*next = NULL;
sys0->pose( a0, &pose0 );
sys1->pose( a1, &pose1 );
- v3_lerp( pose0.root_co, pose1.root_co, t, localplayer.pose.root_co );
- q_nlerp( pose0.root_q, pose1.root_q, t, localplayer.pose.root_q );
- localplayer.pose.type = pose0.type;
- localplayer.pose.board.lean = vg_lerpf( pose0.board.lean,
- pose1.board.lean, t );
-
- struct skeleton *sk = &localplayer.playeravatar->sk;
- if( pose0.type != pose1.type ){
- /* it would be nice to apply IK pass in-keyframes. TOO BAD! */
- skeleton_copy_pose( sk, pose0.keyframes,
- localplayer.pose.keyframes );
- }
- else {
- skeleton_lerp_pose( sk, pose0.keyframes, pose1.keyframes,
- t, localplayer.pose.keyframes );
- }
+ lerp_player_pose( &pose0, &pose1, t, &localplayer.pose );
}
else{
struct player_subsystem_interface
m4x3f *final_mtx );
static void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose,
m4x3f *final_mtx );
+static void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t,
+ player_pose *posed );
#endif /* PLAYER_RENDER_H */
player__render( &small_cam );
}
-static void animate_remote_players(void){
- for( u32 i=0; i<vg_list_size(netplayers.list); i ++ ){
- struct network_player *player = &netplayers.list[i];
- if( !player->active ) continue;
-
- animate_remote_player( i );
-#if 0
- if( player->subsystem > k_player_subsystem_max ) continue;
-
- struct player_subsystem_interface *sys =
- player_subsystems[player->subsystem];
-
- struct player_avatar *av = localplayer.playeravatar;
-
- player_pose pose;
- sys->pose( &player->animdata, &pose );
- apply_full_skeleton_pose( &av->sk, &pose,
- &netplayers.final_mtx[ av->sk.bone_count*i ] );
-#endif
- }
-}
-
-static void render_remote_players( world_instance *world, camera *cam ){
- for( u32 i=0; i<vg_list_size(netplayers.list); i ++ ){
- struct network_player *player = &netplayers.list[i];
- if( !player->active ) continue;
-
- struct player_avatar *av = localplayer.playeravatar;
-
- struct player_model *model = &localplayer.fallback_model;
- render_playermodel( cam, world, 0, model, &av->sk,
- &netplayers.final_mtx[ av->sk.bone_count*i ] );
- }
-}
-
static void render_scene(void){
/* Draw world */
glEnable( GL_DEPTH_TEST );
return 0;
}
-static void str_utf8_collapse( const char *str, char *buf, u32 length )
-{
+static u32 str_utf8_collapse( const char *str, char *buf, u32 length ){
u8 *ustr = (u8 *)str;
u32 utf32_code = 0x00000000;
u32 i=0, j=0, utf32_byte_ct=0;
- for(;i < length-1;){
+ for(;j < length-1;){
if( ustr[i] == 0x00 )
break;
}
buf[j] = 0x00;
+ return j;
}
static int steam_init(void){