stuff
authorhgn <hgodden00@gmail.com>
Wed, 17 Aug 2022 23:58:44 +0000 (00:58 +0100)
committerhgn <hgodden00@gmail.com>
Wed, 17 Aug 2022 23:58:44 +0000 (00:58 +0100)
blender_export.py
build.sh
highscores.h
network.h
network_msg.h
server.c
testaa.c
world_info.h [new file with mode: 0644]
world_routes.h

index 6fadae28decb6428fee5dc197795724c75884b17..c520e04251dffd45ad2780106f806b082ef47f00 100644 (file)
@@ -752,14 +752,10 @@ def cv_draw():
                   continue
 
          if loop_complete:
-            course_colours = [Vector((0,0.8,0.2,1.0)),  \
-                              Vector((0,0.3,0.9,1.0)),  \
-                              Vector((0.4,0.0,0.8,1.0)),\
-                              Vector((0.5,0.8,0.0,1.0)),\
-                              Vector((0.0,0.7,0.6,1.0)),\
-                              Vector((0.2,0.9,0.5,1.0)) ]
-
-            cc = course_colours[ course_count % len(course_colours) ]
+            cc = Vector((obj.cv_data.colour[0],\
+                         obj.cv_data.colour[1],\
+                         obj.cv_data.colour[2],\
+                         1.0))
 
             for sj in range(si):
                sk = (sj+1)%si
