loadsa work
authorhgn <hgodden00@gmail.com>
Sat, 13 Aug 2022 21:47:34 +0000 (22:47 +0100)
committerhgn <hgodden00@gmail.com>
Sat, 13 Aug 2022 21:47:34 +0000 (22:47 +0100)
build.sh
highscores.h [new file with mode: 0644]
main.c
network.h
network_msg.h
testaa.c [new file with mode: 0644]

index a4683b70ee2d26d5c26023928a9f08f454140761..ace67bfe87e6e9ddddec5c1468fb4c7b587e5862 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -155,6 +155,20 @@ vg_command(){
 
          compile_x
       ;;
+      testaa)
+         titleit "Dev"
+         mkdir -p bin/aatest/cfg
+
+         _compiler=$_linux_compiler
+         _options=$_linux_options
+         _link="-lm"
+         _src="testaa.c"
+         _folder=bin/aatest
+         _dst="testaa"
+         _ext=""
+
+         compile_x
+      ;;
       
       #TODO: These are not cross platform in the build script, a full build
       #      from source is therefore not possible on windows, only a linux
@@ -213,6 +227,12 @@ vg_command(){
          run_server
          wait
       ;;
+      aa)
+         run_command testaa
+         cd bin/aatest
+         ./testaa
+         cd ./../
+      ;;
       *)
          echo "Unrecognised command $1"
    esac
