+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;
+
+ int client_id = gameserver_conid( msg->m_conn );
+ if( client_id == -1 ) return;
+
+ struct gameserver_client *client = &gameserver.clients[ client_id ];
+
+ if( tmp->inetmsg_id == k_inetmsg_playerusername ){
+ if( !packet_minsize( msg, sizeof(netmsg_playerusername)+1 ))
+ return;
+
+ netmsg_playerusername *src = msg->m_pData;
+
+ 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 *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, NETWORK_USERNAME_MAX,
+ k_strncpy_always_add_null );
+
+ 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,
+ k_nSteamNetworkingSend_Reliable );
+
+ /* update database about this */
+ db_request *call = db_alloc_request(
+ sizeof(struct db_set_username_thread_data) );
+ struct db_set_username_thread_data *inf = (void *)call->data;
+ inf->steamid = client->steamid;
+ vg_strncpy( client->username, inf->username,
+ sizeof(inf->username), k_strncpy_always_add_null );
+ call->handler = gameserver_update_db_username;
+ db_send_request( call );
+ }
+ else if( tmp->inetmsg_id == k_inetmsg_playerframe ){
+ 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;
+
+ /* record */
+
+ if( item->type_index >= k_netmsg_playeritem_max ){
+ vg_warn( "Client #%d invalid equip type %u\n",
+ client_id, (u32)item->type_index );
+ return;
+ }
+
+ char *dest = client->items[ item->type_index ].uid;
+
+ network_msgstring( item->uid, msg->m_cbSize, sizeof(netmsg_playeritem),
+ dest, ADDON_UID_MAX );
+
+ vg_info( "Client #%d equiped: [%s] %s\n",
+ client_id,
+ (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 );
+
+ gameserver_update_all_knowledge( client_id, 0 );
+
+ /* propogate */
+ netmsg_playeritem *prop = alloca(msg->m_cbSize);
+ memcpy( prop, msg->m_pData, msg->m_cbSize );
+ prop->client = client_id;
+ gameserver_send_to_all( client_id, prop, msg->m_cbSize,
+ k_nSteamNetworkingSend_Reliable );
+ }
+ else if( tmp->inetmsg_id == k_inetmsg_chat ){
+ netmsg_chat *chat = msg->m_pData,
+ *prop = alloca( sizeof(netmsg_chat) + NETWORK_MAX_CHAT );
+ prop->inetmsg_id = k_inetmsg_chat;
+ prop->client = client_id;
+
+ u32 l = network_msgstring( chat->msg, msg->m_cbSize, sizeof(netmsg_chat),
+ prop->msg, NETWORK_MAX_CHAT );
+ vg_info( "[%d]: %s\n", client_id, prop->msg );
+
+ gameserver_send_to_all( client_id, prop, sizeof(netmsg_chat)+l+1,
+ k_nSteamNetworkingSend_Reliable );
+ }
+ else if( tmp->inetmsg_id == k_inetmsg_region ){
+ netmsg_region *region = msg->m_pData,
+ *prop = alloca( sizeof(netmsg_region) + NETWORK_REGION_MAX );
+
+ prop->inetmsg_id = k_inetmsg_region;
+ prop->client = client_id;
+ prop->flags = region->flags;
+
+ u32 l = network_msgstring(
+ region->loc, msg->m_cbSize, sizeof(netmsg_region),
+ client->region, NETWORK_REGION_MAX );
+ client->region_flags = region->flags;
+
+ l = vg_strncpy( client->region, prop->loc, NETWORK_REGION_MAX,
+ k_strncpy_always_add_null );
+
+ gameserver_send_to_all( client_id, prop, sizeof(netmsg_region)+l+1,
+ k_nSteamNetworkingSend_Reliable );
+ vg_info( "client %d moved to region: %s\n", client_id, client->region );
+ }
+ else {
+ vg_warn( "Unknown inetmsg_id recieved from client. (%u)\n",
+ tmp->inetmsg_id );
+ }
+}
+
+static void gameserver_request_respond( enum request_status status,
+ netmsg_request *res, vg_msg *body,
+ SteamNetworkingMessage_t *msg ){
+ int client_id = gameserver_conid( msg->m_conn );
+ u32 len = 0;
+ if( body ){
+ len = body->cur.co;
+ vg_low( "[%d#%d] Response: %d\n", client_id, (i32)res->id, status );
+ vg_msg_print( body, len );
+ }
+
+ res->status = status;