index ace67bfe87e6e9ddddec5c1468fb4c7b587e5862..9fb788624c2229e93f583e6b1d78ac4c5343ad9e 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -144,10 +144,11 @@ vg_command(){
          # Dependencies
          cp vg/dep/steam/steamclient.so bin/linux_server/
          cp vg/dep/steam/libsteam_api.so bin/linux_server/
+         cp vg/dep/steam/libsdkencryptedappticket.so bin/linux_server/
 
          _compiler=$_linux_compiler
          _options=$_linux_options
-         _link="-lm $_linux_linksteam"
+         _link="-lm -lsdkencryptedappticket $_linux_linksteam"
          _src="server.c"
          _folder=$_linux_server_folder
          _dst="skaterift_server"
index 84ab9a4164a5c9e0a8ab14e9d61179d4ca60437e..b1c9cc0a5d591794388213552ab1938a75003a0b 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "vg/vg_store.h"
 #include "vg/vg_stdint.h"
+#include "world_info.h"
 
 /* 
  * Designed to be used across client and server,
@@ -20,7 +21,7 @@ typedef struct highscore_playerinfo highscore_playerinfo;
 
 struct highscore_playerinfo
 {
-   char nickname[16];
+   char nickname[10];
    u64 playerid;
 
    union
@@ -364,9 +365,14 @@ static aatree_ptr highscores_push_record( highscore_record *record )
    return index;
 }
 
-static aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[16] )
+static aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[10] )
 {
-   vg_log( "Updating %lu's nickname\n", steamid );
+   char name[11];
+   for( int i=0; i<10; i++ )
+      name[i] = nick[i];
+   name[10] = '\0';
+
+   vg_log( "Updating %lu's nickname -> %s\n", steamid, name );
 
    struct highscore_system *sys = &highscore_system;
    
@@ -403,76 +409,206 @@ static aatree_ptr highscore_set_user_nickname( u64 steamid, char nick[16] )
             record );
    }
 
-   for( int i=0; i<16; i++ )
+   for( int i=0; i<10; i++ )
       info->nickname[i] = nick[i];
 
    return AATREE_PTR_NIL;
 }
 
-static void _highscore_showtime( void *data )
+/* Get the length of a string, bounded by '\0' or len, whichever is first */
+static int highscore_strlen( const char *str, int len )
+{
+   int str_length;
+   for( str_length=0; str_length<len; str_length++ )
+      if( !str[str_length] )
+         return str_length;
+
+   return str_length;
+}
+
+/* Print the string(max length:len) centered into buf (has width:width) */
+static void highscore_strc( char *buf, const char *str, int len, int width )
+{
+   int str_length = highscore_strlen( str, len ),
+       offs = (width-str_length)/2;
+
+   for( int i=0; i<str_length; i++ )
+   {
+      int j=i+offs;
+
+      if( j >= width )
+         return;
+
+      buf[j] = str[i];
+   }
+}
+
+/* Print the string(max length:len) left aligned into buf */
+static void highscore_strl( char *buf, const char *str, int len )
 {
-   highscore_record *record = data;
-   printf( "%hu", record->time );
+   for( int i=0; i<len; i++ )
+   {
+      if( !str[i] )
+         return;
+
+      buf[i] = str[i];
+   }
+}
+
+/* Print the string (max length:len) right aligned into buf (has width:width) */
+static void highscore_strr( char *buf, const char *str, int len, int width )
+{
+   int str_length = highscore_strlen( str, len );
+   
+   for( int i=0; i<len; i++ )
+   {
+      if( !str[i] )
+         return;
+
+      buf[width-str_length+i] = str[i];
+   }
+}
+
+/* Print integer (padded with: alt), right aligned into buf(width: len) */
+static void highscore_intr( char *buf, int value, int len, char alt )
+{
+   int i=0;
+   while(value)
+   {
+      if( i>=len ) 
+         return;
+
+      buf[ len-1 - (i ++) ] = '0' + (value % 10);
+      value /= 10;
+   }
+
+   for( ;i<len; i ++ )
+      buf[ len-1 - i ] = alt;
 }
 
-static void _highscore_showname( void *data )
+/* Print integer into buffer with max length len */
+static void highscore_intl( char *buf, int value, int len )
 {
-   char namebuf[17];
-   namebuf[16] = '\0';
+   char temp[32];
+
+   int i=0;
+   while(value)
+   {
+      if( i>=len ) 
+         break;
 
-   highscore_playerinfo *info = data;
-   for( int i=0; i<16; i++ )
-      namebuf[i] = info->nickname[i];
+      temp[ i ++ ] = '0' + (value % 10);
+      value /= 10;
+   }
+   
+   if( i>len )
+      i = len;
 
-   printf( " %lu %s", info->playerid, namebuf );
+   for( int j=0; j<i; j ++ )
+   {
+      buf[j] = temp[ i-1-j ];
+   }
+}
+
+/* Clear buffer with length using clr character */
+static void highscore_clear( char *buf, char clr, int length )
+{
+   for( int i=0; i<length; i++ )
+      buf[i] = clr;
 }
 
-static void highscores_print_track( u32 trackid, u32 count )
+/*
+       Megapark Green      
+--------------------------
+ #|   Player |  Time | Pts 
+ 1|aaaabbbbcc 5:23.32 30000
+ 2|       jef 0:20.34 10000
+ 3|aaabbbcccl 2:30.45 20000
+ 4|
+ 5|
+ 6|
+ 7|
+ 8|
+ 9|
+10|
+*/
+
+/* Generate a highscores board in text form, the width is always 27. Buffer 
+ * must be (count+3)*27 in size. */
+static void highscores_board_generate( char *buf, u32 id, u32 count )
 {
+   int w=27;
+   highscore_clear( buf, ' ', (count+3)*w );
+
+   struct track_info *inf = &track_infos[id];
    struct highscore_system *sys = &highscore_system;
 
-   highscore_track_table *table = &sys->dbheader.tracks[ trackid ];
+   highscore_track_table *table = &sys->dbheader.tracks[ id ];
    aatree_ptr it = aatree_kth( &sys->aainfo_time, table->root_time, 0 );
 
-   vg_info( "Highscores: top %u fastest records for track %u\n", count, trackid );
-   vg_info( "================================================\n" );
-   vg_info( "%3s| %16s | %5s | %5s | %s\n", "#", "Player", "Time", "Score", 
-                                                                   "TrackID" );
-   vg_info( "================================================\n" );
-   int i=0;
-   while( it != AATREE_PTR_NIL && i < 10 )
+   highscore_strc ( buf+w*0, inf->name, w,w );
+   highscore_clear( buf+w*1, '-', w );
+   highscore_strl ( buf+w*2, " #|  Player  | Time  | Pts", 27 );
+
+   for( int i=0; i<count; i++ )
    {
-      highscore_record *record = aatree_get_data( &sys->aainfo_time, it );
+      char *line = buf+w*(3+i);
+      highscore_intr( line, i+1, 2, ' ' );
+      line[2] = '|';
 
+      if( it == AATREE_PTR_NIL )
+         continue;
+
+      highscore_record *record = aatree_get_data( &sys->aainfo_time, it );
       highscore_playerinfo temp;
       temp.playerid = record->playerid;
 
       aatree_ptr info_ptr = aatree_find( &sys->aainfo_playerinfo_playerid,
                                           sys->dbheader.playerinfo_root,
                                           &temp );
-
-      char namebuf[17];
+      
+      /* Player name */
       if( info_ptr == AATREE_PTR_NIL )
-         snprintf( namebuf, 16, "[%lu]", record->playerid );
+         highscore_strl( line+3, "unknown", 10 );
       else
       {
          highscore_playerinfo *inf = aatree_get_data( 
                &sys->aainfo_playerinfo_playerid, info_ptr );
 
-         for( int i=0; i<16; i++ )
-            namebuf[i] = inf->nickname[i];
-         namebuf[16] = '\0';
+         highscore_strl( line+3, inf->nickname, 10 );
       }
 
-      vg_info( "%3d| %16s   %5hu   %5hu   %3hu\n",
-                  i+1, namebuf, record->time, record->points,
-                  record->trackid );
+      u16 miliseconds = record->time,
+          seconds     = miliseconds / 100,
+          minutes     = seconds / 60;
+
+      miliseconds %= 100;
+      seconds     %= 60;
+      minutes     %= 60;
 
-      i++;
+      if( minutes > 9 ) minutes = 9;
+      
+      /* Timer */
+      highscore_intr( line+14, minutes, 1, '0' );
+      line[15] = ':';
+      highscore_intr( line+16, seconds, 2, '0' );
+      line[18] = '.';
+      highscore_intr( line+19, miliseconds, 2, '0' );
+
+      /* Score */
+      highscore_intl( line+22, record->time, 5 );
       it = aatree_next( &sys->aainfo_time, it );
    }
+}
+
+/* Print string out to file using newlines. Count is number of records 
+ * ( this requires a buffer of (count+3)*27 size */
+static void highscores_board_printf( FILE *fp, const char *buf, u32 count )
+{
+   int w=27;
 
-   vg_info( "================================================\n" );
+   for( int i=0; i<count+3; i++ )
+      fprintf( fp, "%.27s\n", &buf[i*w] );
 }
 
 #endif /* HIGHSCORES_H */
index ee0f334d5cb04156dda91cac833cdcbd8cd04b9c..b6cb5660e497e36d28e161794a06d2601b04c2de 100644 (file)
--- a/network.h
+++ b/network.h
@@ -4,10 +4,12 @@
 #include "vg/vg_stdint.h"
 #include "steam.h"
 #include "network_msg.h"
+#include "highscores.h"
 
 /* 
  * Interface
  */
+#define SR_USE_LOCALHOST
 
 /* Call it at start; Connects us to the gameserver */
 static void network_init(void);
@@ -35,6 +37,7 @@ static void network_submit_highscore( u32 trackid, u16 points, u16 time );
  */
 static u8 steam_app_ticket[ 1024 ];
 static u32 steam_app_ticket_length;
+static int network_name_update = 1;
 
 static HSteamNetConnection cremote;
 static ESteamNetworkingConnectionState cremote_state = 
@@ -89,14 +92,107 @@ static void request_auth_ticket(void)
                                                               NULL, 0 );
 }
 
