/* items */
for( int j=0; j<k_netmsg_playeritem_max; j++ ){
- chs = vg_strncpy( client->items[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;
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.
NULL, 1 );
}
memset( client, 0, sizeof(struct gameserver_client) );
+ gameserver_update_all_knowledge( index, 1 );
}
/*
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; i<NETWORK_MAX_PLAYERS; i ++ ){
+ if( i == client )
+ continue;
+
+ struct gameserver_client *ci = &gameserver.clients[i];
+
+ if( ci->steamid )
+ 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; i<vg_list_size(gameserver.clients); i++ ){
+ if( i == client_id )
+ continue;
+
+ struct gameserver_client *ci = &gameserver.clients[i];
+
+ int send_full = 0;
+
+ if( c0->instance == 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<<c0->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;
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;
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 );
[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);
#include "highscores.h"
#include <sys/socket.h>
+#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;
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 ];
}
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) && (_a<N) && (_b<N) );
+
+ u32 a = VG_MIN( _a, _b ),
+ b = VG_MAX( _a, _b );
+
+ return ((N-a)*((N-a)-1))/2 - b + a;
+}
+
#endif /* NETWORK_COMMON_H */
/* implementation */
#include "player_common.c"
+
#include "player_walk.c"
#include "player_skate.c"
#include "player_dead.c"
#include "player_drive.c"
+#include "player_basic_info.c"
+
#include "player_render.c"
#include "player_ragdoll.c"
#include "player_replay.c"
k_player_subsystem_skate = 1,
k_player_subsystem_dead = 2,
k_player_subsystem_drive = 3,
+ k_player_subsystem_basic_info = 4,
k_player_subsystem_max,
k_player_subsystem_invalid = 255
};
#include "player_ragdoll.h"
#include "player_render.h"
#include "player_model.h"
+
+/* subsystem headers */
#include "player_walk.h"
#include "player_skate.h"
#include "player_dead.h"
#include "player_drive.h"
+#include "player_basic_info.h"
+
#include "player_replay.h"
#define PLAYER_REWIND_FRAMES 60*4
rigidbody rb;
v3f angles;
-#if 0
- v4f qbasis;
- m3x3f basis, invbasis, basis_gate;
- world_instance *viewable_world;
-#endif
-
/*
* Camera management
* ---------------------------
[k_player_subsystem_walk] = &player_subsystem_walk,
[k_player_subsystem_dead] = &player_subsystem_dead,
[k_player_subsystem_drive] = &player_subsystem_drive,
- [k_player_subsystem_skate] = &player_subsystem_skate
+ [k_player_subsystem_skate] = &player_subsystem_skate,
+ [k_player_subsystem_basic_info]=&player_subsystem_basic_info
};
/*
--- /dev/null
+#include "player_basic_info.h"
+#include "network_compression.h"
+
+static void player__basic_info_animator_exchange(bitpack_ctx *ctx, void *data){
+ struct player_basic_info_animator *animator = data;
+ /* TODO: This range needs to be standardized in a common header */
+ bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->root_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; i<localplayer.skeleton.bone_count; i ++ ){
+ v3_zero(pose->keyframes[i].co);
+ q_identity(pose->keyframes[i].q);
+ v3_fill(pose->keyframes[i].s,1.0f);
+ }
+}
--- /dev/null
+#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 */
#include "addon.h"
#include "font.h"
#include "gui.h"
+#include "ent_miniworld.h"
static i32 k_show_own_name = 0;
.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
* -------------------------------------------------------------*/
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;
.bytes = 0
};
- /* sfx
- * ---------------------------------------------*/
-
- frame->sound_effects = localplayer.sfx_buffer_count;
- for( u32 i=0; i<localplayer.sfx_buffer_count; i ++ )
- net_sfx_exchange( &ctx, &localplayer.sfx_buffer[i] );
-
/* animation
* -----------------------------------------------*/
else
bitpack_bytes( &ctx, sys->animator_size, sys->animator_data );
+ /* sfx
+ * ---------------------------------------------*/
+
+ frame->sound_effects = localplayer.sfx_buffer_count;
+ for( u32 i=0; i<localplayer.sfx_buffer_count; i ++ )
+ net_sfx_exchange( &ctx, &localplayer.sfx_buffer[i] );
+
u32 wire_size = base_size + ctx.bytes;
netplayers.up_bytes += wire_size;
v3f co;
remote_player_position( i, co );
- if( player->active_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 );
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 );
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;
}
" 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"