aainfo_playerinfo;
void *data, *playerinfo_data;
+
+ u32 pool_size, playerinfo_pool_size;
}
highscore_system;
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; i<vg_list_size(sys->dbheader.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;
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; i<vg_list_size(sys->dbheader.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)
"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);
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 );
{
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 ) )
#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,
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; i<vg_list_size(steam_achievement_names); i++ )
+ {
+ int set = 0;
+ const char *name = steam_achievement_names[i];
+
+ if( SteamAPI_ISteamUserStats_GetAchievement(
+ hSteamUserStats, name, &set ) )
+ {
+ vg_info( " %s %s\n", (set? "[YES]": "[ ]"), name );
+ }
+ else
+ {
+ vg_warn( " Error while fetching achievement status '%s'\n", name );
+ }
+ }
+ }
+ else
+ {
+ vg_warn( " Steam is not initialized, no results\n" );
+ }
+
+ return 0;
+}
+
+static int steam_clear_all_achievements( int argc, char const *argv[] )
+{
+ if( steam_ready && steam_stats_ready )
+ {
+ for( int i=0; i<vg_list_size(steam_achievement_names); i++ )
+ {
+ steam_clear_achievement( steam_achievement_names[i] );
+ }
+
+ steam_store_achievements();
+ }
+ else
+ {
+ vg_warn( "steam is not initialized, cannot clear\n" );
+ }
+
+ return 0;
+}
+
+static int steam_set_achievemnt_test( int argc, char const *argv[] )
+{
+ if( argc < 2 )
+ return 0;
+
+ if( strcmp( argv[0], "monkey_island" ) )
+ return 0;
+
+ steam_set_achievement( argv[1] );
+ steam_store_achievements();
+
+ return 0;
+}
+
+static void steam_on_recieve_current_stats( CallbackMsg_t *msg )
+{
+ UserStatsReceived_t *rec = (UserStatsReceived_t *)msg->m_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;
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 */
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
}
};
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
{