-static void server_connect(void)
+static void send_auth_ticket(void)
 {
-   /* Connect to server if not connected */
+   u32 size = sizeof(netmsg_auth) + steam_app_ticket_length;
+   netmsg_auth *auth = alloca(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 );
+}
+
+static void send_score_request(void)
+{
+   vg_info( "Requesting scores\n" );
+   netmsg_scores_request req;
+   req.inetmsg_id = k_inetmsg_scores_request;
+
+   SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+         hSteamNetworkingSockets, cremote, &req, sizeof(netmsg_scores_request),
+         k_nSteamNetworkingSend_Reliable, NULL );
+}
+
+static void send_score_update(void)
+{
+   vg_info( "Sending scores\n" );
+   u32 size = sizeof(netmsg_set_score) + 
+                  1 * sizeof(struct netmsg_score_record);
+
+   netmsg_set_score *setscore = alloca( size );
+   setscore->inetmsg_id = k_inetmsg_set_score;
+   setscore->record_count = 1;
+   setscore->records[0].trackid = 0;
+   setscore->records[0].playerid = 0;
+   setscore->records[0].points = 1386;
+   setscore->records[0].time = 19432;
+
+   SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+         hSteamNetworkingSockets, cremote, setscore, size,
+         k_nSteamNetworkingSend_Reliable, NULL );
+}
+
+static void send_nickname(void)
+{
+   netmsg_set_nickname nick;
+   nick.inetmsg_id = k_inetmsg_set_nickname;
+
+   memset( nick.nickname, 0, 10 );
+   strcpy( nick.nickname, "real H" );
    
+   SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+         hSteamNetworkingSockets, cremote, &nick, sizeof(netmsg_set_nickname),
+         k_nSteamNetworkingSend_Reliable, NULL );
+
+   network_name_update = 0;
+}
+
+static void server_routine_update(void)
+{
+   send_auth_ticket();
+
+   if( network_name_update )
+      send_nickname();
+
+   send_score_update();
+   send_score_request();
+}
+
+static void on_server_connect_status( CallbackMsg_t *msg )
+{
+   SteamNetConnectionStatusChangedCallback_t *info = (void *)msg->m_pubParam;
+   vg_info( "  Connection status changed for %lu\n", info->m_hConn );
+   vg_info( "  %s -> %s\n", 
+         string_ESteamNetworkingConnectionState(info->m_eOldState),
+         string_ESteamNetworkingConnectionState(info->m_info.m_eState) );
+
+   if( info->m_hConn == cremote )
+   {
+      cremote_state = info->m_info.m_eState;
+      if( info->m_info.m_eState ==
+            k_ESteamNetworkingConnectionState_Connected )
+      {
+         vg_success("  Connected to remote server.. running updates\n");
+         server_routine_update();
+      }
+   }
+   else
+   {
+      vg_warn( "  Recieved signal from unknown connection\n" );
+   }
+}
+
+static void network_connect_gc(void)
+{
+   /* Connect to server if not connected */
    SteamNetworkingIPAddr remoteAddr;
 
-#define USE_LOCALHOST
-#ifdef USE_LOCALHOST
+#ifdef SR_USE_LOCALHOST
    SteamAPI_SteamNetworkingIPAddr_SetIPv6LocalHost( &remoteAddr, 27402 );
 #else
    const char *server_lon1 = "46.101.34.155:27402";
@@ -111,55 +207,38 @@ static void server_connect(void)
                   hSteamNetworkingSockets, &remoteAddr, 0, NULL );
 }
 
