more sensible world loading stuff (wip)
authorhgn <hgodden00@gmail.com>
Sat, 22 Jul 2023 08:08:30 +0000 (09:08 +0100)
committerhgn <hgodden00@gmail.com>
Sat, 22 Jul 2023 08:08:30 +0000 (09:08 +0100)
22 files changed:
addon.c
addon.h
ent_skateshop.c
menu.h
player.c
player_skate.c
save.c
skaterift.c
skaterift.h
world.c
world.h
world_audio.c
world_entity.c
world_entity.h
world_gate.c
world_gen.c
world_gen.h
world_load.c
world_load.h
world_render.c
world_routes.c
world_routes.h

diff --git a/addon.c b/addon.c
index ee3f803392a964795bf96f6615bf32f8f105a251..5c9578f67ac2f671c460acd50409662cfbf86d1e 100644 (file)
--- a/addon.c
+++ b/addon.c
@@ -69,6 +69,17 @@ static u32 addon_match( addon_alias *alias ){
    return 0xffffffff;
 }
 
+static void addon_alias_uid( addon_alias *alias, char buf[76] ){
+   if( alias->workshop_id ){
+      snprintf( buf, 128, "sr%03d-steam-"PRINTF_U64, 
+            alias->type, alias->workshop_id );
+   }
+   else {
+      snprintf( buf, 128, "sr%03d-local-%s",
+            alias->type, alias->foldername );
+   }
+}
+
 static void addon_system_init( void ){
    u32 reg_size   = sizeof(addon_reg)*ADDON_MOUNTED_MAX;
    addon_system.registry = vg_linear_alloc( vg_mem.rtmemory, reg_size );
diff --git a/addon.h b/addon.h
index 768bede37bf8f10487aa4ca15658cfa2d71bb139..691046da23299929ae749c1cd5123006f14f5cb9 100644 (file)
--- a/addon.h
+++ b/addon.h
@@ -78,6 +78,8 @@ static u32 get_index_from_addon( enum addon_type type, addon_reg *a );
 static int addon_get_content_folder( addon_reg *reg, vg_str *folder );
 
 /* scanning routines */
+static u32 addon_match( addon_alias *alias );
+static void addon_alias_uid( addon_alias *alias, char buf[76] );
 VG_STATIC void addon_mount_content_folder( enum addon_type type,
                                            const char *base_folder, 
                                            const char *content_ext );
index 42eefa2cfed858ec37d508241031cba5d68721f6..7dd11c0bcd46ea4e9446061b2343805e4991f81a 100644 (file)
@@ -346,9 +346,7 @@ VG_STATIC void global_skateshop_preupdate(void){
          if( loadable && button_down( k_srbind_maccept ) ){
             vg_info( "Select rift (%u)\n", 
                       global_skateshop.selected_world_id );
-            world_loader.reg = reg;
-            world_loader.override_name[0] = '\0';
-            skaterift_change_world_start();
+            skaterift_change_world_start( reg );
             return;
          }
          else{
diff --git a/menu.h b/menu.h
index d51fde599a9f427c74baa8bd4fbabf89d6e66994..44feffdf8cec1f2d5b219c61db681d149b591a9f 100644 (file)
--- a/menu.h
+++ b/menu.h
@@ -215,7 +215,7 @@ static void menu_trigger_item( ent_menuitem *item )
          menu_close();
       }
       else if( MDL_CONST_PSTREQ( &menu.model, q, "reset_home" ) ){
-         world_static.active_world = 0;
+         world_static.active_instance = 0;
          world_static.active_trigger_volume_count = 0;
          localplayer.viewable_world = world_current_instance();
          localplayer_cmd_respawn( 1, (const char *[]){"start"} );
index 0e45e996ca62efedbef1fc97d30e999b7ffe71ec..585fd73e7a14857352b5f16d0766d00f333bc2ac 100644 (file)
--- a/player.c
+++ b/player.c
@@ -165,7 +165,7 @@ void player__pass_gate( player_instance *player, ent_gate *gate )
    m4x3_mulv( gate->transport, player->cam.pos, player->cam.pos );
 
    if( gate->flags & k_ent_gate_nonlocal )
-      world_static.active_world = gate->target;
+      world_static.active_instance = gate->target;
 
    audio_lock();
    audio_oneshot( &audio_gate_pass, 1.0f, 0.0f );
@@ -225,10 +225,22 @@ PLAYER_API void player__im_gui( player_instance *player ){
    g_player_debugger[2] = 300;
    g_player_debugger[3] = 32;
 
-   player__debugtext( 2, "world (%u)", world_static.active_world );
-   player__debugtext( 1, "model version: %u", 
-                     world_current_instance()->meta.info.version );
+   player__debugtext( 2, "instance #%u", world_static.active_instance );
 
+   char buf_hub[96],
+        buf_client[96];
+   if( world_static.addon_client )
+      addon_alias_uid( &world_static.addon_client->alias, buf_client );
+   else
+      strcpy( buf_client, "none" );
+
+   if( world_static.addon_hub )
+      addon_alias_uid( &world_static.addon_hub->alias, buf_hub );
+   else
+      strcpy( buf_hub, "none" );
+
+   player__debugtext( 1, "hub uid: %s", buf_hub );
+   player__debugtext( 1, "client uid: %s", buf_client );
    player__debugtext( 2, "director" );
    player__debugtext( 1, "activity: %s", 
                      (const char *[]){ [k_skaterift_menu]      = "menu",
index baa1ce713116ed266d3afb00af5711b00bb0a99f..3cd9a928194cbc677aa9741e3694b26773849040 100644 (file)
@@ -500,7 +500,7 @@ void player__approximate_best_trajectory( player_instance *player )
                m3x3_mul( gate->transport, basis, basis );
 
                if( gate->flags & k_ent_gate_nonlocal ){
-                  trace_world = &world_static.worlds[ gate->target ];
+                  trace_world = &world_static.instances[ gate->target ];
                }
             }
          }
diff --git a/save.c b/save.c
index 6ea4e0f83307e437a04d7aa9e401a98e7e9fc06d..93169db81eb4c32e25cf5c7b3903163062d1d523 100644 (file)
--- a/save.c
+++ b/save.c
@@ -73,9 +73,10 @@ static void skaterift_write_savedata(void){
 
    vg_msg_frame( &sav, "world" );
    {
-      if( world_loader.reg && (world_static.active_world > 0) ){
-         skaterift_write_addon_alias( &sav, "alias", &world_loader.reg->alias );
-         vg_msg_wkvu32( &sav, "index", world_static.active_world );
+      addon_reg *reg = world_static.addon_client;
+      if( reg && (world_static.active_instance > 0) ){
+         skaterift_write_addon_alias( &sav, "alias", &reg->alias );
+         vg_msg_wkvu32( &sav, "index", world_static.active_instance );
          vg_msg_wkvnum( &sav, "position", k_vg_msg_float|k_vg_msg_32b, 3, 
                         localplayer.rb.co );
       }
index b18ede47466dd8116e1e567524746f23af763823..25a89e652d9421c0a6a367e885334048dc9d58c1 100644 (file)
@@ -132,12 +132,11 @@ static void skaterift_restore_state(void){
       if( reg_id != 0xffffffff ){
          addon_reg *reg = get_addon_from_index( k_addon_type_world, reg_id );
 
-         world_loader.generate_point_cloud = 0;
-         world_loader.reg = reg;
-         world_loader.state = k_world_loader_load;
-         skaterift_world_changer_thread(NULL);
+         world_static.addon_client = reg;
+         world_static.load_state = k_world_loader_load;
+         skaterift_client_world_changer_thread(NULL);
 
-         world_static.active_world = vg_msg_seekkvu32( &world, "index", 0 );
+         world_static.active_instance = vg_msg_seekkvu32( &world, "index", 0 );
          world_static.active_trigger_volume_count = 0;
          localplayer.viewable_world = world_current_instance();
 
@@ -189,16 +188,6 @@ VG_STATIC void vg_load(void){
    vg_loader_step( audio_init, audio_free );
 
    /* 'systems' are completely loaded now */
-   
-   /* load home/permanent world manually */
-   world_loader.reg = NULL;
-   strcpy( world_loader.override_name, "mp_spawn" );
-   world_loader.generate_point_cloud = 1;
-   world_loader.world_index = 0;
-   world_load_mdl( "maps/mp_spawn/main.mdl" );
-
-   vg_async_call( async_skaterift_player_start, NULL, 0 );
-   vg_async_stall();
 
    /* Completing addon registrations
     * -------------------------------------
@@ -234,6 +223,14 @@ VG_STATIC void vg_load(void){
       mtzero->metadata_len = msg.cur;
    }
 
+   /* load home/permanent world manually */
+   world_static.addon_hub = spawn;
+   world_instance_load_mdl( 0, "maps/mp_spawn/main.mdl" );
+
+   vg_async_call( async_skaterift_player_start, NULL, 0 );
+   vg_async_stall();
+
+
    global_skateshop.selected_world_id=1;
    global_skateshop.pointcloud_world_id=1;
    skateshop_world_preview_loader_thread( mtzero ); /* HACK */
@@ -262,7 +259,7 @@ VG_STATIC void draw_origin_axis(void){
    vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
    vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
 }
-static void skaterift_change_world_preupdate(void);
+static void skaterift_change_client_world_preupdate(void);
 
 /* 
  * UPDATE LOOP
@@ -274,8 +271,8 @@ VG_STATIC void vg_pre_update(void){
    steam_update();
    skaterift_preupdate_inputs();
    if( skaterift.op == k_async_op_clientloading ) return;
-   if( world_loader.state == k_world_loader_preload )
-      skaterift_change_world_preupdate();
+   if( world_static.load_state == k_world_loader_preload )
+      skaterift_change_client_world_preupdate();
 
    draw_origin_axis();
    network_update();
@@ -429,9 +426,9 @@ VG_STATIC void render_scene(void){
       return;
    }
 
-   for( u32 i=0; i<vg_list_size(world_static.worlds); i++ ){
-      if( world_static.worlds[i].status == k_world_status_loaded ){
-         world_prerender( &world_static.worlds[i] );
+   for( u32 i=0; i<vg_list_size(world_static.instances); i++ ){
+      if( world_static.instances[i].status == k_world_status_loaded ){
+         world_prerender( &world_static.instances[i] );
       }
    }
 
index 17ed8f8a53a6deb409cdd64238a6a1da7b2ee201..319efa503c5bf8b0f1c3f071cc9d0b612fd19c78 100644 (file)
@@ -56,7 +56,7 @@ struct{
 static skaterift = { .op = k_async_op_clientloading, .time_rate = 1.0f };
 
 /* Skaterift api */
-static void skaterift_change_world_start( void );
+static void skaterift_change_world_start( addon_reg *reg );
 static int  skaterift_change_world_command( int argc, const char *argv[] );
 
 #endif /* SKATERIFT_H */
diff --git a/world.c b/world.c
index 0183acbbd12997d4e3be23296e601bdad6b2c07d..0612644bb305b2a49a9c0f7d93a59210b30fd7e2 100644 (file)
--- a/world.c
+++ b/world.c
@@ -9,7 +9,7 @@
 #include "network.h"
 
 static world_instance *world_current_instance(void){
-   return &world_static.worlds[ world_static.active_world ];
+   return &world_static.instances[ world_static.active_instance ];
 }
 
 static void world_init(void)
diff --git a/world.h b/world.h
index e95f005b5bffb8042108ab82deed8e567b3d6a6b..c412a88097cc3bb98ba044f0a08df45c4dc49764 100644 (file)
--- a/world.h
+++ b/world.h
@@ -201,8 +201,18 @@ struct world_static {
    u32 active_trigger_volumes[8];
    u32 active_trigger_volume_count;
 
-   world_instance worlds[4];
-   i32            active_world;
+   world_instance instances[4];
+   i32            active_instance;
+
+   addon_reg *addon_hub,
+             *addon_client;
+
+   enum world_loader_state{
+      k_world_loader_none,
+      k_world_loader_preload,
+      k_world_loader_load
+   }
+   load_state;
 }
 static world_static;
 
index 510a13401726753e9ab669558bdcbd62d0a15bb2..a8e88d6631fdbf00e14ad98774a32bdbb56a5b64 100644 (file)
@@ -13,7 +13,7 @@ VG_STATIC void world_fadeout_audio( world_instance *world )
                       " audio.\n" );
    }
 
-   u8 world_id = (world - world_static.worlds) + 1;
+   u8 world_id = (world - world_static.instances) + 1;
 
    audio_lock();
    for( u32 i=0; i<AUDIO_CHANNELS; i++ ){
index 7e285d44a54731ea3cd73e93885ff10ed6d70d74..d3c6a8c011b00fc6dc3af5182c66ca33a690bcd3 100644 (file)
@@ -6,9 +6,7 @@
 #include "world.h"
 #include "world_load.h"
 
-VG_STATIC void world_gen_entities_init(void){
-   world_instance *world = world_loading_instance();
-
+VG_STATIC void world_gen_entities_init( world_instance *world ){
    /* lights */
    for( u32 j=0; j<mdl_arrcount(&world->ent_light); j ++ ){
       ent_light *light = mdl_arritm( &world->ent_light, j );
@@ -200,7 +198,7 @@ VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ){
       return;
    }
 
-   u8 world_id = (world - world_static.worlds) + 1;
+   u8 world_id = (world - world_static.instances) + 1;
    u32 index = mdl_entity_id_id( call->id );
    ent_audio *audio = mdl_arritm( &world->ent_audio, index );
 
index eca698ad8bfaa7db84bc2d813f7f883e997e2ae5..bbcfbe20dbb651d1d1a7076cd8e9771f67503504 100644 (file)
@@ -5,7 +5,7 @@
 #include "entity.h"
 #include "bvh.h"
 
-VG_STATIC void world_gen_entities_init(void);
+VG_STATIC void world_gen_entities_init( world_instance *world );
 VG_STATIC ent_spawn *world_find_spawn_by_name( world_instance *world, 
                                                const char *name );
 VG_STATIC ent_spawn *world_find_closest_spawn( world_instance *world, 
index f757cdf8e1b760d167299c080b1731501e9ae1f8..b49113b3f0c381d1f27a618d9a213e57c3748776 100644 (file)
@@ -267,7 +267,7 @@ VG_STATIC ent_gate *world_intersect_gates( world_instance *world,
       if( gate->flags & k_ent_gate_locked ) continue;
 
       if( gate->flags & k_ent_gate_nonlocal ){
-         if( world_loader.state != k_world_loader_none ){
+         if( world_static.load_state != k_world_loader_none ){
             continue;
          }
       }
@@ -296,10 +296,9 @@ VG_STATIC void world_unlink_nonlocal( world_instance *world ){
 /* 
  * attatches nonlocal gates, to be called from main thread ONLY! 
  */
-VG_STATIC void world_link_nonlocal_async( void *payload, u32 size )
-{
+VG_STATIC void world_link_nonlocal_async( void *payload, u32 size ){
    world_instance *world = payload;
-   u32 world_id = world - world_static.worlds;
+   u32 world_id = world - world_static.instances;
 
    for( u32 j=0; j<mdl_arrcount(&world->ent_gate); j ++ ){
       ent_gate *gate = mdl_arritm( &world->ent_gate, j );
@@ -310,8 +309,8 @@ VG_STATIC void world_link_nonlocal_async( void *payload, u32 size )
       const char *key = mdl_pstr( &world->meta, gate->key );
       vg_info( "key: %s\n", key );
 
-      for( u32 i=0; i<vg_list_size(world_static.worlds); i++ ){
-         world_instance *other = &world_static.worlds[i];
+      for( u32 i=0; i<vg_list_size(world_static.instances); i++ ){
+         world_instance *other = &world_static.instances[i];
          if( other == world ) continue;
          if( other->status != k_world_status_loaded ) continue;
          vg_info( "Checking world %u for key matches\n", i );
index 5f7b9a362e7b3fc294b4e6a5d13cd3ce00847f6c..81ad00cbc3c3926e7f2e62ae3344876f15799255 100644 (file)
@@ -46,9 +46,9 @@ VG_STATIC void world_add_all_if_material( m4x3f transform, scene_context *scene,
  * |        |
  * |________|
  */
-VG_STATIC void world_gen_add_blob( scene_context *scene, ray_hit *hit )
+VG_STATIC void world_gen_add_blob( world_instance *world,
+                                   scene_context *scene, ray_hit *hit )
 {
-   world_instance *world = world_loading_instance();
    m4x3f transform;
    v4f qsurface, qrandom;
    v3f axis;
@@ -106,13 +106,13 @@ VG_STATIC void world_gen_add_blob( scene_context *scene, ray_hit *hit )
 /* 
  * Sprinkle foliage models over the map on terrain material 
  */
-VG_STATIC void world_apply_procedural_foliage( scene_context *scene,
+VG_STATIC void world_apply_procedural_foliage( world_instance *world,
+                                               scene_context *scene,
                                                struct world_surface *mat )
 {
    if( vg.quality_profile == k_quality_profile_low )
       return;
 
-   world_instance *world = world_loading_instance();
    vg_info( "Applying foliage (%u)\n", mat->info.pstr_name );
 
    v3f volume;
@@ -139,7 +139,7 @@ VG_STATIC void world_apply_procedural_foliage( scene_context *scene,
       if( ray_world( world, pos, (v3f){0.0f,-1.0f,0.0f}, &hit )){
          struct world_surface *m1 = ray_hit_surface( world, &hit );
          if((hit.normal[1] > 0.8f) && (m1 == mat) && (hit.pos[1] > 0.0f+10.0f)){
-            world_gen_add_blob( scene, &hit );
+            world_gen_add_blob( world, scene, &hit );
             count ++;
          }
       }
@@ -164,12 +164,10 @@ void world_unpack_submesh_dynamic( world_instance *world,
 /*
  * Create the main meshes for the world
  */
-VG_STATIC void world_gen_generate_meshes(void)
-{
+VG_STATIC void world_gen_generate_meshes( world_instance *world ){
    /* 
     * Compile meshes into the world scenes
     */
-   world_instance *world = world_loading_instance();
    scene_init( &world->scene_geo, 320000, 1200000 );
    u32 buf_size = scene_mem_required( &world->scene_geo );
    u8 *buffer = vg_linear_alloc( world->heap, buf_size );
@@ -250,8 +248,10 @@ VG_STATIC void world_gen_generate_meshes(void)
                                     &world->scene_no_collide, &world->meta, i );
       }
 
-      if( surf->info.flags & k_material_flag_grow_grass )
-         world_apply_procedural_foliage( &world->scene_no_collide, surf );
+      if( surf->info.flags & k_material_flag_grow_grass ){
+         world_apply_procedural_foliage( world, &world->scene_no_collide, 
+                                         surf );
+      }
 
       scene_copy_slice( &world->scene_no_collide, &surf->sm_no_collide );
    }
@@ -299,8 +299,7 @@ VG_STATIC void world_gen_generate_meshes(void)
 }
 
 /* signed distance function for cone */
-static f32 fsd_cone_infinite( v3f p, v2f c )
-{
+static f32 fsd_cone_infinite( v3f p, v2f c ){
    v2f q = { v2_length( (v2f){ p[0], p[2] } ), -p[1] };
    float s = vg_maxf( 0.0f, v2_dot( q, c ) );
 
@@ -322,8 +321,7 @@ struct light_indices_upload_info{
 /*
  * Async reciever to buffer light index data 
  */
-VG_STATIC void async_upload_light_indices( void *payload, u32 size )
-{
+VG_STATIC void async_upload_light_indices( void *payload, u32 size ){
    struct light_indices_upload_info *info = payload;
 
    glGenTextures( 1, &info->world->tex_light_cubes );
@@ -338,10 +336,8 @@ VG_STATIC void async_upload_light_indices( void *payload, u32 size )
 /*
  * Computes light indices for world
  */
-VG_STATIC void world_gen_compute_light_indices(void)
-{
+VG_STATIC void world_gen_compute_light_indices( world_instance *world ){
    /* light cubes */
-   world_instance *world = world_loading_instance();
    v3f cubes_min, cubes_max;
    v3_muls( world->scene_geo.bbx[0], 1.0f/k_world_light_cube_size, cubes_min );
    v3_muls( world->scene_geo.bbx[1], 1.0f/k_world_light_cube_size, cubes_max );
@@ -498,10 +494,9 @@ VG_STATIC void world_gen_compute_light_indices(void)
 /*
  * Rendering pass needed to complete the world
  */
-VG_STATIC void async_world_postprocess_render( void *payload, u32 _size )
-{
+VG_STATIC void async_world_postprocess_render( void *payload, u32 _size ){
    /* create scene lighting buffer */
-   world_instance *world = world_loading_instance();
+   world_instance *world = payload;
 
    u32 size = VG_MAX(mdl_arrcount(&world->ent_light),1) * sizeof(float)*12;
    vg_info( "Upload %ubytes (lighting)\n", size );
@@ -624,9 +619,7 @@ VG_STATIC void async_world_postprocess_render( void *payload, u32 _size )
 }
 
 /* Loads textures from the pack file */
-VG_STATIC void world_gen_load_surfaces(void)
-{
-   world_instance *world = world_loading_instance();
+VG_STATIC void world_gen_load_surfaces( world_instance *world ){
    vg_info( "Loading textures\n" );
    world->texture_count = 0;
 
index 90c01e34da09b314bd55f12a1dfa10540a6cea03..42943689aee14723590d3ac061e439bd54089b4e 100644 (file)
@@ -11,9 +11,9 @@
 #include "world.h"
 
 VG_STATIC void world_init_blank( world_instance *world );
-VG_STATIC void world_gen_load_surfaces(void);
-VG_STATIC void world_gen_generate_meshes(void);
-VG_STATIC void world_gen_compute_light_indices(void);
+VG_STATIC void world_gen_load_surfaces( world_instance *world );
+VG_STATIC void world_gen_generate_meshes( world_instance *world );
+VG_STATIC void world_gen_compute_light_indices( world_instance *world );
 VG_STATIC void async_world_postprocess_render( void *payload, u32 _size );
 
 #endif /* WORLD_GEN_H */
index afd4986826e0a63f856e39950fad077c3ca36bf4..f815fa5d2d3675593def3d62c51f3c4a08ae46b5 100644 (file)
@@ -5,24 +5,23 @@
 #include "world_routes.h"
 #include "world_gate.h"
 #include "ent_skateshop.h"
+#include "addon.h"
 
 /* 
- * load the .mdl file located in path (relative to exe), it will load into the 
- * slot specified by world_loader.world_index
+ * load the .mdl file located in path as a world instance
  */
-VG_STATIC void world_load_mdl( const char *path )
-{
+VG_STATIC void world_instance_load_mdl( u32 instance_id, const char *path ){
    vg_rand_seed( 9001 );
 
-   world_instance *world = world_loading_instance();
+   world_instance *world = &world_static.instances[ instance_id ];
    world_init_blank( world );
    world->status = k_world_status_loading;
 
    vg_info( "Loading world: %s\n", path );
 
    void *allocator = NULL;
-   if( world_loader.world_index == 0 ) allocator = world_static.heap;
-   else allocator = world_static.worlds[world_loader.world_index-1].heap;
+   if( instance_id == 0 ) allocator = world_static.heap;
+   else allocator = world_static.instances[instance_id-1].heap;
 
    u32 heap_availible = vg_linear_remaining( allocator );
    u32 min_overhead = sizeof(vg_linear_allocator);
@@ -83,40 +82,35 @@ VG_STATIC void world_load_mdl( const char *path )
    world->time = (float)tm->tm_min/20.0f + (world->info.timezone/24.0f);
 
    /* process resources from pack */
-   world_gen_load_surfaces();
-   world_gen_routes_ent_init();
-   world_gen_entities_init();
+   world_gen_load_surfaces( world );
+   world_gen_routes_ent_init( world );
+   world_gen_entities_init( world );
    
    /* main bulk */
-   world_gen_generate_meshes();
-   world_gen_routes_generate();
-   world_gen_compute_light_indices();
-   vg_async_call( async_world_postprocess_render, NULL, 0 );
+   world_gen_generate_meshes( world );
+   world_gen_routes_generate( instance_id );
+   world_gen_compute_light_indices( world );
+   vg_async_call( async_world_postprocess_render, world, 0 );
    vg_async_stall();
 
    mdl_close( meta );
    world->status = k_world_status_loaded;
 }
 
-static void skaterift_world_change_done( void *payload, u32 size ){
-   world_loader.state = k_world_loader_none;
+static void skaterift_client_world_change_done( void *payload, u32 size ){
+   world_static.load_state = k_world_loader_none;
 }
 
 /*
  * Does a complete world switch using the remaining free slots
  */
-static void skaterift_world_changer_thread( void *_ ){
+static void skaterift_client_world_changer_thread( void *_ ){
    char path_buf[4096];
    vg_str path;
    vg_strnull( &path, path_buf, 4096 );
 
-   if( world_loader.reg ){
-      addon_get_content_folder( world_loader.reg, &path );
-   }
-   else {
-      vg_strcat( &path, "maps/" );
-      vg_strcat( &path, world_loader.override_name );
-   }
+   assert( world_static.addon_client );
+   addon_get_content_folder( world_static.addon_client, &path );
 
    vg_str folder = path;
    if( !vg_strgood( &folder ) ) {
@@ -173,10 +167,10 @@ static void skaterift_world_changer_thread( void *_ ){
       }
    }
 
-   world_loader.generate_point_cloud = 1;
-   world_loader.world_index = 1;
-   world_load_mdl( worlds[first_index] );
+   world_instance_load_mdl( 1, worlds[first_index] );
 
+   /* TODO: Support multiply packed worlds */
+#if 0
    world_loader.generate_point_cloud = 0;
    for( u32 j=0; j<i; j++ ){
       if( j != first_index ){
@@ -184,15 +178,16 @@ static void skaterift_world_changer_thread( void *_ ){
          world_load_mdl( worlds[j] );
       }
    }
+#endif
 
-   vg_async_call( skaterift_world_change_done, NULL, 0 );
+   vg_async_call( skaterift_client_world_change_done, NULL, 0 );
 }
 
 /* holding pattern before we can start loading the new world, since we might be
  * waiting for audio to stop */
-static void skaterift_change_world_preupdate(void){
-   for( u32 i=1; i<vg_list_size(world_static.worlds); i++ ){
-      world_instance *inst = &world_static.worlds[i];
+static void skaterift_change_client_world_preupdate(void){
+   for( u32 i=1; i<vg_list_size(world_static.instances); i++ ){
+      world_instance *inst = &world_static.instances[i];
       
       if( inst->status == k_world_status_unloading ){
          if( world_freeable( inst ) ){
@@ -203,75 +198,82 @@ static void skaterift_change_world_preupdate(void){
    }
 
    vg_info( "worlds cleared, begining load\n" );
-   world_loader.state = k_world_loader_load;
+   world_static.load_state = k_world_loader_load;
 
    /* finally can start the loader */
-   vg_loader_start( skaterift_world_changer_thread, NULL );
+   vg_loader_start( skaterift_client_world_changer_thread, NULL );
 }
 
 /* places all loaded worlds into unloading state */
-static void skaterift_change_world_start(void){
-   if( world_loader.reg ){
-      vg_info( "switching to %s ("PRINTF_U64"\n", 
-               world_loader.reg->alias.foldername, 
-               world_loader.reg->alias.workshop_id );
-   }
-   else{
-      vg_info( "switching to %s(local)\n", world_loader.override_name );
-   }
-
-   if( world_static.active_world != 0 ){
+static void skaterift_change_world_start( addon_reg *reg ){
+   if( world_static.active_instance != 0 )
       vg_error( "Cannot change worlds while in non-root world\n" );
-   }
    else{
-      world_loader.state = k_world_loader_preload;
+      char buf[76];
+      addon_alias_uid( &reg->alias, buf );
+      vg_info( "switching to: %s\n", buf );
+
+      world_static.load_state = k_world_loader_preload;
 
       vg_linear_clear( vg_mem.scratch ); /* ?? */
       vg_info( "unloading old worlds\n" );
-      world_unlink_nonlocal( &world_static.worlds[0] );
+      world_unlink_nonlocal( &world_static.instances[0] );
       
-      for( u32 i=1; i<vg_list_size(world_static.worlds); i++ ){
-         world_instance *inst = &world_static.worlds[i];
+      for( u32 i=1; i<vg_list_size(world_static.instances); i++ ){
+         world_instance *inst = &world_static.instances[i];
 
          if( inst->status == k_world_status_loaded ){
             inst->status = k_world_status_unloading;
             world_fadeout_audio( inst );
+
+            /* TODO: THIS IS WHERE A SAVE SHOULD BE DONE */
          }
       }
+
+      world_static.addon_client = reg;
    }
 }
 
 /* console command for the above function */
-static int skaterift_change_world_command( int argc, const char *argv[] )
-{
+static int skaterift_change_world_command( int argc, const char *argv[] ){
    if( argc == 1 ){
-      world_loader.reg = NULL;
-      vg_strncpy( argv[0], world_loader.override_name,
-                  vg_list_size( world_loader.override_name ),
-                  k_strncpy_always_add_null );
-      skaterift_change_world_start();
+      addon_alias q;
+      q.type = k_addon_type_world;
+      q.workshop_id = 0;
+      vg_strncpy( argv[0], q.foldername, 64, k_strncpy_always_add_null );
+
+      u32 reg_id = addon_match( &q );
+      if( reg_id != 0xffffffff ){
+         addon_reg *reg = get_addon_from_index( k_addon_type_world, reg_id );
+         skaterift_change_world_start( reg );
+      }
+      else {
+         char buf[76];
+         addon_alias_uid( &q, buf );
+         vg_error( "Addon '%s' is not installed or not found.\n", buf );
+      }
    }
 
    return 0;
 }
 
-
+#if 0
 static world_instance *world_loading_instance(void){
-   return &world_static.worlds[ world_loader.world_index ];
+   return &world_static.instances[ world_loader.world_index ];
 }
+#endif
 
 /* 
  * checks:
  *  1. to see if all audios owned by the world have been stopped
  *  2. that this is the least significant world
  */
-static int world_freeable( world_instance *world )
-{
+static int world_freeable( world_instance *world ){
    if( world->status != k_world_status_unloading ) return 0;
-   u8 world_id = (world - world_static.worlds) + 1;
+   u8 world_id = (world - world_static.instances) + 1;
 
-   for( u32 i=world_id; i<vg_list_size(world_static.worlds); i++ ){
-      if( world_static.worlds[i].status != k_world_status_unloaded ){
+   for( u32 i=world_id; i<vg_list_size(world_static.instances); i++ ){
+      if( world_static.instances[i].status != k_world_status_unloaded ){
          return 0;
       }
    }
@@ -315,9 +317,9 @@ static void world_free( world_instance *world )
    /* delete textures and meshes */
    glDeleteTextures( world->texture_count, world->textures );
 
-   u32 world_index = world - world_static.worlds;
+   u32 world_index = world - world_static.instances;
    if( world_index ){
-      vg_linear_del( world_static.worlds[world_index-1].heap, 
+      vg_linear_del( world_static.instances[world_index-1].heap, 
                      vg_linear_header(world->heap) );
    }
 
@@ -367,6 +369,4 @@ VG_STATIC void world_init_blank( world_instance *world )
    v3_copy( (v3f){1.10f, 0.89f, 0.35f}, state->g_sun_colour );
 }
 
-
-
 #endif /* WORLD_LOAD_C */
index 1dc9384b316998aa4599a3753fb95a2aff18e7c1..c4e1d8465e9d9aeb5b213d6e0908f0f0655a1564 100644 (file)
 #include "world_volumes.h"
 #include "addon.h"
 
-struct{
-   addon_reg *reg;
-   char override_name[64];
-   int generate_point_cloud;
-   u32 world_index;
-
-   enum world_loader_state{
-      k_world_loader_none,
-      k_world_loader_preload,
-      k_world_loader_load
-   }
-   state;
-}
-static world_loader;
-
-static world_instance *world_loading_instance(void);
 static void world_free( world_instance *world );
 static int world_freeable( world_instance *world );
 
index d59d4e1b163eb1241d280061c958b669b386e384..ba093b92d75bac2c40172d45b363ef4833624d48 100644 (file)
@@ -23,7 +23,7 @@ VG_STATIC void async_world_render_init( void *payload, u32 size )
 {
    vg_info( "Allocate uniform buffers\n" );
    for( int i=0; i<4; i++ ){
-      world_instance *world = &world_static.worlds[i];
+      world_instance *world = &world_static.instances[i];
       world->ubo_bind_point = i;
 
       glGenBuffers( 1, &world->ubo_lighting );
@@ -37,7 +37,7 @@ VG_STATIC void async_world_render_init( void *payload, u32 size )
 
    vg_info( "Allocate frame buffers\n" );
    for( int i=0; i<4; i++ ){
-      world_instance *world = &world_static.worlds[i];
+      world_instance *world = &world_static.instances[i];
       struct framebuffer *fb = &world->heightmap;
 
       fb->display_name = NULL;
@@ -538,12 +538,12 @@ VG_STATIC void render_world_gates( world_instance *world, camera *cam,
       if( gate->flags & k_ent_gate_locked ) return;
 
       if( gate->flags & k_ent_gate_nonlocal ){
-         if( world_loader.state != k_world_loader_none ){
+         if( world_static.load_state != k_world_loader_none ){
             world->rendering_gate = NULL;
             return;
          }
 
-         world_instance *dest_world = &world_static.worlds[ gate->target ];
+         world_instance *dest_world = &world_static.instances[ gate->target ];
          render_gate( world, dest_world, gate, cam, layer_depth );
       }
       else{
index 44d055b1686409fa68015036d5993f194ce29028..26261a1ed72cc56e4658827dbf83af118e24b1c6 100644 (file)
@@ -745,22 +745,20 @@ VG_STATIC void world_routes_surface_grid( world_instance *world,
    }
 }
 
-VG_STATIC void world_write_preview( pointcloud_buffer *pcbuf ){
+VG_STATIC void world_write_preview( addon_reg *reg, pointcloud_buffer *pcbuf ){
+   if( reg->alias.workshop_id ) return;
+
+   /* 
+    * FIXME: BUG: cannot correctly handle workshop because there is a stalling
+    * call below, which deadlocks the scene upload. TODO: improve the async
+    * stack to handle out of order execution. MAYBE
+    */
+
    char path_buf[4096];
    vg_str path;
    vg_strnull( &path, path_buf, 4096 );
 
-   if( world_loader.reg ){
-      /* Don't want to override the one we get from the workshop */
-      if( world_loader.reg->alias.workshop_id ) return;
-
-      addon_get_content_folder( world_loader.reg, &path );
-   }
-   else{
-      vg_strcat( &path, "maps/" );
-      vg_strcat( &path, world_loader.override_name );
-   }
-
+   addon_get_content_folder( reg, &path );
    vg_strcat( &path, "/preview.bin" );
 
    if( !vg_strgood( &path ) ) vg_fatal_error( "Path too long\n" );
@@ -770,14 +768,14 @@ VG_STATIC void world_write_preview( pointcloud_buffer *pcbuf ){
    fwrite( pcbuf, sizeof(struct pointcloud_buffer) + 
                   sizeof(struct pointcloud_vert)*pcbuf->count, 1, fp );
    fclose( fp );
+   vg_info( "written %s\n", path_buf );
 }
 
 /* 
  * Create the strips of colour that run through the world along course paths
  */
-VG_STATIC void world_gen_routes_generate(void)
-{
-   world_instance *world = world_loading_instance();
+VG_STATIC void world_gen_routes_generate( u32 instance_id ){
+   world_instance *world = &world_static.instances[ instance_id ];
    vg_info( "Generating route meshes\n" );
    vg_async_stall();
 
@@ -789,7 +787,7 @@ VG_STATIC void world_gen_routes_generate(void)
    vg_async_item *call_pointcloud = NULL;
    pointcloud_buffer *pcbuf = NULL;
 
-   if( world_loader.generate_point_cloud ){
+   if( instance_id <= 1 /*world_loader.generate_point_cloud*/ ){
       call_pointcloud = vg_async_alloc( 
             sizeof(pointcloud_buffer) + 
             sizeof(pointcloud_vert)*POINTCLOUD_POINTS );
@@ -850,7 +848,7 @@ VG_STATIC void world_gen_routes_generate(void)
       world_routes_gen_meshes( world, i, &world->scene_lines, pcbuf );
    }
 
-   if( world_loader.generate_point_cloud ){
+   if( instance_id <= 1 /*world_loader.generate_point_cloud*/ ){
       f64 area = 0.0;
       area = world_routes_scatter_surface_points( world, pcbuf, 16.0f );
       world_routes_surface_grid( world, pcbuf );
@@ -866,7 +864,9 @@ VG_STATIC void world_gen_routes_generate(void)
       vg_info( "Distrubuted %u points over %fkm^2!\n", 
                 pcbuf->count, area/1e6f );
 
-      world_write_preview( pcbuf );
+      world_write_preview( instance_id? world_static.addon_client:
+                                        world_static.addon_hub, 
+                                        pcbuf );
       vg_async_dispatch( call_pointcloud, async_pointcloud_sub );
    }
 
@@ -875,9 +875,7 @@ VG_STATIC void world_gen_routes_generate(void)
 }
 
 /* load all routes from model header */
-VG_STATIC void world_gen_routes_ent_init(void)
-{
-   world_instance *world = world_loading_instance();
+VG_STATIC void world_gen_routes_ent_init( world_instance *world ){
    vg_info( "Initializing routes\n" );
 
    for( u32 i=0; i<mdl_arrcount(&world->ent_gate); i++ ){
index c63dd549d95ff1f9bd9e31138547d06b8d613037..f10dc03317b29c1fd1397fabf66babb9059eaff6 100644 (file)
@@ -15,8 +15,8 @@ VG_STATIC void world_routes_activate_entry_gate( world_instance *world,
 VG_STATIC void render_world_routes( world_instance *world, camera *cam, 
                                     int layer_depth );
 
-VG_STATIC void world_gen_routes_ent_init(void);
-VG_STATIC void world_gen_routes_generate(void);
+VG_STATIC void world_gen_routes_ent_init( world_instance *world );
+VG_STATIC void world_gen_routes_generate( u32 instance_id );
 VG_STATIC void world_routes_update_timer_texts( world_instance *world );
 VG_STATIC void world_routes_update( world_instance *world );
 VG_STATIC void world_routes_fixedupdate( world_instance *world );