#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 )
-{
+static f32 sfd_encode_glyph( char c ){
int value = 0;
if( c >= 'a' && c <= 'z' )
value = c-'a'+11;
return (float)value;
}
-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;
+static 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;
+
+ if( (u >= world_sfd.w) || (u < 0) )
+ continue;
+
+ if( !str[i] )
+ return;
+
+ world_sfd.buffer[idx] = sfd_encode_glyph( str[i] );
+ }
+}
+
+static 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;
+ }
- world_sfd.buffer[idx] = sfd_encode_glyph( str[i] );
+ 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 );
+ i32 centiseconds = vg_msg_getkvi32( &body, "time", 0 ),
+ 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 );
+ }
+}
+
+static 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 );
}
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;
}
static void bind_terrain_noise(void);
-static void sfd_render( world_instance *world, camera *cam, m4x3f transform )
-{
+static void sfd_render( world_instance *world, 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();
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 );
mdl_draw_submesh( &world_sfd.sm_base );
}
-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;
-}
-
-static void world_sfd_init(void)
-{
+static 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 );