-static void send_auth_ticket(void)
+static void on_inet_scoreboard( SteamNetworkingMessage_t *msg )
 {
-   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 );
-}
+   netmsg_scoreboard *sb = msg->m_pData;
 
-static void scores_update(void)
-{
-   vg_log( "scores_update()\n" );
+   u32 base_size = sizeof(netmsg_scoreboard)-
+      sizeof(struct netmsg_board)*vg_list_size(track_infos),
+       expected = base_size+sizeof(struct netmsg_board)*sb->board_count;
 
-   if( cremote_state == k_ESteamNetworkingConnectionState_Connected )
+   if( msg->m_cbSize != expected )
    {
-      /*
-       * request updated scores, this does not require any authentication.
-       */
-      netmsg_scores_request req;
-      req.inetmsg_id = k_inetmsg_scores_request;
-
-      SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
-            hSteamNetworkingSockets, cremote, &req, 
-            sizeof(netmsg_scores_request),
-            k_nSteamNetworkingSend_Reliable, NULL );
-
-      /*
-       * Send record update, it requires authentication
-       */
-      if( steam_app_ticket_length )
-      {
-      }
+      vg_error( "Server scoreboard was corrupted. Size: %u != %u\n",
+            msg->m_cbSize, expected );
    }
    else
    {
-      /* 
-       * if we are not connected, make a connection to the server and then in 
-       * the future this function will be called again when it is connected 
-       */
-      server_connect();
+      if( vg_list_size(track_infos) > sb->board_count )
+         vg_warn( "Server is out of date, not enough boards recieved\n");
+      else if( vg_list_size(track_infos) < sb->board_count )
+         vg_warn( "Client out of date, server sent more boards than we have\n");
+      else
+         vg_success( "Recieved new scoreboards from server\n" );
+
+      for( int i=0; i < vg_min(sb->board_count,vg_list_size(track_infos)); i++)
+      {
+         scoreboard_client_data.boards[i] = sb->boards[i];
+         highscores_board_printf( stdout, sb->boards[i].data, 10 );
+      }
    }
+
+   /* We dont need to stay on the server currently */
+   SteamAPI_ISteamNetworkingSockets_CloseConnection(
+         hSteamNetworkingSockets, cremote, 0, NULL, 1 );
 }
 
 static void poll_connection(void)
@@ -181,54 +260,52 @@ static void poll_connection(void)
 
          if( msg->m_cbSize < sizeof(netmsg_blank) )
          {
-            vg_warn( "Discarding message (too small: %d)\n", 
-                  msg->m_cbSize );
+            vg_warn( "Discarding message (too small: %d)\n", msg->m_cbSize );
             continue;
          }
 
          netmsg_blank *tmp = msg->m_pData;
-         if( tmp->inetmsg_id == k_inetmsg_scores_info )
-         {
-            netmsg_scores_info *info = msg->m_pData;
-            vg_log( "Recieved %u score records\n", info->record_count );
 
-            SteamAPI_ISteamNetworkingSockets_CloseConnection(
-                  hSteamNetworkingSockets, cremote, 0, NULL, 1 );
-            cremote_state = k_ESteamNetworkingConnectionState_None;
-         }
+         if( tmp->inetmsg_id == k_inetmsg_scoreboard )
+            on_inet_scoreboard( msg );
 
          SteamAPI_SteamNetworkingMessage_t_Release( msg );
       }
    }
 }
 