diff --git a/highscores.h b/highscores.h
new file mode 100644 (file)
index 0000000..2ffaf6a
--- /dev/null
@@ -0,0 +1,271 @@
+#ifndef HIGHSCORES_H
+#define HIGHSCORES_H
+
+#include "vg/vg_store.h"
+#include "vg/vg_stdint.h"
+
+/* 
+ * Designed to be used across client and server,
+ * for the client its only storing the local users records, for server its 
+ * storing many.
+ */
+
+typedef struct highscore highscore;
+typedef struct highscore_record highscore_record;
+typedef struct highscore_track_table highscore_track_table;
+typedef struct highscore_database highscore_database;
+
+#pragma pack(push,1)
+struct highscore_record
+{
+   u16 trackid, points, time, reserved0;
+   u64 playerid;
+   u32 datetime;
+
+   u32 reserved[7];
+   
+   union
+   {
+      struct
+      {
+         aatree_node points,
+                     time,
+                     playerid,
+                     datetime;
+      }
+      aa;
+
+      struct
+      {
+         /* TODO pool allocator */
+         u32 next, prev;
+      }
+      pool;
+   };
+};
+
+struct highscore_track_table
+{
+   aatree_ptr root_points,
+              root_time,
+              root_playerid,
+              root_datetime;
+
+   u32 reserved[12];
+};
+
+struct highscore_database
+{
+   highscore_track_table tracks[ 128 ];
+
+   aatree_ptr pool_head;
+   u32 reserved[63];
+};
+
+#pragma pack(pop)
+
+static struct highscore_system
+{
+   highscore_database dbheader;
+   aatree aainfo,
+          aainfo_points,
+          aainfo_time,
+          aainfo_playerid,
+          aainfo_datetime;
+
+   void *data;
+}
+highscore_system;
+
+static int highscore_cmp_points( void *a, void *b )
+{
+   highscore_record *pa = a, *pb = b;
+   return (int)pa->points - (int)pb->points;
+}
+
+static int highscore_cmp_datetime( void *a, void *b )
+{
+   highscore_record *pa = a, *pb = b;
+   
+   if( pa->datetime == pb->datetime ) return 0;
+   return pa->datetime < pb->datetime? 1: -1;
+}
+
+static int highscore_cmp_time( void *a, void *b )
+{
+   highscore_record *pa = a, *pb = b;
+   return (int)pb->time - (int)pa->time;
+}
+
+static int highscore_cmp_playerid( void *a, void *b )
+{
+   highscore_record *pa = a, *pb = b;
+   if( pa->playerid == pb->playerid ) return 0;
+   return pa->playerid < pb->playerid? -1: 1;
+}
+
+static int highscores_init( u32 pool_size )
+{
+   struct highscore_system *sys = &highscore_system;
+
+   size_t requested_mem = pool_size * sizeof(highscore_record);
+   sys->data = malloc( requested_mem );
+
+   requested_mem /= 1024;
+   requested_mem /= 1024;
+
+   if( !highscore_system.data )
+   {
+      vg_error( "Could not allocated %dmb of memory for database\n",
+                  requested_mem );
+      return 0;
+   }
+   else
+      vg_success( "Allocated %dmb for database\n", requested_mem );
+
+   /* This is ugly.. too bad! */
+   sys->aainfo.base = highscore_system.data;
+   sys->aainfo.stride = sizeof(highscore_record);
+   sys->aainfo.offset = offsetof(highscore_record,pool);
+   sys->aainfo.p_cmp = NULL;
+
+   sys->aainfo_datetime.base = highscore_system.data;
+   sys->aainfo_datetime.stride = sizeof(highscore_record);
+   sys->aainfo_datetime.offset = offsetof(highscore_record,aa.datetime);
+   sys->aainfo_datetime.p_cmp = highscore_cmp_datetime;
+
+   sys->aainfo_points.base = highscore_system.data;
+   sys->aainfo_points.stride = sizeof(highscore_record);
+   sys->aainfo_points.offset = offsetof(highscore_record,aa.points);
+   sys->aainfo_points.p_cmp = highscore_cmp_points;
+
+   sys->aainfo_time.base = highscore_system.data;
+   sys->aainfo_time.stride = sizeof(highscore_record);
+   sys->aainfo_time.offset = offsetof(highscore_record,aa.time);
+   sys->aainfo_time.p_cmp = highscore_cmp_time;
+
+   sys->aainfo_playerid.base = highscore_system.data;
+   sys->aainfo_playerid.stride = sizeof(highscore_record);
+   sys->aainfo_playerid.offset = offsetof(highscore_record,aa.playerid);
+   sys->aainfo_playerid.p_cmp = highscore_cmp_playerid;
+
+
+   /* TODO: Load from disk if avalible */
+   if( 0 )
+   {
+
+   }
+   else
+   {
+      vg_info( "Initializing database nodes\n" );
+      sys->dbheader.pool_head = aatree_init_pool( &sys->aainfo, 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;
+      }
+   }
+
+   return 1;
+}
+
+static void highscores_free(void)
+{
+   free( highscore_system.data );
+}
+
+static aatree_ptr highscores_push_record( highscore_record *record )
+{
+   struct highscore_system *sys = &highscore_system;
+
+   /* TODO: Verify steam ID */
+   vg_log( "Inserting record into database for track %hu\n",record->trackid );
+
+   if( record->trackid >= vg_list_size(sys->dbheader.tracks) )
+   {
+      vg_error( "TrackID out of range (%hu>=%d)\n", record->trackid,
+                  vg_list_size(sys->dbheader.tracks) );
+
+      return AATREE_PTR_NIL;
+   }
+
+   /* Search for existing record on this track */
+   highscore_track_table *table = &sys->dbheader.tracks[record->trackid];
+   aatree_ptr existing = aatree_find( &sys->aainfo_playerid, 
+                                       table->root_playerid,
+                                       record );
+
+   if( existing != AATREE_PTR_NIL )
+   {
+      vg_log( "Freeing existing record for player %lu\n", record->playerid );
+      table->root_playerid = aatree_del( &sys->aainfo_playerid, existing );
+      table->root_datetime = aatree_del( &sys->aainfo_datetime, existing );
+      table->root_points = aatree_del( &sys->aainfo_points, existing );
+      table->root_time = aatree_del( &sys->aainfo_time, existing );
+
+      aatree_pool_free( &sys->aainfo, existing, &sys->dbheader.pool_head );
+   }
+
+   aatree_ptr index = 
+      aatree_pool_alloc( &sys->aainfo, &sys->dbheader.pool_head );
+
+   if( index == AATREE_PTR_NIL )
+      return index;
+
+   highscore_record *dst = aatree_get_data( &sys->aainfo, index );
+   memset( dst, 0, sizeof(highscore_record) );
+
+   dst->trackid = record->trackid;
+   dst->datetime = record->datetime;
+   dst->playerid = record->playerid;
+   dst->points = record->points;
+   dst->time = record->time;
+
+   table->root_time = 
+      aatree_insert( &sys->aainfo_time, table->root_time, index );
+   table->root_datetime =
+      aatree_insert( &sys->aainfo_datetime, table->root_datetime, index );
+   table->root_playerid = 
+      aatree_insert( &sys->aainfo_playerid, table->root_playerid, index );
+   table->root_points =
+      aatree_insert( &sys->aainfo_points, table->root_points, index );
+
+   return index;
+}
+
+static void _highscore_showtime( void *data )
+{
+   highscore_record *record = data;
+   printf( "%hu", record->time );
+}
+
+static void highscores_print_track( u32 trackid, u32 count )
+{
+   struct highscore_system *sys = &highscore_system;
+
+   highscore_track_table *table = &sys->dbheader.tracks[ trackid ];
+   aatree_ptr it = aatree_kth( &sys->aainfo_time, table->root_time, 0 );
+
+   vg_info( "Highscores, top %u records for track %u\n", count, trackid );
+   vg_info( "==============================================\n" );
+
+   int i=0;
+   while( it != AATREE_PTR_NIL && i < 10 )
+   {
+      highscore_record *record = aatree_get_data( &sys->aainfo_time, it );
+      vg_info( "  [%d]: player(%lu), time: %hu, score: %hu, track:%hu\n",
+                  i+1, record->playerid, record->time, record->points,
+                  record->trackid );
+
+      i++;
+      it = aatree_next( &sys->aainfo_time, it );
+   }
+
+   vg_info( "==============================================\n" );
+}
+
+#endif /* HIGHSCORES_H */
diff --git a/main.c b/main.c
index bfac7fd7fe2a93c7ac3d495778fa8f61fb1f5669..175f12efe879a4af4a8244c231bf57fd3f47117a 100644 (file)
--- a/main.c
+++ b/main.c
@@ -23,7 +23,7 @@ static int sv_scene = 0;
 #define SR_NETWORKED
 
 /* uncomment this to run the game without any graphics being drawn */
