From f6bc1299d5b30e1aba87e6ce084bcd7eed22975f Mon Sep 17 00:00:00 2001 From: hgn Date: Sun, 29 Oct 2023 22:57:19 +0000 Subject: [PATCH] lap timing publish and store, username store in db --- gameserver.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++--- gameserver_db.h | 6 ++-- network.c | 33 ++++++++++++++++++-- network.h | 2 ++ network_msg.h | 1 + world_info.h | 3 -- world_routes.c | 29 +++++++++++++++--- 7 files changed, 138 insertions(+), 17 deletions(-) diff --git a/gameserver.c b/gameserver.c index 1d67536..840f9d0 100644 --- a/gameserver.c +++ b/gameserver.c @@ -321,6 +321,24 @@ static int packet_minsize( SteamNetworkingMessage_t *msg, u32 size ){ } } +struct db_set_username_thread_data { + u64 steamid; + char username[ NETWORK_USERNAME_MAX ]; +}; + +static void gameserver_update_db_username( db_request *db_req ){ + struct db_set_username_thread_data *inf = (void *)db_req->data; + + if( inf->steamid == k_connection_unauthorized ) + return; + + int admin = 0; + if( inf->steamid == 76561198072130043 ) + admin = 2; + + db_updateuser( inf->steamid, inf->username, admin ); +} + static void gameserver_rx_200_300( SteamNetworkingMessage_t *msg ){ netmsg_blank *tmp = msg->m_pData; @@ -353,6 +371,16 @@ static void gameserver_rx_200_300( SteamNetworkingMessage_t *msg ){ 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 = get_connection_authsteamid( msg ); + 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 ){ /* propogate */ @@ -405,14 +433,11 @@ static void gameserver_request_respond( enum request_status status, SteamNetworkingMessage_t *msg ){ int client_id = gameserver_client_index( msg->m_conn ); u32 len = 0; - if( status == k_request_status_ok ){ + if( body ){ len = body->cur.co; - vg_success( "[%d#%d] Response: %d\n", client_id, (i32)res->id, status ); + vg_low( "[%d#%d] Response: %d\n", client_id, (i32)res->id, status ); vg_msg_print( body, len ); } - else{ - vg_warn( "[%d#%d] Response: %d\n", client_id, (i32)res->id, status ); - } res->status = status; @@ -427,6 +452,10 @@ struct user_request_thread_data { SteamNetworkingMessage_t *msg; }; +static u32 gameserver_get_current_week(void){ + return time(NULL) / (7*24*60*60); +} + static void gameserver_process_user_request( db_request *db_req ){ struct user_request_thread_data *inf = (void *)db_req->data; SteamNetworkingMessage_t *msg = inf->msg; @@ -497,6 +526,9 @@ static void gameserver_process_user_request( db_request *db_req ){ i64 steamid_i64 = sqlite3_column_int64( stmt, 0 ); u64 steamid = *((u64 *)&steamid_i64); + if( steamid == k_connection_unauthorized ) + continue; + vg_msg_frame( &body, "" ); vg_msg_wkvu32( &body, "time", time ); vg_msg_wkvu64( &body, "steamid", steamid ); @@ -528,6 +560,45 @@ static void gameserver_process_user_request( db_request *db_req ){ gameserver_request_respond( k_request_status_ok, res, &body, msg ); } + else if( !strcmp( endpoint, "setlap" ) ){ + /* TODO: we can change userdata to be the client ID and store that in + * the client structure. it also would save us scanning the + * client array over and over..? + */ + u64 steamid = get_connection_authsteamid( msg ); + if( steamid == k_connection_unauthorized ){ + gameserver_request_respond( k_request_status_unauthorized, + res, NULL, msg ); + return; + } + + const char *mod = vg_msg_getkvstr( &data, "mod" ); + const char *route = vg_msg_getkvstr( &data, "route" ); + + char weekly_table[ DB_TABLE_UID_MAX ], + alltime_table[ DB_TABLE_UID_MAX ]; + + u32 week = gameserver_get_current_week(); + + if( !db_get_highscore_table_name( mod, route, 0, alltime_table ) || + !db_get_highscore_table_name( mod, route, week, weekly_table ) ){ + gameserver_request_respond( k_request_status_out_of_memory, + res, NULL, msg ); + return; + } + + i32 centiseconds = vg_msg_getkvi32( &data, "time", -1 ); + if( centiseconds < 5*100 ){ + gameserver_request_respond( k_request_status_client_error, + res, NULL, msg ); + return; + } + + db_writeusertime( alltime_table, steamid, centiseconds, 1 ); + db_writeusertime( weekly_table, steamid, centiseconds, 1 ); + + gameserver_request_respond( k_request_status_ok, res, NULL, msg ); + } else{ gameserver_request_respond( k_request_status_invalid_endpoint, res, NULL, msg ); diff --git a/gameserver_db.h b/gameserver_db.h index 9085248..b7f3360 100644 --- a/gameserver_db.h +++ b/gameserver_db.h @@ -277,7 +277,7 @@ static void *db_loop(void *_){ sqlite3_stmt *stmt = db_stmt( "CREATE TABLE IF NOT EXISTS \n" - " users(steamid BIGINT PRIMARY KEY, name VARCHAR(128), type INT);" ); + " users(steamid BIGINT UNIQUE, name VARCHAR(128), type INT);" ); if( stmt ){ int fc = sqlite3_step( stmt ); @@ -376,10 +376,10 @@ static void db_free(void){ } static db_request *db_alloc_request( u32 size ){ - u32 total = sizeof(db_request) + vg_align8(size); + u32 total = sizeof(db_request) + size; pthread_mutex_lock( &database.mux ); - vg_queue_frame *frame = vg_queue_alloc( &database.queue, size ); + vg_queue_frame *frame = vg_queue_alloc( &database.queue, total ); if( frame ){ db_request *req = (db_request *)frame->data; diff --git a/network.c b/network.c index 96832ae..59982b2 100644 --- a/network.c +++ b/network.c @@ -205,7 +205,12 @@ static void network_scoreboard_callback( netmsg_request *res, vg_msg *body ){ if( vg_msg_seekframe( body, "rows" ) ){ while( vg_msg_seekframe( body, NULL ) ){ const char *username = vg_msg_getkvstr( body, "username" ); - sfd_encode( l ++, username ); + + if( username ) + sfd_encode( l ++, username ); + else + sfd_encode( l ++, "UNKNOWN USER" ); + vg_msg_skip_frame( body ); } } @@ -223,7 +228,6 @@ static void network_request_scoreboard( const char *mod_uid, netmsg_request *req = alloca( sizeof(netmsg_request) + 512 ); req->inetmsg_id = k_inetmsg_request; - req->id = 0; /* TODO: pool allocatable */ vg_msg data; vg_msg_init( &data, req->q, 512 ); @@ -234,6 +238,31 @@ static void network_request_scoreboard( const char *mod_uid, network_send_request( req, &data, network_scoreboard_callback ); } +static void network_publish_callback( netmsg_request *res, vg_msg *body ){ + if( res->status != k_request_status_ok ){ + vg_error( "Publish laptime, server error #%d\n", (i32)res->status ); + } +} + +static void network_publish_laptime( const char *mod_uid, + const char *route_uid, f64 lap_time ){ + if( !network_client.remote ) + return; + + i32 time_centiseconds = lap_time * 100.0; + + netmsg_request *req = alloca( sizeof(netmsg_request) + 512 ); + req->inetmsg_id = k_inetmsg_request; + + vg_msg data; + vg_msg_init( &data, req->q, 512 ); + vg_msg_wkvstr( &data, "endpoint", "setlap" ); + vg_msg_wkvstr( &data, "mod", mod_uid ); + vg_msg_wkvstr( &data, "route", route_uid ); + vg_msg_wkvi32( &data, "time", time_centiseconds ); + network_send_request( req, &data, network_publish_callback ); +} + static void network_request_rx_300_400( SteamNetworkingMessage_t *msg ){ netmsg_blank *tmp = msg->m_pData; diff --git a/network.h b/network.h index 752c6c3..2916ad9 100644 --- a/network.h +++ b/network.h @@ -72,5 +72,7 @@ static void network_send_item( enum netmsg_playeritem_type type ); static void network_request_scoreboard( const char *mod_uid, const char *route_uid, u32 week ); +static void network_publish_laptime( const char *mod_uid, + const char *route_uid, f64 lap_time ); #endif /* NETWORK_H */ diff --git a/network_msg.h b/network_msg.h index 83f8707..ca5557c 100644 --- a/network_msg.h +++ b/network_msg.h @@ -159,6 +159,7 @@ struct netmsg_request { enum request_status { k_request_status_client_error = 0, k_request_status_invalid_endpoint = 1, + k_request_status_unauthorized = 2, k_request_status_server_error = 100, k_request_status_out_of_memory = 101, diff --git a/world_info.h b/world_info.h index 7135752..772d9e1 100644 --- a/world_info.h +++ b/world_info.h @@ -14,9 +14,6 @@ struct track_info { const char *name, *achievement_id; - - highscore_record record; /* session */ - int push; } static track_infos[] = { diff --git a/world_routes.c b/world_routes.c index 36d70d7..b271faa 100644 --- a/world_routes.c +++ b/world_routes.c @@ -11,6 +11,7 @@ #include "world_gate.h" #include "world_load.h" #include "highscores.h" +#include "network.h" #include "font.h" #include "pointcloud.h" @@ -20,7 +21,7 @@ #include "shaders/scene_route.h" #include "shaders/routeui.h" - +#if 0 static void world_routes_local_set_record( world_instance *world, ent_route *route, f64 lap_time ) @@ -50,7 +51,7 @@ void world_routes_local_set_record( world_instance *world, ent_route *route, vg_warn( "There is no associated track for this record...\n" ); } } - +#endif static void world_routes_clear( world_instance *world ) { @@ -114,8 +115,28 @@ static void world_routes_time_lap( world_instance *world, ent_route *route ) vg_info( "%u %f\n", world_static.current_run_version, world_static.time ); if( valid_count==route->checkpoints_count ){ - double lap_time = world_static.time - start_time; - world_routes_local_set_record( world, route, lap_time ); + f64 lap_time = world_static.time - start_time; + //world_routes_local_set_record( world, route, lap_time ); + + if( route->anon.official_track_id != 0xffffffff ){ + struct track_info *ti = &track_infos[ route->anon.official_track_id ]; + if( ti->achievement_id ){ + steam_set_achievement( ti->achievement_id ); + steam_store_achievements(); + } + } + + addon_alias *alias = &world_static.addon_hub->alias; + if( world_static.active_instance ) + alias = &world_static.addon_client->alias; + + /* TODO: we should probably generate this once. and also ditch + * sub-worlds */ + char mod_uid[ ADDON_UID_MAX ]; + addon_alias_uid( &world_static.addon_client->alias, mod_uid ); + network_publish_laptime( mod_uid, + mdl_pstr( &world->meta, route->pstr_name ), + lap_time ); } route->valid_checkpoints = valid_count+1; -- 2.25.1