-static u64 in_server_ticks( double seconds )
+/*
+ * Subroutine to be connected to main game loop, runs all routines on timers
+ */
+static void network_update(void)
 {
-   return (u64)(seconds / 0.1);
-}
+   if( steam_ready )
+   {
+      static double last_update = 0.0;
+      poll_connection();
+      
+      if( vg_time > (last_update + 60.0) )
+      {
+         last_update = vg_time;
 
-static void on_server_connect_status( CallbackMsg_t *msg )
-{
-   SteamNetConnectionStatusChangedCallback_t *info = (void *)msg->m_pubParam;
-   vg_info( "  Connection status changed for %lu\n", info->m_hConn );
-   vg_info( "  %s -> %s\n", 
-         string_ESteamNetworkingConnectionState(info->m_info.m_eState),
-         string_ESteamNetworkingConnectionState(info->m_eOldState) );
+         if( steam_app_ticket_length )
+         {
+            network_connect_gc();
+         }
+         else
+         {
+            vg_log( "Not making remote connection; app ticket not gotten\n" );
+         }
+      }
 
-   if( info->m_hConn == cremote )
-   {
-      cremote_state = info->m_info.m_eState;
-      if( info->m_info.m_eState ==
-            k_ESteamNetworkingConnectionState_Connected )
+      if( vg_time > (last_update + 10.0) && 
+            (cremote_state == k_ESteamNetworkingConnectionState_Connected ))
       {
-         vg_success("  Connected to remote server\n");
-         scores_update();
+         vg_warn( "Connected to server but no return... disconnecting\n" );
+         SteamAPI_ISteamNetworkingSockets_CloseConnection(
+               hSteamNetworkingSockets, cremote, 0, NULL, 1 );
       }
    }
-   else
-   {
-      vg_warn( "  Recieved signal from unknown connection\n" );
-   }
 }
 
 static void network_init(void)
@@ -241,24 +318,15 @@ static void network_init(void)
    }
 }
 
-static void network_update(void)
-{
-   if( steam_ready )
-   {
-      static double last_update = -9000.0;
-      poll_connection();
-      
-      if( vg_time > (last_update + 60.0) )
-      {
-         last_update = vg_time;
-         scores_update();
-      }
-   }
-}
-
 static void network_end(void)
 {
    /* TODO: Fire off any buffered highscores that need to be setn */
+   if( cremote_state == k_ESteamNetworkingConnectionState_Connected ||
+       cremote_state == k_ESteamNetworkingConnectionState_Connecting )
+   {
+      SteamAPI_ISteamNetworkingSockets_CloseConnection(
+            hSteamNetworkingSockets, cremote, 0, NULL, 1 );
+   }
 }
 
 #endif
index 4ab094227cc014935397656e3082507695aedf87..0a0d1f820b0417e9c0dbed5dd29a4b17381a850d 100644 (file)
@@ -2,6 +2,8 @@
 #define NETWORK_MSG_H
 
 #include "vg/vg_stdint.h"
+#include "world_info.h"
+#include "vg/vg_platform.h"
 
 #pragma pack(push,1)
 
@@ -49,9 +51,29 @@ typedef struct netmsg_set_nickname netmsg_set_nickname;
 struct netmsg_set_nickname
 {
    u32 inetmsg_id;
-   char nickname[16];
+   char nickname[10];
 };
 enum{ k_inetmsg_set_nickname = 4 };
 
+
+typedef struct netmsg_scoreboard netmsg_scoreboard;
+enum{ k_inetmsg_scoreboard = 5 };
+struct netmsg_scoreboard
+{
+   u32 inetmsg_id;
+   
+   u32 board_count;
+   struct netmsg_board
+   {
+      char data[27*13];
+   }
+   boards[ vg_list_size(track_infos) ];
+}
+static scoreboard_client_data = { 
+   .inetmsg_id = k_inetmsg_scoreboard,
+   .board_count = vg_list_size(track_infos)
+}; 
+/* probably about 10k */
+
 #pragma pack(pop)
 #endif /* NETWORK_MSG_H */
index 578c3f5b5723d407cdc94e09c7772082498fae9f..1f2863380ecf254a75f93797d110f72d39e32612 100644 (file)
--- a/server.c
+++ b/server.c
@@ -26,11 +26,13 @@ void inthandler( int signum )
 #include "network_msg.h"
 #include "highscores.h"
 
-void  *hSteamHTTP,
-      *hSteamNetworkingSockets;
+static const u64 k_connection_unauthorized = 0xffffffffffffffff;
 