-#define SR_NETWORK_TEST
+//#define SR_NETWORK_TEST
 
 #include "steam.h"
 #include "network.h"
index 1644982917a49d4b5d08e7bf1abb72bfaf396f40..ee0f334d5cb04156dda91cac833cdcbd8cd04b9c 100644 (file)
--- a/network.h
+++ b/network.h
@@ -24,7 +24,6 @@ static void network_end(void);
  */
 static void network_submit_highscore( u32 trackid, u16 points, u16 time );
 
-
 /*
  * Game endpoints are provided with the same names to allow running without a
  * network connection.
@@ -112,6 +111,23 @@ static void server_connect(void)
                   hSteamNetworkingSockets, &remoteAddr, 0, NULL );
 }
 
+static void send_auth_ticket(void)
+{
+   u32 size = sizeof(netmsg_auth) + steam_app_ticket_length;
+   netmsg_auth *auth = malloc(size);
+
+   auth.inetmsg_id = k_inetmsg_auth;
+   auth.ticket_length = steam_app_ticket_length; 
+   for( int i=0; i<steam_app_ticket_length; i++ )
+      auth.ticket[i] = steam_app_ticket[i];
+
+   SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+         hSteamNetworkingSockets, cremote, auth, size,
+         k_nSteamNetworkingSend_Reliable, NULL );
+   
+   free( auth );
+}
+
 static void scores_update(void)
 {
    vg_log( "scores_update()\n" );
@@ -119,7 +135,7 @@ static void scores_update(void)
    if( cremote_state == k_ESteamNetworkingConnectionState_Connected )
    {
       /*
-       * request updated scores
+       * request updated scores, this does not require any authentication.
        */
       netmsg_scores_request req;
       req.inetmsg_id = k_inetmsg_scores_request;
@@ -128,6 +144,13 @@ static void scores_update(void)
             hSteamNetworkingSockets, cremote, &req, 
             sizeof(netmsg_scores_request),
             k_nSteamNetworkingSend_Reliable, NULL );
+
+      /*
+       * Send record update, it requires authentication
+       */
+      if( steam_app_ticket_length )
+      {
+      }
    }
    else
    {
index b26300926fc3412b971dc01e63971989da7d405f..6c072f14fc44196f9ce7f6af2912a0a2431cd908 100644 (file)
@@ -40,5 +40,15 @@ struct netmsg_scores_info
 };
 enum{ k_inetmsg_scores_info = 2 };
 
+typedef struct netmsg_auth netmsg_auth;
+struct netmsg_auth
+{
+   u32 inetmsg_id;
+
+   u32 ticket_length;
+   u8 ticket[];
+};
+enum{ k_inetmsg_auth = 3 };
+
 #pragma pack(pop)
 #endif /* NETWORK_MSG_H */
