From 70792eeb23451cef1f3a103e0c9515b833f81899 Mon Sep 17 00:00:00 2001 From: hgn Date: Thu, 13 Oct 2022 20:53:38 +0100 Subject: [PATCH] achievements --- highscores.h | 150 ++++++++++++++++++++++-------------------- main.c | 3 + player_physics.h | 3 - server.c | 4 ++ steam.h | 168 ++++++++++++++++++++++++++++++++++++++++++++++- world_info.h | 9 ++- world_routes.h | 10 ++- 7 files changed, 268 insertions(+), 79 deletions(-) diff --git a/highscores.h b/highscores.h index 931c708..494cd83 100644 --- a/highscores.h +++ b/highscores.h @@ -92,6 +92,8 @@ static struct highscore_system aainfo_playerinfo; void *data, *playerinfo_data; + + u32 pool_size, playerinfo_pool_size; } highscore_system; @@ -154,20 +156,86 @@ static void highscores_free(void) vg_free( highscore_system.playerinfo_data ); } -static int highscores_init( u32 pool_size, u32 playerinfo_pool_size ) +static void highscores_create_db(void) { struct highscore_system *sys = &highscore_system; - sys->data = highscore_malloc( pool_size, sizeof(highscore_record) ); - if( !sys->data ) return 0; + vg_info( "Initializing database nodes\n" ); + memset( &sys->dbheader, 0, sizeof(highscore_database) ); + + sys->dbheader.pool_head = aatree_init_pool( &sys->aainfo, sys->pool_size ); + sys->dbheader.entry_capacity = sys->pool_size; + + for( int i=0; idbheader.tracks); i++ ) + { + highscore_track_table *table = &sys->dbheader.tracks[i]; + table->root_points = AATREE_PTR_NIL; + table->root_playerid = AATREE_PTR_NIL; + table->root_time = AATREE_PTR_NIL; + table->root_datetime = AATREE_PTR_NIL; + } + + /* Initialize secondary db */ + sys->dbheader.playerinfo_head = aatree_init_pool( + &sys->aainfo_playerinfo, + sys->playerinfo_pool_size ); + sys->dbheader.playerinfo_capacity = sys->playerinfo_pool_size; + sys->dbheader.playerinfo_root = AATREE_PTR_NIL; +} + +static int highscores_read(void) +{ + struct highscore_system *sys = &highscore_system; - sys->playerinfo_data = - highscore_malloc( playerinfo_pool_size, sizeof(highscore_playerinfo)); - if( !sys->playerinfo_data ) + FILE *fp = fopen( ".aadb", "rb" ); + if( fp ) { - vg_free( sys->data ); + vg_info( "Loading existing database\n" ); + + u64 count = fread( &sys->dbheader, sizeof(highscore_database), 1, fp ); + + if( count != 1 ) + { + vg_error( "Unexpected EOF reading database header\n" ); + return 0; + } + + count = fread( sys->data, sizeof(highscore_record), sys->pool_size, fp ); + if( count != sys->pool_size ) + { + vg_error( "Unexpected EOF reading database contents;" + " %lu records of %u were read\n", count, sys->pool_size ); + return 0; + } + + count = fread( sys->playerinfo_data, sizeof(highscore_playerinfo), + sys->playerinfo_pool_size, fp ); + + if( count != sys->playerinfo_pool_size ) + { + vg_error( "Unexpected EOF reading playerinfo contents;" + " %lu records of %u were read\n", count, + sys->playerinfo_pool_size ); + return 0; + } + + fclose( fp ); + return 1; + } + else + { + vg_low( "No existing database found (.aadb)\n" ); return 0; } +} + +static void highscores_init( u32 pool_size, u32 playerinfo_pool_size ) +{ + struct highscore_system *sys = &highscore_system; + + sys->data = highscore_malloc( pool_size, sizeof(highscore_record) ); + sys->playerinfo_data = highscore_malloc( playerinfo_pool_size, + sizeof(highscore_playerinfo)); /* This is ugly.. too bad! */ sys->aainfo.base = highscore_system.data; @@ -206,72 +274,8 @@ static int highscores_init( u32 pool_size, u32 playerinfo_pool_size ) sys->aainfo_playerinfo.offset = offsetof(highscore_playerinfo,aapn); sys->aainfo_playerinfo.p_cmp = NULL; - FILE *fp = fopen( ".aadb", "rb" ); - if( fp ) - { - vg_info( "Loading existing database\n" ); - - u64 count = fread( &sys->dbheader, sizeof(highscore_database), 1, fp ); - - if( count != 1 ) - { - vg_error( "Unexpected EOF reading database header\n" ); - - highscores_free(); - return 0; - } - - count = fread( sys->data, sizeof(highscore_record), pool_size, fp ); - if( count != pool_size ) - { - vg_error( "Unexpected EOF reading database contents;" - " %lu records of %u were read\n", count, pool_size ); - - highscores_free(); - return 0; - } - - count = fread( sys->playerinfo_data, sizeof(highscore_playerinfo), - playerinfo_pool_size, fp ); - if( count != playerinfo_pool_size ) - { - vg_error( "Unexpected EOF reading playerinfo contents;" - " %lu records of %u were read\n", count, - playerinfo_pool_size ); - - highscores_free(); - return 0; - } - - fclose( fp ); - } - else - { - vg_low( "No existing database found (.aadb)\n" ); - vg_info( "Initializing database nodes\n" ); - memset( &sys->dbheader, 0, sizeof(highscore_database) ); - - sys->dbheader.pool_head = aatree_init_pool( &sys->aainfo, pool_size ); - sys->dbheader.entry_capacity = pool_size; - - for( int i=0; idbheader.tracks); i++ ) - { - highscore_track_table *table = &sys->dbheader.tracks[i]; - table->root_points = AATREE_PTR_NIL; - table->root_playerid = AATREE_PTR_NIL; - table->root_time = AATREE_PTR_NIL; - table->root_datetime = AATREE_PTR_NIL; - } - - /* Initialize secondary db */ - sys->dbheader.playerinfo_head = aatree_init_pool( - &sys->aainfo_playerinfo, - playerinfo_pool_size ); - sys->dbheader.playerinfo_capacity = playerinfo_pool_size; - sys->dbheader.playerinfo_root = AATREE_PTR_NIL; - } - - return 1; + sys->playerinfo_pool_size = playerinfo_pool_size; + sys->pool_size = pool_size; } static int highscores_serialize_all(void) diff --git a/main.c b/main.c index 6e61fa2..2ac5e20 100644 --- a/main.c +++ b/main.c @@ -61,6 +61,9 @@ vg_info(" ' ' '--' [] '----- '----- ' ' '---' " "SOFTWARE\n" ); highscores_init( 2000, 50 ); + if( !highscores_read() ) + highscores_create_db(); + vg_loader_highwater( NULL, highscores_save_at_exit, NULL ); vg_sleep_ms(200); diff --git a/player_physics.h b/player_physics.h index 5d18433..8d0b5b8 100644 --- a/player_physics.h +++ b/player_physics.h @@ -717,9 +717,6 @@ static void player_mouseview(void) v2_muladds( view_vel, delta, 0.06f*vg.time_delta, view_vel ); } - v2_muladds( view_vel, (v2f){ vg_get_axis("h1"), vg_get_axis("v1") }, - 3.0f * vg.time_delta, view_vel ); - v2_muls( view_vel, 1.0f-4.2f*vg.time_delta, view_vel ); v2_add( view_vel, player.angles, player.angles ); player.angles[1] = vg_clampf( player.angles[1], -VG_PIf*0.5f, VG_PIf*0.5f ); diff --git a/server.c b/server.c index 8225c6e..d5d5d91 100644 --- a/server.c +++ b/server.c @@ -332,8 +332,12 @@ int main( int argc, char *argv[] ) { signal( SIGINT, inthandler ); signal( SIGQUIT, inthandler ); + + /* TODO: Options to override, ammend, remove etc */ highscores_init( 250000, 10000 ); + if( !highscores_read() ) + highscores_create_db(); steamworks_ensure_txt( "2103940" ); if( !vg_load_steam_symetric_key( "application_key", steam_symetric_key ) ) diff --git a/steam.h b/steam.h index 0be3ff6..fbb4f8a 100644 --- a/steam.h +++ b/steam.h @@ -12,6 +12,7 @@ #include "vg/vg_steam_auth.h" #include "vg/vg_steam_http.h" #include "vg/vg_steam_friends.h" +#include "vg/vg_steam_user_stats.h" /* * We only want to use steamworks if building for the networked version, @@ -34,12 +35,145 @@ static void recv_steam_warning( int severity, const char *msg ) vg_info( "%s\n", msg ); } -static int steam_ready = 0; +static int steam_ready = 0, + steam_stats_ready = 0; + static void *hSteamNetworkingSockets, *hSteamUser; +static ISteamUserStats *hSteamUserStats; static HSteamPipe hSteamClientPipe; +static const char *steam_achievement_names[] = +{ + "ALBERT", "MARC", + "ROUTE_MPY", "ROUTE_MPG", "ROUTE_MPB", "ROUTE_MPR", + "ROUTE_TO", "ROUTE_TC" +}; + +static void steam_store_achievements(void) +{ + SteamAPI_ISteamUserStats_StoreStats( hSteamUserStats ); +} + +static void steam_set_achievement( const char *name ) +{ + if( steam_ready && steam_stats_ready ) + { + if( SteamAPI_ISteamUserStats_SetAchievement( hSteamUserStats, name ) ) + { + vg_success( "Achievement set! '%s'\n", name ); + } + else + { + vg_warn( "Failed to set achievement: %s\n", name ); + } + } + else + { + vg_warn( "Failed to set achievement (steam not ready): %s\n", name ); + } +} + +static void steam_clear_achievement( const char *name ) +{ + if( steam_ready && steam_stats_ready ) + { + if( SteamAPI_ISteamUserStats_ClearAchievement( hSteamUserStats, name ) ) + { + vg_info( "Achievement cleared: '%s'\n", name ); + } + else + { + vg_warn( "Failed to clear achievement: %s\n", name ); + } + } + else + { + vg_warn( "Failed to clear achievement (steam not ready): %s\n", name ); + } +} + + +static int steam_list_achievements( int argc, char const *argv[] ) +{ + vg_info( "Achievements: \n" ); + + if( steam_ready && steam_stats_ready ) + { + for( int i=0; im_pubParam; + + if( rec->m_eResult == k_EResultOK ) + { + vg_info( "Recieved stats for: %lu (user: %lu)\n", rec->m_nGameID, + rec->m_steamIDUser ); + steam_stats_ready = 1; + } + else + { + vg_error( "Error recieveing stats for user (%u)\n", rec->m_eResult ); + } +} + static int steam_init(void) { const char *username = NULL; @@ -71,6 +205,38 @@ static int steam_init(void) ISteamFriends *hSteamFriends = SteamAPI_SteamFriends(); username = SteamAPI_ISteamFriends_GetPersonaName( hSteamFriends ); + + /* + * Request stats + * -------------------------------------------------------- + */ + hSteamUserStats = SteamAPI_SteamUserStats(); + + steam_register_callback( k_iUserStatsReceived, + steam_on_recieve_current_stats ); + + if( !SteamAPI_ISteamUserStats_RequestCurrentStats( hSteamUserStats ) ) + vg_warn( "No Steam Logon: Cannot request stats\n" ); + + + vg_function_push( (struct vg_cmd) + { + .name = "ach_list", + .function = steam_list_achievements + }); + + vg_function_push( (struct vg_cmd) + { + .name = "ach_clear_all", + .function = steam_clear_all_achievements + }); + + vg_function_push( (struct vg_cmd) + { + .name = "ach_set", + .function = steam_set_achievemnt_test + }); + #endif /* TODO: On username update callback */ diff --git a/world_info.h b/world_info.h index c8b3e28..143fb70 100644 --- a/world_info.h +++ b/world_info.h @@ -18,33 +18,40 @@ world_info; static struct track_info { - const char *name; + const char *name, + *achievement_id; int push; } track_infos[] = { { .name = "Megapark Green", + .achievement_id = "ROUTE_MPG", .push = 1 }, { .name = "Megapark Blue", + .achievement_id = "ROUTE_MPB", .push = 1 }, { .name = "Megapark Yellow", + .achievement_id = "ROUTE_MPY", .push = 1 }, { .name = "Megapark Red", + .achievement_id = "ROUTE_MPR", .push = 1 }, { .name = "Coastal Run", + .achievement_id = "ROUTE_TC", .push = 1 }, { .name = "Docks Jumps", + .achievement_id = "ROUTE_TO", .push = 1 } }; diff --git a/world_routes.h b/world_routes.h index 480f705..d8d36d2 100644 --- a/world_routes.h +++ b/world_routes.h @@ -496,7 +496,15 @@ static void world_routes_local_set_record( u32 route, double lap_time ) temp.time = time_centiseconds; highscores_push_record( &temp ); - track_infos[ pr->track_id ].push = 1; + + struct track_info *pti = &track_infos[ pr->track_id ]; + pti->push = 1; + + if( pti->achievement_id ) + { + steam_set_achievement( pti->achievement_id ); + steam_store_achievements(); + } } else { -- 2.25.1