-u8 steam_symetric_key[ k_nSteamEncryptedAppTicketSymmetricKeyLen ];
-HSteamNetPollGroup client_pollgroup;
+static void  *hSteamHTTP,
+             *hSteamNetworkingSockets;
+
+static u8 steam_symetric_key[ k_nSteamEncryptedAppTicketSymmetricKeyLen ];
+static HSteamNetPollGroup client_pollgroup;
 
 static void recieve_http( void *callresult, void *context )
 {
@@ -79,8 +81,9 @@ static void new_client_connecting( HSteamNetConnection client )
       SteamAPI_ISteamNetworkingSockets_SetConnectionPollGroup(
             hSteamNetworkingSockets,
             client, client_pollgroup );
-
-      set_connection_authsteamid( client, 0 );
+      
+      /* Just to be sure */
+      set_connection_authsteamid( client, -1 );
    }
    else
    {
@@ -102,8 +105,8 @@ static void on_connect_status( CallbackMsg_t *msg )
    vg_info( "  Connection status changed for %lu\n", info->m_hConn );
 
    vg_info( "  %s -> %s\n", 
-         string_ESteamNetworkingConnectionState(info->m_info.m_eState),
-         string_ESteamNetworkingConnectionState(info->m_eOldState) );
+         string_ESteamNetworkingConnectionState(info->m_eOldState),
+         string_ESteamNetworkingConnectionState(info->m_info.m_eState) );
 
    if( info->m_info.m_eState==k_ESteamNetworkingConnectionState_Connecting )
    {
@@ -113,7 +116,7 @@ static void on_connect_status( CallbackMsg_t *msg )
 
 static void on_inet_auth( SteamNetworkingMessage_t *msg )
 {
-   if( get_connection_authsteamid( msg ) )
+   if( get_connection_authsteamid( msg ) != k_connection_unauthorized )
    {
       vg_warn( "Already authorized this user but app ticket was sent"
                " again (%u)\n", msg->m_conn );
@@ -149,10 +152,11 @@ static void on_inet_auth( SteamNetworkingMessage_t *msg )
    if( !success )
    {
       vg_error( "Failed to decrypt users ticket (client %u)\n", msg->m_conn );
+      vg_error( "  ticket length: %u\n", auth->ticket_length );
 
       SteamAPI_ISteamNetworkingSockets_CloseConnection(
             hSteamNetworkingSockets,
-            msg->m_conn, 0, NULL, 0 );
+            msg->m_conn, 0, NULL, 1 );
       return;
    }
 
@@ -170,7 +174,7 @@ static void on_inet_auth( SteamNetworkingMessage_t *msg )
          /* TODO: Send expired information */
          SteamAPI_ISteamNetworkingSockets_CloseConnection(
                hSteamNetworkingSockets,
-               msg->m_conn, 0, NULL, 0 );
+               msg->m_conn, 0, NULL, 1 );
          return;
       }
    }
@@ -185,14 +189,14 @@ static void on_inet_auth( SteamNetworkingMessage_t *msg )
 
 static int inet_require_auth( SteamNetworkingMessage_t *msg )
 {
-   if( !get_connection_authsteamid( msg ) )
+   if( get_connection_authsteamid( msg ) == k_connection_unauthorized )
    {
       vg_warn( "Unauthorized request! Disconnecting client: %u\n", 
             msg->m_conn );
 
       SteamAPI_ISteamNetworkingSockets_CloseConnection(
             hSteamNetworkingSockets,
-            msg->m_conn, 0, NULL, 0 );
+            msg->m_conn, 0, NULL, 1 );
 
       return 0;
    }
@@ -201,35 +205,12 @@ static int inet_require_auth( SteamNetworkingMessage_t *msg )
 
 static void on_inet_score_request( SteamNetworkingMessage_t *msg )
 {
-#if 0
-   if( get_connection_authsteamid( msg ) )
-   {
-      vg_log( "Recieved score request, sending records. (id: %u)\n", 
-               msg->m_conn );
-
-      /* Send back current scores */
-      u32 data_size = sizeof(netmsg_scores_info) + 
-                        0*sizeof(struct netmsg_score_record);
-      netmsg_scores_info *return_info = malloc( data_size );
-
-      return_info->inetmsg_id = k_inetmsg_scores_info;
-      return_info->record_count = 0;
-
-      SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
-            hSteamNetworkingSockets, msg->m_conn, 
-            return_info, data_size,
-            k_nSteamNetworkingSend_Reliable, NULL );
-   }
-   else
-   {
-      vg_warn( "Unauthorized request! Disconnecting client: %u\n", 
-            msg->m_conn );
+   if( !inet_require_auth(msg) ) return;
 
-      SteamAPI_ISteamNetworkingSockets_CloseConnection(
-            hSteamNetworkingSockets,
-            msg->m_conn, 0, NULL, 0 );
-   }
-#endif
+   SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+         hSteamNetworkingSockets, msg->m_conn, 
+         &scoreboard_client_data, sizeof(netmsg_scoreboard),
+         k_nSteamNetworkingSend_Reliable, NULL );
 }
 
 static void on_inet_set_nickname( SteamNetworkingMessage_t *msg )
@@ -317,17 +298,34 @@ static void poll_connections(void)
             on_inet_score_request( msg );
          else if( tmp->inetmsg_id == k_inetmsg_set_nickname )
             on_inet_set_nickname( msg );
+         else if( tmp->inetmsg_id == k_inetmsg_set_score )
+            on_inet_set_score( msg );
 
          SteamAPI_SteamNetworkingMessage_t_Release( msg );
       }
    }
 }
 
-u64 seconds_to_server_ticks( double s )
+static u64 seconds_to_server_ticks( double s )
 {
    return s / 0.1;
 }
 
