change shader properties to be vg_msg based
[carveJwlIkooP6JGAAIwe30JlM.git] / world_sfd.c
index a5ba3f6d82981fa6103fc51b2546a6118ef6f8e6..6473d63b3404b24f3699a789d9d9ffcd171afbf7 100644 (file)
@@ -4,9 +4,14 @@
 #include "world_sfd.h"
 #include "shaders/scene_scoretext.h"
 #include "shaders/scene_vertex_blend.h"
+#include "network.h"
+#include "entity.h"
+#include "network_common.h"
+#include "world_routes.h"
 
-static f32 sfd_encode_glyph( char c )
-{
+struct world_sfd world_sfd;
+
+static f32 sfd_encode_glyph( char c ){
    int value = 0;
    if( c >= 'a' && c <= 'z' )
       value = c-'a'+11;
@@ -39,27 +44,154 @@ static f32 sfd_encode_glyph( char c )
    return (float)value;
 }
 
-VG_STATIC void sfd_encode( u32 row, const char *str )
-{
-   int end=0;
+static void sfd_clear( u32 row ){
    u32 row_h = world_sfd.h -1 -row;
-
    for( int i=0; i<world_sfd.w; i++ ){
       u32 idx = (world_sfd.w*row_h + i) * 2;
+      world_sfd.buffer[idx] = 0.0f;
+   }
+}
 
-      if( end ){
-         world_sfd.buffer[idx] = 0.0f;
-      }
-      else{
-         if( !str[i] )
-            end = 1;
+void sfd_encode( v2i co, const char *str, enum world_sfd_align align )
+{
+   i32 row_h = world_sfd.h -1 -co[1];
+   i32 offset_x = 0;
+
+   i32 w = VG_MIN( strlen(str), world_sfd.w );
+   if( align == k_world_sfd_center )
+      offset_x = (world_sfd.w - w) / 2;
+   else if( align == k_world_sfd_right )
+      offset_x = world_sfd.w - w;
+   else
+      offset_x = co[0];
+
+   for( i32 i=0; i<world_sfd.w; i++ ){
+      i32 u = i + offset_x,
+          idx = (world_sfd.w*row_h + u) * 2;
 
-         world_sfd.buffer[idx] = sfd_encode_glyph( str[i] );
+      if( (u >= world_sfd.w) || (u < 0) )
+         continue;
+
+      if( !str[i] ) 
+         return;
+
+      world_sfd.buffer[idx] = sfd_encode_glyph( str[i] );
+   }
+}
+
+void world_sfd_compile_scores( struct leaderboard_cache *board,
+                               const char *title )
+{
+   for( u32 i=0; i<13; i++ )
+      sfd_clear(i);
+
+   sfd_encode( (v2i){0,0}, title, k_world_sfd_left );
+
+   if( !board ){
+      sfd_encode( (v2i){-1,4}, "Error out of range", k_world_sfd_center );
+      return;
+   }
+
+   if( !network_connected() ){
+      sfd_encode( (v2i){-1,0}, "Offline", k_world_sfd_right );
+      return;
+   }
+
+   if( board->status == k_request_status_not_found ){
+      sfd_encode( (v2i){-1,4}, "No records", k_world_sfd_center );
+      return;
+   }
+
+   if( board->status != k_request_status_ok ){
+      char buf[32];
+      vg_str s;
+      vg_strnull( &s, buf, 32 );
+      vg_strcat( &s, "Error: " );
+      vg_strcati32( &s, board->status );
+      sfd_encode( (v2i){-1,4}, buf, k_world_sfd_center );
+      return;
+   }
+
+   vg_msg body;
+   vg_msg_init( &body, board->data, board->data_len );
+
+   const char *alias = "rows";
+
+   if( world_sfd.view_weekly ){
+      alias = "rows_weekly";
+      sfd_encode( (v2i){-1,0}, "Weekly", k_world_sfd_right );
+   }
+   else {
+      sfd_encode( (v2i){-1,0}, "All-Time", k_world_sfd_right );
+   }
+
+   u32 l = 1;
+   if( vg_msg_seekframe( &body, alias ) ){
+      while( vg_msg_seekframe( &body, NULL ) ){
+         /* name */
+         const char *username = vg_msg_getkvstr( &body, "username" );
+
+         char buf[100];
+         vg_str str;
+         vg_strnull( &str, buf, 100 );
+         vg_strcati32( &str, l );
+         vg_strcat( &str, " " );
+
+         if( username )
+            vg_strcat( &str, username );
+         else
+            vg_strcat( &str, "??????" );
+
+         sfd_encode( (v2i){0,l}, str.buffer, k_world_sfd_left );
+
+         /* time */
+         vg_strnull( &str, buf, 100 );
+         
+         u32 centiseconds;
+         vg_msg_getkvintg( &body, "time", k_vg_msg_i32, &centiseconds, NULL );
+
+         i32 seconds      = centiseconds / 100,
+             minutes      = seconds / 60;
+
+         centiseconds %= 100;
+         seconds     %= 60;
+         minutes     %= 60;
+         if( minutes > 9 ) vg_strcat( &str, "?" );
+         else vg_strcati32( &str, minutes );
+         vg_strcat( &str, ":" );
+         vg_strcati32r( &str, seconds, 2, '0' );
+         vg_strcat( &str, "." );
+         vg_strcati32r( &str, centiseconds, 2, '0' );
+         sfd_encode( (v2i){-1,l}, str.buffer, k_world_sfd_right );
+         l ++;
+
+         vg_msg_skip_frame( &body );
       }
    }
+   else {
+      sfd_encode( (v2i){-1,4}, "No records", k_world_sfd_center );
+   }
+}
+
+void world_sfd_compile_active_scores(void)
+{
+   world_instance *world = world_current_instance();
+   
+   struct leaderboard_cache *board = NULL;
+   const char *name = "Out of range";
+
+   if( world_sfd.active_route_board < mdl_arrcount( &world->ent_route ) ){
+      board = &world->leaderboard_cache[ world_sfd.active_route_board ];
+      ent_route *route = mdl_arritm( &world->ent_route, 
+                                     world_sfd.active_route_board );
+      name = mdl_pstr( &world->meta, route->pstr_name );
+   }
+         
+   world_sfd_compile_scores( board, name );
 }
 
-VG_STATIC void world_sfd_update( world_instance *world, v3f pos ){
+void world_sfd_update( world_instance *world, v3f pos )
+{
    if( mdl_arrcount( &world->ent_route ) ){
       u32 closest = 0;
       float min_dist = INFINITY;
@@ -74,59 +206,59 @@ VG_STATIC void world_sfd_update( world_instance *world, v3f pos ){
          }
       }
 
-      if( (world_sfd.active_route_board != closest) || network_scores_updated )
-      {
-         network_scores_updated = 0;
-         world_sfd.active_route_board = closest;
+      struct leaderboard_cache *board = &world->leaderboard_cache[ closest ];
 
-         ent_route *route = mdl_arritm( &world->ent_route, closest );
-         u32 id = route->official_track_id;
+      /* request new board if cache expires */
+      if( network_connected() ){
+         f64 delta = vg.time_real - board->cache_time;
+         if( (delta > 45.0) || (board->cache_time == 0.0) ){
+            board->cache_time = vg.time_real;
+            ent_route *route = mdl_arritm( &world->ent_route, closest );
+            addon_reg *world_reg = 
+               world_static.instance_addons[ world - world_static.instances ];
 
-         if( id != 0xffffffff ){
-            struct netmsg_board *local_board = 
-               &scoreboard_client_data.boards[id];
+            char mod_uid[ ADDON_UID_MAX ];
+            addon_alias_uid( &world_reg->alias, mod_uid );
 
-            for( int i=0; i<13; i++ ){
-               sfd_encode( i, &local_board->data[27*i] );
-            }
-         }else{
-            sfd_encode( 0, mdl_pstr( &world->meta, route->pstr_name ) );
-            sfd_encode( 1, "No data" );
+            network_request_scoreboard( 
+                  mod_uid, 
+                  mdl_pstr( &world->meta, route->pstr_name ),
+                  NETWORK_LEADERBOARD_ALLTIME_AND_CURRENT_WEEK, closest );
          }
       }
+
+      /* compile board text if we changed. */
+      if( world_sfd.active_route_board != closest ){
+         world_sfd_compile_active_scores();
+      }
+
+      world_sfd.active_route_board = closest;
    }
 
    for( int i=0; i<world_sfd.w*world_sfd.h; i++ ){
       float *target = &world_sfd.buffer[i*2+0],
             *cur =    &world_sfd.buffer[i*2+1];
       
-      float const rate = vg.time_delta * 15.2313131414f;
+      float const rate = vg.time_delta * 25.2313131414f;
       float d1 = *target-*cur;
       
       if( fabsf(d1) > rate ){
          *cur += rate;
-         if( *cur > 60.0f )
-            *cur -= 60.0f;
+         if( *cur > 49.0f )
+            *cur -= 49.0f;
       }
       else
          *cur = *target;
    }
 }
 
-VG_STATIC void bind_terrain_noise(void);
-VG_STATIC void sfd_render( world_instance *world, camera *cam, m4x3f transform )
+void bind_terrain_noise(void);
+void sfd_render( world_instance *world, vg_camera *cam, m4x3f transform )
 {
    mesh_bind( &world_sfd.mesh_display );
    shader_scene_scoretext_use();
    shader_scene_scoretext_uTexMain(1);
-
-   world_link_lighting_ub( world, _shader_scene_scoretext.id );
-   world_bind_position_texture( world, _shader_scene_scoretext.id, 
-                        _uniform_scene_scoretext_g_world_depth, 2 );
-   world_bind_light_array( world, _shader_scene_scoretext.id,
-                        _uniform_scene_scoretext_uLightsArray, 3 );
-   world_bind_light_index( world, _shader_scene_scoretext.id,
-                           _uniform_scene_scoretext_uLightsIndex, 4 );
+   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_scoretext );
 
    bind_terrain_noise();
 
@@ -153,13 +285,8 @@ VG_STATIC void sfd_render( world_instance *world, camera *cam, m4x3f transform )
    shader_scene_vertex_blend_use();
    shader_scene_vertex_blend_uTexGarbage(0);
    shader_scene_vertex_blend_uTexGradients(1);
-   world_link_lighting_ub( world, _shader_scene_vertex_blend.id );
-   world_bind_position_texture( world, _shader_scene_vertex_blend.id, 
-                                _uniform_scene_vertex_blend_g_world_depth, 2 );
-   world_bind_light_array( world, _shader_scene_vertex_blend.id,
-                                _uniform_scene_vertex_blend_uLightsArray, 3 );
-   world_bind_light_index( world, _shader_scene_vertex_blend.id,
-                                _uniform_scene_vertex_blend_uLightsIndex, 4 );
+   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_vertex_blend );
+
    bind_terrain_noise();
    glActiveTexture( GL_TEXTURE1 );
    glBindTexture( GL_TEXTURE_2D, world_sfd.tex_scoretex );
@@ -173,28 +300,15 @@ VG_STATIC void sfd_render( world_instance *world, camera *cam, m4x3f transform )
    mdl_draw_submesh( &world_sfd.sm_base );
 }
 
-VG_STATIC int world_sfd_test( int argc, const char *argv[] )
-{
-   if( argc == 2 ){
-      int row = vg_min( vg_max(atoi(argv[0]),0), world_sfd.h);
-      sfd_encode( row, argv[1] );
-   }
-
-   return 0;
-}
-
-VG_STATIC void world_sfd_init(void)
+void world_sfd_init(void)
 {
    vg_info( "world_sfd_init\n" );
-   shader_scene_scoretext_register();
-   vg_console_reg_cmd( "sfd", world_sfd_test, NULL );
-
    vg_linear_clear( vg_mem.scratch );
 
    mdl_context mscoreboard;
    mdl_open( &mscoreboard, "models/rs_scoretext.mdl", vg_mem.scratch );
    mdl_load_metadata_block( &mscoreboard, vg_mem.scratch );
-   mdl_async_load_glmesh( &mscoreboard, &world_sfd.mesh_base );
+   mdl_async_load_glmesh( &mscoreboard, &world_sfd.mesh_base, NULL );
 
    mdl_load_mesh_block( &mscoreboard, vg_mem.scratch );