diff --git a/testaa.c b/testaa.c
new file mode 100644 (file)
index 0000000..aa1bf13
--- /dev/null
+++ b/testaa.c
@@ -0,0 +1,150 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "vg/vg_platform.h"
+#include "vg/vg_stdint.h"
+#include "vg/vg_store.h"
+#include "vg/vg_io.h"
+#include "vg/vg_m.h"
+
+#include "highscores.h"
+
+int main(int argc, const char *argv[])
+{
+   vg_info( "Database test\n" );
+
+   if( !highscores_init( 200000 ) )
+      return 0;
+
+   vg_log( "Inserting test records...\n" );
+   for( int i=0; i<200000; i++ )
+   {
+      highscore_record entry;
+      entry.trackid = vg_randf() * 129.0f;
+      entry.points = vg_randf() * 10000.0f;
+      entry.time = vg_randf() * 20000.0f;
+      entry.playerid = rand() % 800;
+      entry.datetime = vg_randf() * 100000.0f;
+      
+      highscores_push_record( &entry );
+   }
+   vg_log( "Done.\n" );
+
+   highscores_print_track( 2, 10 );
+   highscores_free();
+   return 0;
+}
+
+#if 0
+typedef struct yoyo_t yoyo_t;
+struct yoyo_t
+{
+   int my_data;
+   aatree_node anode;
+};
+
+static void yoyo_t_show( void *_data )
+{
+   yoyo_t *data = _data;
+   printf( "%d ", data->my_data );
+}
+
+static int yoyo_t_cmp( void *_a, void *_b )
+{
+   yoyo_t *a = _a, *b = _b;
+   return b->my_data - a->my_data;
+}
+
+int main(int argc, const char *argv[])
+{
+   yoyo_t *allsorts = malloc( sizeof(yoyo_t) * 10000 );
+
+   aatree test;
+   test.base = allsorts;
+   test.offset = offsetof( yoyo_t, anode );
+   test.stride = sizeof( yoyo_t );
+   test.p_cmp = yoyo_t_cmp;
+   
+   for( int i=0; i<30; i++ ) vg_randf();
+
+   for( int j=0; j<1000; j++ )
+   {
+      int spam_amt = 100;
+      aatree_ptr root = AATREE_PTR_NIL;
+      for( int i=0; i<spam_amt; i++ )
+      {
+         yoyo_t *rando = &allsorts[i];
+         rando->my_data = vg_randf() * 563.0f;
+         root = aatree_insert( &test, root, i );
+      }
+
+      int ln=0, err=0;
+      int drawting = 1;
+      aatree_show_counts( &test, root, 0, &ln, &err, yoyo_t_show, drawting );
+
+#if 0
+      int value = 3;
+      vg_info( "Ptr of %d: %u\n", value, aatree_find( &test, root, &value ) );
+
+      for( int i=0; i<20; i++ )
+      {
+         yoyo_t *v = aatree_get_data(&test,aatree_kth( &test, root, i ));
+         vg_info( "Value of [%d]: %d\n", i, v->my_data );
+      }
+#endif
+      if( ln != spam_amt || err != 0 )
+      {
+         vg_error( "ADJAWIUDWAJD\n" );
+         break;
+      }
+
+      aatree_ptr traverser = aatree_kth( &test, root, 0 );
+
+      while( traverser != AATREE_PTR_NIL )
+      {
+         yoyo_t *v = aatree_get_data( &test, traverser );
+         vg_info( "... %d\n", v->my_data );
+
+         traverser = aatree_next( &test, traverser );
+      }
+
+      int orig = spam_amt;
+      for( int i=0; i<orig; i++ )
+      {
+         int remover = vg_min( (int)(vg_randf() * spam_amt), spam_amt-1 );
+         aatree_ptr kremove = aatree_kth( &test, root, remover );
+
+         vg_info( "Removing K %d\n", remover );
+         vg_info( "id: %d\n", kremove );
+
+         if( drawting )
+         vg_info( "AND NOW REMOVE K %d (id: %d, value: %d)\n", remover, kremove,
+               *((int*)aatree_get_data( &test, kremove )) );
+
+         root = aatree_del( &test, kremove );
+
+         ln=0;
+         err=0;
+         aatree_show_counts( &test, root, 0, &ln, &err, yoyo_t_show, drawting );
+
+         if( ln != spam_amt-1 || err != 0 )
+         {
+            vg_error( "ADJAWIUDWAJD ( %d %d // %d, %d)\n",
+                        j, ln, spam_amt, err );
+            free( allsorts );
+            return 0;
+         }
+         vg_success( "%d\n", j );
+         spam_amt --;
+      }
+   }
+
+   free( allsorts );
+   return 0;
+}
+
+#endif