+static void generate_boards(void)
+{
+   FILE *fp = fopen( "www/html/srhighscores.txt", "w" );
+
+   for( int i=0; i<vg_list_size(track_infos); i++ )
+   {
+      struct netmsg_board *board = &scoreboard_client_data.boards[i];
+
+      highscores_board_generate( board->data, i, 10 );
+      highscores_board_printf( fp, board->data, 10 );
+   }
+
+   fclose( fp );
+}
+
 int main( int argc, char *argv[] )
 {
    signal( SIGINT, inthandler );
@@ -393,7 +391,10 @@ int main( int argc, char *argv[] )
 #endif
 
    u64 server_ticks = 8000,
-       last_record_save = 8000;
+       last_record_save = 8000,
+       last_scoreboard_gen = 0;
+
+   generate_boards();
 
    while( !sig_stop )
    {
@@ -403,13 +404,19 @@ int main( int argc, char *argv[] )
       usleep(100000);
       server_ticks ++;
 
-      if(last_record_save+server_ticks > seconds_to_server_ticks( 10.0*60.0 ))
+      if(server_ticks > last_scoreboard_gen + seconds_to_server_ticks(1.0*60.0))
+      {
+         last_scoreboard_gen = server_ticks;
+         generate_boards();
+      }
+
+      if(server_ticks > last_record_save + seconds_to_server_ticks( 10.0*60.0 ))
       {
          last_record_save = server_ticks;
          highscores_serialize_all();
       }
    }
-
+   
    highscores_serialize_all();
    highscores_free();
    
index 5e2cd93c8ed863676e8d5690c2d54f682c92049d..0f2bd3ba12a939b47c7d9ae7c823152dabc67823 100644 (file)
--- a/testaa.c
+++ b/testaa.c
@@ -34,9 +34,9 @@ int main(int argc, const char *argv[])
       highscores_push_record( &entry );
    }
 
-   for( int i=0; i<80; i++ )
+   for( int i=0; i<800; i++ )
    {
-      char rando[16];
+      char rando[10];
 
       int l=2+rand()%8;
       for( int i=0; i<l; i++ )
@@ -54,8 +54,15 @@ int main(int argc, const char *argv[])
                         highscore_system.dbheader.playerinfo_root, 0,
                         &ln, &err, _highscore_showname, 1 );
 #endif
+   
+   char testy[27*(10+3)];
+
+   for( int i=0; i<vg_list_size(track_infos); i++ )
+   {
+      highscores_board_generate( testy, i, 10 );
+      highscores_board_printf( stdout, testy, 10 );
+   }
 
-   highscores_print_track( 12, 10 );
    highscores_serialize_all();
    highscores_free();
    return 0;
diff --git a/world_info.h b/world_info.h
new file mode 100644 (file)
index 0000000..a8d42d8
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef WORLD_INFO_H
+#define WORLD_INFO_H
+
+#include "vg/vg_stdint.h"
+
+/* Purely an information header, shares common strings across client and 
+ * server programs. */
+
+static struct world_info
+{
+   
+}
+world_info;
+
+static struct track_info
+{
+   const char *name;
+}
+track_infos[] = 
+{
+   {
+      .name = "Megapark Green"
+   },
+   {
+      .name = "Megapark Blue"
+   },
+   {
+      .name = "Megapark Yellow"
+   },
+   {
+      .name = "Megapark Red"
+   }
+};
+
+#endif
index 4c198e1a429a23001ed299045790297353e96575..a4624dc8f579c6b7308f363c014308d2c6afd683 100644 (file)
@@ -43,15 +43,18 @@ struct subworld_routes
    {
       teleport_gate gate;
       
-      u32 route_count,
-          node_id;
+      u32 node_id;
+
+      double time_passed; /* When did we last pass this gate? */
+      u32    passed_version; /* Incremented on every reset */
    }
    *gates;
 
    u32 gate_count,
        gate_cap;
 
-   u32 active_gate;
+   u32 active_gate,
+       current_run_version;
 
    scene scene_lines;
 };
@@ -84,37 +87,12 @@ static void debug_sbpath( struct route_node *rna, struct route_node *rnb,
    }
 }
 
-static void world_routes_activate_gate( u32 id )
-{
-   struct subworld_routes *r = subworld_routes();
-   struct route_gate *ig = &r->gates[id];
-   struct route_node *pnode = &r->nodes[ig->node_id],
-                     *pdest = &r->nodes[pnode->next[0]];
-   
-   r->active_gate = id;
-
-   for( int i=0; i<r->route_count; i++ )
-   {
-      struct route *route = &r->routes[i];
-
-      route->active = 0;
-      for( int j=0; j<pdest->ref_count; j++ )
-      {
-         if( pdest->route_ids[j] == i )
-         {
-            route->active = 1;
-            break;
-         }
-      }
-   }
-}
-
-static u32 world_routes_get_path( struct route *route, u32 stack[64] )
+static u32 world_routes_get_path( u32 starter, u32 stack[64] )
 {
    struct subworld_routes *r = subworld_routes();
    u32 stack_i[64];
 
-   stack[0] = route->start;
+   stack[0] = starter;
    stack_i[0] = 0;
 
    u32 si = 1;
@@ -166,6 +144,94 @@ static u32 world_routes_get_path( struct route *route, u32 stack[64] )
    return 0;
 }
 
+static void world_routes_verify_run( u32 route, double new_pass_time )
+{
+   struct subworld_routes *r = subworld_routes();
+   if( r->current_run_version == 0 ) return;
+
+   u32 stack[64];
+   u32 si = world_routes_get_path( r->routes[route].start, stack );
+
+   /* 
+    * we only care about gates that ref gates, so shuffle down the array
+    */
+   u32 sj = 0;
+   for( u32 i=0; i<si; i++ )
+      if( r->nodes[stack[i]].is_gate && r->nodes[stack[(i+1)%si]].is_gate )
+         stack[sj ++] = r->nodes[stack[i]].gate_id;
+
+   /* 
+    * run versions & times must always ASCEND apart from exactly once, where
+    * the tail connects to the head
+    */
+
+   vg_info("Verifying run (%u)\n", route);
+
+   u32 descend_allowance = 1;
+   double lap_time = 0.0;
+
+   for( u32 i=0; i<sj; i++ )
+   {
+      struct route_gate *pa = &r->gates[stack[i]],
+                        *pb = &r->gates[stack[(i+1) % sj]];
+
+      vg_info( " pa: %u, pb: %u\n", pa->passed_version, pb->passed_version );
+      
+      int version_inorder = 0;
+      double diff = 0.0;
+
+      if( pb->passed_version == pa->passed_version+1 )
+      {
+         version_inorder = 1;
+         diff = pb->time_passed - pa->time_passed;
+      }
+      else if( pb->passed_version == pa->passed_version+1-sj &&
+               pa->passed_version+1 == r->current_run_version )
+      {
+         version_inorder = 1;
+         diff = new_pass_time - pa->time_passed;
+      }
+
+      if( !version_inorder )
+         return;
+
+      lap_time += diff;
+   }
+
+   /* We've now verified the run was completed correctly */
+   vg_success( "Lap time set. route %u: %lf\n", route, lap_time );
+}
+
+static void world_routes_activate_gate( u32 id )
+{
+   struct subworld_routes *r = subworld_routes();
+   struct route_gate *ig = &r->gates[id];
+   struct route_node *pnode = &r->nodes[ig->node_id],
+                     *pdest = &r->nodes[pnode->next[0]];
+
+   r->active_gate = id;
+
+   for( u32 i=0; i<r->route_count; i++ )
+   {
+      struct route *route = &r->routes[i];
+
+      route->active = 0;
+      for( u32 j=0; j<pdest->ref_count; j++ )
+      {
+         if( pdest->route_ids[j] == i )
+         {
+            world_routes_verify_run( i, vg_time );
+            route->active = 1;
+            break;
+         }
+      }
+   }
+   
+   ig->time_passed = vg_time;
+   ig->passed_version = r->current_run_version;
+   r->current_run_version ++;
+}
+
 static void world_routes_debug(void)
 {
    struct subworld_routes *r = subworld_routes();
@@ -181,7 +247,7 @@ static void world_routes_debug(void)
       struct route *route = &r->routes[i];
 
       u32 stack[64];
-      u32 si = world_routes_get_path( route, stack );
+      u32 si = world_routes_get_path( route->start, stack );
 
       u32 colours[] = { 0xfff58142, 0xff42cbf5, 0xff42f56c, 0xfff542b3,
                         0xff5442f5 };
@@ -239,7 +305,7 @@ static void world_routes_gen_meshes(void)
       struct route *route = &r->routes[i];
 
       u32 stack[64];
-      u32 si = world_routes_get_path( route, stack );
+      u32 si = world_routes_get_path( route->start, stack );
 
       u32 last_valid = 0;
 
@@ -459,6 +525,8 @@ static void world_routes_loadfrom( mdl_header *mdl )
                {
                   struct route_gate *rg = &r->gates[r->gate_count];
                   rg->node_id = r->node_count;
+                  rg->passed_version = 0;
+                  rg->time_passed = 0.0;
 
                   v3_copy( pnode->co,  rg->gate.co[0] );
                   v3_copy( pother->co, rg->gate.co[1] );
@@ -527,7 +595,7 @@ static void world_routes_loadfrom( mdl_header *mdl )
       struct route *route = &r->routes[i];
 
       u32 stack[64];
-      u32 si = world_routes_get_path( route, stack );
+      u32 si = world_routes_get_path( route->start, stack );
 
       for( int sj=0; sj<si; sj++ )
       {