King horrendous
authorhgn <hgodden00@gmail.com>
Tue, 15 Apr 2025 20:29:12 +0000 (21:29 +0100)
committerhgn <hgodden00@gmail.com>
Tue, 15 Apr 2025 20:29:12 +0000 (21:29 +0100)
49 files changed:
src/addon.c
src/addon.h
src/addon_types.h
src/board_maker.c
src/client.c
src/control_overlay.c
src/ent_region.c
src/ent_skateshop.c
src/ent_skateshop.h
src/entity.h
src/gameserver_database.c
src/gameserver_replay.c
src/gameserver_requests.c
src/menu.c
src/menu.h
src/metascene.c
src/model.c
src/network.c
src/network.h
src/particle.c
src/player.c
src/player_remote.c
src/player_render.c
src/player_skate.c
src/render.c
src/replay2.c
src/replay2.h
src/save.c
src/save.h
src/scene.c
src/scene.h
src/skaterift.c
src/trail.c
src/utest.c
src/workshop.c
src/workshop.h
src/world.c
src/world.h
src/world_entity.c
src/world_gate.c
src/world_gate.h
src/world_gen.c
src/world_gen.h
src/world_load.c
src/world_load.h
src/world_map.c
src/world_render.c
src/world_routes.c
src/world_sfd.c

index 2ac69d1e8c917a7686de3ce7f35cae338463e3eb..c3221f7e0a88ddbef9f9d5e6a0ecb6710558f82f 100644 (file)
@@ -8,7 +8,18 @@
 #include "workshop.h"
 #include <string.h>
 
-struct addon_system addon_system;
+struct _addon _addon;
+
+/* 
+ * internal
+ * --------------------------------------------------------------------------------------------------------------------
+ */
+
+addon_reg *addon_details( addon_id id )
+{
+   if( id ) return &_addon.registry[id-1];
+   else return NULL;
+}
 
 static bool addon_filter( addon_reg *reg, u32 whitelist, u32 blacklist )
 {
@@ -21,136 +32,128 @@ static bool addon_filter( addon_reg *reg, u32 whitelist, u32 blacklist )
    return 1;
 }
 
-u32 addon_count( enum addon_type type, u32 whitelist, u32 blacklist )
+u32 _addon_filtered_count( enum addon_type type, u32 whitelist, u32 blacklist )
 {
-   if( whitelist || blacklist )
+   VG_MUTEX_LOCK( _addon.registry_lock );
+   u32 registry_count = _addon.registry_count;
+   VG_MUTEX_UNLOCK( _addon.registry_lock );
+
+   u32 count = 0;
+   for( u32 i=0; i < registry_count; i++ )
    {
-      u32 typecount = 0, count = 0;
-      for( u32 i=0; typecount<addon_count( type, 0,0 ); i++ )
+      addon_reg *reg = &_addon.registry[i];
+      if( reg->alias.type == type )
       {
-         addon_reg *reg = &addon_system.registry[i];
-         if( reg->alias.type == type )
-         {
-            typecount ++;
-
-            if( addon_filter( reg, whitelist, blacklist ) )
-               count ++;
-         }
+         if( addon_filter( reg, whitelist, blacklist ) )
+            count ++;
       }
-
-      return count;
    }
-   else
-      return addon_system.registry_type_counts[ type ];
+   return count;
 }
 
-
-/* these kind of suck, oh well. */
-addon_reg *get_addon_from_index( enum addon_type type, u32 index, u32 whitelist, u32 blacklist )
+addon_id _addon_get_filtered( enum addon_type type, u32 index, u32 whitelist, u32 blacklist )
 {
-   u32 typecount = 0, count = 0;
-   for( u32 i=0; typecount<addon_count(type,0,0); i++ )
+   VG_MUTEX_LOCK( _addon.registry_lock );
+   u32 registry_count = _addon.registry_count;
+   VG_MUTEX_UNLOCK( _addon.registry_lock );
+
+   u32 count = 0;
+   for( u32 i=0; i<registry_count; i++ )
    {
-      addon_reg *reg = &addon_system.registry[i];
+      addon_reg *reg = &_addon.registry[i];
       if( reg->alias.type == type )
       {
-         typecount ++;
-
          if( addon_filter( reg, whitelist, blacklist ) )
          {
             if( index == count )
-               return reg;
+               return i+1;
 
             count ++;
          }
       }
    }
-
-   return NULL;
+   return 0;
 }
 
-u32 get_index_from_addon( enum addon_type type, addon_reg *a, u32 whitelist, u32 blacklist )
+bool _addon_get_filtered_index( enum addon_type type, addon_id id, u32 whitelist, u32 blacklist, u32 *out_index )
 {
-   u32 typecount = 0, count = 0;
-   for( u32 i=0; typecount<addon_system.registry_type_counts[type]; i++ )
+   if( !id )
+      return 0;
+
+   VG_MUTEX_LOCK( _addon.registry_lock );
+   u32 registry_count = _addon.registry_count;
+   VG_MUTEX_UNLOCK( _addon.registry_lock );
+
+   u32 count = 0;
+   for( u32 i=0; i < registry_count; i++ )
    {
-      addon_reg *reg = &addon_system.registry[i];
+      addon_reg *reg = &_addon.registry[i];
       if( reg->alias.type == type )
       {
-         typecount ++;
-
          if( addon_filter( reg, whitelist, blacklist ) )
          {
-            if( reg == a )
-               return count;
+            if( i == (id-1) )
+            {
+               *out_index = count;
+               return 1;
+            }
 
             count ++;
          }
       }
    }
-
-   return 0xffffffff;
+   return 0;
 }
 
-u32 addon_match( addon_alias *alias )
+addon_id _get_addon_by_alias( addon_alias *alias )
 {
-   if( alias->type == k_addon_type_none ) return 0xffffffff;
+   if( alias->type == k_addon_type_none ) 
+      return 0;
 
    u32 foldername_djb2 = 0;
    if( !alias->workshop_id )
       foldername_djb2 = vg_strdjb2( alias->foldername );
 
+   VG_MUTEX_LOCK( _addon.registry_lock );
+   u32 registry_count = _addon.registry_count;
+   VG_MUTEX_UNLOCK( _addon.registry_lock );
+
    u32 count = 0;
-   for( u32 i=0; count<addon_system.registry_type_counts[alias->type]; i++ )
+   for( u32 i=0; i < registry_count; i++ )
    {
-      addon_reg *reg = &addon_system.registry[i];
+      addon_reg *reg = &_addon.registry[i];
       if( reg->alias.type == alias->type )
       {
          if( alias->workshop_id )
          {
             if( alias->workshop_id == reg->alias.workshop_id )
-               return count;
+               return i+1;
          }
          else
          {
             if( reg->foldername_hash == foldername_djb2 )
             {
                if( !strcmp( reg->alias.foldername, alias->foldername ) )
-                  return count;
+                  return i+1;
             }
          }
 
          count ++;
       }
    }
-
-   return 0xffffffff;
-}
-
-/*
- * Create a string version of addon alias in buf
- */
-void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] )
-{
-   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 );
-   }
+   return 0;
 }
 
 /*
  * equality check
  */
-int addon_alias_eq( addon_alias *a, addon_alias *b )
+bool addon_alias_eq( addon_alias *a, addon_alias *b )
 {
-   if( a->type == b->type ){
-      if( a->workshop_id == b->workshop_id ){
+   if( a->type == b->type )
+   {
+      if( a->workshop_id == b->workshop_id )
+      {
          if( a->workshop_id )
             return 1;
          else
@@ -162,20 +165,26 @@ int addon_alias_eq( addon_alias *a, addon_alias *b )
    else return 0;
 }
 
+
 /*
- * make alias represent NULL.
+ * Create a string version of addon alias in buf
  */
-void invalidate_addon_alias( addon_alias *alias )
+void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] )
 {
-   alias->type = k_addon_type_none;
-   alias->workshop_id = 0;
-   alias->foldername[0] = '\0';
+   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 );
+}
+
+void addon_uid( addon_id id, char buf[ ADDON_UID_MAX ] )
+{
+   if( id ) addon_alias_uid( &addon_details(id)->alias, buf );
+   else     buf[0] = '\0';
 }
 
 /*
  * parse uid to alias. returns 1 if successful
  */
-int addon_uid_to_alias( const char *uid, addon_alias *alias )
+bool addon_uid_to_alias( const char *uid, addon_alias *alias )
 {
 /*           1
  * 01234567890123
@@ -185,14 +194,14 @@ int addon_uid_to_alias( const char *uid, addon_alias *alias )
  *         |
  *     location
  */
-   if( strlen(uid) < 13 ){
-      invalidate_addon_alias( alias );
+   alias->type = k_addon_type_none;
+   alias->workshop_id = 0;
+   alias->foldername[0] = '\0';
+
+   if( strlen(uid) < 13 )
       return 0;
-   }
-   if( !((uid[0] == 's') && (uid[1] == 'r')) ){
-      invalidate_addon_alias( alias );
+   if( !((uid[0] == 's') && (uid[1] == 'r')) )
       return 0;
-   }
 
    char type[4];
    memcpy( type, uid+2, 3 );
@@ -205,29 +214,28 @@ int addon_uid_to_alias( const char *uid, addon_alias *alias )
 
    if( !strcmp(location,"steam") )
       alias->workshop_id = atoll( uid+12 );
-   else if( !strcmp(location,"local") ){
+   else if( !strcmp(location,"local") )
+   {
       alias->workshop_id = 0;
       vg_strncpy( uid+12, alias->foldername, 64, k_strncpy_always_add_null );
    }
-   else{
-      invalidate_addon_alias( alias );
+   else
       return 0;
-   }
 
    return 1;
 }
 
 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 );
-   addon_system.cache_lock = SDL_CreateMutex();
-   VG_ASSERT( addon_system.cache_lock );
+   THREAD_1;
+
+   u32 reg_size = sizeof(addon_reg)*ADDON_MOUNTED_MAX;
+   _addon.registry = vg_linear_alloc( vg_mem.rtmemory, reg_size );
 
    for( u32 type=0; type<k_addon_type_max; type++ )
    {
       struct addon_type_info *inf = &addon_type_infos[type];
-      struct addon_cache *cache = &addon_system.cache[type];
+      struct addon_cache *cache = &_addon.cache[type];
 
       if( inf->cache_count )
       {
@@ -257,59 +265,73 @@ void addon_system_init( void )
          for( i32 j=0; j<inf->cache_count; j++ )
          {
             struct addon_cache_entry *alloc = &cache->allocs[j];
-            alloc->reg_ptr   = NULL;
-            alloc->reg_index = 0xffffffff;
+            alloc->addon_id = 0;
 
             if( inf->item_arena_size )
             {
-               cache->arenas[j] = _vg_create_linear_allocator( 
-                     vg_mem.rtmemory, inf->item_arena_size, VG_MEMORY_SYSTEM,
-                     "Item cache's arena" );
+               cache->arenas[j] = _vg_create_linear_allocator( vg_mem.rtmemory, inf->item_arena_size, VG_MEMORY_SYSTEM,
+                                                               "Item cache's arena" );
             }
          }
       }
    }
 }
 
-/*
- * Scanning routines
- * -----------------------------------------------------------------------------
- */
+static void addon_set_foldername( addon_reg *reg, const char name[64] )
+{
+   vg_strncpy( name, reg->alias.foldername, 64, k_strncpy_always_add_null );
+   reg->foldername_hash = vg_strdjb2( reg->alias.foldername );
+}
 
-/*
- * Reciever for scan completion. copies the registry counts back into main fred
- */
-void async_addon_reg_update( void *data, u32 size )
+static bool addon_try_load_metadata( addon_reg *reg, const char *folder_path )
 {
-   vg_info( "Registry update notify\n" );
-   
-   for( u32 i=0; i<k_addon_type_max; i++ ){
-      addon_system.registry_type_counts[i] = 0;
+   THREAD_1;
+   VG_ASSERT( reg );
+
+   char path_buf[ 4096 ];
+   vg_str meta_path;
+   vg_strnull( &meta_path, path_buf, sizeof(path_buf) );
+   vg_strcat( &meta_path, folder_path );
+   vg_strcat( &meta_path, "/addon.inf" );
+
+   if( !vg_strgood( &meta_path ) )
+   {
+      vg_error( "The metadata path is too long\n" );
+      return 0;
    }
 
-   for( u32 i=0; i<addon_system.registry_count; i++ ){
-      enum addon_type type = addon_system.registry[i].alias.type;
-      addon_system.registry_type_counts[ type ] ++;
+   FILE *fp = fopen( meta_path.buffer, "rb" );
+   if( !fp )
+   {
+      vg_error( "Could not open the '%s'\n", meta_path.buffer );
+      return 0;
    }
-}
 
-static void addon_set_foldername( addon_reg *reg, const char name[64] ){
-   vg_strncpy( name, reg->alias.foldername, 64, k_strncpy_always_add_null );
-   reg->foldername_hash = vg_strdjb2( reg->alias.foldername );
+   reg->metadata_len = fread( reg->metadata, 1, 512, fp );
+   if( !feof(fp) )
+   {
+      fclose(fp);
+      vg_error( "Metadata too big\n" );
+      return 0;
+   }
+   fclose(fp);
+
+   return 1;
 }
 
-/*
- * Create a new registry 
- */
-static addon_reg *addon_alloc_reg( PublishedFileId_t workshop_id, enum addon_type type )
+static addon_id addon_alloc_reg( PublishedFileId_t workshop_id, enum addon_type type )
 {
-   if( addon_system.registry_count == ADDON_MOUNTED_MAX )
+   VG_MUTEX_LOCK( _addon.registry_lock );
+   if( _addon.registry_count == ADDON_MOUNTED_MAX )
    {
       vg_error( "You have too many addons installed!\n" );
-      return NULL;
+      VG_MUTEX_UNLOCK( _addon.registry_lock );
+      return 0;
    }
+   addon_id id = _addon.registry_count+1;
+   VG_MUTEX_UNLOCK( _addon.registry_lock );
 
-   addon_reg *reg = &addon_system.registry[ addon_system.registry_count ];
+   addon_reg *reg = &_addon.registry[ id-1 ];
    reg->flags = 0;
    reg->metadata_len = 0;
    reg->cache_id = 0;
@@ -324,144 +346,88 @@ static addon_reg *addon_alloc_reg( PublishedFileId_t workshop_id, enum addon_typ
       addon_set_foldername( reg, foldername );
       reg->flags |= ADDON_REG_WORKSHOP;
    }
-   return reg;
+   return id;
 }
 
-/*
- * If the addon.inf exists int the folder, load into the reg
- */
-static int addon_try_load_metadata( addon_reg *reg, vg_str folder_path )
+static void addon_complete_allocation(void)
 {
-   vg_str meta_path = folder_path;
-   vg_strcat( &meta_path, "/addon.inf" );
-   if( !vg_strgood( &meta_path ) )
-   {
-      vg_error( "The metadata path is too long\n" );
-      return 0;
-   }
-
-   FILE *fp = fopen( meta_path.buffer, "rb" );
-   if( !fp )
-   {
-      vg_error( "Could not open the '%s'\n", meta_path.buffer );
-      return 0;
-   }
-
-   reg->metadata_len = fread( reg->metadata, 1, 512, fp );
-   if( reg->metadata_len != 512 )
-   {
-      if( !feof(fp) )
-      {
-         fclose(fp);
-         vg_error( "unknown error codition" );
-         reg->metadata_len = 0;
-         return 0;
-      }
-   }
-   fclose(fp);
-   return 1;
+   VG_MUTEX_LOCK( _addon.registry_lock );
+   _addon.registry_count ++;
+   VG_MUTEX_UNLOCK( _addon.registry_lock );
 }
 
-static void addon_print_info( addon_reg *reg )
+static void addon_fail_allocation(void)
 {
-   vg_info( "addon_reg #%u{\n", addon_system.registry_count );
-   vg_info( "  type: %d\n", reg->alias.type );
-   vg_info( "  workshop_id: " PRINTF_U64 "\n", reg->alias.workshop_id );
-   vg_info( "  folder: [%u]%s\n", reg->foldername_hash, reg->alias.foldername );
-   vg_info( "  metadata_len: %u\n", reg->metadata_len );
-   vg_info( "  cache_id: %hu\n", reg->cache_id );
-   vg_info( "  flags: %hu\n", reg->flags );
-   vg_info( "}\n" );
-}
-
-static void addon_mount_finish( addon_reg *reg ){
-#if 0
-   addon_print_info( reg );
-#endif
-   addon_system.registry_count ++;
 }
 
 /*
- * Mount a fully packaged addon, one that certainly has a addon.inf
+ * local addons / mods
+ * ---------------------------------------------------------------------------------------------------------------------
  */
-static addon_reg *addon_mount_workshop_folder( PublishedFileId_t workshop_id, vg_str folder_path )
+addon_id _addon_mount_from_folder( const char *folder, enum addon_type type, const char *content_ext )
 {
-   addon_reg *reg = addon_alloc_reg( workshop_id, k_addon_type_none );
-   if( !reg ) return NULL;
+   THREAD_1;
 
-   if( !addon_try_load_metadata( reg, folder_path ) )
-      return NULL;
-
-   enum addon_type type = k_addon_type_none;
-   vg_msg msg;
-   vg_msg_init( &msg, reg->metadata, reg->metadata_len );
-
-   if( vg_msg_seekframe( &msg, "workshop" ))
+   const char *folder_name = folder;
+   for( u32 i=0; i<4096; i ++ )
    {
-      vg_msg_getkvintg( &msg, "type", k_vg_msg_u32, &type, NULL );
-   }
-
-   if( type == k_addon_type_none )
-   {
-      vg_error( "Cannot determine addon type\n" );
-      return NULL;
+      if( folder[i] == '/' )
+      {
+         folder_name = folder + i + 1;
+         break;
+      }
+      else if( folder[i] == '\0' ) 
+         break;
    }
 
-   reg->alias.type = type;
-   addon_mount_finish( reg );
-   return reg;
-}
-
-/*
- * Mount a local folder. may or may not have addon.inf
- */
-addon_reg *addon_mount_local_addon( const char *folder, enum addon_type type, const char *content_ext )
-{
-   char folder_path_buf[4096];
-   vg_str folder_path;
-   vg_strnull( &folder_path, folder_path_buf, 4096 );
-   vg_strcat( &folder_path, folder );
-
-   const char *folder_name = vg_strch( &folder_path, '/' )+1;
+   VG_MUTEX_LOCK( _addon.registry_lock );
+   u32 registry_count = _addon.registry_count;
+   VG_MUTEX_UNLOCK( _addon.registry_lock );
+   
    u32 folder_hash = vg_strdjb2(folder_name);
-   for( u32 i=0; i<addon_system.registry_count; i++ )
+   for( u32 i=0; i<registry_count; i++ )
    {
-      addon_reg *reg = &addon_system.registry[i];
-
+      addon_reg *reg = &_addon.registry[i];
       if( (reg->alias.type == type) && (reg->foldername_hash == folder_hash) )
       {
          if( !strcmp( reg->alias.foldername, folder_name ) )
-         {
-            return reg;
-         }
+            return i+1;
       }
    }
 
-   addon_reg *reg = addon_alloc_reg( 0, type );
-   if( !reg ) return NULL;
+   addon_id id = addon_alloc_reg( 0, type );
+   if( !id )
+      return 0;
+
+   addon_reg *reg = &_addon.registry[ id-1 ];
    addon_set_foldername( reg, folder_name );
-   addon_try_load_metadata( reg, folder_path );
+   bool loaded_metadata = addon_try_load_metadata( reg, folder );
 
-   if( reg->metadata_len )
+   if( loaded_metadata )
    {
       vg_msg msg;
       vg_msg_init( &msg, reg->metadata, reg->metadata_len );
 
       u32 flags = 0x00;
       vg_msg_getkvintg( &msg, "flags", k_vg_msg_u32, &flags, NULL );
-      reg->flags |= flags;
+      reg->flags = ADDON_REG_MOUNTED | flags;
+      addon_complete_allocation();
+      return id;
    }
    else
    {
-      vg_strcat( &folder_path, "" ); /* NOTE: this looks fucky because try_load_metadata edits the buffer, this sets it 
-                                              back. to remove the addon.inf which it appened to that buffer (but not
-                                              edit the vg_str)....... */
+      char path_buf[ 4096 ];
+      vg_str folder_path;
+      vg_strnull( &folder_path, path_buf, sizeof(path_buf) );
+      vg_strcat( &folder_path, folder );
+
       vg_dir subdir;
-      enum dir_open_result result = vg_dir_open(&subdir, folder_path.buffer);
+      enum dir_open_result result = vg_dir_open( &subdir, folder_path.buffer );
       if( result != k_dir_open_ok )
       {
          vg_error( "Failed to open '%s' (%s)\n", folder_path.buffer, dir_open_result_str[result] );
-         return NULL;
+         addon_fail_allocation();
+         return 0;
       }
 
       /* create our own content commands */
@@ -475,21 +441,22 @@ addon_reg *addon_mount_local_addon( const char *folder, enum addon_type type, co
       vg_msg_end_frame( &msg );
 
       u32 content_count = 0;
-
       while( vg_dir_next_entry(&subdir) )
       {
          if( vg_dir_entry_type(&subdir) == k_vg_entry_type_file )
          {
             const char *fname = vg_dir_entry_name(&subdir);
-            vg_str file = folder_path;
-            vg_strcat( &file, "/" );
-            vg_strcat( &file, fname );
-            if( !vg_strgood( &file ) ) continue;
-
-            char *ext = vg_strch( &file, '.' );
-            if( !ext ) continue;
-            if( strcmp(ext,content_ext) ) continue;
-            
+            vg_str file_path = folder_path;
+            vg_strcat( &file_path, "/" );
+            vg_strcat( &file_path, fname );
+            if( !vg_strgood( &file_path ) ) 
+               continue;
+
+            char *ext = vg_strch( &file_path, '.' );
+            if( !ext ) 
+               continue;
+            if( strcmp( ext, content_ext ) ) 
+               continue;
             vg_msg_wkvstr( &msg, "content", fname );
             content_count ++;
          }
@@ -497,90 +464,32 @@ addon_reg *addon_mount_local_addon( const char *folder, enum addon_type type, co
       vg_dir_close(&subdir);
 
       if( !content_count ) 
-         return NULL;
+      {
+         addon_fail_allocation();
+         return 0;
+      }
 
       if( msg.error == k_vg_msg_error_OK )
+      {
          reg->metadata_len = msg.cur.co;
+         reg->flags = ADDON_REG_MOUNTED;
+         addon_complete_allocation();
+         return id;
+      }
       else
       {
          vg_error( "Error creating metadata: %d\n", msg.error );
-         return NULL;
+         addon_fail_allocation();
+         return 0;
       }
    }
-
-   addon_mount_finish( reg );
-   return reg;
 }
 
-/*
- * Check all subscribed items
- */
-void addon_mount_workshop_items(void)
+void _addon_mount_content_folder( enum addon_type type, const char *base_folder, const char *content_ext )
 {
-   if( skaterift.demo_mode )
-   {
-      vg_info( "Won't load workshop items in demo mode\n" );
-      return;
-   }
-
-   if( !steam_ready ) 
-      return;
-
-   /*
-    * Steam workshop scan
-    */
-   vg_info( "Mounting steam workshop subscriptions\n" );
-   PublishedFileId_t workshop_ids[ ADDON_MOUNTED_MAX ];
-   u32 workshop_count = ADDON_MOUNTED_MAX;
-
-   vg_async_item *call = vg_async_alloc( sizeof(struct async_workshop_installed_files_info));
-   struct async_workshop_installed_files_info *info = call->payload;
-   info->buffer = workshop_ids;
-   info->len = &workshop_count;
-   vg_async_dispatch( call, async_workshop_get_installed_files );
-   vg_async_stall();
-
-   for( u32 j=0; j<workshop_count; j++ )
-   {
-      /* check for existance in both our caches
-       * ----------------------------------------------------------*/
-      PublishedFileId_t id = workshop_ids[j];
-      for( u32 i=0; i<addon_system.registry_count; i++ )
-      {
-         addon_reg *reg = &addon_system.registry[i];
-
-         if( reg->alias.workshop_id == id )
-            goto next_file_workshop;
-      }
-
-      vg_async_item *call1 = 
-         vg_async_alloc( sizeof(struct async_workshop_filepath_info) );
-
-      char path[ 4096 ];
-
-      struct async_workshop_filepath_info *info = call1->payload;
-      info->buf = path;
-      info->id = id;
-      info->len = VG_ARRAY_LEN(path);
-      vg_async_dispatch( call1, async_workshop_get_filepath );
-      vg_async_stall(); /* too bad! */
+   THREAD_1;
 
-      vg_str folder = {.buffer = path, .i=strlen(path), .len=4096};
-      addon_mount_workshop_folder( id, folder );
-next_file_workshop:;
-   }
-}
-
-/*
- * Scan a local content folder for addons. It must find at least one file with 
- * the specified content_ext to be considered.
- */
-void addon_mount_content_folder( enum addon_type type,
-                                 const char *base_folder, 
-                                 const char *content_ext )
-{
-   vg_info( "Mounting addons(type:%d) matching skaterift/%s/*/*%s\n", 
-                  type, base_folder, content_ext );
+   vg_info( "Mounting addons(type:%d) matching skaterift/%s/*/*%s\n", type, base_folder, content_ext );
 
    char path_buf[4096];
    vg_str path;
@@ -596,162 +505,236 @@ void addon_mount_content_folder( enum addon_type type,
 
    vg_strcat(&path,"/");
 
-   while( vg_dir_next_entry(&dir) ){
-      if( vg_dir_entry_type(&dir) == k_vg_entry_type_dir ){
+   while( vg_dir_next_entry(&dir) )
+   {
+      if( vg_dir_entry_type(&dir) == k_vg_entry_type_dir )
+      {
          const char *d_name = vg_dir_entry_name(&dir);
 
          vg_str folder = path;
-         if( strlen( d_name ) > ADDON_FOLDERNAME_MAX ){
+         if( strlen( d_name ) > ADDON_FOLDERNAME_MAX )
+         {
             vg_warn( "folder too long: %s\n", d_name );
             continue;
          }
 
          vg_strcat( &folder, d_name );
-         if( !vg_strgood( &folder ) ) continue;
-
-         addon_mount_local_addon( folder.buffer, type, content_ext );
+         if( !vg_strgood( &folder ) ) 
+            continue;
+         
+         _addon_mount_from_folder( path_buf, type, content_ext );
       }
    }
    vg_dir_close(&dir);
 }
 
-/*
- * write the full path of the addon's folder into the vg_str
+/* workshop mounting 
+ * ------------------------------------------------------------------------------------------------------------------ 
  */
-int addon_get_content_folder( addon_reg *reg, vg_str *folder, int async)
+struct workshop_mount_info
 {
-   if( reg->alias.workshop_id )
+   u64 workshop_id;
+   char path[];
+};
+static void workshop_mount_task( vg_async_task *task )
+{
+   THREAD_1;
+   struct workshop_mount_info *info = (void *)task->data;
+
+   addon_id id = addon_alloc_reg( info->workshop_id, k_addon_type_none );
+   if( !id )
+      return;
+
+   addon_reg *reg = &_addon.registry[ id-1 ];
+   bool loaded_metadata = addon_try_load_metadata( reg, info->path );
+
+   if( !loaded_metadata )
+   {
+      addon_fail_allocation();
+      return;
+   }
+
+   enum addon_type type = k_addon_type_none;
+   vg_msg msg;
+   vg_msg_init( &msg, reg->metadata, reg->metadata_len );
+
+   if( vg_msg_seekframe( &msg, "workshop" ))
+      vg_msg_getkvintg( &msg, "type", k_vg_msg_u32, &type, NULL );
+
+   if( type == k_addon_type_none )
+   {
+      vg_error( "Cannot determine addon type\n" );
+      addon_fail_allocation();
+      return;
+   }
+
+   reg->alias.type = type;
+   reg->flags = ADDON_REG_MOUNTED;
+   addon_complete_allocation();
+}
+
+struct workshop_scan_info
+{
+   enum workshop_scan_state
+   {
+      k_workshop_scan_state_filter_mounted,
+      k_workshop_scan_state_mount
+   }
+   state;
+
+   u32 count;
+   PublishedFileId_t workshop_ids[ ADDON_MOUNTED_MAX ];
+};
+static void workshop_scan_t1( vg_async_task *co_task )
+{
+   THREAD_1;
+   struct workshop_scan_info *co_info = (void *)co_task->data;
+
+   if( co_info->state == k_workshop_scan_state_filter_mounted )
    {
-      struct async_workshop_filepath_info *info = NULL;
-      vg_async_item *call = NULL;
+      vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct workshop_scan_info), 1 );
+      struct workshop_scan_info *info = (void *)task->data;
+      info->state = k_workshop_scan_state_mount;
 
-      if( async )
+      u32 send_count = 0;
+      for( u32 i=0; i<co_info->count; i ++ )
       {
-         call = vg_async_alloc( sizeof(struct async_workshop_filepath_info) );
-         info = call->payload;
+         for( u32 j=0; j<_addon.registry_count; j ++ )
+         {
+            if( _addon.registry[j].alias.workshop_id == co_info->workshop_ids[i] )
+               goto s1;
+         }
+         
+         info->workshop_ids[ send_count ++ ] = co_info->workshop_ids[i];
+s1:;
       }
-      else 
-         info = alloca( sizeof(struct async_workshop_filepath_info) );
 
-      info->buf = folder->buffer;
-      info->id = reg->alias.workshop_id;
-      info->len = folder->len;
+      info->count = send_count;
+      vg_async_task_dispatch( task, _mount_workshop_addons );
+   }
+}
+
+void _mount_workshop_addons( vg_async_task *co_task )
+{
+   THREAD_0;
+
+   if( skaterift.demo_mode )
+   {
+      vg_info( "Won't load workshop items in demo mode\n" );
+      return;
+   }
+
+   if( !steam_ready ) 
+      return;
+
+   ISteamUGC *hSteamUGC = SteamAPI_SteamUGC();
 
-      if( async )
+   if( !co_task )
+   {
+      vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct workshop_scan_info), 1 );
+      struct workshop_scan_info *info = (void *)task->data;
+      info->state = k_workshop_scan_state_filter_mounted;
+
+      u32 count = SteamAPI_ISteamUGC_GetSubscribedItems( hSteamUGC, info->workshop_ids, ADDON_MOUNTED_MAX );
+      vg_info( "Found %u subscribed items\n", count );
+
+      u32 send_count = 0;
+
+      for( u32 i=0; i<count; i++ )
       {
-         vg_async_dispatch( call, async_workshop_get_filepath );
-         vg_async_stall(); /* too bad! */
+         u32 state = SteamAPI_ISteamUGC_GetItemState( hSteamUGC, info->workshop_ids[i] );
+         if( !(state & k_EItemStateInstalled) )
+            continue;
+
+         info->workshop_ids[ send_count ++ ] = info->workshop_ids[i];
       }
-      else 
+
+      info->count = send_count;
+      vg_async_task_dispatch( task, workshop_scan_t1 );
+   }
+   else
+   {
+      struct workshop_scan_info *co_info = (void *)co_task->data;
+      for( u32 i=0; i<co_info->count; i ++ )
       {
-         async_workshop_get_filepath( info, 0 );
+         char path[ 4096 ];
+
+         u64 _size;
+         u32 _ts;
+         if( !SteamAPI_ISteamUGC_GetItemInstallInfo( hSteamUGC, co_info->workshop_ids[i], 
+                                                     &_size, path, sizeof(path), &_ts ))
+         {
+            vg_error( "GetItemInstallInfo failed for addon %lu\n", co_info->workshop_ids[i] );
+            continue;
+         }
+
+         u32 len = strlen( path );
+         vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct workshop_mount_info)+len+1, 1 );
+         struct workshop_mount_info *info = (void *)task->data;
+         strcpy( info->path, path );
+         info->workshop_id = co_info->workshop_ids[i];
+         vg_async_task_dispatch( task, workshop_mount_task );
       }
+   }
+}
 
-      if( folder->buffer[0] == '\0' )
+bool addon_get_content_folder( addon_id addon_id, vg_str *folder )
+{
+   THREAD_0;
+   VG_ASSERT( addon_id );
+
+   addon_reg *reg = addon_details( addon_id );
+   if( reg->alias.workshop_id )
+   {
+      ISteamUGC *hSteamUGC = SteamAPI_SteamUGC();
+      u64 _size;
+      u32 _ts;
+      if( !SteamAPI_ISteamUGC_GetItemInstallInfo( hSteamUGC, reg->alias.workshop_id, &_size, 
+                                                   folder->buffer, folder->len, &_ts ))
       {
-         vg_error( "Failed SteamAPI_GetItemInstallInfo(" PRINTF_U64 ")\n", reg->alias.workshop_id );
+         vg_error( "GetItemInstallInfo failed for addon %lu\n", reg->alias.workshop_id );
          return 0;
       }
+
       folder->i = strlen( folder->buffer );
       return 1;
    }
    else
    {
-      folder->i = 0;
-      
-      const char *local_folder = 
-         addon_type_infos[reg->alias.type].local_content_folder;
+      const char *local_folder = addon_type_infos[reg->alias.type].local_content_folder;
+      if( !local_folder ) 
+         return 0;
 
-      if( !local_folder ) return 0;
       vg_strcat( folder, local_folder );
       vg_strcat( folder, reg->alias.foldername );
       return 1;
    }
 }
 
+#if 0
 /*
- * Return existing cache id if reg_index points to a registry with its cache
- * already set.
+ * write the full path of the addon's folder into the vg_str
  */
-u16 addon_cache_fetch( enum addon_type type, u32 reg_index )
-{
-   addon_reg *reg = NULL;
-
-   if( reg_index < addon_count( type, 0,0 ) )
-   {
-      reg = get_addon_from_index( type, reg_index, 0,0 );
-      if( reg->cache_id ) 
-         return reg->cache_id;
-   }
-
-   return 0;
-}
+#endif
 
+#if 0
 /*
- * Allocate a new cache item from the pool
+ * cache section
+ * --------------------------------------------------------------------------------------------------------------------
  */
-u16 addon_cache_alloc( enum addon_type type, u32 reg_index )
-{
-   struct addon_cache *cache = &addon_system.cache[ type ];
-
-   u16 new_id = vg_pool_lru( &cache->pool );
-   struct addon_cache_entry *new_entry = vg_pool_item( &cache->pool, new_id );
-
-   addon_reg *reg = NULL;
-   if( reg_index < addon_count( type, 0,0 ) )
-      reg = get_addon_from_index( type, reg_index, 0,0 );
-
-   if( new_entry ){
-      if( new_entry->reg_ptr )
-         new_entry->reg_ptr->cache_id = 0;
-
-      if( reg )
-         reg->cache_id = new_id;
 
-      new_entry->reg_ptr = reg;
-      new_entry->reg_index = reg_index;
-      return new_id;
-   }
-   else{
-      vg_error( "cache full (type: %u)!\n", type );
-      return 0;
-   }
-}
+/*
+ * Return existing cache id if reg_index points to a registry with its cache
+ * already set.
+ */
 
 /*
  * Get the real item data for cache id 
  */
-void *addon_cache_item( enum addon_type type, u16 id )
-{
-   if( !id ) return NULL;
-
-   struct addon_cache *cache = &addon_system.cache[type];
-   return cache->items + ((size_t)(id-1) * cache->stride);
-}
-
-void *addon_cache_item_arena( enum addon_type type, u16 id )
-{
-   VG_ASSERT( id );
-   struct addon_cache *cache = &addon_system.cache[type];
-   return cache->arenas[ id-1 ];
-}
 
 /*
  * Get the real item data for cache id ONLY if the item is completely loaded.
  */
-void *addon_cache_item_if_loaded( enum addon_type type, u16 id )
-{
-   if( !id ) 
-      return NULL;
-
-   struct addon_cache *cache = &addon_system.cache[type];
-   struct addon_cache_entry *entry = vg_pool_item( &cache->pool, id );
-
-   if( entry->state == k_addon_cache_state_loaded )
-      return addon_cache_item( type, id );
-   else 
-      return NULL;
-}
 
 /* 
  * Updates the item state from the main thread
@@ -759,9 +742,9 @@ void *addon_cache_item_if_loaded( enum addon_type type, u16 id )
 void async_addon_setstate( void *_entry, u32 _state )
 {
    addon_cache_entry *entry = _entry;
-   SDL_LockMutex( addon_system.cache_lock );
+   SDL_LockMutex( _addon.cache_lock );
    entry->state = _state;
-   SDL_UnlockMutex( addon_system.cache_lock );
+   SDL_UnlockMutex( _addon.cache_lock );
    vg_success( "   loaded (%s)\n", entry->reg_ptr->alias.foldername );
 }
 
@@ -818,17 +801,6 @@ static int addon_cache_load_request( enum addon_type type, u16 id,
    return 0;
 }
 
-static void addon_cache_free_item( enum addon_type type, u16 id ){
-   if( type == k_addon_type_board ){
-      struct player_board *board = addon_cache_item( type, id );
-      player_board_unload( board );
-   }
-   else if( type == k_addon_type_player ){
-      struct player_model *model = addon_cache_item( type, id );
-      player_model_unload( model );
-   }
-}
-
 /*
  * Goes over cache item load requests and calls the above ^
  */
@@ -839,13 +811,13 @@ static void T1_addon_cache_load_loop(void *_)
 
    for( u32 type=0; type<k_addon_type_max; type++ )
    {
-      struct addon_cache *cache = &addon_system.cache[type];
+      struct addon_cache *cache = &_addon.cache[type];
 
       for( u32 id=1; id<=cache->pool.count; id++ )
       {
          addon_cache_entry *entry = vg_pool_item( &cache->pool, id );
 
-         SDL_LockMutex( addon_system.cache_lock );
+         SDL_LockMutex( _addon.cache_lock );
          if( entry->state == k_addon_cache_state_load_request )
          {
             vg_info( "process cache load request (%u#%u, reg:%u)\n", type, id, entry->reg_index );
@@ -854,11 +826,11 @@ static void T1_addon_cache_load_loop(void *_)
             {
                /* should maybe have a different value for this case */
                entry->state = k_addon_cache_state_none;
-               SDL_UnlockMutex( addon_system.cache_lock );
+               SDL_UnlockMutex( _addon.cache_lock );
                continue;
             }
 
-            SDL_UnlockMutex( addon_system.cache_lock );
+            SDL_UnlockMutex( _addon.cache_lock );
 
             /* continue with the request */
             addon_reg *reg = get_addon_from_index( type, entry->reg_index, 0,0 );
@@ -876,12 +848,12 @@ static void T1_addon_cache_load_loop(void *_)
             }
             
             vg_warn( "cache item did not load (%u#%u)\n", type, id );
-            SDL_LockMutex( addon_system.cache_lock );
+            SDL_LockMutex( _addon.cache_lock );
             entry->state = k_addon_cache_state_none;
-            SDL_UnlockMutex( addon_system.cache_lock );
+            SDL_UnlockMutex( _addon.cache_lock );
          }
          else
-            SDL_UnlockMutex( addon_system.cache_lock );
+            SDL_UnlockMutex( _addon.cache_lock );
       }
    }
 }
@@ -890,92 +862,274 @@ void addon_system_pre_update(void)
 {
    if( !vg_loader_availible() ) return;
 
-   SDL_LockMutex( addon_system.cache_lock );
+   SDL_LockMutex( _addon.cache_lock );
    for( u32 type=0; type<k_addon_type_max; type++ )
    {
-      struct addon_cache *cache = &addon_system.cache[type];
+      struct addon_cache *cache = &_addon.cache[type];
 
       for( u32 id=1; id<=cache->pool.count; id++ )
       {
          addon_cache_entry *entry = vg_pool_item( &cache->pool, id );
          if( entry->state == k_addon_cache_state_load_request )
          {
-            SDL_UnlockMutex( addon_system.cache_lock );
+            SDL_UnlockMutex( _addon.cache_lock );
             vg_loader_start( T1_addon_cache_load_loop, NULL );
             return;
          }
       }
    }
-   SDL_UnlockMutex( addon_system.cache_lock );
+   SDL_UnlockMutex( _addon.cache_lock );
+}
+
+#endif
+
+void *addon_cache_item_arena( enum addon_type type, addon_cache_id id )
+{
+   VG_ASSERT( id );
+   struct addon_cache *cache = &_addon.cache[type];
+   return cache->arenas[ id-1 ];
+}
+
+struct cache_complete_info
+{
+   enum addon_type type;
+   addon_cache_id cache_id;
+   enum addon_cache_state result_state;
+};
+static void cache_load_complete( vg_async_task *task )
+{
+   THREAD_0;
+   struct cache_complete_info *info = (void *)task->data;
+   
+   struct addon_cache *cache = &_addon.cache[info->type];
+   addon_cache_entry *cache_entry = vg_pool_item( &cache->pool, info->cache_id );
+   cache_entry->state = info->result_state;
+}
+
+struct cache_load_info
+{
+   enum addon_type type;
+   addon_cache_id cache_id;
+
+   char path[];
+};
+static void cache_load_task( vg_async_task *task )
+{
+   THREAD_1;
+   struct cache_load_info *info = (void *)task->data;
+   struct addon_cache *cache = &_addon.cache[info->type];
+   addon_cache_entry *cache_entry = vg_pool_item( &cache->pool, info->cache_id );
+   vg_info( "process cache load request (%u#%u): %s\n", info->type, info->cache_id, info->path );
+
+   /* load content files
+    * --------------------------------- */
+   char path_buf[4096];
+   vg_str content_path;
+   vg_strnull( &content_path, path_buf, sizeof(path_buf) );
+   vg_strcat( &content_path, info->path );
+
+   addon_reg *reg = addon_details( cache_entry->addon_id );
+   vg_msg msg;
+   vg_msg_init( &msg, reg->metadata, reg->metadata_len );
+   enum addon_cache_state result_state = k_addon_cache_state_errored;
+
+   const char *kv_content = vg_msg_getkvstr( &msg, "content" );
+   if( kv_content )
+   {
+      vg_strcat( &content_path, "/" );
+      vg_strcat( &content_path, kv_content );
+   }
+   else
+   {
+      vg_error( "   No content paths in metadata\n" );
+      goto e0;
+   }
+
+   if( !vg_strgood( &content_path ) ) 
+   {
+      vg_error( "   Metadata path too long\n" );
+      goto e0;
+   }
+   
+   if( info->type == k_addon_type_board )
+   {
+      struct player_board *board = addon_cache_item_data( info->type, info->cache_id, 0 );
+      void *arena = addon_cache_item_arena( info->type, info->cache_id );
+      vg_linear_clear( arena );
+
+      player_board_load( board, content_path.buffer, arena );
+      result_state = k_addon_cache_state_loaded;
+   }
+   else if( info->type == k_addon_type_player )
+   {
+      struct player_model *model = addon_cache_item_data( info->type, info->cache_id, 0 );
+      void *arena = addon_cache_item_arena( info->type, info->cache_id );
+      vg_linear_clear( arena );
+
+      player_model_load( model, content_path.buffer, arena );
+      result_state = k_addon_cache_state_loaded;
+   }
+
+e0:;
+   vg_async_task *res_task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct cache_complete_info), 1 );
+   struct cache_complete_info *complete_info = (void *)res_task->data;
+   complete_info->type = info->type;
+   complete_info->cache_id = info->cache_id;
+   complete_info->result_state = result_state;
+   vg_async_task_dispatch( res_task, cache_load_complete );
 }
 
 /*
- * Perform the cache interactions required to create a viewslot which will
- * eventually be loaded by other parts of the system.
+ * cache section
+ * --------------------------------------------------------------------------------------------------------------------
  */
-u16 addon_cache_create_viewer( enum addon_type type, u16 reg_id )
+void _addon_system_pre_update(void)
 {
-   struct addon_cache *cache = &addon_system.cache[type];
-   vg_pool *pool = &cache->pool;
+   for( u32 type=0; type<k_addon_type_max; type++ )
+   {
+      struct addon_cache *cache = &_addon.cache[type];
 
-   u16 cache_id = addon_cache_fetch( type, reg_id );
+      for( u32 id=1; id<=cache->pool.count; id++ )
+      {
+         addon_cache_entry *entry = vg_pool_item( &cache->pool, id );
+         if( entry->state == k_addon_cache_state_load_request )
+         {
+            char path_buf[4096];
+            vg_str folder;
+            vg_strnull( &folder, path_buf, 4096 );
+            if( !addon_get_content_folder( entry->addon_id, &folder ) )
+            {
+               entry->state = k_addon_cache_state_errored;
+               continue;
+            }
+            
+            u32 len = strlen( path_buf ) + 1;
+            vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct cache_load_info) + len, 1 );
+            struct cache_load_info *info = (void *)task->data;
+
+            info->type = type;
+            info->cache_id = id;
+            strcpy( info->path, path_buf );
+
+            entry->state = k_addon_cache_state_loading;
+            vg_async_task_dispatch( task, cache_load_task );
+         }
+      }
+   }
+}
+
+void *addon_cache_item_data( enum addon_type type, addon_cache_id cache_id, bool only_if_loaded )
+{
+   if( !cache_id ) 
+      return NULL;
+
+   struct addon_cache *cache = &_addon.cache[type];
+
+   if( only_if_loaded )
+   {
+      struct addon_cache_entry *entry = vg_pool_item( &cache->pool, cache_id );
+      if( entry->state != k_addon_cache_state_loaded )
+         return NULL;
+   }
+
+   return cache->items + ((size_t)(cache_id-1) * cache->stride);
+}
+
+addon_cache_id addon_cache_create_viewer( enum addon_type type, addon_id addon_id )
+{
+   THREAD_0;
+
+   if( !addon_id )
+      return 0;
+
+   struct addon_cache *cache = &_addon.cache[type];
+   addon_reg *reg = addon_details( addon_id );
+   VG_ASSERT( reg->alias.type == type );
+
+   addon_cache_id cache_id = reg->cache_id;
    if( !cache_id )
    {
-      cache_id = addon_cache_alloc( type, reg_id );
+      struct addon_cache *cache = &_addon.cache[ type ];
+      cache_id = vg_pool_lru( &cache->pool );
 
-      if( cache_id )
+      if( !cache_id )
       {
-         SDL_LockMutex( addon_system.cache_lock );
-         addon_cache_entry *entry = vg_pool_item( pool, cache_id );
+         vg_error( "cache full (type: %u)!\n", type );
+         return 0;
+      }
 
-         if( entry->state == k_addon_cache_state_loaded )
-            addon_cache_free_item( type, cache_id );
+      struct addon_cache_entry *new_entry = vg_pool_item( &cache->pool, cache_id );
+      if( new_entry->state == k_addon_cache_state_loaded )
+      {
+         if( type == k_addon_type_board )
+         {
+            player_board_unload( addon_cache_item_data( type, cache_id, 0 ) );
+         }
+         else if( type == k_addon_type_player )
+         {
+            player_model_unload( addon_cache_item_data( type, cache_id, 0 ) );
+         }
+         new_entry->state = k_addon_cache_state_none;
+      }
 
-         entry->state = k_addon_cache_state_load_request;
-         SDL_UnlockMutex( addon_system.cache_lock );
+      if( new_entry->addon_id )
+      {
+         addon_reg *previous_owner = addon_details( new_entry->addon_id );
+         previous_owner->cache_id = 0;
       }
+
+      new_entry->state = k_addon_cache_state_load_request;
+      new_entry->addon_id = addon_id;
+      reg->cache_id = cache_id;
    }
 
    if( cache_id )
-      vg_pool_watch( pool, cache_id );
+      vg_pool_watch( &cache->pool, cache_id );
 
    return cache_id;
 }
 
-u16 addon_cache_create_viewer_from_uid( enum addon_type type, const char uid[ADDON_UID_MAX] )
+addon_cache_id addon_cache_create_viewer_from_uid( enum addon_type type, const char uid[ADDON_UID_MAX] )
 {
+   THREAD_0;
+
    addon_alias q;
    if( !addon_uid_to_alias( uid, &q ) ) 
       return 0;
    if( q.type != type ) 
       return 0;
 
-   u32 reg_id = addon_match( &q );
-
-   if( reg_id == 0xffffffff )
+   addon_id addon_id = _get_addon_by_alias( &q );
+   if( addon_id )
+   {
+      return addon_cache_create_viewer( type, addon_id );
+   }
+   else
    {
       vg_warn( "We dont have the addon '%s' installed.\n", uid );
       return 0;
    }
-   else
-      return addon_cache_create_viewer( type, reg_id );
 }
 
-void addon_cache_watch( enum addon_type type, u16 cache_id )
+void addon_cache_watch( enum addon_type type, addon_cache_id cache_id )
 {
-   if( !cache_id ) return;
+   THREAD_0;
+
+   if( !cache_id ) 
+      return;
 
-   struct addon_cache *cache = &addon_system.cache[type];
-   vg_pool *pool = &cache->pool;
-   vg_pool_watch( pool, cache_id );
+   struct addon_cache *cache = &_addon.cache[type];
+   vg_pool_watch( &cache->pool, cache_id );
 }
 
-void addon_cache_unwatch( enum addon_type type, u16 cache_id )
+void addon_cache_unwatch( enum addon_type type, addon_cache_id cache_id )
 {
+   THREAD_0;
+
    if( !cache_id ) 
       return;
 
-   struct addon_cache *cache = &addon_system.cache[type];
-   vg_pool *pool = &cache->pool;
-   vg_pool_unwatch( pool, cache_id );
+   struct addon_cache *cache = &_addon.cache[type];
+   vg_pool_unwatch( &cache->pool, cache_id );
 }
+
index c65524babf66b7433b846f1dc7a6dbb8394401f6..2bfdc9c4229dd5b714e4c60c0bd074e460330134 100644 (file)
@@ -3,10 +3,13 @@
 #include "vg/vg_mem_pool.h"
 #include "vg/vg_string.h"
 #include "addon_types.h"
+#include "vg/vg_mutex.h"
 
 typedef struct addon_reg addon_reg;
 typedef struct addon_cache_entry addon_cache_entry;
 typedef struct addon_alias addon_alias;
+typedef u16 addon_id;
+typedef u16 addon_cache_id;
 
 struct addon_alias 
 {
@@ -15,7 +18,7 @@ struct addon_alias
    char foldername[ ADDON_FOLDERNAME_MAX ];
 };
 
-struct addon_system
+struct _addon
 {
    struct addon_reg
    {
@@ -24,27 +27,26 @@ struct addon_system
       u8 metadata[512];  /* vg_msg buffer */
       u32 metadata_len;
       u32 flags;
-      u16 cache_id;
+      addon_cache_id cache_id;
    }
    *registry;
    u32 registry_count;
-
-   /* deffered: updates in main thread */
-   u32 registry_type_counts[k_addon_type_max];
+   vg_mutex registry_lock;
 
    struct addon_cache
    {
       struct addon_cache_entry
       {
-         u32 reg_index;
-         addon_reg *reg_ptr;     /* TODO: only use reg_index? */
-
+         addon_id addon_id;
          vg_pool_node poolnode;
 
-         enum addon_cache_state{
+         enum addon_cache_state
+         {
             k_addon_cache_state_none,
             k_addon_cache_state_loaded,
-            k_addon_cache_state_load_request
+            k_addon_cache_state_load_request,
+            k_addon_cache_state_loading,
+            k_addon_cache_state_errored
          }
          state;
       }
@@ -56,39 +58,35 @@ struct addon_system
       size_t stride;
    }
    cache[k_addon_type_max];
-   SDL_mutex *cache_lock;
 }
-extern addon_system;
+extern _addon;
 
 void addon_system_init( void );
-u32 addon_count( enum addon_type type, u32 whitelist, u32 blacklist );
-addon_reg *get_addon_from_index( enum addon_type type, u32 index, u32 whitelist, u32 blacklist );
-u32 get_index_from_addon( enum addon_type type, addon_reg *a, u32 whitelist, u32 blacklist );
-int addon_get_content_folder( addon_reg *reg, vg_str *folder, int async);
 
-/* scanning routines */
-u32 addon_match( addon_alias *alias );
-int addon_alias_eq( addon_alias *a, addon_alias *b );
+addon_reg *addon_details( addon_id id );
+u32 _addon_filtered_count( enum addon_type type, u32 whitelist, u32 blacklist );
+addon_id _addon_get_filtered( enum addon_type type, u32 index, u32 whitelist, u32 blacklist );
+bool _addon_get_filtered_index( enum addon_type type, addon_id id, u32 whitelist, u32 blacklist, u32 *out_index );
+addon_id _get_addon_by_alias( addon_alias *alias );
+bool addon_alias_eq( addon_alias *a, addon_alias *b );
 void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] );
-int addon_uid_to_alias( const char *uid, addon_alias *alias );
-void invalidate_addon_alias( addon_alias *alias );
-void addon_mount_content_folder( enum addon_type type,
-                                    const char *base_folder, 
-                                    const char *content_ext );
-void addon_mount_workshop_items(void);
-void async_addon_reg_update( void *data, u32 size );
-addon_reg *addon_mount_local_addon( const char *folder,
-                                       enum addon_type type,
-                                       const char *content_ext );
-u16 addon_cache_fetch( enum addon_type type, u32 reg_index );
-u16 addon_cache_alloc( enum addon_type type, u32 reg_index );
-void *addon_cache_item( enum addon_type type, u16 id );
-void *addon_cache_item_if_loaded( enum addon_type type, u16 id );
-void async_addon_setstate( void *data, u32 size );
+bool addon_uid_to_alias( const char *uid, addon_alias *alias );
+bool addon_get_content_folder( addon_id addon_id, vg_str *folder );
+
+/* Loader thread only
+ * Mount a specific addon from folder path
+ */
+addon_id _addon_mount_from_folder( const char *folder, enum addon_type type, const char *content_ext );
+
+void _addon_mount_content_folder( enum addon_type type, const char *base_folder, const char *content_ext );
+void _mount_workshop_addons( vg_async_task *co_task );
+
+
 
-void addon_system_pre_update(void);
-u16 addon_cache_create_viewer( enum addon_type type, u16 reg_id);
 
-void addon_cache_watch( enum addon_type type, u16 cache_id );
-void addon_cache_unwatch( enum addon_type type, u16 cache_id );
-u16 addon_cache_create_viewer_from_uid( enum addon_type type, const char uid[ADDON_UID_MAX] );
+void _addon_system_pre_update(void);
+addon_cache_id addon_cache_create_viewer( enum addon_type type, addon_id addon_id );
+addon_cache_id addon_cache_create_viewer_from_uid( enum addon_type type, const char uid[ADDON_UID_MAX] );
+void addon_cache_watch( enum addon_type type, addon_cache_id cache_id );
+void addon_cache_unwatch( enum addon_type type, addon_cache_id cache_id );
+void *addon_cache_item_data( enum addon_type type, addon_cache_id cache_id, bool only_if_loaded );
index 5f50d618e36ccc1dc68f2d2a925834bf058e1fd0..2b6e8bbf38b5045f34b47fc5fa6ee9a7fa7572fe 100644 (file)
@@ -24,6 +24,9 @@ enum addon_type{
 
 #define ADDON_REG_VALLEY   0x100
 
+#define ADDON_REG_MOUNTED  0x10000
+#define ADDON_REG_BROKEN   0x20000
+
 #ifdef VG_ENGINE
 
 struct addon_type_info 
index 35ab07a08c7db1b998b0ee0bc3342465d96bc0a0..40ac2a36d58cd2eaffd2d308464ee63d43b8d0dd 100644 (file)
@@ -28,16 +28,15 @@ struct _board_maker _board_maker =
 /* image loader thread 
  * ---------------------------------------- */
 
-struct async_board_maker_image_load_thread_data
+struct board_maker_image_info
 {
    void *data;
    i32 w, h;
 };
 
-static void _async_board_maker_image_finish( void *payload, u32 size )
+static void _async_board_maker_image_finish( vg_async_task *task )
 {
-   struct async_board_maker_image_load_thread_data *inf = payload;
-
+   struct board_maker_image_info *inf = (void *)task->data;
    struct board_maker_decal *decal = &_board_maker.decals[ _board_maker.ui_target_part ];
 
    if( decal->loaded )
@@ -60,21 +59,21 @@ static void _async_board_maker_image_finish( void *payload, u32 size )
    _board_maker.compositor_state = k_board_maker_compositor_dirty;
 }
 
-static void _board_maker_image_thread( void *_ )
+static void _board_maker_image_t1( void *userdata )
 {
-   vg_async_item *call = vg_async_alloc( sizeof(struct async_board_maker_image_load_thread_data) );
-   struct async_board_maker_image_load_thread_data *inf = call->payload;
-
+   THREAD_1;
+   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct board_maker_image_info), 1 );
+   struct board_maker_image_info *info = (void *)task->data;
    i32 nc;
    stbi_set_flip_vertically_on_load(1);
-   inf->data = stbi_load( _board_maker.browser->current_path, &inf->w, &inf->h, &nc, 4 );
-   vg_async_dispatch( call, _async_board_maker_image_finish );
+   info->data = stbi_load( _board_maker.browser->current_path, &info->w, &info->h, &nc, 4 );
+   vg_async_task_dispatch( task, _async_board_maker_image_finish );
 }
 
 /* model loader thread 
  * ----------------------------------------- */
 
-static void _async_board_maker_load_finish( void *payload, u32 size )
+static void _async_board_maker_load_finish( void *userdata )
 {
    _board_maker.state = k_board_maker_state_none;
    _board_maker.template_loaded = _board_maker.template_selection;
@@ -112,6 +111,7 @@ const char *_board_maker_template_paths[] =
 
 static void _board_maker_load_template( void *_ )
 {
+   THREAD_1;
    vg_linear_clear( _board_maker.template_heap );
 
    mdl_context *mdl = &_board_maker.template_mdl;
@@ -124,22 +124,23 @@ static void _board_maker_load_template( void *_ )
 
    mdl_async_full_load_std( mdl, NULL );
    mdl_close( mdl );
-
-   vg_async_call( _async_board_maker_load_finish, NULL, 0 );
+   vg_async_call( &vg.main_tasks, _async_board_maker_load_finish, NULL );
 }
 
 /* system init thread 
  * ----------------------------------------------------- */
 
-static void _async_board_maker_init_finish( void *payload, u32 size )
+static void _async_board_maker_init_finish( void *userdata )
 {
+   THREAD_0;
    _board_maker.state = k_board_maker_state_none;
 }
 
-static void _board_maker_init_thread( void *_ )
+static void _board_maker_init_t1( void *userdata )
 {
+   THREAD_1;
    vg_framebuffer_create( &_board_maker.compositor_fb );
-   vg_async_call( _async_board_maker_init_finish, NULL, 0 );
+   vg_async_call( &vg.main_tasks, _async_board_maker_init_finish, NULL );
 }
 
 static void _board_maker_export(void)
@@ -311,30 +312,21 @@ void _board_maker_pre_update(void)
             _board_maker.template_loaded = -1;
          }
 
-         if( vg_loader_availible() )
-         {
-            _board_maker.state = k_board_maker_state_loading_template;
-            vg_loader_start( _board_maker_load_template, NULL );
-         }
+         _board_maker.state = k_board_maker_state_loading_template;
+         vg_async_call( &vg.loader_tasks, _board_maker_load_template, NULL );
       }
    }
    else
    {
       if( _board_maker.state == k_board_maker_state_not_ready )
       {
-         if( vg_loader_availible() )
-         {
-            _board_maker.state = k_board_maker_state_initializing;
-            vg_loader_start( _board_maker_init_thread, NULL );
-         }
+         _board_maker.state = k_board_maker_state_initializing;
+         vg_async_call( &vg.loader_tasks, _board_maker_init_t1, NULL );
       }
       else if( _board_maker.state == k_board_maker_state_load_image )
       {
-         if( vg_loader_availible() )
-         {
-            vg_loader_start( _board_maker_image_thread, NULL );
-            _board_maker.state = k_board_maker_state_loading_image;
-         }
+         _board_maker.state = k_board_maker_state_loading_image;
+         vg_async_call( &vg.loader_tasks, _board_maker_image_t1, NULL );
       }
       else if( _board_maker.state == k_board_maker_state_export )
       {
index daedaa58b16fdcd9f69f528cc77edc50ae7303c5..6d0dbd903e481bea49b6d431d2f018dc456db920 100644 (file)
@@ -2,7 +2,6 @@
 #include "vg/vg_loader.h"
 #include "vg/vg_io.h"
 #include "vg/vg_audio.h"
-#include "vg/vg_async.h"
 
 #include "client.h"
 #include "render.h"
@@ -18,8 +17,10 @@ struct game_client g_client =
    .unreadyness = 2  /* once for client, once for world switcher */
 };
 
-static void async_client_ready( void *payload, u32 size )
+void async_client_ready( void *userdata )
 {
+   THREAD_0;
+
    g_client.unreadyness --;
 
    if( network_client.auto_connect )
@@ -30,12 +31,11 @@ static void async_client_ready( void *payload, u32 size )
 
 void vg_load(void)
 {
+   THREAD_1;
+
    //vg_audio.always_keep_compressed = 1;
    vg_loader_step( render_init, NULL );
-
    game_load();
-
-   vg_async_call( async_client_ready, NULL, 0 );
 }
 
 void vg_preload(void)
index d6963a2cc5798e3bdf7eb2b99cefb5a673931d32..735bb0bfcc5d875e82cb19d28580ca9885b00b13 100644 (file)
@@ -16,18 +16,9 @@ static void render_overlay_mesh( enum control_overlay_mesh index )
    mdl_draw_submesh( &control_overlay.mdl.submeshes[ index ] );
 }
 
-void control_overlay_init(void)
+static void control_overlay_init_finish( void *userdata )
 {
-   void *alloc = vg_mem.rtmemory;
    mdl_context *mdl = &control_overlay.mdl;
-
-   mdl_open( mdl, "models/rs_overlay.mdl", alloc );
-   mdl_load_metadata_block( mdl, alloc );
-   mdl_async_full_load_std( mdl, NULL );
-   mdl_close( mdl );
-
-   vg_async_stall();
-
    if( mdl->texture_count )
    {
       mdl_texture *tex = &mdl->textures[ 0 ];
@@ -38,9 +29,20 @@ void control_overlay_init(void)
       control_overlay.tex = vg.tex_missing;
       vg_error( "No texture in control overlay\n" );
    }
+}
+
+void control_overlay_init(void)
+{
+   void *alloc = vg_mem.rtmemory;
+   mdl_context *mdl = &control_overlay.mdl;
+
+   mdl_open( mdl, "models/rs_overlay.mdl", alloc );
+   mdl_load_metadata_block( mdl, alloc );
+   mdl_async_full_load_std( mdl, NULL );
+   mdl_close( mdl );
+   vg_async_call( &vg.main_tasks, control_overlay_init_finish, NULL );
 
-   vg_console_reg_var( "control_overlay", &control_overlay.enabled, 
-                       k_var_dtype_i32, VG_VAR_PERSISTENT );
+   vg_console_reg_var( "control_overlay", &control_overlay.enabled, k_var_dtype_i32, VG_VAR_PERSISTENT );
 }
 
 static void draw_key( bool press, bool wide )
index 35df0b1119ebe18a86d323fa9ef08e76addd3859..94ea1ba9c2b30aaa31d266c26ea8ade5504699f3 100644 (file)
@@ -148,7 +148,9 @@ void ent_region_re_eval( world_instance *world )
       }
    }
 
-   if( _world.main.addon->flags & ADDON_REG_MTZERO )
+   addon_reg *world_reg = addon_details( _world.main.addon_id );
+
+   if( world_reg->flags & ADDON_REG_MTZERO )
    {
       if( world_total & k_ent_route_flag_achieve_gold )
       {
@@ -162,7 +164,7 @@ void ent_region_re_eval( world_instance *world )
          steam_store_achievements();
       }
    }
-   else if( _world.main.addon->flags & ADDON_REG_CITY )
+   else if( world_reg->flags & ADDON_REG_CITY )
    {
       if( world_total & k_ent_route_flag_achieve_silver )
       {
index 076b3e19f17439c25b91676ad64f630d6fd721cd..23962f80d7f01096e935e6b2fe7996a37601e807 100644 (file)
 #include "save.h"
 #include "network.h"
 
-struct global_skateshop _skateshop = 
-{
-   .render={.reg_id=0xffffffff,.world_reg=0xffffffff},
-};
+struct global_skateshop _skateshop;
 
 static void skateshop_update_viewpage(void)
 {
-   u32 page = _skateshop.selected_board_id/SKATESHOP_VIEW_SLOT_MAX;
+   u32 page = _skateshop.selected_board_index/SKATESHOP_VIEW_SLOT_MAX;
 
    for( u32 i=0; i<SKATESHOP_VIEW_SLOT_MAX; i++ )
    {
@@ -32,118 +29,15 @@ static void skateshop_update_viewpage(void)
    for( u32 i=0; i<SKATESHOP_VIEW_SLOT_MAX; i++ )
    {
       struct shop_view_slot *slot = &_skateshop.shop_view_slots[i];
-      u32 request_id = page*SKATESHOP_VIEW_SLOT_MAX + i;
-      slot->cache_id = addon_cache_create_viewer( k_addon_type_board, request_id );
-   }
-}
-
-struct async_preview_load_thread_data
-{
-   void *data;
-   addon_reg *reg;
-};
-
-static void skateshop_async_preview_imageload( void *data, u32 len )
-{
-   struct async_preview_load_thread_data *inf = data;
-
-   if( inf->data ){
-      glBindTexture( GL_TEXTURE_2D, _skateshop.tex_preview );
-      glTexSubImage2D( GL_TEXTURE_2D, 0,0,0,
-                        WORKSHOP_PREVIEW_WIDTH, WORKSHOP_PREVIEW_HEIGHT, 
-                        GL_RGB, GL_UNSIGNED_BYTE, inf->data );
-      glGenerateMipmap( GL_TEXTURE_2D );
-      stbi_image_free( inf->data );
-
-      skaterift.rt_textures[k_skaterift_rt_workshop_preview] = _skateshop.tex_preview;
-   }
-   else {
-      skaterift.rt_textures[k_skaterift_rt_workshop_preview] = vg.tex_missing;
+      u32 index = page*SKATESHOP_VIEW_SLOT_MAX + i;
+      addon_id addon_id = _addon_get_filtered( k_addon_type_board, index, 0, ADDON_REG_HIDDEN );
+      slot->cache_id = addon_cache_create_viewer( k_addon_type_board, addon_id );
    }
-
-   SDL_LockMutex( addon_system.cache_lock );
-   _skateshop.reg_loaded_preview = inf->reg;
-   SDL_UnlockMutex( addon_system.cache_lock );
 }
 
-static void skateshop_update_preview_image_thread(void *_args)
+static void skateshop_init_async( void *userdata )
 {
-   char path_buf[4096];
-   vg_str folder;
-   vg_strnull( &folder, path_buf, sizeof(path_buf) );
-
-   SDL_LockMutex( addon_system.cache_lock );
-   addon_reg *reg_preview = _skateshop.reg_preview;
-   SDL_UnlockMutex( addon_system.cache_lock );
-
-   if( !addon_get_content_folder( reg_preview, &folder, 1 ) )
-   {
-      SDL_LockMutex( addon_system.cache_lock );
-      _skateshop.reg_loaded_preview = reg_preview;
-      SDL_UnlockMutex( addon_system.cache_lock );
-      return;
-   }
-
-   vg_strcat( &folder, "/preview.jpg" );
-   vg_async_item *call = vg_async_alloc( sizeof(struct async_preview_load_thread_data) );
-   struct async_preview_load_thread_data *inf = call->payload;
-
-   inf->reg = reg_preview;
-
-   if( vg_strgood( &folder ) )
-   {
-      stbi_set_flip_vertically_on_load(1);
-      int x, y, nc;
-      inf->data = stbi_load( folder.buffer, &x, &y, &nc, 3 );
-
-      if( inf->data )
-      {
-         if( (x != WORKSHOP_PREVIEW_WIDTH) || (y != WORKSHOP_PREVIEW_HEIGHT) )
-         {
-            vg_error( "Resolution does not match framebuffer, so we can't show it\n" );
-            stbi_image_free( inf->data );
-            inf->data = NULL;
-         }
-      }
-
-      vg_async_dispatch( call, skateshop_async_preview_imageload );
-   }
-   else
-   {
-      vg_error( "Path too long to workshop preview image.\n" );
-
-      SDL_LockMutex( addon_system.cache_lock );
-      _skateshop.reg_loaded_preview = reg_preview;
-      SDL_UnlockMutex( addon_system.cache_lock );
-   }
-}
-
-void skateshop_world_preview_preupdate(void)
-{
-   /* try to load preview image if we availible to do. */
-   if( vg_loader_availible() )
-   {
-      SDL_LockMutex( addon_system.cache_lock );
-      if( _skateshop.reg_preview != _skateshop.reg_loaded_preview )
-      {
-         SDL_UnlockMutex( addon_system.cache_lock );
-         vg_loader_start( skateshop_update_preview_image_thread, NULL );
-      }
-      else SDL_UnlockMutex( addon_system.cache_lock );
-   }
-}
-
-static void skateshop_init_async(void *_data,u32 size)
-{
-       glGenTextures( 1, &_skateshop.tex_preview );
-       glBindTexture( GL_TEXTURE_2D, _skateshop.tex_preview );
-   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, WORKSHOP_PREVIEW_WIDTH, WORKSHOP_PREVIEW_HEIGHT,
-                  0, GL_RGB, GL_UNSIGNED_BYTE, NULL );
-
-   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
-   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
-   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
-   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+   THREAD_0;
 
    skaterift.rt_textures[ k_skaterift_rt_workshop_preview ] = vg.tex_missing;
    skaterift.rt_textures[ k_skaterift_rt_server_status ] = vg.tex_missing;
@@ -155,14 +49,16 @@ static void skateshop_init_async(void *_data,u32 size)
  */
 void skateshop_init(void)
 {
-   vg_async_call( skateshop_init_async, NULL, 0 );
+   THREAD_1;
+   vg_async_call( &vg.main_tasks, skateshop_init_async, NULL );
 }
 
-static u16 skateshop_selected_cache_id(void)
+static addon_cache_id skateshop_selected_board_cache_id(void)
 {
-   if( addon_count(k_addon_type_board, 0,ADDON_REG_HIDDEN) )
+   addon_id id = _addon_get_filtered( k_addon_type_board, _skateshop.selected_board_index, 0, ADDON_REG_HIDDEN );
+   if( id )
    {
-      addon_reg *reg = get_addon_from_index( k_addon_type_board, _skateshop.selected_board_id, 0, ADDON_REG_HIDDEN );
+      addon_reg *reg = addon_details( id );
       return reg->cache_id;
    }
    else return 0;
@@ -186,22 +82,32 @@ static void skateshop_server_helper_update(void)
    }
 }
 
-static void board_scan_thread( void *_args )
+struct skateshop_scan_info
+{
+   enum addon_type type;
+};
+static void skateshop_addon_scan_task( vg_async_task *task )
 {
-   addon_mount_content_folder( k_addon_type_board, "boards", ".mdl" );
-   addon_mount_workshop_items();
-   vg_async_call( async_addon_reg_update, NULL, 0 );
-   vg_async_stall();
+   THREAD_1;
+   struct skateshop_scan_info *info = (void *)task->data;
+   if( info->type == k_addon_type_board )
+      _addon_mount_content_folder( k_addon_type_board, "boards", ".mdl" );
+   else if( info->type == k_addon_type_player )
+      _addon_mount_content_folder( k_addon_type_world, "playermodels", ".mdl" );
+   else if( info->type == k_addon_type_world )
+      _addon_mount_content_folder( k_addon_type_world, "maps", ".mdl" );
 }
 
-static void world_scan_thread( void *_args )
+static void skateshop_scan( enum addon_type specific_type )
 {
-   addon_mount_content_folder( k_addon_type_world, "maps", ".mdl" );
-   addon_mount_workshop_items();
-   vg_async_call( async_addon_reg_update, NULL, 0 );
+   THREAD_0;
+   _mount_workshop_addons( NULL );
+   vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct skateshop_scan_info), 1 );
+   struct skateshop_scan_info *info = (void *)task->data;
+   info->type = specific_type;
+   vg_async_task_dispatch( task, skateshop_addon_scan_task );
 }
 
-
 static void ent_skateshop_helpers_pickable( const char *acceptance )
 {
    vg_str text;
@@ -225,9 +131,9 @@ static void skateshop_playermod( bool immobile )
    srinput.state = k_input_state_resume;
 }
 
-static void skateshop_accept_board( u16 cache_id )
+static void skateshop_accept_board( addon_cache_id cache_id )
 {
-   vg_info( "chose board from skateshop (%u)\n", _skateshop.selected_board_id );
+   vg_info( "chose board from skateshop (%u)\n", _skateshop.selected_board_index );
    addon_cache_unwatch( k_addon_type_board, localplayer.board_view_slot );
    addon_cache_watch( k_addon_type_board, cache_id );
    localplayer.board_view_slot = cache_id;
@@ -239,10 +145,12 @@ static void skateshop_accept_board( u16 cache_id )
 
 static void skateshop_accept_playermodel(void)
 {
-   addon_reg *addon = get_addon_from_index( k_addon_type_player, _skateshop.selected_player_id, 0, ADDON_REG_HIDDEN );
-   u32 real_id = get_index_from_addon( k_addon_type_player, addon,0,0 );
-   player__use_model( real_id );
-   network_send_item( k_netmsg_playeritem_player );
+   addon_id id = _addon_get_filtered( k_addon_type_player, _skateshop.selected_player_index, 0, ADDON_REG_HIDDEN );
+   if( id )
+   {
+      player__use_model( id );
+      network_send_item( k_netmsg_playeritem_player );
+   }
 }
 
 void ent_skateshop_update(void)
@@ -294,32 +202,29 @@ void ent_skateshop_update(void)
       /* input */
       if( shop->type == k_skateshop_type_boardshop )
       {
-         if( !vg_loader_availible() ) 
-            return;
-
-         u16 cache_id = skateshop_selected_cache_id();
+         addon_cache_id cache_id = skateshop_selected_board_cache_id();
          _skateshop.helper_pick->greyed = !cache_id;
 
          /*
           * Controls
           * ----------------------
           */
-         u32 opage = _skateshop.selected_board_id/SKATESHOP_VIEW_SLOT_MAX;
+         u32 opage = _skateshop.selected_board_index/SKATESHOP_VIEW_SLOT_MAX;
 
          if( button_down( k_srbind_mleft ) )
          {
-            if( _skateshop.selected_board_id > 0 )
-               _skateshop.selected_board_id --;
+            if( _skateshop.selected_board_index > 0 )
+               _skateshop.selected_board_index --;
          }
 
          if( button_down( k_srbind_mright ) )
          {
-            u32 valid_count = addon_count( k_addon_type_board, 0,0 );
-            if( _skateshop.selected_board_id+1 < valid_count )
-               _skateshop.selected_board_id ++;
+            u32 valid_count = _addon_filtered_count( k_addon_type_board, 0,0 );
+            if( _skateshop.selected_board_index+1 < valid_count )
+               _skateshop.selected_board_index ++;
          }
 
-         u32 npage = _skateshop.selected_board_id/SKATESHOP_VIEW_SLOT_MAX;
+         u32 npage = _skateshop.selected_board_index/SKATESHOP_VIEW_SLOT_MAX;
          if( opage != npage )
             skateshop_update_viewpage();
 
@@ -331,28 +236,25 @@ void ent_skateshop_update(void)
       }
       else if( shop->type == k_skateshop_type_charshop )
       {
-         if( !vg_loader_availible() ) 
-            return;
-
          int changed = 0;
-         u32 valid_count = addon_count( k_addon_type_player, 0, ADDON_REG_HIDDEN );
+         u32 valid_count = _addon_filtered_count( k_addon_type_player, 0, ADDON_REG_HIDDEN );
 
          if( button_down( k_srbind_mleft ) )
          {
-            if( _skateshop.selected_player_id > 0 )
-               _skateshop.selected_player_id --;
+            if( _skateshop.selected_player_index > 0 )
+               _skateshop.selected_player_index --;
             else
-               _skateshop.selected_player_id = valid_count-1;
+               _skateshop.selected_player_index = valid_count-1;
 
             changed = 1;
          }
 
          if( button_down( k_srbind_mright ) )
          {
-            if( _skateshop.selected_player_id+1 < valid_count )
-               _skateshop.selected_player_id ++;
+            if( _skateshop.selected_player_index+1 < valid_count )
+               _skateshop.selected_player_index ++;
             else
-               _skateshop.selected_player_id = 0;
+               _skateshop.selected_player_index = 0;
 
             changed = 1;
          }
@@ -367,60 +269,6 @@ void ent_skateshop_update(void)
             _skateshop.open = 0;
          }
       }
-      else if( shop->type == k_skateshop_type_worldshop )
-      {
-#if 0
-         int browseable = 0,
-             loadable = 0;
-
-         u32 valid_count = addon_count( k_addon_type_world, ADDON_REG_HIDDEN );
-
-         if( valid_count && vg_loader_availible() )
-            browseable = 1;
-
-         if( valid_count && vg_loader_availible() )
-            loadable = 1;
-
-         _skateshop.helper_browse->greyed = !browseable;
-         _skateshop.helper_pick->greyed = !loadable;
-         
-         addon_reg *selected_world = NULL;
-
-         int change = 0;
-         if( browseable ){
-            if( button_down( k_srbind_mleft ) ){
-               if( _skateshop.selected_world_id > 0 ){
-                  _skateshop.selected_world_id --;
-                  change = 1;
-               }
-            }
-
-            if( button_down( k_srbind_mright ) ){
-               if( _skateshop.selected_world_id+1 < valid_count ){
-                  _skateshop.selected_world_id ++;
-                  change = 1;
-               }
-            }
-
-            selected_world = get_addon_from_index( k_addon_type_world, 
-                        _skateshop.selected_world_id, ADDON_REG_HIDDEN );
-
-            if( change || (_skateshop.reg_preview == NULL) ){
-               SDL_LockMutex( addon_system.cache_lock );
-               _skateshop.reg_preview = selected_world;
-               SDL_UnlockMutex( addon_system.cache_lock );
-            }
-         }
-
-         if( loadable )
-         {
-            if( button_down( k_srbind_maccept ) )
-            {
-               skaterift_switch_world_start( selected_world );
-            }
-         }
-#endif
-      }
       else if( shop->type == k_skateshop_type_server )
       {
          f64 delta = vg.time_real - network_client.last_intent_change;
@@ -444,64 +292,33 @@ void ent_skateshop_update(void)
    }
    else
    {
-      if( vg_loader_availible() )
+      if( button_down( k_srbind_use ) )
       {
-         if( button_down( k_srbind_use ) )
+         ent_skateshop *shop = _skateshop.current_shop;
+         if( shop->type == k_skateshop_type_boardshop )
          {
-            ent_skateshop *shop = _skateshop.current_shop;
-            if( shop->type == k_skateshop_type_boardshop )
-            {
-               skateshop_update_viewpage();
-               vg_loader_start( board_scan_thread, NULL );
-            }
-
-            gui_helper_reset( k_gui_helper_mode_clear );
-            ent_skateshop_helpers_pickable( "Pick" );
-            _skateshop.open = 1;
-
-            skateshop_playermod( 1 );
+            skateshop_update_viewpage();
+            skateshop_scan( k_addon_type_board );
          }
-      }
-   }
-}
-
-#if 0
-void skateshop_world_preupdate(void)
-{
-   world_instance *world = &_world.main;
-   for( u32 i=0; i<af_arrcount(&world->ent_skateshop); i++ )
-   {
-      ent_skateshop *shop = af_arritm( &world->ent_skateshop, i );
-
-      if( shop->type == k_skateshop_type_server )
-      {
-         f32 a = network_client.user_intent;
-
-         vg_slewf( &network_client.fintent, a, vg.time_frame_delta );
-         a = (vg_smoothstepf( network_client.fintent ) - 0.5f) * (VG_PIf/2.0f);
-
-         ent_prop *lever = af_arritm( &world->ent_prop,
-               mdl_entity_id_id(shop->server.id_lever) );
 
-         /* we need parent transforms now? */
-         q_axis_angle( lever->transform.q, (v3f){0,0,1}, a );
+         gui_helper_reset( k_gui_helper_mode_clear );
+         ent_skateshop_helpers_pickable( "Pick" );
+         _skateshop.open = 1;
+         skateshop_playermod( 1 );
       }
    }
 }
-#endif
 
 static void skateshop_render_boardshop( ent_skateshop *shop, vg_camera *cam )
 {
    world_instance *world = &_world.main;
    u32 slot_count = VG_ARRAY_LEN(_skateshop.shop_view_slots);
 
-   ent_marker *mark_rack = af_arritm( &world->ent_marker, 
-                                  mdl_entity_id_id(shop->boards.id_rack)),
-              *mark_display = af_arritm( &world->ent_marker,
-                                  mdl_entity_id_id(shop->boards.id_display));
+   ent_marker *mark_rack = af_arritm( &world->ent_marker, mdl_entity_id_id(shop->boards.id_rack)),
+              *mark_display = af_arritm( &world->ent_marker, mdl_entity_id_id(shop->boards.id_display));
 
-   SDL_LockMutex( addon_system.cache_lock );
-   struct addon_cache *cache = &addon_system.cache[k_addon_type_board];
+   struct addon_cache *cache = &_addon.cache[k_addon_type_board];
+   u32 page = _skateshop.selected_board_index/SKATESHOP_VIEW_SLOT_MAX;
    
    /* Render loaded boards in the view slots */
    for( u32 i=0; i<slot_count; i++ )
@@ -513,13 +330,10 @@ static void skateshop_render_boardshop( ent_skateshop *shop, vg_camera *cam )
          goto fade_out;
 
       addon_cache_entry *entry = vg_pool_item( &cache->pool, slot->cache_id );
-
-      if( entry->state != k_addon_cache_state_loaded )
+      struct player_board *board = addon_cache_item_data( k_addon_type_board, slot->cache_id, 1 );
+      if( !board )
          goto fade_out;
 
-      struct player_board *board = 
-         addon_cache_item( k_addon_type_board, slot->cache_id );
-
       mdl_transform xform;
       transform_identity( &xform );
 
@@ -527,9 +341,8 @@ static void skateshop_render_boardshop( ent_skateshop *shop, vg_camera *cam )
       mdl_transform_mul( &mark_rack->transform, &xform, &xform );
 
 
-      if( entry->reg_index == _skateshop.selected_board_id ){
+      if( page*SKATESHOP_VIEW_SLOT_MAX + i == _skateshop.selected_board_index )
          selected = 1.0f;
-      }
 
       float t = slot->view_blend;
       v3_lerp( xform.co, mark_display->transform.co, t, xform.co );
@@ -570,36 +383,34 @@ fade_out:;
    mlocal[3][2] = -0.7f;
    m4x3_mul( mrack, mlocal, mmdl );
 
-   u32 valid_count = addon_count(k_addon_type_board,0,0);
+   u32 valid_count = _addon_filtered_count(k_addon_type_board,0,0);
    if( valid_count )
    {
       char buf[16];
       vg_str str;
       vg_strnull( &str, buf, sizeof(buf) );
-      vg_strcati32( &str, _skateshop.selected_board_id+1 );
+      vg_strcati32( &str, _skateshop.selected_board_index+1 );
       vg_strcatch( &str, '/' );
       vg_strcati32( &str, valid_count );
       font3d_simple_draw( 0, buf, cam, mmdl );
    }
-   else{
+   else
       font3d_simple_draw( 0, "Nothing installed", cam, mmdl );
-   }
 
-   u16 cache_id = skateshop_selected_cache_id();
+   u16 cache_id = skateshop_selected_board_cache_id();
    struct addon_cache_entry *entry = vg_pool_item( &cache->pool, cache_id );
    addon_reg *reg = NULL;
-
-   if( entry ) reg = entry->reg_ptr;
+   if( entry ) 
+      reg = addon_details( entry->addon_id );
 
    if( !reg )
    {
-      SDL_UnlockMutex( addon_system.cache_lock );
       _skateshop.render.item_title = "";
       _skateshop.render.item_desc = "";
       return;
    }
 
-   if( _skateshop.render.reg_id != _skateshop.selected_board_id )
+   if( _skateshop.render.addon_id != entry->addon_id )
    {
       _skateshop.render.item_title = "";
       _skateshop.render.item_desc = "";
@@ -616,7 +427,7 @@ fade_out:;
          vg_msg_skip_frame( &msg );
       }
 
-      _skateshop.render.reg_id = _skateshop.selected_board_id;
+      _skateshop.render.addon_id = entry->addon_id;
    }
 
    /* Skin title
@@ -640,109 +451,12 @@ fade_out:;
    mlocal[3][2] = 0.0f;
    m4x3_mul( mtext, mlocal, mmdl );
    font3d_simple_draw( 0, _skateshop.render.item_desc, cam, mmdl );
-
-   SDL_UnlockMutex( addon_system.cache_lock );
 }
 
 static void skateshop_render_charshop( ent_skateshop *shop, vg_camera *cam )
 {
 }
 
-static void skateshop_render_worldshop( ent_skateshop *shop, vg_camera *cam )
-{
-   world_instance *world = &_world.main;
-
-   ent_marker *mark_display = af_arritm( &world->ent_marker, mdl_entity_id_id(shop->worlds.id_display)),
-              *mark_info = af_arritm( &world->ent_marker, mdl_entity_id_id(shop->boards.id_info));
-
-   if( _skateshop.render.world_reg != _skateshop.selected_world_id)
-   {
-      _skateshop.render.world_title = "missing: workshop.title";
-      addon_reg *reg = get_addon_from_index( k_addon_type_world, _skateshop.selected_world_id, 0, ADDON_REG_HIDDEN );
-
-      if( !reg ) 
-         goto none;
-
-      if( reg->alias.workshop_id )
-      {
-         vg_msg msg;
-         vg_msg_init( &msg, reg->metadata, reg->metadata_len );
-
-         _skateshop.render.world_loc = vg_msg_getkvstr(&msg,"location");
-         _skateshop.render.world_reg = _skateshop.selected_world_id;
-
-         if( vg_msg_seekframe( &msg, "workshop" ) )
-         {
-            _skateshop.render.world_title = vg_msg_getkvstr(&msg,"title");
-            vg_msg_skip_frame( &msg );
-         }
-         else
-            vg_warn( "No workshop body\n" );
-      }
-      else
-         _skateshop.render.world_title = reg->alias.foldername;
-   }
-
-none:;
-
-   /* Text */
-   char buftext[128], bufsubtext[128];
-   vg_str info, subtext;
-   vg_strnull( &info, buftext, 128 );
-   vg_strnull( &subtext, bufsubtext, 128 );
-   
-   u32 valid_count = addon_count(k_addon_type_world,0,ADDON_REG_HIDDEN);
-   if( valid_count )
-   {
-      vg_strcati32( &info, _skateshop.selected_world_id+1 );
-      vg_strcatch( &info, '/' );
-      vg_strcati32( &info, valid_count );
-      vg_strcatch( &info, ' ' );
-      vg_strcat( &info, _skateshop.render.world_title );
-
-      if( !vg_loader_availible() )
-      {
-         vg_strcat( &subtext, "Loading..." );
-      }
-      else
-      {
-         addon_reg *reg = get_addon_from_index( k_addon_type_world, _skateshop.selected_world_id, 0, ADDON_REG_HIDDEN );
-
-         if( reg->alias.workshop_id )
-            vg_strcat( &subtext, "(Workshop) " );
-
-         vg_strcat( &subtext, _skateshop.render.world_loc );
-      }
-   }
-   else
-   {
-      vg_strcat( &info, "No workshop worlds installed" );
-   }
-
-   m4x3f mtext,mlocal,mtextmdl;
-   mdl_transform_m4x3( &mark_info->transform, mtext );
-
-   font3d_bind( &gui.font, k_font_shader_default, 0, NULL, cam );
-   shader_model_font_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
-
-   float scale = 0.2f, thickness = 0.015f, scale1 = 0.08f;
-   m3x3_zero( mlocal );
-   m3x3_setdiagonalv3( mlocal, (v3f){ scale, scale, thickness } );
-   mlocal[3][0] = -font3d_string_width( 0, buftext );
-   mlocal[3][0] *= scale*0.5f;
-   mlocal[3][1] = 0.1f;
-   mlocal[3][2] = 0.0f;
-   m4x3_mul( mtext, mlocal, mtextmdl );
-   font3d_simple_draw( 0, buftext, cam, mtextmdl );
-
-   m3x3_setdiagonalv3( mlocal, (v3f){ scale1, scale1, thickness } );
-   mlocal[3][0] = -font3d_string_width( 0, bufsubtext );
-   mlocal[3][0] *= scale1*0.5f;
-   mlocal[3][1] = -scale1*0.3f;
-   m4x3_mul( mtext, mlocal, mtextmdl );
-   font3d_simple_draw( 0, bufsubtext, cam, mtextmdl );
-}
-
 void ent_skateshop_render( vg_camera *cam )
 {
    bool dont_render_ghost = 0;
@@ -756,8 +470,6 @@ void ent_skateshop_render( vg_camera *cam )
             skateshop_render_boardshop( shop, cam );
          else if( shop->type == k_skateshop_type_charshop )
             skateshop_render_charshop( shop, cam );
-         else if( shop->type == k_skateshop_type_worldshop )
-            skateshop_render_worldshop( shop, cam );
          else if( shop->type == k_skateshop_type_server ){
          }
          else
@@ -892,23 +604,23 @@ void ent_skateshop_gui( ui_context *ctx )
          bool changed_playermodel = 0;
 
          if( shop->type == k_skateshop_type_boardshop )
-            original_page = _skateshop.selected_board_id/SKATESHOP_VIEW_SLOT_MAX;
+            original_page = _skateshop.selected_board_index/SKATESHOP_VIEW_SLOT_MAX;
 
          if( menu_button_rect( ctx, left_box, 0, 1, "<" ) )
          {
             if( shop->type == k_skateshop_type_boardshop )
             {
-               if( _skateshop.selected_board_id > 0 )
-                  _skateshop.selected_board_id --;
+               if( _skateshop.selected_board_index > 0 )
+                  _skateshop.selected_board_index --;
             }
             else if( shop->type == k_skateshop_type_charshop )
             {
-               u32 valid_count = addon_count( k_addon_type_player, 0, ADDON_REG_HIDDEN );
+               u32 valid_count = _addon_filtered_count( k_addon_type_player, 0, ADDON_REG_HIDDEN );
 
-               if( _skateshop.selected_player_id > 0 )
-                  _skateshop.selected_player_id --;
+               if( _skateshop.selected_player_index > 0 )
+                  _skateshop.selected_player_index --;
                else
-                  _skateshop.selected_player_id = valid_count-1;
+                  _skateshop.selected_player_index = valid_count-1;
 
                changed_playermodel = 1;
             }
@@ -917,17 +629,17 @@ void ent_skateshop_gui( ui_context *ctx )
          {
             if( shop->type == k_skateshop_type_boardshop )
             {
-               u32 valid_count = addon_count( k_addon_type_board, 0,0 );
-               if( _skateshop.selected_board_id+1 < valid_count )
-                  _skateshop.selected_board_id ++;
+               u32 valid_count = _addon_filtered_count( k_addon_type_board, 0,0 );
+               if( _skateshop.selected_board_index+1 < valid_count )
+                  _skateshop.selected_board_index ++;
             }
             else if( shop->type == k_skateshop_type_charshop )
             {
-               u32 valid_count = addon_count( k_addon_type_player, 0, ADDON_REG_HIDDEN );
-               if( _skateshop.selected_player_id+1 < valid_count )
-                  _skateshop.selected_player_id ++;
+               u32 valid_count = _addon_filtered_count( k_addon_type_player, 0, ADDON_REG_HIDDEN );
+               if( _skateshop.selected_player_index+1 < valid_count )
+                  _skateshop.selected_player_index ++;
                else
-                  _skateshop.selected_player_id = 0;
+                  _skateshop.selected_player_index = 0;
 
                changed_playermodel = 1;
             }
@@ -935,7 +647,7 @@ void ent_skateshop_gui( ui_context *ctx )
 
          if( shop->type == k_skateshop_type_boardshop )
          {
-            u32 new_page = _skateshop.selected_board_id/SKATESHOP_VIEW_SLOT_MAX;
+            u32 new_page = _skateshop.selected_board_index/SKATESHOP_VIEW_SLOT_MAX;
             if( original_page != new_page )
                skateshop_update_viewpage();
          }
@@ -951,7 +663,7 @@ void ent_skateshop_gui( ui_context *ctx )
          {
             if( shop->type == k_skateshop_type_boardshop )
             {
-               u16 cache_id = skateshop_selected_cache_id();
+               addon_cache_id cache_id = skateshop_selected_board_cache_id();
                if( cache_id )
                   skateshop_accept_board( cache_id );
             }
index c3a869d21ef40a417ef13ff9b405c9291ae12e6b..182bcd6177067644845f8064ea47183d4c2dccb3 100644 (file)
@@ -12,23 +12,20 @@ struct global_skateshop
 {
    v3f look_target;
 
-   struct shop_view_slot{
-      u16 cache_id;
+   struct shop_view_slot
+   {
+      addon_cache_id cache_id;
       float view_blend;
    }
    shop_view_slots[ SKATESHOP_VIEW_SLOT_MAX ];
 
-   u32 selected_world_id,
-       selected_board_id,
-       selected_player_id,
-       pointcloud_world_id;
+   u32 selected_board_index,
+       selected_player_index;
 
-   struct {
+   struct 
+   {
       const char *item_title, *item_desc;
-      u32 reg_id;
-
-      const char *world_title, *world_loc;
-      u32 world_reg;
+      addon_id addon_id;
    }
    render;
 
@@ -38,9 +35,6 @@ struct global_skateshop
 
    struct gui_helper *helper_browse;
 
-   addon_reg *reg_preview, *reg_loaded_preview;
-   GLuint tex_preview;
-
    ent_skateshop *current_shop;
    bool open;
 }
index 5f853779ea34729a545a6caf663524adc3c9ce90..d91ad8923f58da6d32aae574e7e35883f3d4d6d0 100644 (file)
@@ -222,7 +222,7 @@ struct ent_gate{
    union
    {
       u32 timing_version;
-      u32 addon_reg;
+      addon_id remote_addon_id;
 
       struct{
          u8 ref_count;
index d4ec092071230a245d4e1331cefd77cb8cac8f42..deab2457cdd25b33600434367e6846d1c44a376f 100644 (file)
@@ -362,7 +362,7 @@ void db_action_set_username( u64 steamid, const char *username )
    struct task_set_username *info = (void *)task->data;
    info->steamid = steamid;
    vg_strncpy( username, info->name, sizeof(info->name), k_strncpy_always_add_null );
-   vg_async_task_dispatch( &_gs_db.tasks, task, task_set_username );
+   vg_async_task_dispatch( task, task_set_username );
 }
 
 enum request_status gameserver_cat_table( vg_msg *msg, const char *mod, const char *route, u32 week, const char *alias )
index 3910c5500823a59dc91eee9b1884134125d1a995..d7446270bdd8645474dbc7189dba0b654416730d 100644 (file)
@@ -110,7 +110,7 @@ void _gs_replay_run_save_requests( u32 client_id )
             }
 
             replay_inf->buffer_size = output_size;
-            vg_async_task_dispatch( &_gs_db.tasks, task, task_write_replay );
+            vg_async_task_dispatch( task, task_write_replay );
 
             flags |= (u8)k_replay_minute_saved;
          }
@@ -184,7 +184,7 @@ void _gs_replay_request_save( u32 client_id, u64 steamid, i64 last_second, u32 c
       info->steam_id = steamid;
       info->last_second = last_second;
       info->centiseconds = centiseconds;
-      vg_async_task_dispatch( &_gameserver.tasks, task, _gs_replay_async_request_save );
+      vg_async_task_dispatch( task, _gs_replay_async_request_save );
       return;
    }
 
@@ -230,7 +230,7 @@ void _gs_replay_request_save( u32 client_id, u64 steamid, i64 last_second, u32 c
    descriptor_info->message_length = msg.cur.co;
    descriptor_info->last_second = last_second;
    descriptor_info->steamid = steamid;
-   vg_async_task_dispatch( &_gs_db.tasks, replay_descriptor_task, _gs_replay_write_descriptor );
+   vg_async_task_dispatch( replay_descriptor_task, _gs_replay_write_descriptor );
 }
 
 void _gs_replay_server_tick(void)
index 9d8c121aafc00823049edec85fd1b764019348ae..6699d3276718f634935f135e8952c01ea2035901 100644 (file)
@@ -118,7 +118,7 @@ void _gs_requests_tick(void)
          vg_async_task *run_task = vg_allocate_async_task( &_gs_db.tasks, sizeof(struct task_request_run_info), 1 );
          struct task_request_run_info *info = (void *)run_task->data;
          info->pool_id = rc->current_request;
-         vg_async_task_dispatch( &_gs_db.tasks, run_task, task_request_run );
+         vg_async_task_dispatch( run_task, task_request_run );
 
          req->state = k_request_state_server_processing;
          log_request_status( req );
@@ -385,7 +385,7 @@ static void task_request_run( vg_async_task *task )
 E0:;
    vg_async_task *return_task = vg_allocate_async_task( &_gameserver.tasks, sizeof(struct task_request_run_info), 1 );
    memcpy( return_task->data, info, sizeof(struct task_request_run_info) );
-   vg_async_task_dispatch( &_gameserver.tasks, return_task, task_request_processing_complete );
+   vg_async_task_dispatch( return_task, task_request_processing_complete );
 }
 
 void _gs_handle_request_message( u32 client_id, SteamNetworkingMessage_t *msg )
index d381f62b60c332df6741909b7916906e30570f6f..77c82f00d5289dc9f86226db34acc2573f4d701e 100644 (file)
@@ -25,8 +25,7 @@ void menu_at_begin(void)
 void menu_init(void)
 {
    vg_console_reg_var( "skip_starter_menu", &menu.skip_starter, k_var_dtype_i32, VG_VAR_PERSISTENT );
-   vg_tex2d_load_qoi_async_file( "textures/prem.qoi", 
-         VG_TEX2D_CLAMP|VG_TEX2D_NOMIP|VG_TEX2D_NEAREST, &menu.prem_tex );
+   vg_tex2d_load_qoi_async_file( "textures/prem.qoi", VG_TEX2D_CLAMP|VG_TEX2D_NOMIP|VG_TEX2D_NEAREST, &menu.prem_tex );
 }
 
 static void menu_update_world_filter(void)
@@ -44,33 +43,36 @@ static void menu_update_world_filter(void)
       menu.world_list_whitelist = ADDON_REG_VENUS;
 }
 
-void menu_on_world_change( addon_reg *addon_reg )
+void menu_on_world_change( addon_id addon )
 {
-   if( addon_reg == NULL )
+   if( !addon )
       return;
+
+   addon_reg *reg = addon_details( addon );
    
    i32 super_id = 0;
-   if( addon_reg->flags & ADDON_REG_CAMPAIGN ) super_id = k_superworld_campaign;
-   if( addon_reg->flags & ADDON_REG_INFINITE ) super_id = k_superworld_infinite;
-   if( addon_reg->flags & ADDON_REG_WORKSHOP ) super_id = k_superworld_steam_workshop;
-   if( addon_reg->flags & ADDON_REG_VENUS    ) super_id = k_superworld_venus_moon;
+   if( reg->flags & ADDON_REG_CAMPAIGN ) super_id = k_superworld_campaign;
+   if( reg->flags & ADDON_REG_INFINITE ) super_id = k_superworld_infinite;
+   if( reg->flags & ADDON_REG_WORKSHOP ) super_id = k_superworld_steam_workshop;
+   if( reg->flags & ADDON_REG_VENUS    ) super_id = k_superworld_venus_moon;
 
    world_map.superworld_actual_world = super_id;
    world_map.superworld_list_selected = super_id;
 
    menu_update_world_filter();
-   u32 index = get_index_from_addon( k_addon_type_world, addon_reg, 
-                                     menu.world_list_whitelist, menu.world_list_blacklist );
-   menu.world_list_selected_index[ super_id ] = (index == 0xffffffff)? 0: index;
-   menu.clicked_world_reg = addon_reg;
+
+   u32 index = 0;
+   _addon_get_filtered_index( k_addon_type_world, addon, menu.world_list_whitelist, menu.world_list_blacklist, &index );
+   menu.world_list_selected_index[ super_id ] = index;
+   menu.clicked_world_id = addon;
 
    vg_msg msg;
-   vg_msg_init( &msg, addon_reg->metadata, addon_reg->metadata_len );
+   vg_msg_init( &msg, reg->metadata, reg->metadata_len );
    const char *name = NULL;
    if( vg_msg_seekframe( &msg, "workshop" ) )
       name = vg_msg_getkvstr( &msg, "title" );
    if( !name )
-      name = addon_reg->alias.foldername;
+      name = reg->alias.foldername;
    menu.clicked_world_name = name;
    world_map_initialize_view();
 }
@@ -385,7 +387,8 @@ void menu_update_world_list(void)
       menu.world_list_display_count = 0;
    }
 
-   menu.world_list_total_count = addon_count( k_addon_type_world, menu.world_list_whitelist, menu.world_list_blacklist );
+   u32 total = _addon_filtered_count( k_addon_type_world, menu.world_list_whitelist, menu.world_list_blacklist );
+   menu.world_list_total_count = total;
    menu.world_list_display_count = 0;
 
    i32 *selected_world_index = &menu.world_list_selected_index[ world_map.superworld_list_selected ];
@@ -407,13 +410,14 @@ void menu_update_world_list(void)
       u32 world_index = page_base + i;
 
       if( world_index >= menu.world_list_total_count )
-         menu.world_list_entries[i] = NULL;
+         menu.world_list_entries[i] = 0;
       else
       {
-         addon_reg *reg = get_addon_from_index( k_addon_type_world, world_index, 
-                                                menu.world_list_whitelist, menu.world_list_blacklist );
+         addon_id addon_id = _addon_get_filtered( k_addon_type_world, world_index, 
+                                                  menu.world_list_whitelist, menu.world_list_blacklist );
+         VG_ASSERT( addon_id );
+         addon_reg *reg = addon_details( addon_id );
          bool unlocked = 1;
-
          if( reg->flags & ADDON_REG_MTZERO )
             unlocked = _skaterift_script_nugget_status( "unlock_mtzero" )?1:0;
          if( reg->flags & ADDON_REG_CITY )
@@ -421,7 +425,7 @@ void menu_update_world_list(void)
          if( reg->flags & ADDON_REG_VALLEY )
             unlocked = _skaterift_script_nugget_status( "unlock_valley" )?1:0;
 
-         menu.world_list_entries[ menu.world_list_display_count ] = unlocked? reg: NULL;
+         menu.world_list_entries[ menu.world_list_display_count ] = unlocked? addon_id: 0;
 
          if( unlocked )
          {
@@ -430,9 +434,7 @@ void menu_update_world_list(void)
             vg_msg_init( &msg, reg->metadata, reg->metadata_len );
 
             if( vg_msg_seekframe( &msg, "workshop" ) )
-            {
                name = vg_msg_getkvstr( &msg, "title" );
-            }
 
             if( !name )
                name = reg->alias.foldername;
@@ -440,9 +442,7 @@ void menu_update_world_list(void)
             menu.world_list_names[ menu.world_list_display_count ] = name;
          }
          else
-         {
             menu.world_list_names[ menu.world_list_display_count ] = "...";
-         }
          menu.world_list_display_count ++;
       }
    }
index 85cbe7ba4542bbc6f8c8c358caf5df1c9600cf96..40f24ddb732523e30207bab28e877658b0b7d46a 100644 (file)
@@ -50,7 +50,7 @@ struct global_menu
 
    GLuint prem_tex;
 
-   addon_reg *world_list_entries[ MENU_WORLD_MAX_COUNT ];
+   addon_id world_list_entries[ MENU_WORLD_MAX_COUNT ];
    const char *world_list_names[ MENU_WORLD_MAX_COUNT ];
 
    i32 world_list_display_count, 
@@ -60,7 +60,7 @@ struct global_menu
    u32 world_list_whitelist,
        world_list_blacklist;
 
-   addon_reg *clicked_world_reg;
+   addon_id clicked_world_id;
    const char *clicked_world_name;
 }
 extern menu;
@@ -72,5 +72,5 @@ void menu_open( enum menu_page page );
 bool menu_viewing_map(void);
 bool menu_viewing_preview(void);
 void menu_update_world_list(void);
-void menu_on_world_change( addon_reg *addon_reg );
+void menu_on_world_change( addon_id addon );
 bool menu_button_rect( ui_context *ctx, ui_rect rect, bool select, bool clickable, const char *text );
index 20ca10f3fd76f06a861359ebbeacbda793400f90..437f42f90d601c21298df7237b55606dc2f332ee 100644 (file)
@@ -164,26 +164,30 @@ static void _cutscene_get_strip_asoc( ms_strip *strip,
    }
 }
 
-static void sync_cutscene_loaded( void *payload, u32 size )
+static void sync_cutscene_loaded( void *userdata )
 {
+   THREAD_0;
+
    vg_info( "Cutscene loaded\n" );
    _cutscene.state = k_cutscene_state_ready;
 }
 
-static void cutscene_load_thread( void *data )
+struct cutscene_load_info 
+{
+   u32 nothing;
+   char path[];
+};
+static void cutscene_load_thread( vg_async_task *task )
 {
-   const char *path = data;
-   vg_info( "Loading cutscene: %s\n", path );
+   struct cutscene_load_info *info = (void *)task->data;
+   vg_info( "Loading cutscene: %s\n", info->path );
 
    u32 size = 20*1024*1024;
-   _cutscene.arena = 
-      _vg_create_linear_allocator( NULL, size, VG_MEMORY_SYSTEM, "Cutscene" );
-
-   metascene_load( &_cutscene.meta, path, _cutscene.arena );
+   _cutscene.arena = _vg_create_linear_allocator( NULL, size, VG_MEMORY_SYSTEM, "Cutscene" );
+   metascene_load( &_cutscene.meta, info->path, _cutscene.arena );
 
    _cutscene.instance_count = af_arrcount( &_cutscene.meta.instances );
-   _cutscene.instances = vg_linear_alloc( _cutscene.arena, 
-      sizeof(struct cs_instance) * _cutscene.instance_count );
+   _cutscene.instances = vg_linear_alloc( _cutscene.arena, sizeof(struct cs_instance) * _cutscene.instance_count );
 
    _cutscene.refs = NULL;
    _cutscene.unique_refs = 0;
@@ -329,7 +333,7 @@ static void cutscene_load_thread( void *data )
       }
    }
 
-   vg_async_call( sync_cutscene_loaded, NULL, 0 );
+   vg_async_call( &vg.main_tasks, sync_cutscene_loaded, NULL );
 }
 
 static int cmd_cutscene_load( int argc, const char *argv[] )
@@ -342,25 +346,17 @@ static int cmd_cutscene_load( int argc, const char *argv[] )
          return 0;
       }
 
-      if( vg_loader_availible() )
-      {
-         _cutscene.state = k_cutscene_state_loading;
-         _cutscene.time = 0.0f;
-         _cutscene.strip = 0;
-         _cutscene.active_samplers = 0;
-
-         vg_linear_clear( vg_async.buffer );
-         u32 len = strlen( argv[0] ) +1;
-         char *path_buf = vg_linear_alloc( vg_async.buffer, len );
-         strcpy( path_buf, argv[0] );
-         vg_loader_start( cutscene_load_thread, path_buf );
-         return 1;
-      }
-      else
-      {
-         vg_error( "The loading thread is currently occupied.\n" );
-         return 0;
-      }
+      _cutscene.state = k_cutscene_state_loading;
+      _cutscene.time = 0.0f;
+      _cutscene.strip = 0;
+      _cutscene.active_samplers = 0;
+
+      u32 len = strlen( argv[0] ) +1;
+      vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct cutscene_load_info) + len, 1 );
+      struct cutscene_load_info *info = (void *)task->data;
+      strcpy( info->path, argv[0] );
+      vg_async_task_dispatch( task, cutscene_load_thread );
+      return 1;
    }
    else
    {
index dea1bb894aa27e5e2bdc15449d034bd954b7ba48..f5a53702e46836a947a8d0b7b913cff7eed3d6f2 100644 (file)
@@ -7,7 +7,6 @@
 #include "vg/vg_io.h"
 
 #ifdef VG_3D
-#include "vg/vg_async.h"
 #include "vg/vg_tex.h"
 #endif
 
@@ -410,14 +409,18 @@ struct payload_glmesh_load
    glmesh *mesh;
 };
 
-static void _sync_mdl_load_glmesh( void *payload, u32 size )
+static void _sync_mdl_load_glmesh( vg_async_task *task )
 {
-   struct payload_glmesh_load *job = payload;
+   THREAD_0;
+
+   struct payload_glmesh_load *job = (void *)task->data;
    mesh_upload( job->mesh, job->verts, job->vertex_count, job->indices, job->indice_count );
 }
 
 void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh, u32 *fixup_table )
 {
+   THREAD_1;
+
    array_file_meta *arr_vertices = af_find_array( &mdl->af, "mdl_vert" );
    array_file_meta *arr_indices = af_find_array( &mdl->af, "mdl_indice" );
 
@@ -428,17 +431,14 @@ void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh, u32 *fixup_table )
           size_hdr     = vg_align8(sizeof(struct payload_glmesh_load)),
           total        = size_hdr + size_verts + size_indices;
 
-      vg_async_item *call = vg_async_alloc( total );
-      struct payload_glmesh_load *job = call->payload;
-
-      u8 *payload = call->payload;
+      vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, total, 1 );
+      struct payload_glmesh_load *job = (void *)task->data;
 
       job->mesh = mesh;
-      job->verts = (void*)(payload + size_hdr);
-      job->indices = (void*)(payload + size_hdr + size_verts);
+      job->verts = (void*)(task->data + size_hdr);
+      job->indices = (void*)(task->data + size_hdr + size_verts);
       job->vertex_count = arr_vertices->item_count;
       job->indice_count = arr_indices->item_count;
-
       af_load_array_file_buffer( &mdl->af, arr_vertices, job->verts, sizeof(mdl_vert) );
       af_load_array_file_buffer( &mdl->af, arr_indices, job->indices, sizeof(mdl_indice) );
 
@@ -482,7 +482,7 @@ void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh, u32 *fixup_table )
        * -------------------------
        */
 
-      vg_async_dispatch( call, _sync_mdl_load_glmesh );
+      vg_async_task_dispatch( task, _sync_mdl_load_glmesh );
    }
    else
    {
index df807fbcdd8539943535e514b776f6783e12eadd..174903a84c6c44e28ec17beaa47e57d148e7d21b 100644 (file)
@@ -149,12 +149,7 @@ void network_send_item( enum netmsg_playeritem_type type )
 
    if( (type == k_netmsg_playeritem_world0) || (type == k_netmsg_playeritem_world1) )
    {
-      addon_reg *reg = _world.main.addon;
-
-      if( reg )
-         addon_alias_uid( &reg->alias, item->uid );
-      else 
-         item->uid[0] = '\0';
+      addon_uid( _world.main.addon_id, item->uid );
    }
    else
    {
@@ -171,23 +166,16 @@ void network_send_item( enum netmsg_playeritem_type type )
          addon_type = k_addon_type_player;
       }
 
-      struct addon_cache *cache = &addon_system.cache[addon_type];
-      vg_pool *pool = &cache->pool;
-
-      SDL_LockMutex( addon_system.cache_lock );
-      addon_cache_entry *entry = vg_pool_item( pool, view_id );
-      addon_alias_uid( &entry->reg_ptr->alias, item->uid );
-      SDL_UnlockMutex( addon_system.cache_lock );
+      struct addon_cache *cache = &_addon.cache[addon_type];
+      addon_cache_entry *entry = vg_pool_item( &cache->pool, view_id );
+      addon_uid( entry->addon_id, item->uid );
    }
 
-   vg_info( "send equip: [%u] %s\n", 
-            item->type_index, item->uid );
+   vg_info( "send equip: [%u] %s\n", item->type_index, item->uid );
    u32 chs = strlen(item->uid);
-
-   SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
-         hSteamNetworkingSockets, network_client.remote, 
-         item, sizeof(netmsg_playeritem)+chs+1,
-         k_nSteamNetworkingSend_Reliable, NULL );
+   SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( hSteamNetworkingSockets, network_client.remote, 
+                                                             item, sizeof(netmsg_playeritem)+chs+1,
+                                                             k_nSteamNetworkingSend_Reliable, NULL );
 }
 
 static void network_disconnect(void)
@@ -376,22 +364,19 @@ static void on_persona_state_change( CallbackMsg_t *msg ){
 
 void network_set_host( const char *host_str, const char *port_str )
 {
-   vg_strncpy( host_str, network_client.host_adress, 
-               sizeof(network_client.host_adress), k_strncpy_overflow_fatal );
+   vg_strncpy( host_str, network_client.host_adress, sizeof(network_client.host_adress), k_strncpy_overflow_fatal );
 
    memset( &network_client.ip, 0, sizeof(network_client.ip) );
-   network_client.ip_resolved = 0;
+   network_client.resolve_state = k_resolve_state_no;
 
    if( port_str )
    {
-      vg_strncpy( port_str, network_client.host_port, 
-                  sizeof(network_client.host_port), k_strncpy_overflow_fatal );
+      vg_strncpy( port_str, network_client.host_port, sizeof(network_client.host_port), k_strncpy_overflow_fatal );
    }
    else
    {
       vg_str str;
-      vg_strnull( &str, network_client.host_port, 
-                  sizeof(network_client.host_port) );
+      vg_strnull( &str, network_client.host_port, sizeof(network_client.host_port) );
       vg_strcati32( &str, NETWORK_PORT );
    }
 
@@ -400,11 +385,11 @@ void network_set_host( const char *host_str, const char *port_str )
 
 static void network_connect(void)
 {
-   VG_ASSERT( network_client.ip_resolved );
+   VG_ASSERT( network_client.resolve_state == k_resolve_state_resolved );
 
    vg_info( "connecting...\n" );
-   network_client.remote = SteamAPI_ISteamNetworkingSockets_ConnectByIPAddress( 
-                  hSteamNetworkingSockets, &network_client.ip, 0, NULL );
+   network_client.remote = SteamAPI_ISteamNetworkingSockets_ConnectByIPAddress(
+         hSteamNetworkingSockets, &network_client.ip, 0, NULL );
 }
 
 static void network_sign_on_complete(void)
@@ -478,77 +463,132 @@ static void poll_remote_connection(void){
    }
 }
 
-static void network_resolve_host_async( void *payload, u32 size )
+struct resolve_info
 {
-   u32 *status = payload;
-   network_client.ip_resolved = *status;
-
-   char buf[256];
-   SteamAPI_SteamNetworkingIPAddr_ToString( &network_client.ip, buf, 256, 1 );
-   vg_info( "Resolved host address to: %s\n", buf );
-}
-
-static void network_resolve_host_thread( void *_ )
-{
-   vg_async_item *call = vg_async_alloc(8);
-   u32 *status = call->payload;
-   *status = 0;
+   enum resolve_opt
+   {
+      k_resolve_opt_resolve,
+      k_resolve_opt_parse_numeric,
+      k_resolve_opt_ipv6,
+      k_resolve_opt_fail
+   }
+   opt;
 
-   if( (network_client.host_adress[0] >= '0') && 
-       (network_client.host_adress[0] <= '9') )
+   union
    {
-      SteamAPI_SteamNetworkingIPAddr_ParseString( 
-            &network_client.ip, 
-            network_client.host_adress );
-      network_client.ip.m_port = atoi( network_client.host_port );
-      *status = 1;
-      goto end;
+      struct
+      {
+         char port[8], adress[256];
+      }
+      host;
+      struct addrinfo *ipv6;
    }
+   alias;
+};
+static void _network_resolve_host( vg_async_task *co_task )
+{
+   VG_ASSERT( co_task );
 
-   vg_info( "Resolving host.. %s (:%s)\n",
-             network_client.host_adress, network_client.host_port );
+   if( co_task )
+   {
+      struct resolve_info *co_info = (void *)co_task->data;
+      if( co_info->opt == k_resolve_opt_resolve )
+      {
+         THREAD_1;
 
-   struct addrinfo  hints;
-   struct addrinfo  *result;
+         vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct resolve_info), 1 );
+         struct resolve_info *info = (void *)task->data;
+         vg_info( "Resolving host.. %s (:%s)\n", co_info->alias.host.adress, co_info->alias.host.port );
 
-   /* Obtain address(es) matching host/port. */
+         /* Obtain address(es) matching host/port. */
 
-   memset( &hints, 0, sizeof(hints) );
-   hints.ai_family = AF_INET6;
-   hints.ai_socktype = SOCK_DGRAM;
-   hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
-   hints.ai_protocol = 0;
+         struct addrinfo  hints;
+         memset( &hints, 0, sizeof(hints) );
+         hints.ai_family = AF_INET6;
+         hints.ai_socktype = SOCK_DGRAM;
+         hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
+         hints.ai_protocol = 0;
 
-   int s = getaddrinfo( network_client.host_adress, network_client.host_port, 
-                        &hints, &result);
-   if( s != 0 ) 
-   {
+         int s = getaddrinfo( co_info->alias.host.adress, co_info->alias.host.port, &hints, &info->alias.ipv6 );
+         if( s != 0 ) 
+         {
 #ifndef _WIN32
-      vg_error( "getaddrinfo: %s\n", gai_strerror(s) );
+            vg_error( "getaddrinfo: %s\n", gai_strerror(s) );
 #endif
+            if( !strcmp( co_info->alias.host.adress, "skaterift.com" ) )
+            {
+               vg_warn( "getaddrinfo failed for skaterift.com;\n "
+                        "falling back to a hardcoded IPv4. This might be wrong.\n" );
+
+               strcpy( info->alias.host.adress, "46.101.34.155" );
+               strcpy( info->alias.host.port, "27403" );
+               info->opt = k_resolve_opt_parse_numeric;
+               vg_async_task_dispatch( task, _network_resolve_host );
+               return;
+            }
+            else
+            {
+               info->opt = k_resolve_opt_fail;
+               vg_async_task_dispatch( task, _network_resolve_host );
+               return;
+            }
+         }
+         else
+         {
+            info->opt = k_resolve_opt_ipv6;
+            vg_async_task_dispatch( task, _network_resolve_host );
+            return;
+         }
+      }
+      else
+      {
+         THREAD_0;
+
+         strcpy( network_client.host_adress, co_info->alias.host.adress );
+         strcpy( network_client.host_port, co_info->alias.host.port );
 
-      if( !strcmp( network_client.host_adress, "skaterift.com" ) )
+         if( co_info->opt == k_resolve_opt_fail )
+         {
+            network_client.resolve_state = k_resolve_state_no;
+            return;
+         }
+         else if( co_info->opt == k_resolve_opt_ipv6 )
+         {
+            struct sockaddr_in6 *inaddr = (struct sockaddr_in6 *)co_info->alias.ipv6->ai_addr;
+            memcpy( network_client.ip.m_ipv6, &inaddr->sin6_addr, 16 );
+            freeaddrinfo( co_info->alias.ipv6 );
+            network_client.resolve_state = k_resolve_state_resolved;
+            return;
+         }
+         else if( co_info->opt == k_resolve_opt_parse_numeric )
+            goto parse_numeric;
+      }
+   }
+   else
+   {
+      THREAD_0;
+      if( (network_client.host_adress[0] >= '0') && (network_client.host_adress[0] <= '9') )
+         goto parse_numeric;
+      else
       {
-         vg_warn( "getaddrinfo failed for skaterift.com;\n "
-                  "falling back to a hardcoded IPv4\n" );
-         strcpy( network_client.host_adress, "46.101.34.155" );
-         SteamAPI_SteamNetworkingIPAddr_ParseString( 
-               &network_client.ip, 
-               network_client.host_adress );
-         network_client.ip.m_port = NETWORK_PORT;
-         *status = 1;
+         network_client.resolve_state = k_resolve_state_resolving;
+         vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct resolve_info), 1 );
+         struct resolve_info *info = (void *)task->data;
+         info->opt = k_resolve_opt_resolve;
+         strcpy( info->alias.host.port, network_client.host_port );
+         strcpy( info->alias.host.adress, network_client.host_adress );
+         vg_async_task_dispatch( task, _network_resolve_host );
+         return;
       }
-
-      goto end;
    }
 
-   struct sockaddr_in6 *inaddr = (struct sockaddr_in6 *)result->ai_addr;
-   memcpy( network_client.ip.m_ipv6, &inaddr->sin6_addr, 16 );
-   freeaddrinfo( result );
-
-   *status = 1;
+   VG_ASSERT(0);
+parse_numeric:
 
-end: vg_async_dispatch( call, network_resolve_host_async );
+   THREAD_0;
+   SteamAPI_SteamNetworkingIPAddr_ParseString( &network_client.ip, network_client.host_adress );
+   network_client.ip.m_port = atoi( network_client.host_port );
+   network_client.resolve_state = k_resolve_state_resolved;
 }
 
 void network_update(void)
@@ -598,15 +638,9 @@ void network_update(void)
          if( waited < min_wait )
             return;
 
-         if( !network_client.ip_resolved )
-         {
-            if( vg_loader_availible() )
-            {
-               vg_loader_start( network_resolve_host_thread, NULL );
-            }
-            else return;
-         }
-         else
+         if( network_client.resolve_state == k_resolve_state_no )
+            _network_resolve_host(NULL);
+         else if( network_client.resolve_state == k_resolve_state_resolved )
             network_connect();
          
          network_client.retries ++;
index cb3649c6eb59b39ec5d51b0c5401be40e481d67a..07e8dd7428f3138b7141c4736fa5405230813367 100644 (file)
@@ -56,7 +56,14 @@ struct network_client
 
    SteamNetworkingIPAddr ip;
    char host_port[8], host_adress[256];
-   bool ip_resolved;
+
+   enum resolve_state
+   {
+      k_resolve_state_no,
+      k_resolve_state_resolving,
+      k_resolve_state_resolved
+   }
+   resolve_state;
 
    enum server_intent {
       k_server_intent_offline,
index 58bc3ed874df7aa91f7d4dc025650ddebb1e8522..d589679e811e624fdad68d3370aa1305de49fcd4 100644 (file)
@@ -1,5 +1,4 @@
 #include "vg/vg_lines.h"
-#include "vg/vg_async.h"
 #include "particle.h"
 #include "shaders/particle.h"
 
@@ -79,13 +78,14 @@ void particle_system_debug( particle_system *sys )
    }
 }
 
-struct particle_init_args {
+struct particle_init_args 
+{
    particle_system *sys;
    u16 indices[];
 };
-
-static void async_particle_init( void *payload, u32 size ){
-   struct particle_init_args *args = payload;
+static void particle_init_task( vg_async_task *task )
+{
+   struct particle_init_args *args = (void *)task->data;
    particle_system *sys = args->sys;
 
    glGenVertexArrays( 1, &sys->vao );
@@ -98,16 +98,14 @@ static void async_particle_init( void *payload, u32 size ){
    glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
    glBufferData( GL_ARRAY_BUFFER, sys->max*stride*4, NULL, GL_DYNAMIC_DRAW );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, sys->ebo );
-   glBufferData( GL_ELEMENT_ARRAY_BUFFER, 
-                  sys->max*sizeof(u16)*6, args->indices, GL_STATIC_DRAW );
+   glBufferData( GL_ELEMENT_ARRAY_BUFFER, sys->max*sizeof(u16)*6, args->indices, GL_STATIC_DRAW );
 
    /* 0: coordinates */
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
    glEnableVertexAttribArray( 0 );
 
    /* 3: colour */
-   glVertexAttribPointer( 1, 4, GL_UNSIGNED_BYTE, GL_TRUE, 
-         stride, (void *)offsetof(particle_vert, colour) );
+   glVertexAttribPointer( 1, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, (void *)offsetof(particle_vert, colour) );
    glEnableVertexAttribArray( 1 );
 }
 
@@ -119,12 +117,12 @@ void particle_alloc( particle_system *sys, u32 max )
    sys->array = vg_linear_alloc( vg_mem.rtmemory, max*sizeof(particle) );
    sys->vertices = vg_linear_alloc( vg_mem.rtmemory, max*stride*4 );
 
-   vg_async_item *call = 
-      vg_async_alloc( sizeof(particle_system *) + max*sizeof(u16)*6 );
-   struct particle_init_args *init = call->payload;
+   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(particle_system *) + max*sizeof(u16)*6, 1 );
+   struct particle_init_args *init = (void *)task->data;
    init->sys = sys;
 
-   for( u32 i=0; i<max; i ++ ){
+   for( u32 i=0; i<max; i ++ )
+   {
       init->indices[i*6+0] = i*4;
       init->indices[i*6+1] = i*4+1;
       init->indices[i*6+2] = i*4+2;
@@ -132,8 +130,7 @@ void particle_alloc( particle_system *sys, u32 max )
       init->indices[i*6+4] = i*4+2;
       init->indices[i*6+5] = i*4+3;
    }
-
-   vg_async_dispatch( call, async_particle_init );
+   vg_async_task_dispatch( task, particle_init_task );
 }
 
 void particle_system_prerender( particle_system *sys )
index c8681915e333e5ca91e77a3af2a07f137aeff956..bc6326829a02990f25df7289664699b4e887e372 100644 (file)
@@ -107,10 +107,10 @@ void player__debugtext( ui_context *ctx, int size, const char *fmt, ... )
  * Appearence
  */
 
-void player__use_model( u16 reg_id )
+void player__use_model( addon_id addon_id )
 {
    addon_cache_unwatch( k_addon_type_player, localplayer.playermodel_view_slot );
-   localplayer.playermodel_view_slot = addon_cache_create_viewer( k_addon_type_player, reg_id );
+   localplayer.playermodel_view_slot = addon_cache_create_viewer( k_addon_type_player, addon_id );
 }
 
 void player__bind(void)
@@ -218,15 +218,9 @@ void player__pass_gate( u32 id )
       _world.copy_of_nonlocal_sender.key = 0;
       _world.copy_of_nonlocal_sender.submesh_start = 0;
       _world.copy_of_nonlocal_sender.submesh_count = 0;
-
-      vg_strncpy( af_str( &world->meta.af, gate->key ), 
-                  _world.nonlocal_destination_key, 32, 
-                  k_strncpy_overflow_fatal );
-
+      vg_strncpy( af_str( &world->meta.af, gate->key ), _world.nonlocal_destination_key, 32, k_strncpy_overflow_fatal );
       player__clean_refs();
-
-      addon_reg *reg = get_addon_from_index( k_addon_type_world, gate->addon_reg, 0,0 );
-      skaterift_load_world_start( reg, 0 );
+      skaterift_load_world_start( gate->remote_addon_id, 0 );
       return;
    }
    else
@@ -291,8 +285,8 @@ void player__im_gui( ui_context *ctx )
    g_player_debugger[3] = 32;
 
    char buf[96];
-   if( _world.main.addon )
-      addon_alias_uid( &_world.main.addon->alias, buf );
+   if( _world.main.addon_id )
+      addon_uid( _world.main.addon_id, buf );
    else
       strcpy( buf, "none" );
    player__debugtext( ctx, 1, "world #%u: %s", 0, buf );
index 76d0bf3527086655efe8fa16ea7e95803af54866..74a0cdab851db2a9aef5f0048e1c4f25a62b9d89 100644 (file)
@@ -32,7 +32,8 @@ static void relink_remote_player_worlds( u32 client_id )
    addon_alias q;
    addon_uid_to_alias( player->items[k_netmsg_playeritem_world0], &q );
 
-   if( addon_alias_eq( &q, &_world.main.addon->alias ) )
+   addon_reg *current_world_reg = addon_details( _world.main.addon_id );
+   if( addon_alias_eq( &q, &current_world_reg->alias ) )
       player->same_world = 1;
 }
 
@@ -604,13 +605,12 @@ void animate_remote_player( u32 index )
       }
    }
 
-   // FIXME: Need to redo addon caching. board can be in race condition here!
    struct network_player *player = &netplayers.list[ index ];
    struct skeleton *sk = &localplayer.skeleton;
    m4x3f *final_mtx = &netplayers.final_mtx[ sk->bone_count*index ];
    v3f *glider_mtx = netplayers.glider_mtx[ index ];
    struct player_board_pose *board_pose = &netplayers.board_poses[index];
-   struct player_board *board = addon_cache_item_if_loaded( k_addon_type_board, player->board_view_slot );
+   struct player_board *board = addon_cache_item_data( k_addon_type_board, player->board_view_slot, 1 );
    struct player_effects_data *effects = &player->effect_data;
    bool *glider_flag = &player->render_glider;
    
@@ -672,8 +672,6 @@ void render_remote_players( world_instance *world, vg_camera *cam )
 
    struct skeleton *sk = &localplayer.skeleton;
 
-   // TODO: Make this a reference count instead of mutex?
-   SDL_LockMutex( addon_system.cache_lock );
    for( u32 j=0; j<draw_list_count; j ++ )
    {
       u32 index = draw_list[j];
@@ -681,17 +679,13 @@ void render_remote_players( world_instance *world, vg_camera *cam )
       struct network_player *player = &netplayers.list[index];
       m4x3f *final_mtx = &netplayers.final_mtx[ sk->bone_count*index ];
 
-      struct player_model *model = addon_cache_item_if_loaded( k_addon_type_player, player->playermodel_view_slot );
-
-      if( !model ) 
-         model = &localplayer.fallback_model;
+      struct player_model *model = addon_cache_item_data( k_addon_type_player, player->playermodel_view_slot, 1 );
       render_playermodel( cam, world, 0, model, sk, final_mtx );
 
-      struct player_board *board = addon_cache_item_if_loaded( k_addon_type_board, player->board_view_slot );
+      struct player_board *board = addon_cache_item_data( k_addon_type_board, player->board_view_slot, 1 );
       render_board( cam, world, board, final_mtx[localplayer.id_board], 
                     &netplayers.board_poses[ index ], k_board_shader_player );
    }
-   SDL_UnlockMutex( addon_system.cache_lock );
 
    if( !gliders )
       return;
index 9bbb6ca59ad5b55073404e8c0159f9f755af5636..700c60099a74d23f2bc162500cf10f5a7a05aa8b 100644 (file)
@@ -116,6 +116,8 @@ void player_load_animation_reference( const char *path )
 /* TODO: allow error handling */
 void player_board_load( player_board *board, const char *path, void *arena )
 {
+   THREAD_1;
+
    mdl_open( &board->mdl, path, arena );
    mdl_load_metadata_block( &board->mdl, arena );
    mdl_async_full_load_std( &board->mdl, NULL );
@@ -138,7 +140,6 @@ void player_board_load( player_board *board, const char *path, void *arena )
 
       u32 index = mdl_entity_id_id( mesh->entity_id );
       ent_marker *marker = af_arritm( &markers, index );
-
       mdl_submesh *sm0 = &board->mdl.submeshes[ mesh->submesh_start ];
       
       const char *alias = af_str( &board->mdl.af, marker->pstr_alias );
@@ -239,12 +240,11 @@ void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose,
 
 void player__animate(void)
 {
-   struct player_subsystem_interface *sys = 
-      player_subsystems[localplayer.subsystem];
+   struct player_subsystem_interface *sys = player_subsystems[localplayer.subsystem];
 
-   struct player_board *board = 
-      addon_cache_item_if_loaded( k_addon_type_board, 
-                                  localplayer.board_view_slot );
+   struct player_board *board = addon_cache_item_data( k_addon_type_board, localplayer.board_view_slot, 1 );
+   if( !board ) 
+      board = &localplayer.fallback_board;
 
    sys->animate();
 
@@ -270,10 +270,8 @@ void player__animate(void)
                        &localplayer.pose, vg.time_delta );
    apply_full_skeleton_pose( sk, &localplayer.pose, localplayer.final_mtx );
    
-   if( sys->effects ){
-      sys->effects( sys->animator_data, localplayer.final_mtx, board,
-                    &localplayer.effect_data );
-   }
+   if( sys->effects )
+      sys->effects( sys->animator_data, localplayer.final_mtx, board, &localplayer.effect_data );
 
    skeleton_debug( sk, localplayer.final_mtx );
 
@@ -287,18 +285,19 @@ void player__animate(void)
    player__cam_iterate();
 }
 
-static void player_copy_frame_animator( replay_frame *frame ){
-   struct player_subsystem_interface *sys = 
-      player_subsystems[localplayer.subsystem];
+static void player_copy_frame_animator( replay_frame *frame )
+{
+   struct player_subsystem_interface *sys = player_subsystems[localplayer.subsystem];
 
-   if( sys->animator_size ){
+   if( sys->animator_size )
+   {
       void *src = replay_frame_data( frame, k_replay_framedata_animator );
       memcpy( sys->animator_data, src, sys->animator_size );
    }
 }
 
-void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t,
-                       player_pose *posed ){
+void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t, player_pose *posed )
+{
    struct skeleton *sk = &localplayer.skeleton;
    
    v3_lerp( pose0->root_co, pose1->root_co, t, posed->root_co );
@@ -306,23 +305,23 @@ void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t,
    posed->type = pose0->type;
    posed->board.lean = vg_lerpf( pose0->board.lean, pose1->board.lean, t );
 
-   if( pose0->type != pose1->type ){
+   if( pose0->type != pose1->type )
+   {
       /* it would be nice to apply IK pass in-keyframes. TOO BAD! */
       skeleton_copy_pose( sk, pose0->keyframes, posed->keyframes );
    }
-   else {
-      skeleton_lerp_pose( sk, pose0->keyframes, pose1->keyframes, t, 
-                          posed->keyframes );
-   }
+   else 
+      skeleton_lerp_pose( sk, pose0->keyframes, pose1->keyframes, t, posed->keyframes );
 }
 
 void player__observe_system( enum player_subsystem id )
 {
-   if( id != localplayer.observing_system ){
-      struct player_subsystem_interface *sysm1 = 
-         player_subsystems[ localplayer.observing_system ];
+   if( id != localplayer.observing_system )
+   {
+      struct player_subsystem_interface *sysm1 = player_subsystems[ localplayer.observing_system ];
 
-      if( sysm1->sfx_kill ) sysm1->sfx_kill();
+      if( sysm1->sfx_kill ) 
+         sysm1->sfx_kill();
       localplayer.observing_system = id;
    }
 }
@@ -331,11 +330,11 @@ void player__animate_from_replay( replay_buffer *replay )
 {
    replay_frame *frame = replay->cursor_frame,
                 *next = NULL;
-   if( frame ){
+   if( frame )
+   {
       next = frame->r;
 
-      struct player_subsystem_interface 
-         *sys0 = player_subsystems[frame->system];
+      struct player_subsystem_interface *sys0 = player_subsystems[frame->system];
       void *a0 = replay_frame_data( frame, k_replay_framedata_animator );
 
       struct replay_glider_data 
@@ -344,13 +343,12 @@ void player__animate_from_replay( replay_buffer *replay )
 
       f32 t = 0.0f;
 
-      if( next ){
+      if( next )
+      {
          t = replay_subframe_time( replay );
 
          player_pose pose0, pose1;
-
-         struct player_subsystem_interface 
-            *sys1 = player_subsystems[next->system];
+         struct player_subsystem_interface *sys1 = player_subsystems[next->system];
          void *a1 = replay_frame_data( next, k_replay_framedata_animator );
 
          sys0->pose( a0, &pose0 );
@@ -359,7 +357,8 @@ void player__animate_from_replay( replay_buffer *replay )
          lerp_player_pose( &pose0, &pose1, t, &localplayer.pose );
          g1 = replay_frame_data( next,  k_replay_framedata_glider );
       }
-      else{
+      else
+      {
          sys0->pose( a0, &localplayer.pose );
          g1 = NULL;
       }
@@ -368,13 +367,17 @@ void player__animate_from_replay( replay_buffer *replay )
       if( sys0->sfx_comp ) 
          sys0->sfx_comp( a0 );
 
-      if( g0 ){
-         if( g0->glider_orphan ){
-            if( g1 ){
+      if( g0 )
+      {
+         if( g0->glider_orphan )
+         {
+            if( g1 )
+            {
                v3_lerp( g0->co, g1->co, t, player_glide.rb.co );
                q_nlerp( g0->q,  g1->q,  t, player_glide.rb.q );
             }
-            else {
+            else 
+            {
                v3_copy( g0->co, player_glide.rb.co );
                v4_copy( g0->q,  player_glide.rb.q );
             }
@@ -390,7 +393,8 @@ void player__animate_from_replay( replay_buffer *replay )
          localplayer.have_glider   = g0->have_glider;
          localplayer.glider_orphan = g0->glider_orphan;
       }
-      else /* no glider data in g1, or edge case we dont care about */ {
+      else /* no glider data in g1, or edge case we dont care about */ 
+      {
          localplayer.have_glider = 0;
          localplayer.glider_orphan = 0;
          player_glide.t = 0.0f;
@@ -398,18 +402,16 @@ void player__animate_from_replay( replay_buffer *replay )
    }
    else return;
 
-   apply_full_skeleton_pose( &localplayer.skeleton, &localplayer.pose,
-                             localplayer.final_mtx );
+   apply_full_skeleton_pose( &localplayer.skeleton, &localplayer.pose, localplayer.final_mtx );
 }
 
 void player__pre_render(void)
 {
    /* shadowing/ao info */
-   struct player_board *board = 
-      addon_cache_item_if_loaded( k_addon_type_board,
-                                  localplayer.board_view_slot );
+   struct player_board *board = addon_cache_item_data( k_addon_type_board, localplayer.board_view_slot, 1 );
    v3f vp0, vp1;
-   if( board ){
+   if( board )
+   {
       v3_copy((v3f){0.0f,0.1f, board->truck_positions[0][2]}, vp0 );
       v3_copy((v3f){0.0f,0.1f, board->truck_positions[1][2]}, vp1 );
    }
@@ -473,7 +475,8 @@ void render_board( vg_camera *cam, world_instance *world,
 
    m4x4f m4mdl;
 
-   if( board->board.indice_count ){
+   if( board->board.indice_count )
+   {
       m4x3f mlocal;
       m3x3_identity( mlocal );
 
@@ -554,7 +557,8 @@ void render_playermodel( vg_camera *cam, world_instance *world,
                          struct skeleton *skeleton,
                          m4x3f *final_mtx )
 {
-   if( !model ) return;
+   if( !model ) 
+      model = &localplayer.fallback_model;
    
    shader_model_character_view_use();
 
@@ -589,24 +593,12 @@ void render_playermodel( vg_camera *cam, world_instance *world,
 void player__render( vg_camera *cam )
 {
    world_instance *world = &_world.main;
-   SDL_LockMutex( addon_system.cache_lock );
-
-   struct player_model *model = 
-      addon_cache_item_if_loaded( k_addon_type_player, 
-                                  localplayer.playermodel_view_slot );
-
-   if( !model ) model = &localplayer.fallback_model;
-   render_playermodel( cam, world, 1, model, &localplayer.skeleton,
-                       localplayer.final_mtx );
-
-   struct player_board *board = 
-      addon_cache_item_if_loaded( k_addon_type_board,
-                                  localplayer.board_view_slot );
+   struct player_model *model = addon_cache_item_data( k_addon_type_player, localplayer.playermodel_view_slot, 1 );
+   render_playermodel( cam, world, 1, model, &localplayer.skeleton, localplayer.final_mtx );
 
+   struct player_board *board = addon_cache_item_data( k_addon_type_board, localplayer.board_view_slot, 1 );
    render_board( cam, world, board, localplayer.final_mtx[localplayer.id_board],
-                  &localplayer.pose.board, k_board_shader_player );
-
-   SDL_UnlockMutex( addon_system.cache_lock );
+                 &localplayer.pose.board, k_board_shader_player );
 
    glEnable( GL_CULL_FACE );
    player_glide_render( cam, world, &localplayer.pose );
index 84c5c3756a425fa4a481a0fea72e3321b8b18ec5..9d2f5bb3700e82bd22948c87f5711f359fac2b05 100644 (file)
@@ -3088,24 +3088,18 @@ void player__skate_animate(void){
       vg_lerpf(animator->board_lean, lean, vg.time_delta*18.0f);
 
    /* feet placement */
-   struct player_board *board = 
-      addon_cache_item_if_loaded( k_addon_type_board,
-                                  localplayer.board_view_slot );
-   if( board ){
-      if( animator->weight > 0.0f ){
-         animator->foot_offset[0] = 
-            board->truck_positions[k_board_truck_back][2]+0.3f;
-      }
-      else{
-         animator->foot_offset[1] = 
-            board->truck_positions[k_board_truck_front][2]-0.3f;
-      }
+   struct player_board *board = addon_cache_item_data( k_addon_type_board, localplayer.board_view_slot, 1 );
+   if( board )
+   {
+      if( animator->weight > 0.0f )
+         animator->foot_offset[0] = board->truck_positions[k_board_truck_back][2]+0.3f;
+      else
+         animator->foot_offset[1] = board->truck_positions[k_board_truck_front][2]-0.3f;
    }
 
    f32 slapm = vg_maxf( 1.0f-v3_length2( state->trick_vel ), 0.0f );
    animator->slap = state->slap;
-   animator->subslap = vg_lerpf( animator->subslap, slapm, 
-                                 vg.time_delta*10.0f );
+   animator->subslap = vg_lerpf( animator->subslap, slapm, vg.time_delta*10.0f );
 
 #if 0
    f32 l = ((state->activity < k_skate_activity_ground) &&
index 190c5069398f9f9128bd5e4ba9922e11130fe9ab..20beb4bc034b3ea3c129c21460cc619d4ee2cda5 100644 (file)
@@ -3,8 +3,9 @@
 #include "vg/vg_platform.h"
 #include "vg/vg_framebuffer.h"
 
-static void async_render_init( void *payload, u32 size )
+static void async_render_init( void *userdata )
 {
+   THREAD_0;
    f32 rh = 0x1p-4f, ih = 0.3f;
 
    float quad[] = { 
@@ -59,6 +60,8 @@ static void async_render_init( void *payload, u32 size )
 
 void render_init(void)
 {
+   THREAD_1;
+
    vg_console_reg_var( "fov", &k_fov, k_var_dtype_f32, VG_VAR_PERSISTENT );
    vg_console_reg_var( "cam_height", &k_cam_height, k_var_dtype_f32, VG_VAR_PERSISTENT );
 
@@ -121,7 +124,7 @@ void render_init(void)
    };
    vg_framebuffer_create( g_render.fb_compass );
 
-   vg_async_call( async_render_init, NULL, 0 );
+   vg_async_call( &vg.main_tasks, async_render_init, NULL );
 }
 
 /*
index 8ce513291774fc5af082359413dc4d1bd5102385..6ab05d03ee63bc87bbaa2e9b640a20df5539a251 100644 (file)
@@ -119,7 +119,7 @@ static void replay_download_callback( void *data, u32 data_size, u64 userdata, e
             }
          }
 
-         _remote_replay.state = k_remote_replay_state_downloading;
+         _remote_replay.state = k_remote_replay_state_waitnext;
          return;
       }
 
@@ -209,6 +209,8 @@ S0:      offset += sizeof(serialized_netmsg) + snm->msg_size;
             _replay2_seek( frame_end->time, 0 );
          }
       }
+      else
+         _remote_replay.state = k_remote_replay_state_waitnext;
 
       return;
    }
@@ -229,10 +231,10 @@ struct async_cache_check_result
    u32 data_length;
    u8 data[];
 };
-
-static void async_cache_check_result( void *payload, u32 size )
+static void async_cache_check_result( vg_async_task *task )
 {
-   struct async_cache_check_result *result = payload;
+   THREAD_0;
+   struct async_cache_check_result *result = (void *)task->data;
    
    if( result->found_in_cache )
    {
@@ -271,7 +273,7 @@ static void async_cache_check_result( void *payload, u32 size )
 static const u32 k_download_option_preparing = 0x00;
 static const u32 k_download_option_data = 0x00;
 
-static void _remote_replay_cache_check( void *_ )
+static void _remote_replay_cache_check( void *userdata )
 {
    char path[1024];
    if( _remote_replay.state == k_remote_replay_state_getinfo )
@@ -284,8 +286,9 @@ static void _remote_replay_cache_check( void *_ )
       snprintf( path, sizeof(path), "replaydata/%lx@%x", _remote_replay.steamid, chunk->minute );
    }
 
-   vg_async_item *item = vg_async_alloc( sizeof(struct async_cache_check_result) + 20*1024*1024 );
-   struct async_cache_check_result *result = item->payload;
+   vg_async_task *result_task = 
+      vg_allocate_async_task( &vg.main_tasks, sizeof(struct async_cache_check_result) + 8*1024*1024, 1 );
+   struct async_cache_check_result *result = (void *)result_task->data;
    result->broken = 0;
 
    FILE *fp = fopen( path, "rb" );
@@ -305,30 +308,25 @@ static void _remote_replay_cache_check( void *_ )
       result->data_length = 0;
    }
 
-   vg_async_dispatch( item, async_cache_check_result );
-   vg_async_stall();
+   vg_async_task_dispatch( result_task, async_cache_check_result );
 }
 
 static void _remote_replay_pre_update(void)
 {
    if( _remote_replay.state == k_remote_replay_state_init )
    {
-      if( vg_loader_availible() )
-      {
-         _remote_replay.state = k_remote_replay_state_getinfo;
-         vg_loader_start( _remote_replay_cache_check, NULL );
-      }
+      _remote_replay.state = k_remote_replay_state_getinfo;
+      vg_async_call( &vg.loader_tasks, _remote_replay_cache_check, NULL );
    }
-   else if( _remote_replay.state == k_remote_replay_state_downloading )
+   else if( _remote_replay.state == k_remote_replay_state_waitnext )
    {
+      _remote_replay.state = k_remote_replay_state_downloading;
+
       struct remote_replay_chunk *chunk = &_remote_replay.chunks[ _remote_replay.chunks_downloaded ];
       if( chunk->state == k_chunk_state_none )
       {
-         if( vg_loader_availible() )
-         {
-            chunk->state = k_chunk_state_cache_check;
-            vg_loader_start( _remote_replay_cache_check, NULL );
-         }
+         chunk->state = k_chunk_state_cache_check;
+         vg_async_call( &vg.loader_tasks, _remote_replay_cache_check, NULL );
       }
    }
 }
@@ -359,7 +357,6 @@ void _replay2_pre_update(void)
       u32 s0 = current_frame->net_frame_size - sizeof(netmsg_playerframe);
       decode_playerframe( &current_frame->net_frame, s0, &interp_frame0 );
 
-
       m4x3f *final_mtx = _replay_player.final_mtx;
       v3f *glider_mtx = _replay_player.glider_mtx;
       struct player_board_pose *board_pose = &_replay_player.board_pose;
@@ -389,8 +386,6 @@ void _replay2_render_player( world_instance *world, vg_camera *cam )
    if( skaterift.activity != k_skaterift_replay ) 
       return;
 
-   SDL_LockMutex( addon_system.cache_lock );
-
    //struct player_model *model = addon_cache_item_if_loaded( k_addon_type_player, player->playermodel_view_slot );
    //if( !model ) 
    //   model = &localplayer.fallback_model;
@@ -403,8 +398,6 @@ void _replay2_render_player( world_instance *world, vg_camera *cam )
    render_board( cam, world, board, _replay_player.final_mtx[localplayer.id_board], 
                  &_replay_player.board_pose, k_board_shader_player );
 
-   SDL_UnlockMutex( addon_system.cache_lock );
-
 #if 0
    if( !gliders )
       return;
index 879cec8b05ccb65429330121cf133ddb6774ae29..3b5ea93bec2d44c033f406e33abf1e4e9ab305db 100644 (file)
@@ -48,9 +48,13 @@ struct _remote_replay
    enum remote_replay_state
    {
       k_remote_replay_state_none,
+
       k_remote_replay_state_init,
       k_remote_replay_state_getinfo,
+
+      k_remote_replay_state_waitnext,
       k_remote_replay_state_downloading,
+
       k_remote_replay_state_ready,
       k_remote_replay_state_failed
    }
index af89885fe26ffedd85598e2dfa02671ddc5d46f9..5ae6efd590ec3b7d5ba4ae8df0ec2aac4e3e7270 100644 (file)
@@ -26,8 +26,6 @@ void savedata_file_write( savedata_file *file )
 
 void savedata_group_write( savedata_group *group )
 {
-   for( u32 i=0; i<group->file_count; i++ )
-      savedata_file_write( &group->files[i] );
 }
 
 void savedata_file_read( savedata_file *file )
@@ -55,12 +53,15 @@ static void skaterift_write_addon_alias( vg_msg *msg, const char *key, addon_ali
 
 static void skaterift_write_viewslot( vg_msg *msg, const char *key, enum addon_type type, u16 cache_id )
 {
-   if( !cache_id ) return;
+   THREAD_0;
 
-   struct addon_cache *cache = &addon_system.cache[type];
-   addon_cache_entry *entry = vg_pool_item( &cache->pool, cache_id );
-   addon_reg *reg = entry->reg_ptr;
+   if( !cache_id ) 
+      return;
 
+   struct addon_cache *cache = &_addon.cache[type];
+   addon_cache_entry *entry = vg_pool_item( &cache->pool, cache_id );
+   
+   addon_reg *reg = addon_details( entry->addon_id );
    if( reg )
       skaterift_write_addon_alias( msg, key, &reg->alias );
 }
@@ -95,12 +96,10 @@ static void skaterift_populate_main_savedata( savedata_file *file )
 
    vg_msg_frame( &sav, "player" );
    {
-      skaterift_write_viewslot( &sav, "board", k_addon_type_board, 
-                                localplayer.board_view_slot );
-      skaterift_write_viewslot( &sav, "playermodel", k_addon_type_player,
-                                localplayer.playermodel_view_slot );
+      skaterift_write_viewslot( &sav, "board", k_addon_type_board, localplayer.board_view_slot );
+      skaterift_write_viewslot( &sav, "playermodel", k_addon_type_player, localplayer.playermodel_view_slot );
 
-      addon_reg *reg = _world.main.addon;
+      addon_reg *reg = addon_details( _world.main.addon_id );
       if( reg )
          skaterift_write_addon_alias( &sav, "location", &reg->alias );
       else
@@ -122,15 +121,14 @@ static void skaterift_populate_world_savedata( savedata_file *file )
 {
    file->path[0] = '\0';
    file->len = 0;
-   addon_reg *reg = _world.main.addon;
 
-   if( !reg )
+   if( !_world.main.addon_id )
    {
-      vg_error( "Tried to save unspecified world (reg was null)\n" );
+      vg_error( "Tried to save unspecified world (id was null)\n" );
       return;
    }
 
-   skaterift_world_get_save_path( reg, file->path );
+   skaterift_world_get_save_path( _world.main.addon_id, file->path );
 
    vg_msg sav;
    vg_msg_init( &sav, file->buf, sizeof(file->buf) );
@@ -148,20 +146,22 @@ static void skaterift_populate_world_savedata( savedata_file *file )
    file->len = sav.cur.co;
 }
 
-int skaterift_write_all_savedata( bool async )
+static void savedata_group_write_task( vg_async_task *task )
 {
-   if( async )
-   {
-      if( !vg_loader_availible() ) 
-         return 0;
-   }
+   savedata_group *group = (void *)task->data;
+   for( u32 i=0; i<group->file_count; i++ )
+      savedata_file_write( &group->files[i] );
+}
 
+void skaterift_write_all_savedata( bool async )
+{
    u32 save_data_size = sizeof(savedata_group) + sizeof(savedata_file)*2;
+   vg_async_task *task = NULL;
    savedata_group *group;
    if( async )
    {
-      vg_linear_clear( vg_async.buffer );
-      group = vg_linear_alloc( vg_async.buffer, vg_align8(save_data_size) );
+      task = vg_allocate_async_task( &vg.loader_tasks, sizeof(save_data_size), 1 );
+      group = (void *)task->data;
    }
    else
       group = alloca( save_data_size );
@@ -171,11 +171,12 @@ int skaterift_write_all_savedata( bool async )
    skaterift_populate_world_savedata( &group->files[1] );
 
    if( async )
-      vg_loader_start( (void *)savedata_group_write, group );
+      vg_async_task_dispatch( task, savedata_group_write_task );
    else
-      savedata_group_write( group );
-
-   return 1;
+   {
+      for( u32 i=0; i<group->file_count; i++ )
+         savedata_file_write( &group->files[i] );
+   }
 }
 
 void skaterift_autosave_synchronous(void)
@@ -187,15 +188,26 @@ void skaterift_autosave_update( void )
 {
    if( (vg.time - _last_autosave) > 60.0 )
    {
-      if( skaterift_write_all_savedata(1) )
-      {
-         _last_autosave = vg.time;
-      }
+      skaterift_write_all_savedata(1);
+      _last_autosave = vg.time;
    }
 }
 
+struct equip_saved_items_info
+{
+   addon_id board_id, player_id;
+};
+static void equip_async( vg_async_task *task )
+{
+   struct equip_saved_items_info *info = (void *)task->data;
+   localplayer.board_view_slot = addon_cache_create_viewer( k_addon_type_board, info->board_id );
+   localplayer.playermodel_view_slot = addon_cache_create_viewer( k_addon_type_player, info->player_id );
+}
+   
 void skaterift_load_mainsave(void)
 {
+   THREAD_1;
+
    savedata_file sav;
    strcpy( sav.path, str_skaterift_main_save );
    savedata_file_read( &sav );
@@ -207,52 +219,42 @@ void skaterift_load_mainsave(void)
    vg_msg_getkvintg( &kvsav, "ach", k_vg_msg_u32, &ach, NULL );
    skaterift.achievements |= ach;
 
-   u32 board_reg_id = time(NULL) % addon_count( k_addon_type_board, 0,0 ),
-       player_reg_id = (time(NULL)+44) % addon_count( k_addon_type_player, 0,0 );
+   u32 board_index = time(NULL) % _addon_filtered_count( k_addon_type_board, 0,0 ),
+       player_index = (time(NULL)+44) % _addon_filtered_count( k_addon_type_player, 0,0 );
+   addon_id board_id = _addon_get_filtered( k_addon_type_board, board_index, 0,0 ),
+            player_id =_addon_get_filtered( k_addon_type_player,player_index, 0,0 );
 
    vg_msg_cursor orig = kvsav.cur;
    if( vg_msg_seekframe( &kvsav, "player" ) )
    {
       addon_alias q;
-      u32 reg_id;
-
-      /* board */
       if( skaterift_read_addon_alias( &kvsav, "board", k_addon_type_board, &q ) )
-      {
-         reg_id = addon_match( &q );
-         if( reg_id != 0xffffffff ) 
-            board_reg_id = reg_id;
-      }
+         board_id = _get_addon_by_alias( &q );
 
-      /* playermodel */
       if( skaterift_read_addon_alias( &kvsav, "playermodel", k_addon_type_player, &q ) )
-      {
-         reg_id = addon_match( &q );
-         if( reg_id != 0xffffffff ) 
-            player_reg_id = reg_id;
-      }
+         player_id = _get_addon_by_alias( &q );
 
       if( skaterift_read_addon_alias( &kvsav, "location", k_addon_type_world, &q ) )
       {
          vg_info( "Loading client world from save.\n" );
+         addon_id world_id = _get_addon_by_alias( &q );
 
-         reg_id = addon_match( &q );
-         if( reg_id != 0xffffffff )
-         {
-            _world.loader_reg = get_addon_from_index( k_addon_type_world, reg_id, 0,0 );
-         }
+         if( world_id )
+            _world.load_addon = world_id;
          else
          {
             char buf[ADDON_UID_MAX];
             addon_alias_uid( &q, buf );
-
             vg_error( "While loading player location from save file, couldn't find addon '%s'\n", buf );
          }
       }
    }
 
-   localplayer.board_view_slot = addon_cache_create_viewer( k_addon_type_board, board_reg_id );
-   localplayer.playermodel_view_slot = addon_cache_create_viewer( k_addon_type_player, player_reg_id );
+   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct equip_saved_items_info), 1 );
+   struct equip_saved_items_info *info = (void *)task->data;
+   info->board_id = board_id;
+   info->player_id = player_id;
+   vg_async_task_dispatch( task, equip_async );
 
    kvsav.cur = orig;
 
@@ -263,6 +265,6 @@ void skaterift_load_mainsave(void)
    else
    {
       vg_info( "Starting new story!\n" );
-      _world.loader_reg = addon_mount_local_addon( "maps/dev_heaven", k_addon_type_world, ".mdl" );
+      _world.load_addon = _addon_mount_from_folder( "maps/dev_heaven", k_addon_type_world, ".mdl" );
    }
 }
index ba19ea9fbf5cf798105b36d3c07e2fea81b87315..39feea71096363df6b0eda6ec2ff48a3ec403463 100644 (file)
@@ -22,5 +22,5 @@ void savedata_group_write( savedata_group *group );
 void skaterift_autosave_synchronous(void);
 void skaterift_autosave_update(void);
 
-int skaterift_write_all_savedata( bool async );
+void skaterift_write_all_savedata( bool async );
 void skaterift_load_mainsave(void);
index 0834b567887708c4b5d70f8cffc05cfb64c50989..e2040064b85c4aede797f4c9b3c2b14f6c007f8c 100644 (file)
@@ -175,11 +175,11 @@ struct scene_upload_info{
    glmesh *mesh;
 };
 
-void async_scene_upload( void *payload, u32 size )
+void async_scene_upload( vg_async_task *task )
 {
-   struct scene_upload_info *info = payload;
+   THREAD_0;
 
-   //assert( mesh->loaded == 0 );
+   struct scene_upload_info *info = (void *)task->data;
    
    glmesh *mesh = info->mesh;
    scene_context *ctx = info->ctx;
@@ -192,26 +192,22 @@ void async_scene_upload( void *payload, u32 size )
    size_t stride = sizeof(scene_vert);
 
    glBindBuffer( GL_ARRAY_BUFFER, mesh->vbo );
-   glBufferData( GL_ARRAY_BUFFER, ctx->vertex_count*stride, 
-                 ctx->arrvertices, GL_STATIC_DRAW );
+   glBufferData( GL_ARRAY_BUFFER, ctx->vertex_count*stride, ctx->arrvertices, GL_STATIC_DRAW );
 
    glBindVertexArray( mesh->vao );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo );
-   glBufferData( GL_ELEMENT_ARRAY_BUFFER, ctx->indice_count*sizeof(u32),
-                 ctx->arrindices, GL_STATIC_DRAW );
+   glBufferData( GL_ELEMENT_ARRAY_BUFFER, ctx->indice_count*sizeof(u32), ctx->arrindices, GL_STATIC_DRAW );
    
    /* 0: coordinates */
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
    glEnableVertexAttribArray( 0 );
 
    /* 1: normal */
-   glVertexAttribPointer( 1, 4, GL_BYTE, GL_TRUE,
-         stride, (void *)offsetof(scene_vert, norm) );
+   glVertexAttribPointer( 1, 4, GL_BYTE, GL_TRUE, stride, (void *)offsetof(scene_vert, norm) );
    glEnableVertexAttribArray( 1 );
 
    /* 2: uv */
-   glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, 
-         stride, (void *)offsetof(scene_vert, uv) );
+   glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, stride, (void *)offsetof(scene_vert, uv) );
    glEnableVertexAttribArray( 2 );
 
    mesh->indice_count = ctx->indice_count;
@@ -222,38 +218,24 @@ void async_scene_upload( void *payload, u32 size )
    vg_info( "   verts:%u\n",   ctx->vertex_count );
 }
 
-void scene_upload_async( scene_context *ctx, glmesh *mesh )
+vg_async_task *scene_alloc_async( scene_context *scene, glmesh *mesh, u32 max_vertices, u32 max_indices )
 {
-   vg_async_item *call = vg_async_alloc( sizeof(struct scene_upload_info) );
+   THREAD_1;
 
-   struct scene_upload_info *info = call->payload;
-   info->mesh = mesh;
-   info->ctx = ctx;
-
-   vg_async_dispatch( call, async_scene_upload );
-}
-
-vg_async_item *scene_alloc_async( scene_context *scene, glmesh *mesh,
-                                  u32 max_vertices, u32 max_indices )
-{
    scene_init( scene, max_vertices, max_indices );
    u32 buf_size = scene_mem_required( scene );
 
    u32 hdr_size = vg_align8(sizeof(struct scene_upload_info));
-   vg_async_item *call = vg_async_alloc( hdr_size + buf_size );
+   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, hdr_size + buf_size, 1 );
 
-   struct scene_upload_info *info = call->payload;
+   struct scene_upload_info *info = (void *)task->data;
 
    info->mesh = mesh;
    info->ctx = scene;
-
-   void *buffer = ((u8*)call->payload)+hdr_size;
-   scene_supply_buffer( scene, buffer );
-
-   return call;
+   scene_supply_buffer( scene, task->data + hdr_size );
+   return task;
 }
 
-
 /*
  * BVH implementation
  */
index 8d6f57a89e279ac8f349f35c2b846769ba2e80dc..c2ba3a9c7146cbb8f8f44e0900dc79888c7bd703 100644 (file)
@@ -1,6 +1,5 @@
 #pragma once
 #include "vg/vg_bvh.h"
-#include "vg/vg_async.h"
 #include "common.h"
 #include "model.h"
 
@@ -42,20 +41,15 @@ struct scene_context
 
 extern bh_system bh_system_scene;
 bh_tree *scene_bh_create( void *lin_alloc, scene_context *s );
-int scene_raycast( scene_context *s, bh_tree *bh, 
-                   v3f co, v3f dir, ray_hit *hit, u16 ignore );
-vg_async_item *scene_alloc_async( scene_context *scene, glmesh *mesh,
-                                  u32 max_vertices, u32 max_indices );
+int scene_raycast( scene_context *s, bh_tree *bh, v3f co, v3f dir, ray_hit *hit, u16 ignore );
+vg_async_task *scene_alloc_async( scene_context *scene, glmesh *mesh, u32 max_vertices, u32 max_indices );
 void scene_copy_slice( scene_context *ctx, mdl_submesh *sm );
 void scene_push_vert( scene_context *ctx, scene_vert *v );
 void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend );
 void scene_push_tri( scene_context *ctx, u32 tri[3] );
-void scene_add_mdl_submesh( scene_context *ctx, mdl_context *mdl, 
-                            mdl_submesh *sm, m4x3f transform );
-void scene_set_vertex_flags( scene_context *ctx, 
-                             u32 start, u32 count, u16 flags );
+void scene_add_mdl_submesh( scene_context *ctx, mdl_context *mdl, mdl_submesh *sm, m4x3f transform );
+void scene_set_vertex_flags( scene_context *ctx, u32 start, u32 count, u16 flags );
 void scene_supply_buffer( scene_context *ctx, void *buffer );
 void scene_init( scene_context *ctx, u32 max_vertices, u32 max_indices );
 u32 scene_mem_required( scene_context *ctx );
-void async_scene_upload( void *payload, u32 size );
-void scene_upload_async( scene_context *ctx, glmesh *mesh );
+void async_scene_upload( vg_async_task *task );
index e7762eef2f7246ee338d59394cf1cd34fa23f15f..d4e432cc179f34356fbc11acee540a9d26ce2194 100644 (file)
@@ -80,12 +80,20 @@ static void skaterift_load_player_content(void)
    player_board_load( &localplayer.fallback_board, "models/board_none.mdl", vg_mem.rtmemory );
 }
 
-void game_load(void)
+static void game_load_0(void *_);
+static void game_load_1(void *_);
+static void game_load_2(void *_);
+static void game_load_3(void *_);
+static void game_load_4( vg_async_task *task );
+void game_load(void) { THREAD_1; game_load_0(NULL); }
+
+static void game_load_0(void *_)
 {
+   THREAD_1;
+
    _skaterift_script_init();
 
    vg_loader_set_user_information( "Initializing subsystems" );
-
    vg_console_reg_cmd( "load_world", skaterift_load_world_command, NULL );
    vg_console_reg_var( "immobile", &localplayer.immobile, k_var_dtype_i32, 0 );
    vg_console_reg_var( "allow_resume", &skaterift.allow_replay_resume, k_var_dtype_i32, VG_VAR_CHEAT );
@@ -116,47 +124,71 @@ void game_load(void)
    vg_loader_set_user_information( "Loading content files" );
    vg_loader_step( audio_init, NULL );
 
-   _world.default_hub_addon = addon_mount_local_addon( "maps/dev_hub", k_addon_type_world, ".mdl" );
-   if( !_world.default_hub_addon )
-      vg_fatal_error( "Hub world not found\n" );
+   _world.default_hub_addon = _addon_mount_from_folder( "maps/dev_hub", k_addon_type_world, ".mdl" );
+   VG_ASSERT( _world.default_hub_addon );
 
    vg_console_load_autos();
-
    vg_loader_set_user_information( "Mounting addons" );
-   addon_mount_content_folder( k_addon_type_player, "playermodels", ".mdl" );
-   addon_mount_content_folder( k_addon_type_board, "boards", ".mdl" );
-   addon_mount_content_folder( k_addon_type_world, "maps", ".mdl" );
-   addon_mount_workshop_items();
-   vg_async_call( async_addon_reg_update, NULL, 0 );
-   vg_async_stall();
+   _addon_mount_content_folder( k_addon_type_player, "playermodels", ".mdl" );
+   _addon_mount_content_folder( k_addon_type_board, "boards", ".mdl" );
+   _addon_mount_content_folder( k_addon_type_world, "maps", ".mdl" );
+   vg_async_call( &vg.main_tasks, game_load_1, NULL );
+}
+
+static void game_load_1(void *_)
+{
+   THREAD_0;
+   _mount_workshop_addons( NULL );
+   vg_async_call( &vg.loader_tasks, game_load_2, NULL );
+}
+
+static void game_load_2(void *_)
+{
+   THREAD_1;
 
    /* initializing / loading world. */
    vg_loader_set_user_information( "Loading savedata" );
    skaterift_load_mainsave();
 
    if( skaterift.override_load_world )
-      _world.loader_reg = addon_mount_local_addon( skaterift.override_load_world, k_addon_type_world, ".mdl" );
+      _world.load_addon = _addon_mount_from_folder( skaterift.override_load_world, k_addon_type_world, ".mdl" );
 
    _world.loader_instance = &_world.main;
    _world.loader_preview_mode = 0;
    _world.loader_heap = _world.heap; 
 
-   if( !_world.loader_reg )
+   if( !_world.load_addon )
    {
       vg_warn( "Falling back to default hub world...\n" );
-      _world.loader_reg = _world.default_hub_addon;
+      _world.load_addon = _world.default_hub_addon;
    }
 
-   _world_loader_set_target_reg( _world.loader_reg );
-   world_switcher_thread( NULL );
-   
-   vg_async_stall();
-   menu_on_world_change( _world.main.addon );
+   _world_loader_set_addon( _world.load_addon );
+   vg_async_call( &vg.main_tasks, game_load_3, NULL );
+}
+
+static void game_load_3(void *_)
+{
+   THREAD_0;
+   vg_async_task *task = world_load_go();
+   vg_async_task_dispatch( task, game_load_4 );
+}
+
+static void game_load_4( vg_async_task *task )
+{
+   THREAD_1;
+   skaterift_world_load_t1( task );
 
    /* add autosave function to exit list */
    vg_loader_step( NULL, skaterift_autosave_synchronous );
+   vg_async_call( &vg.main_tasks, async_client_ready, NULL );
+   _vg_load_temp_end();
 }
 
+/* 
+ * UPDATE LOOP
+ * ---------------------------------------------------------------------------*/
+
 static void draw_origin_axis(void)
 {
    vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
@@ -165,10 +197,6 @@ static void draw_origin_axis(void)
 }
 void skaterift_change_client_world_preupdate(void);
 
-/* 
- * UPDATE LOOP
- * ---------------------------------------------------------------------------*/
-
 void vg_pre_update(void)
 {
    skaterift_preupdate_inputs();
@@ -181,8 +209,7 @@ void vg_pre_update(void)
 
    //draw_origin_axis();
    //_skaterift_script_update();
-   addon_system_pre_update();
-   skateshop_world_preview_preupdate();
+   _addon_system_pre_update();
    network_update();
 
    /* time rate */
@@ -312,7 +339,7 @@ static void skaterift_composite_maincamera(void)
    else
    {
       _world.entity_camera_modulate = vg_maxf( 0.0f, _world.entity_camera_modulate-vg.time_frame_delta );
-   }
+}
    
    vg_camera_lerp( &localplayer.cam, &_world.entity_driven_camera,
                    vg_smoothstepf(_world.entity_camera_modulate), &g_render.cam );
index 376a00917b4e18609d0e3d21d3d065c4c0dbb2ef..20c83b593ee73bbbe31180a494d21e9bb80736bf 100644 (file)
@@ -3,7 +3,6 @@
 #include "vg/vg_platform.h"
 #include "vg/vg_m.h"
 #include "vg/vg_lines.h"
-#include "vg/vg_async.h"
 #include "vg/vg_camera.h"
 #include "trail.h"
 #include "shaders/particle.h"
@@ -20,19 +19,20 @@ static void trail_increment( trail_system *sys ){
       sys->count ++;
 }
 
-void trail_system_update( trail_system *sys, f32 dt,
-                          v3f co, v3f normal, f32 alpha )
+void trail_system_update( trail_system *sys, f32 dt, v3f co, v3f normal, f32 alpha )
 {
    /* update existing points and clip dead ones */
    bool clip_allowed = 1;
-   for( i32 i=0; i<sys->count; i ++ ){
+   for( i32 i=0; i<sys->count; i ++ )
+   {
       i32 i0 = sys->head - sys->count + i;
       if( i0 < 0 ) i0 += sys->max;
 
       trail_point *p0 = &sys->array[i0];
       p0->alpha -= dt/sys->lifetime;
 
-      if( clip_allowed ){
+      if( clip_allowed )
+      {
          if( p0->alpha <= 0.0f )
             sys->count --;
          else
@@ -55,12 +55,14 @@ void trail_system_update( trail_system *sys, f32 dt,
 
    f32 k_min = 0.001f;
 
-   if( sys->count == 0 ){
+   if( sys->count == 0 )
+   {
       trail_increment( sys );
       v3_copy( (v3f){0,0,-1}, dir );
       pdest = phead;
    }
-   else if( sys->count == 1 ){
+   else if( sys->count == 1 )
+   {
       if( v3_dist2( pcur->co, co ) < k_min*k_min )
          return;
 
@@ -68,11 +70,13 @@ void trail_system_update( trail_system *sys, f32 dt,
       pdest = phead;
       v3_sub( co, pcur->co, dir );
    }
-   else {
+   else 
+   {
       if( v3_dist2( pprev->co, co ) < k_min*k_min )
          return;
 
-      if( v3_dist2( pprev->co, co ) > sys->min_dist*sys->min_dist ){
+      if( v3_dist2( pprev->co, co ) > sys->min_dist*sys->min_dist )
+      {
          trail_increment( sys );
          pdest = phead;
       }
@@ -91,7 +95,8 @@ void trail_system_update( trail_system *sys, f32 dt,
 
 void trail_system_debug( trail_system *sys )
 {
-   for( i32 i=0; i<sys->count; i ++ ){
+   for( i32 i=0; i<sys->count; i ++ )
+   {
       i32 i0 = sys->head - sys->count + i;
       if( i0 < 0 ) i0 += sys->max;
 
@@ -113,9 +118,11 @@ struct trail_init_args {
    trail_system *sys;
 };
 
-void async_trail_init( void *payload, u32 size )
+void async_trail_init( vg_async_task *task )
 {
-   struct trail_init_args *args = payload;
+   THREAD_0;
+
+   struct trail_init_args *args = (void *)task->data;
    trail_system *sys = args->sys;
 
    glGenVertexArrays( 1, &sys->vao );
@@ -134,16 +141,17 @@ void async_trail_init( void *payload, u32 size )
 
 void trail_alloc( trail_system *sys, u32 max )
 {
+   THREAD_1;
+
    size_t stride = sizeof(trail_vert);
    sys->max = max;
    sys->array = vg_linear_alloc( vg_mem.rtmemory, max*sizeof(trail_point) );
    sys->vertices = vg_linear_alloc( vg_mem.rtmemory, max*stride*2 );
 
-   vg_async_item *call = vg_async_alloc( sizeof(struct trail_init_args) );
-
-   struct trail_init_args *init = call->payload;
+   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct trail_init_args), 1 );
+   struct trail_init_args *init = (void *)task->data;
    init->sys = sys;
-   vg_async_dispatch( call, async_trail_init );
+   vg_async_task_dispatch( task, async_trail_init );
 }
 
 void trail_system_prerender( trail_system *sys )
index c28578c007b5cae7866a09558bf7aac22c17c41b..7145bec8c09583e9d583581f5d59c1d51100fb8c 100644 (file)
@@ -2,7 +2,6 @@
 #include "vg/vg_loader.h"
 #include "vg/vg_io.h"
 #include "vg/vg_audio.h"
-#include "vg/vg_async.h"
 #include "vg/vg_magi.h"
 #include "vg/vg_ui/imgui.h"
 #include "vg/vg_ui/filebrowser.h"
index cf8be7d3a6ed0591d784ed6f804e89af7538516e..89d86c08d06b55c185c981ec021b0d6c89f75c29 100644 (file)
@@ -32,7 +32,8 @@ static struct ui_enum_opt workshop_form_type_opts[] = {
 /* 
  * Close the form and discard UGC query result
  */
-static void workshop_quit_form(void){
+static void workshop_quit_form(void)
+{
    player_board_unload( &workshop_form.board_model );
    workshop_form.file_intent = k_workshop_form_file_intent_none;
 
@@ -160,31 +161,30 @@ static const char *workshop_filetype_folder(void){
  * reciever on completion of packaging the files, it will then start the item
  * update with Steam API
  */
-static void workshop_form_upload_submission( PublishedFileId_t file_id,
-                                                char *metadata )
+static void workshop_form_upload_submission( PublishedFileId_t file_id, char *metadata )
 {
+   THREAD_0;
    ISteamUGC *hSteamUGC = SteamAPI_SteamUGC();
-   UGCUpdateHandle_t handle 
-      = SteamAPI_ISteamUGC_StartItemUpdate( hSteamUGC, SKATERIFT_APPID,
-                                            file_id );
+   UGCUpdateHandle_t handle = SteamAPI_ISteamUGC_StartItemUpdate( hSteamUGC, SKATERIFT_APPID, file_id );
 
    /* TODO: Handle failure cases for these */
 
    SteamAPI_ISteamUGC_SetItemMetadata( hSteamUGC, handle, metadata );
 
-   if( workshop_form.submission.submit_title ){
+   if( workshop_form.submission.submit_title )
+   {
       vg_info( "Setting title\n" );
-      SteamAPI_ISteamUGC_SetItemTitle( hSteamUGC, handle, 
-                                       workshop_form.submission.title );
+      SteamAPI_ISteamUGC_SetItemTitle( hSteamUGC, handle, workshop_form.submission.title );
    }
 
-   if( workshop_form.submission.submit_description ){
+   if( workshop_form.submission.submit_description )
+   {
       vg_info( "Setting description\n" );
-      SteamAPI_ISteamUGC_SetItemDescription( hSteamUGC, handle, 
-                                       workshop_form.submission.description);
+      SteamAPI_ISteamUGC_SetItemDescription( hSteamUGC, handle, workshop_form.submission.description);
    }
 
-   if( workshop_form.submission.submit_file_and_image ){
+   if( workshop_form.submission.submit_file_and_image )
+   {
       char path_buf[4096];
       vg_str folder;
       vg_strnull( &folder, path_buf, 4096 );
@@ -204,8 +204,7 @@ static void workshop_form_upload_submission( PublishedFileId_t file_id,
    }
 
    vg_info( "Setting visibility\n" );
-   SteamAPI_ISteamUGC_SetItemVisibility( hSteamUGC, handle, 
-                                 workshop_form.submission.visibility );
+   SteamAPI_ISteamUGC_SetItemVisibility( hSteamUGC, handle, workshop_form.submission.visibility );
 
    vg_info( "Submitting updates\n" );
    vg_steam_async_call *call = vg_alloc_async_steam_api_call();
@@ -222,23 +221,20 @@ static void on_workshop_createitem( void *data, void *user )
 {
    CreateItemResult_t *result = data;
 
-   if( result->m_eResult == k_EResultOK ){
-      vg_info( "Created workshop file with id: %lu\n", 
-                result->m_nPublishedFileId );
+   if( result->m_eResult == k_EResultOK )
+   {
+      vg_info( "Created workshop file with id: %lu\n", result->m_nPublishedFileId );
 
-      if( result->m_bUserNeedsToAcceptWorkshopLegalAgreement ){
+      if( result->m_bUserNeedsToAcceptWorkshopLegalAgreement )
          vg_warn( "Workshop agreement currently not accepted\n" );
-      }
-      
       workshop_form_upload_submission( result->m_nPublishedFileId, user );
    }
-   else{
+   else
+   {
       const char *errstr = workshop_EResult_user_string( result->m_eResult );
       
-      if( errstr ){
-         vg_error( "ISteamUGC_CreateItem() failed(%d): '%s' \n", 
-                     result->m_eResult, errstr );
-      }
+      if( errstr )
+         vg_error( "ISteamUGC_CreateItem() failed(%d): '%s' \n", result->m_eResult, errstr );
 
       workshop_form.page = k_workshop_form_closing_bad;
       workshop_form.failure_or_success_string = errstr;
@@ -248,52 +244,33 @@ static void on_workshop_createitem( void *data, void *user )
 /*
  * Starts the workshop upload process through Steam API
  */
-static void workshop_form_async_submit_begin( void *payload, u32 size )
+static void workshop_form_async_submit_begin( void *userdata )
 {
-
    /* use existing file */
-   if( workshop_form.submission.file_id ){
-      workshop_form_upload_submission( workshop_form.submission.file_id,
-                                       payload );
+   if( workshop_form.submission.file_id )
+   {
+      workshop_form_upload_submission( workshop_form.submission.file_id, userdata );
    }
-   else{
+   else
+   {
       vg_steam_async_call *call = vg_alloc_async_steam_api_call();
-      call->userdata = payload;
+      call->userdata = userdata;
       call->p_handler = on_workshop_createitem;
       ISteamUGC *hSteamUGC = SteamAPI_SteamUGC();
-      call->id = SteamAPI_ISteamUGC_CreateItem( hSteamUGC, SKATERIFT_APPID, 
-                                                k_EWorkshopFileTypeCommunity );
+      call->id = SteamAPI_ISteamUGC_CreateItem( hSteamUGC, SKATERIFT_APPID, k_EWorkshopFileTypeCommunity );
    }
 }
 
-/*
- * Downloads the framebuffer into scratch memory
- */
-static void workshop_form_async_download_image( void *payload, u32 size )
+static void _workshop_form_end_op( void *userdata )
 {
-   int w, h;
-   vg_framebuffer_get_res( g_render.fb_workshop_preview, &w, &h );
-   vg_linear_clear( vg_mem.scratch );
-   workshop_form.img_buffer = vg_linear_alloc( vg_mem.scratch, w*h*3 );
-
-   vg_info( "read framebuffer: glReadPixels( %dx%d )\n", w,h );
-
-   glBindFramebuffer( GL_READ_FRAMEBUFFER, g_render.fb_workshop_preview->id );
-   glReadBuffer( GL_COLOR_ATTACHMENT0 );
-   glReadPixels( 0,0, w,h, GL_RGB, GL_UNSIGNED_BYTE, workshop_form.img_buffer );
-
-   workshop_form.img_w = w;
-   workshop_form.img_h = h;
+   workshop_form.op = k_workshop_op_none;
 }
 
 /*
  * Thread which kicks off the upload process
  */
-static void _workshop_form_submit_thread( void *data )
+static void _workshop_form_submit_t1( void *userdata )
 {
-   vg_async_call( workshop_form_async_download_image, NULL, 0 );
-   vg_async_stall();
-
    char path_buf[4096];
    vg_str folder;
    vg_strnull( &folder, path_buf, 4096 );
@@ -301,9 +278,10 @@ static void _workshop_form_submit_thread( void *data )
    vg_strcat( &folder, workshop_filetype_folder() );
    vg_strcat( &folder, workshop_form.addon_folder );
 
-   if( !vg_strgood(&folder) ){
+   if( !vg_strgood(&folder) )
+   {
       vg_error( "addon folder path too long\n" );
-      workshop_form.op = k_workshop_op_none;
+      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
       return;
    }
 
@@ -317,16 +295,16 @@ static void _workshop_form_submit_thread( void *data )
 
    /* short description */
    vg_msg_frame( &descriptor, "workshop" );
+   {
       vg_msg_wkvstr( &descriptor, "title", workshop_form.submission.title );
       //vg_msg_wkvstr( &descriptor, "author", "unknown" );
-      vg_msg_wkvnum( &descriptor, "type", k_vg_msg_u32, 1,
-                     &workshop_form.submission.type );
+      vg_msg_wkvnum( &descriptor, "type", k_vg_msg_u32, 1, &workshop_form.submission.type );
       vg_msg_wkvstr( &descriptor, "folder", workshop_form.addon_folder );
+   }
    vg_msg_end_frame( &descriptor );
    //vg_msg_wkvstr( &descriptor, "location", "USA" );
 
-   char *short_descriptor_str = 
-      vg_linear_alloc( vg_mem.scratch, vg_align8(descriptor.cur.co*2+1));
+   char *short_descriptor_str = vg_linear_alloc( vg_mem.scratch, vg_align8(descriptor.cur.co*2+1));
    vg_bin_str( descriptor_buf, short_descriptor_str, descriptor.cur.co );
    short_descriptor_str[descriptor.cur.co*2] = '\0';
    vg_info( "binstr: %s\n", short_descriptor_str );
@@ -335,7 +313,7 @@ static void _workshop_form_submit_thread( void *data )
    if( vg_dir_open( &dir, folder.buffer ) != k_dir_open_ok )
    {
       vg_error( "could not open addon folder '%s'\n", folder.buffer );
-      workshop_form.op = k_workshop_op_none;
+      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
       return;
    }
 
@@ -365,15 +343,15 @@ static void _workshop_form_submit_thread( void *data )
    vg_strcat( &descriptor_file, "/addon.inf" );
    if( !vg_strgood(&descriptor_file) ){
       vg_error( "Addon info path too long\n" );
-      workshop_form.op = k_workshop_op_none;
+      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
       return;
    }
    
    FILE *fp = fopen( descriptor_file.buffer, "wb" );
-   if( !fp ){
-      vg_error( "Could not open addon info file '%s'\n", 
-                descriptor_file.buffer );
-      workshop_form.op = k_workshop_op_none;
+   if( !fp )
+   {
+      vg_error( "Could not open addon info file '%s'\n", descriptor_file.buffer );
+      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
       return;
    }
    fwrite( descriptor_buf, descriptor.cur.co, 1, fp );
@@ -384,9 +362,10 @@ static void _workshop_form_submit_thread( void *data )
    vg_str preview = folder;
    vg_strcat( &preview, "/preview.jpg" );
 
-   if( !vg_strgood(&preview) ){
+   if( !vg_strgood(&preview) )
+   {
       vg_error( "preview image path too long\n" );
-      workshop_form.op = k_workshop_op_none;
+      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
       return;
    }
 
@@ -397,7 +376,7 @@ static void _workshop_form_submit_thread( void *data )
    stbi_flip_vertically_on_write(1);
    stbi_write_jpg( preview.buffer, w,h, 3, workshop_form.img_buffer, 90 );
 
-   vg_async_call( workshop_form_async_submit_begin, short_descriptor_str, 0 );
+   vg_async_call( &vg.main_tasks, workshop_form_async_submit_begin, short_descriptor_str );
 }
 
 /*
@@ -440,7 +419,21 @@ static void workshop_op_submit( ui_context *ctx )
    workshop_form.file_intent = k_workshop_form_file_intent_none;
    workshop_form.op = k_workshop_op_publishing_update;
 
-   vg_loader_start( _workshop_form_submit_thread, NULL );
+   int w, h;
+   vg_framebuffer_get_res( g_render.fb_workshop_preview, &w, &h );
+   vg_linear_clear( vg_mem.scratch );
+   workshop_form.img_buffer = vg_linear_alloc( vg_mem.scratch, w*h*3 );
+
+   vg_info( "read framebuffer: glReadPixels( %dx%d )\n", w,h );
+
+   glBindFramebuffer( GL_READ_FRAMEBUFFER, g_render.fb_workshop_preview->id );
+   glReadBuffer( GL_COLOR_ATTACHMENT0 );
+   glReadPixels( 0,0, w,h, GL_RGB, GL_UNSIGNED_BYTE, workshop_form.img_buffer );
+
+   workshop_form.img_w = w;
+   workshop_form.img_h = h;
+
+   vg_async_call( &vg.loader_tasks, _workshop_form_submit_t1, NULL );
 }
 
 /*
@@ -451,8 +444,10 @@ static void workshop_op_submit( ui_context *ctx )
 /*
  * Reciever for completion of the model file load
  */
-static void workshop_form_loadmodel_async_complete( void *payload, u32 size )
+static void workshop_form_loadmodel_async_complete( void *userdata )
 {
+   THREAD_0;
+
    v2_zero( workshop_form.view_angles );
    v3_zero( workshop_form.view_offset );
    workshop_form.view_dist = 1.0f;
@@ -463,17 +458,13 @@ static void workshop_form_loadmodel_async_complete( void *payload, u32 size )
    workshop_form.op = k_workshop_op_none;
 }
 
-/*
- * Reciever for failure to load
- */
-static void workshop_form_loadmodel_async_error( void *payload, u32 size ){
-}
-
 /*
  * Thread which loads the model from the disk 
  */
-static void _workshop_form_load_thread( void *data )
+static void _workshop_form_load_t1( void *userdata )
 {
+   THREAD_1;
+
    char path_buf[4096];
    vg_str folder;
    vg_strnull( &folder, path_buf, 4096 );
@@ -481,10 +472,10 @@ static void _workshop_form_load_thread( void *data )
    vg_strcat( &folder, workshop_filetype_folder() );
    vg_strcat( &folder, workshop_form.addon_folder );
 
-   if( !vg_strgood(&folder) ){
+   if( !vg_strgood(&folder) )
+   {
       vg_error( "workshop async load failed: path too long\n" );
-      vg_async_call( workshop_form_loadmodel_async_error, NULL, 0 );
-      workshop_form.op = k_workshop_op_none;
+      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
       return;
    }
 
@@ -492,16 +483,17 @@ static void _workshop_form_load_thread( void *data )
    if( vg_dir_open( &dir, folder.buffer ) != k_dir_open_ok )
    {
       vg_error( "workshop async load failed: could not open folder\n" );
-      vg_async_call( workshop_form_loadmodel_async_error, NULL, 0 );
-      workshop_form.op = k_workshop_op_none;
+      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
       return;
    }
 
    vg_info( "Searching %s for model files\n", folder.buffer );
 
    int found_mdl = 0;
-   while( vg_dir_next_entry(&dir) ){
-      if( vg_dir_entry_type(&dir) == k_vg_entry_type_file ){
+   while( vg_dir_next_entry(&dir) )
+   {
+      if( vg_dir_entry_type(&dir) == k_vg_entry_type_file )
+      {
          const char *d_name = vg_dir_entry_name(&dir);
          if( d_name[0] == '.' ) continue;
 
@@ -519,31 +511,27 @@ static void _workshop_form_load_thread( void *data )
    }
    vg_dir_close(&dir);
 
-   if( !found_mdl ){
+   if( !found_mdl )
+   {
       vg_error( "workshop async load failed: no model files found\n" );
-      vg_async_call( workshop_form_loadmodel_async_error, NULL, 0 );
-      workshop_form.op = k_workshop_op_none;
+      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
       return;
    }
 
    if( workshop_form.model_arena == NULL )
    {
-      workshop_form.model_arena = _vg_create_linear_allocator(
-         NULL, 1024*2, VG_MEMORY_SYSTEM, "Workshop model data arena" );
+      workshop_form.model_arena = 
+         _vg_create_linear_allocator( NULL, 1024*2, VG_MEMORY_SYSTEM, "Workshop model data arena" );
    }
    void *arena = workshop_form.model_arena;
    vg_linear_clear( arena );
 
    if( workshop_form.submission.type == k_addon_type_board )
-   {
       player_board_load( &workshop_form.board_model, path_buf, arena );
-   }
    else if( workshop_form.submission.type == k_addon_type_player )
-   {
       player_model_load( &workshop_form.player_model, path_buf, arena );
-   }
 
-   vg_async_call( workshop_form_loadmodel_async_complete, NULL, 0 );
+   vg_async_call( &vg.main_tasks, workshop_form_loadmodel_async_complete, NULL );
 }
 
 /*
@@ -551,6 +539,7 @@ static void _workshop_form_load_thread( void *data )
  */
 static void workshop_op_load_model( ui_context *ctx )
 {
+   THREAD_0;
    world_instance *world = &_world.main;
    workshop_form.view_world = world;
 
@@ -578,7 +567,7 @@ static void workshop_op_load_model( ui_context *ctx )
    }
 
    workshop_form.op = k_workshop_op_loading_model;
-   vg_loader_start( _workshop_form_load_thread, NULL );
+   vg_async_call( &vg.loader_tasks, _workshop_form_load_t1, NULL );
 }
 
 /*
@@ -589,17 +578,15 @@ static void workshop_op_load_model( ui_context *ctx )
 /*
  * The image has been decoded and is ready to slap into the framebuffer
  */
-static void workshop_form_async_imageload( void *data, u32 len )
+static void workshop_form_async_imageload( void *data )
 {
+   THREAD_0;
+
    if( data )
    {
-      vg_framebuffer_attachment *a = 
-         &g_render.fb_workshop_preview->attachments[0];
-
+      vg_framebuffer_attachment *a = &g_render.fb_workshop_preview->attachments[0];
       glBindTexture( GL_TEXTURE_2D, a->id );
-      glTexSubImage2D( GL_TEXTURE_2D, 0,0,0,
-                        WORKSHOP_PREVIEW_WIDTH, WORKSHOP_PREVIEW_HEIGHT, 
-                        a->format, a->type, data );
+      glTexSubImage2D( GL_TEXTURE_2D, 0,0,0, WORKSHOP_PREVIEW_WIDTH, WORKSHOP_PREVIEW_HEIGHT, a->format, a->type, data );
       stbi_image_free( data );
       vg_success( "Loaded workshop preview image\n" );
    }
@@ -616,7 +603,10 @@ static void workshop_form_async_imageload( void *data, u32 len )
 /*
  * Load the image located at ./workshop_preview.jpg into our framebuffer
  */
-static void _workshop_load_preview_thread( void *data ){
+static void _workshop_load_preview_t1( void *userdata )
+{
+   THREAD_1;
+
    char path_buf[ 4096 ];
    vg_str path;
    vg_strnull( &path, path_buf, 4096 );
@@ -634,24 +624,23 @@ static void _workshop_load_preview_thread( void *data ){
       {
          if( (x == WORKSHOP_PREVIEW_WIDTH) && (y == WORKSHOP_PREVIEW_HEIGHT) )
          {
-            vg_async_call( workshop_form_async_imageload, rgb, x*y*3 );
+            vg_async_call( &vg.main_tasks, workshop_form_async_imageload, rgb );
          }
          else
          {
-            vg_error( "Resolution does not match framebuffer, so we can't"
-                      " show it\n" );
+            vg_error( "Resolution does not match framebuffer, so we can't show it\n" );
             stbi_image_free( rgb );
-            vg_async_call( workshop_form_async_imageload, NULL, 0 );
+            vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
          }
       }
       else
       {
-         vg_async_call( workshop_form_async_imageload, NULL, 0 );
+         vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
       }
    }
    else
    {
-      vg_async_call( workshop_form_async_imageload, NULL, 0 );
+      vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
    }
 }
 
@@ -660,14 +649,13 @@ static void _workshop_load_preview_thread( void *data ){
  */
 static void workshop_op_download_and_view_submission( int result_index )
 {
+   THREAD_0;
+
    workshop_form.op = k_workshop_op_downloading_submission;
    ISteamUGC *hSteamUGC = SteamAPI_SteamUGC();
    ISteamRemoteStorage *hSteamRemoteStorage = SteamAPI_SteamRemoteStorage();
    SteamUGCDetails_t details;
-   if( SteamAPI_ISteamUGC_GetQueryUGCResult( hSteamUGC, 
-                                             workshop_form.ugc_query.handle,
-                                             result_index,
-                                             &details ) )
+   if( SteamAPI_ISteamUGC_GetQueryUGCResult( hSteamUGC, workshop_form.ugc_query.handle, result_index, &details ) )
    {
       workshop_reset_submission_data();
       workshop_form.submission.submit_description = 0;
@@ -676,23 +664,17 @@ static void workshop_op_download_and_view_submission( int result_index )
 
       u8 metadata_buf[512];
       char metadata_str[1024+1];
-      int have_meta = SteamAPI_ISteamUGC_GetQueryUGCMetadata( hSteamUGC, 
-                                              workshop_form.ugc_query.handle,
+      int have_meta = SteamAPI_ISteamUGC_GetQueryUGCMetadata( hSteamUGC, workshop_form.ugc_query.handle,
                                               result_index, metadata_str, 
                                               1024+1 );
 
-      vg_strncpy( details.m_rgchDescription, 
-                  workshop_form.submission.description, 
-                  VG_ARRAY_LEN( workshop_form.submission.description ),
-                  k_strncpy_always_add_null );
+      vg_strncpy( details.m_rgchDescription, workshop_form.submission.description, 
+                  VG_ARRAY_LEN( workshop_form.submission.description ), k_strncpy_always_add_null );
 
-      vg_strncpy( details.m_rgchTitle,
-                  workshop_form.submission.title,
-                  VG_ARRAY_LEN( workshop_form.submission.title ),
-                  k_strncpy_always_add_null );
+      vg_strncpy( details.m_rgchTitle, workshop_form.submission.title,
+                  VG_ARRAY_LEN( workshop_form.submission.title ), k_strncpy_always_add_null );
 
-      snprintf( workshop_form.addon_folder, 
-                 VG_ARRAY_LEN( workshop_form.addon_folder ),
+      snprintf( workshop_form.addon_folder, VG_ARRAY_LEN( workshop_form.addon_folder ),
                  "Steam Cloud ("PRINTF_U64")", details.m_nPublishedFileId );
 
       workshop_form.submission.file_id = details.m_nPublishedFileId;
@@ -720,8 +702,7 @@ static void workshop_op_download_and_view_submission( int result_index )
             const char *kv_folder = vg_msg_getkvstr( &msg, "folder" );
             if( kv_folder )
             {
-               vg_strncpy( kv_folder, workshop_form.addon_folder,
-                           sizeof(workshop_form.addon_folder),
+               vg_strncpy( kv_folder, workshop_form.addon_folder, sizeof(workshop_form.addon_folder),
                            k_strncpy_always_add_null );
             }
          }
@@ -737,7 +718,7 @@ static void workshop_op_download_and_view_submission( int result_index )
       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
       glViewport( 0,0, vg.window_x, vg.window_y );
 
-      vg_loader_start( _workshop_load_preview_thread, NULL );
+      vg_async_call( &vg.loader_tasks, _workshop_load_preview_t1, NULL );
    }
    else
    {
@@ -765,8 +746,7 @@ static void workshop_view_page( int req )
 
    int page = VG_MAX(VG_MIN(req, workshop_form.view_published_page_count-1),0),
        start = page * WORKSHOP_VIEW_PER_PAGE,
-       end   = VG_MIN( (page+1) * WORKSHOP_VIEW_PER_PAGE, 
-                       workshop_form.ugc_query.returned_item_count ),
+       end   = VG_MIN( (page+1) * WORKSHOP_VIEW_PER_PAGE, workshop_form.ugc_query.returned_item_count ),
        count = end-start;
 
    vg_info( "View page %d\n", page );
@@ -780,20 +760,12 @@ static void workshop_view_page( int req )
       struct published_file *pfile = &workshop_form.published_files_list[i];
 
       SteamUGCDetails_t details;
-      if( SteamAPI_ISteamUGC_GetQueryUGCResult( hSteamUGC, 
-                                                workshop_form.ugc_query.handle,
-                                                start+i,
-                                                &details ) )
+      if( SteamAPI_ISteamUGC_GetQueryUGCResult( hSteamUGC, workshop_form.ugc_query.handle, start+i, &details ) )
       {
          if( details.m_eResult != k_EResultOK )
-         {
             snprintf( pfile->title, 80, "Error (%d)", details.m_eResult );
-         }
          else
-         {
-            vg_strncpy( details.m_rgchTitle, pfile->title, 80,
-                        k_strncpy_always_add_null );
-         }
+            vg_strncpy( details.m_rgchTitle, pfile->title, 80, k_strncpy_always_add_null );
 
          pfile->result = details.m_eResult;
          pfile->result_index = start+i;
@@ -819,21 +791,17 @@ static void on_workshop_UGCQueryComplete( void *data, void *userdata )
    {
       if( query->m_unTotalMatchingResults > 50 )
       {
-         vg_warn( "You have %d items submitted, "
-                  "we can only view the last 50\n" );
+         vg_warn( "You have %d items submitted, we can only view the last 50\n" );
       }
 
       workshop_form.ugc_query.all_item_count = query->m_unTotalMatchingResults;
-      workshop_form.ugc_query.returned_item_count =
-                                             query->m_unNumResultsReturned;
+      workshop_form.ugc_query.returned_item_count = query->m_unNumResultsReturned;
 
       workshop_form.ugc_query.handle = query->m_handle;
-      workshop_form.view_published_page_count = 
-         (query->m_unNumResultsReturned+WORKSHOP_VIEW_PER_PAGE-1)/
-            WORKSHOP_VIEW_PER_PAGE;
+      workshop_form.view_published_page_count = (query->m_unNumResultsReturned+WORKSHOP_VIEW_PER_PAGE-1)/
+                                                   WORKSHOP_VIEW_PER_PAGE;
       workshop_form.view_published_page_id = 0;
       workshop_form.published_files_list_length = 0;
-
       workshop_view_page( 0 );
    }
    else
@@ -957,8 +925,7 @@ static void workshop_render_player_preview(void)
    vg_camera_update_projection( &cam, WORKSHOP_PREVIEW_WIDTH, WORKSHOP_PREVIEW_HEIGHT );
    vg_camera_finalize( &cam );
 
-   render_playermodel( &cam, &_world.main, 0, 
-                       &workshop_form.player_model, sk, localplayer.final_mtx );
+   render_playermodel( &cam, &_world.main, 0, &workshop_form.player_model, sk, localplayer.final_mtx );
 
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
    glViewport( 0,0, vg.window_x, vg.window_y );
@@ -1230,8 +1197,7 @@ static void workshop_form_gui_edit_page( ui_context *ctx, ui_rect content )
    ui_rect file_button, file_label;
 
    char buf[128];
-   snprintf( buf, 128, 
-             "Addon folder: skaterift/%s", workshop_filetype_folder() );
+   snprintf( buf, 128, "Addon folder: skaterift/%s", workshop_filetype_folder() );
 
    if( type == k_addon_type_world )
    {
@@ -1250,8 +1216,7 @@ static void workshop_form_gui_edit_page( ui_context *ctx, ui_rect content )
 
       if( workshop_form.file_intent != k_workshop_form_file_intent_none )
       {
-         ui_text( ctx, file_entry, workshop_form.addon_folder, 1, 
-                  k_ui_align_middle_left, ui_colour( ctx, k_ui_fg+4 ) );
+         ui_text( ctx, file_entry, workshop_form.addon_folder, 1, k_ui_align_middle_left, ui_colour( ctx, k_ui_fg+4 ) );
 
          if( ui_button_text( ctx, file_button, "Remove", 1 ) == 1 )
          {
@@ -1271,14 +1236,11 @@ static void workshop_form_gui_edit_page( ui_context *ctx, ui_rect content )
             .change = workshop_changed_model_path
          };
 
-         ui_textbox( ctx, file_entry, buf, workshop_form.addon_folder,
-                     VG_ARRAY_LEN(workshop_form.addon_folder), 1,
+         ui_textbox( ctx, file_entry, buf, workshop_form.addon_folder, VG_ARRAY_LEN(workshop_form.addon_folder), 1,
                      0, &callbacks );
 
          if( ui_button_text( ctx, file_button, "Load", 1 ) == 1 )
-         {
             workshop_op_load_model( ctx );
-         }
       }
    }
 
@@ -1296,8 +1258,7 @@ static void workshop_form_gui_edit_page( ui_context *ctx, ui_rect content )
 
    /* visibility option */
    {
-      ui_enum( ctx, content, "Visibility:", workshop_form_visibility_opts,
-               4, &workshop_form.submission.visibility );
+      ui_enum( ctx, content, "Visibility:", workshop_form_visibility_opts, 4, &workshop_form.submission.visibility );
    }
 
    /* description box */
@@ -1321,8 +1282,7 @@ static void workshop_form_gui_edit_page( ui_context *ctx, ui_rect content )
    ui_rect_center( final_row, submission_center );
 
    ui_rect btn_left, btn_right;
-   ui_split_ratio( submission_center, k_ui_axis_v, 0.5f, 8, 
-                   btn_left, btn_right );
+   ui_split_ratio( submission_center, k_ui_axis_v, 0.5f, 8, btn_left, btn_right );
 
    if( ui_button_text( ctx, btn_left, "Publish", 1 ) == 1 )
    {
@@ -1336,8 +1296,7 @@ static void workshop_form_gui_edit_page( ui_context *ctx, ui_rect content )
    }
 
    /* disclaimer */
-   const char *disclaimer_text = 
-      "By submitting this item, you agree to the workshop terms of service";
+   const char *disclaimer_text = "By submitting this item, you agree to the workshop terms of service";
 
    ui_rect disclaimer_row, inner, link;
    ui_split( content, k_ui_axis_h, content[3]-32, 0, content, disclaimer_row );
@@ -1360,8 +1319,7 @@ static void workshop_form_gui_edit_page( ui_context *ctx, ui_rect content )
             k_EActivateGameOverlayToWebPageMode_Default );
    }
 
-   ui_text( ctx, label, disclaimer_text, 1, k_ui_align_middle_left,
-            ui_colour( ctx, k_ui_fg+4 ) );
+   ui_text( ctx, label, disclaimer_text, 1, k_ui_align_middle_left, ui_colour( ctx, k_ui_fg+4 ) );
 }
 
 static void workshop_form_gui_sidebar( ui_context *ctx, ui_rect sidebar )
@@ -1472,7 +1430,8 @@ static void workshop_form_gui_sidebar( ui_context *ctx, ui_rect sidebar )
 void workshop_form_gui( ui_context *ctx )
 {
    enum workshop_form_page stable_page = workshop_form.page;
-   if( stable_page == k_workshop_form_hidden ) return;
+   if( stable_page == k_workshop_form_hidden ) 
+      return;
 
    ui_rect null;
    ui_rect screen = { 0, 0, vg.window_x, vg.window_y };
@@ -1486,20 +1445,7 @@ void workshop_form_gui( ui_context *ctx )
    ui_rect title, panel;
    ui_split( window, k_ui_axis_h, 28, 0, title, panel );
    ui_fill( ctx, title, ui_colour( ctx, k_ui_bg+7 ) );
-   ui_text( ctx, title, "Workshop tool", 1, k_ui_align_middle_center, 
-            ui_colourcont( ctx, k_ui_bg+7 ) );
-
-   ui_rect quit_button;
-   ui_split( title, k_ui_axis_v, title[2]-title[3], 2, title, quit_button );
-
-   if( vg_loader_availible() )
-   {
-      if( ui_button_text( ctx, quit_button, "X", 1 ) == 1 )
-      {
-         workshop_quit_form();
-         return;
-      }
-   }
+   ui_text( ctx, title, "Workshop tool", 1, k_ui_align_middle_center, ui_colourcont( ctx, k_ui_bg+7 ) );
 
    /* 
     * temporary operation blinders, we don't yet have a nice way to show the
@@ -1531,6 +1477,16 @@ void workshop_form_gui( ui_context *ctx )
       ui_text( ctx, panel, op_string, 1, k_ui_align_middle_center, 0 );
       return;
    }
+   else
+   {
+      ui_rect quit_button;
+      ui_split( title, k_ui_axis_v, title[2]-title[3], 2, title, quit_button );
+      if( ui_button_text( ctx, quit_button, "X", 1 ) == 1 )
+      {
+         workshop_quit_form();
+         return;
+      }
+   }
 
    /* re draw board preview if need to */
    if( (stable_page == k_workshop_form_edit) && 
@@ -1605,6 +1561,7 @@ void workshop_form_gui( ui_context *ctx )
  * -----------------------------------------------------------------------------
  */
 
+#if 0
 void async_workshop_get_filepath( void *data, u32 len )
 {
    struct async_workshop_filepath_info *info = data;
@@ -1613,31 +1570,10 @@ void async_workshop_get_filepath( void *data, u32 len )
    u32 _ts;
 
    ISteamUGC *hSteamUGC = SteamAPI_SteamUGC();
-   if( !SteamAPI_ISteamUGC_GetItemInstallInfo( hSteamUGC, info->id, &_size,
-                                               info->buf, info->len, &_ts ))
+   if( !SteamAPI_ISteamUGC_GetItemInstallInfo( hSteamUGC, info->id, &_size, info->buf, info->len, &_ts ))
    {
       vg_error( "GetItemInstallInfo failed\n" );
       info->buf[0] = '\0';
    }
 }
-
-void async_workshop_get_installed_files( void *data, u32 len )
-{
-   struct async_workshop_installed_files_info *info = data;
-
-   ISteamUGC *hSteamUGC = SteamAPI_SteamUGC();
-   u32 count = SteamAPI_ISteamUGC_GetSubscribedItems( hSteamUGC, info->buffer,
-                                                      *info->len );
-
-   vg_info( "Found %u subscribed items\n", count );
-
-   u32 j=0;
-   for( u32 i=0; i<count; i++ ){
-      u32 state = SteamAPI_ISteamUGC_GetItemState( hSteamUGC, info->buffer[i] );
-      if( state & k_EItemStateInstalled ){
-         info->buffer[j ++] = info->buffer[i];
-      }
-   }
-
-   *info->len = j;
-}
+#endif
index 14b2d23bc476b7530ca60c8d301eb68291108859..c644fce38f769d38898c03771838ef66cf7f97bc 100644 (file)
@@ -27,8 +27,10 @@ struct async_workshop_metadata_info{
 
 #define WORKSHOP_VIEW_PER_PAGE 15
 
-struct workshop_form{
-   enum workshop_op {
+struct workshop_form
+{
+   enum workshop_op 
+   {
       k_workshop_op_none,
       k_workshop_op_downloading_submission,
       k_workshop_op_publishing_update,
@@ -36,7 +38,8 @@ struct workshop_form{
    }
    op;
 
-   struct {
+   struct 
+   {
       char title[80];
       char description[512];
       char author[32];
@@ -52,7 +55,8 @@ struct workshop_form{
    } 
    submission;
 
-   enum workshop_form_page{
+   enum workshop_form_page
+   {
       k_workshop_form_hidden, 
       k_workshop_form_open,      /* open but not looking at anything */
       k_workshop_form_edit,      /* editing a submission */
index 2cd84c147e68febc26cea208e7bce76c898e515f..ba08fd8c5250daaa99be9114cc36bed52884e530 100644 (file)
@@ -29,11 +29,11 @@ void world_init(void)
    _world.preview_heap = vg_create_linear_allocator( vg_mem.rtmemory, max_size, VG_MEMORY_SYSTEM );
 }
 
-void skaterift_world_get_save_path( addon_reg *world_reg, char buf[128] )
+void skaterift_world_get_save_path( addon_id addon_id, char buf[128] )
 {
-   char id[76];
-   addon_alias_uid( &world_reg->alias, id );
-   snprintf( buf, 128, "savedata/%s.bkv", id );
+   char uid[76];
+   addon_uid( addon_id, uid );
+   snprintf( buf, 128, "savedata/%s.bkv", uid );
 }
 
 void world_update( world_instance *world, v3f pos )
index bd46891367634a5fda5f7714970a5c24cd873ff5..2c8cdcca9210568b4bee359d48bf4ff748d8c322 100644 (file)
@@ -28,7 +28,7 @@ struct leaderboard_cache
 
 typedef struct world_instance world_instance;
 
-void skaterift_world_get_save_path( addon_reg *world_reg, char buf[128] );
+void skaterift_world_get_save_path( addon_id world_id, char buf[128] );
 
 /* submodule headers */
 #include "world_entity.h"
@@ -59,7 +59,7 @@ struct world_instance
 {
    bool complete;
 
-   addon_reg *addon;
+   addon_id addon_id;
    void *heap;
 
    struct
@@ -197,6 +197,7 @@ struct world_instance
 
    /* world geometry */
    scene_context scene_geo,
+                 scene_geo_gpu,
                  scene_no_collide,
                  scene_lines;
 
@@ -235,9 +236,8 @@ struct world_static
    u32 active_trigger_volume_count;
 
    world_instance main, preview_instance;
-   addon_reg *default_hub_addon;
-
-   addon_reg *previous_world_addon;
+   addon_id default_hub_addon,
+            previous_world_addon;
    char nonlocal_destination_key[32];
    bool travelled_through_nonlocal_gate;
    ent_gate copy_of_nonlocal_sender;
@@ -249,11 +249,13 @@ struct world_static
       k_world_loader_unloading_current,
       k_world_loader_ready,
       k_world_loader_loading,
+      k_world_loader_init,
+      k_world_loader_load_savedata,
       k_world_loader_done
    }
    loader_state;
 
-   addon_reg *loader_reg;
+   addon_id load_addon;
    world_instance *loader_instance;
    void *loader_heap;
    bool loader_preview_mode;
index 279667a08f5f4d0edf7de76b96b7d29951ffcd9d..dbc7a48bda385a95ff6b223dce34b382cbd237b8 100644 (file)
@@ -43,9 +43,7 @@ void world_gen_entities_init( world_instance *world )
       light->angle_sin_cos[1] = cosf( light->angle * 0.5f );
    }
 
-   vg_async_call( world_link_gates_async, world, 0 );
-   vg_async_stall();
-
+   world_link_gates( world );
    world->nonlocal_gate_count = 0;
    for( u32 j=0; j<af_arrcount(&world->ent_gate); j ++ )
    {
@@ -69,12 +67,10 @@ void world_gen_entities_init( world_instance *world )
          ent_gate *gate = af_arritm( &world->ent_gate, j );
          if( (gate->flags & k_ent_gate_nonlocal) && (gate->flags & k_ent_gate_linked) )
          {
-            if( gate->addon_reg != 0xffffffff )
+            if( gate->remote_addon_id )
             {
-               addon_reg *reg = get_addon_from_index( k_addon_type_world, gate->addon_reg, 0,0 );
-               
                char cubemap_path[256];
-               nonlocal_gate_cubemap_path( reg, af_str( &world->meta.af, gate->key ), cubemap_path );
+               nonlocal_gate_cubemap_path( gate->remote_addon_id, af_str( &world->meta.af, gate->key ), cubemap_path );
                vg_tex2d_load_qoi_async_file( cubemap_path, VG_TEX2D_CUBEMAP, 
                                              &world->nonlocal_gates_cubemaps[ gate->cubemap_id ] );
             }
index 1b6c9bede1c50138179612864cc5735955506af5..086aef453b72b2d101c85d229a606ff9236b9899 100644 (file)
@@ -310,29 +310,27 @@ entity_call_result ent_gate_call( world_instance *world, ent_call *call )
    }
 }
 
-void nonlocal_gate_cubemap_path( addon_reg *world_addon, const char *gate_key, char path[256] )
+void nonlocal_gate_cubemap_path( addon_id world_addon_id, const char *gate_key, char path[256] )
 {
-   char id[76];
-   addon_alias_uid( &world_addon->alias, id );
+   char uid[76];
+   addon_uid( world_addon_id, uid );
 
    vg_str path_str;
    vg_strnull( &path_str, path, 256 );
    vg_strcat( &path_str, "maps/" );
-   vg_strcat( &path_str, id );
+   vg_strcat( &path_str, uid );
    vg_strcat( &path_str, "-cm-" );
    vg_strcat( &path_str, gate_key );
    vg_strcat( &path_str, ".qoi" );
 }
 
-/*
- * This has to be synchronous because main thread looks at gate data for 
- * rendering, and we modify gates that the main thread has ownership of.
+/* NOTE: This used to be async'd to main thread. But isn't anymore. I think the reason was because some gates would 
+ *       refresh / relink sometimes. But now it should be OK to do in the loader.
  */
-void world_link_gates_async( void *payload, u32 size )
+void world_link_gates( world_instance *world )
 {
-   VG_ASSERT( vg_thread_purpose() == k_thread_purpose_main );
+   THREAD_1;
 
-   world_instance *world = payload;
    bool found_nonlocal_reciever = 0;
 
    for( u32 j=0; j<af_arrcount(&world->ent_gate); j ++ )
@@ -352,16 +350,14 @@ void world_link_gates_async( void *payload, u32 size )
             addon_alias q;
             addon_uid_to_alias( dest_world, &q );
 
-            gate->addon_reg = addon_match( &q );
-            if( gate->addon_reg != 0xffffffff )
+            gate->remote_addon_id = _get_addon_by_alias( &q );
+            if( gate->remote_addon_id )
             {
                gate->flags |= k_ent_gate_linked;
-               vg_info( "Linked non-local gate to addon #%u\n", gate->addon_reg );
+               vg_info( "Linked non-local gate to addon #%u\n", (u32)gate->remote_addon_id );
             }
             else
-            {
                vg_error( "Reference in non-local gate to other world '%s' was not found.\n", dest_world );
-            }
          }
 
          if( _world.travelled_through_nonlocal_gate )
@@ -401,17 +397,14 @@ void world_link_gates_async( void *payload, u32 size )
                   
                   if( !(_world.copy_of_nonlocal_sender.flags & k_ent_gate_no_linkback) )
                   {
-                     gate->addon_reg = get_index_from_addon( k_addon_type_world, _world.previous_world_addon,0,0 );
-
-                     if( gate->addon_reg != 0xffffffff )
+                     gate->remote_addon_id = _world.previous_world_addon;
+                     if( gate->remote_addon_id )
                      {
                         gate->flags |= k_ent_gate_linked;
-                        vg_info( "Linked non-local gate to addon #%u\n", gate->addon_reg );
+                        vg_info( "Linked non-local gate to addon #%u\n", gate->remote_addon_id );
                      }
                      else
-                     {
                         vg_error( "Error while linking to previous world.\n" );
-                     }
                   }
                }
             }
@@ -421,7 +414,8 @@ void world_link_gates_async( void *payload, u32 size )
 
    if( _world.travelled_through_nonlocal_gate && !found_nonlocal_reciever )
    {
-      vg_error( "Player travelled through non-local gate, but no reciever gate was found. Player will default to start spawn or world save file.\n" );
+      vg_error( "Player travelled through non-local gate, but no reciever gate was found.\n"
+                "Player will default to start spawn or world save file.\n" );
       _world.travelled_through_nonlocal_gate = 0;
    }
 }
index 20f60426eecd0d439177d4701a5f2efffbec1276..135d8568c77643cd23738a97b695bc2ff825426f 100644 (file)
@@ -22,7 +22,7 @@ extern world_gates;
 void world_gates_init(void);
 void gate_transform_update( ent_gate *gate );
 int render_gate( world_instance *world, world_instance *world_inside,
-                    ent_gate *gate, vg_camera *cam, vg_framebuffer *target_fb );
+                 ent_gate *gate, vg_camera *cam, vg_framebuffer *target_fb );
 
 int gate_intersect( ent_gate *gate, v3f pos, v3f last );
 u32 world_intersect_gates( world_instance *world, v3f pos, v3f last );
@@ -30,8 +30,7 @@ u32 world_intersect_gates( world_instance *world, v3f pos, v3f last );
 entity_call_result ent_gate_call( world_instance *world, ent_call *call );
 void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl );
 
-void world_link_gates_async( void *payload, u32 size );
+void world_link_gates( world_instance *world );
 void world_unlink_nonlocal( world_instance *world );
-void render_gate_unlinked( world_instance *world,
-                           ent_gate *gate, vg_camera *cam );
-void nonlocal_gate_cubemap_path( addon_reg *world_addon, const char *gate_key, char path[256] );
+void render_gate_unlinked( world_instance *world, ent_gate *gate, vg_camera *cam );
+void nonlocal_gate_cubemap_path( addon_id world_addon_id, const char *gate_key, char path[256] );
index cd1e5709e9835f38a66237739b44d96165974952..443096be232b0a4d3658de9e35ebb7437aa66948 100644 (file)
@@ -215,7 +215,9 @@ void world_gen_generate_meshes( world_instance *world )
    /* 
     * Compile meshes into the world scenes
     */
-   scene_init( &world->scene_geo, 320000, 1200000 );
+   u32 geo_max_verts = 320000,
+       geo_max_indices = 1200000;
+   scene_init( &world->scene_geo, geo_max_verts, geo_max_indices );
    u32 buf_size = scene_mem_required( &world->scene_geo );
    u8 *buffer = vg_linear_alloc( world->heap, buf_size );
    scene_supply_buffer( &world->scene_geo, buffer );
@@ -235,8 +237,7 @@ void world_gen_generate_meshes( world_instance *world )
       struct world_surface *surf = &world->surfaces[ i ];
 
       if( surf->info.flags & k_material_flag_collision )
-         world_add_all_if_material( midentity, &world->scene_geo, 
-                                    &world->meta, i );
+         world_add_all_if_material( midentity, &world->scene_geo, &world->meta, i );
 
       scene_copy_slice( &world->scene_geo, &surf->sm_geo );
       scene_set_vertex_flags( &world->scene_geo, 
@@ -245,29 +246,31 @@ void world_gen_generate_meshes( world_instance *world )
                               (u16)(surf->info.flags & 0xffff) );
    }
 
-   /* compress that bad boy */
+   /* reduce down to minimum size */
    u32 new_vert_max = world->scene_geo.vertex_count,
        new_vert_size = vg_align8(new_vert_max*sizeof(scene_vert)),
        new_indice_len = world->scene_geo.indice_count*sizeof(u32);
-
    u32 *src_indices = world->scene_geo.arrindices,
        *dst_indices = (u32 *)(buffer + new_vert_size);
-
    memmove( dst_indices, src_indices, new_indice_len );
 
    world->scene_geo.max_indices = world->scene_geo.indice_count;
    world->scene_geo.max_vertices = world->scene_geo.vertex_count;
    buf_size = scene_mem_required( &world->scene_geo );
-
    buffer = vg_linear_resize( world->heap, buffer, buf_size );
 
    world->scene_geo.arrvertices = (scene_vert *)(buffer);
    world->scene_geo.arrindices = (u32 *)(buffer + new_vert_size);
 
-   scene_upload_async( &world->scene_geo, &world->mesh_geo );
-
-   /* need send off the memory to the gpu before we can create the bvh. */
-   vg_async_stall();
+   /* create a copy for the GPU (bvh scrambles the data) */
+   scene_context *gpu_scene = &world->scene_geo_gpu;
+   vg_async_task *task = scene_alloc_async( gpu_scene, &world->mesh_geo, geo_max_verts, geo_max_indices );
+   memcpy( gpu_scene->arrvertices, world->scene_geo.arrvertices, world->scene_geo.vertex_count*sizeof(scene_vert) );
+   memcpy( gpu_scene->arrindices, world->scene_geo.arrindices, world->scene_geo.indice_count*sizeof(u32) );
+   gpu_scene->vertex_count = world->scene_geo.vertex_count;
+   gpu_scene->indice_count = world->scene_geo.indice_count;
+   box_copy( world->scene_geo.bbx, gpu_scene->bbx );
+   vg_async_task_dispatch( task, async_scene_upload );
 
    if( !_world.loader_preview_mode )
    {
@@ -280,10 +283,7 @@ void world_gen_generate_meshes( world_instance *world )
     * ----------------------------------------------------------------
     */
    vg_info( "Generating non-collidable geometry\n" );
-
-   vg_async_item *call = scene_alloc_async( &world->scene_no_collide,
-                                            &world->mesh_no_collide,
-                                            250000, 500000 );
+   vg_async_task *task2 = scene_alloc_async( &world->scene_no_collide, &world->mesh_no_collide, 250000, 500000 );
 
    for( u32 i=0; i<world->surface_count; i++ )
    {
@@ -374,7 +374,7 @@ void world_gen_generate_meshes( world_instance *world )
    }
 
 IL_UPLOAD:
-   vg_async_dispatch( call, async_scene_upload );
+   vg_async_task_dispatch( task2, async_scene_upload );
 }
 
 /* signed distance function for cone */
@@ -391,23 +391,20 @@ static f32 fsd_cone_infinite( v3f p, v2f c )
    return d * ((q[0]*c[1]-q[1]*c[0]<0.0f)?-1.0f:1.0f);
 }
 
-struct light_indices_upload_info{
+struct light_indices_upload_info
+{
    world_instance *world;
    v3i count;
-
-   void *data;
+   u8 data[];
 };
-
-/*
- * Async reciever to buffer light index data 
- */
-static void async_upload_light_indices( void *payload, u32 size ){
-   struct light_indices_upload_info *info = payload;
+static void async_upload_light_indices_task( vg_async_task *task )
+{
+   THREAD_0;
+   struct light_indices_upload_info *info = (void *)task->data;
 
    glGenTextures( 1, &info->world->tex_light_cubes );
    glBindTexture( GL_TEXTURE_3D, info->world->tex_light_cubes );
-   glTexImage3D( GL_TEXTURE_3D, 0, GL_RG32UI,
-                 info->count[0], info->count[1], info->count[2],
+   glTexImage3D( GL_TEXTURE_3D, 0, GL_RG32UI, info->count[0], info->count[1], info->count[2],
                  0, GL_RG_INTEGER, GL_UNSIGNED_INT, info->data );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
@@ -464,14 +461,13 @@ void world_gen_compute_light_indices( world_instance *world )
 
    int total_cubes = icubes_count[0]*icubes_count[1]*icubes_count[2];
 
-   u32 data_size = vg_align8(total_cubes*sizeof(u32)*2),
-       hdr_size  = vg_align8(sizeof(struct light_indices_upload_info));
+   u32 data_size = total_cubes*sizeof(u32)*2;
 
-   vg_async_item *call = vg_async_alloc( data_size + hdr_size );
-   struct light_indices_upload_info *info = call->payload;
-   info->data = ((u8*)call->payload) + hdr_size;
+   vg_async_task *task = 
+      vg_allocate_async_task( &vg.main_tasks, sizeof(struct light_indices_upload_info) + data_size, 1 );
+   struct light_indices_upload_info *info = (void *)task->data;
    info->world = world;
-   u32 *cubes_index = info->data;
+   u32 *cubes_index = (void *)info->data;
 
    for( int i=0; i<3; i++ )
       info->count[i] = icubes_count[i];
@@ -483,9 +479,12 @@ void world_gen_compute_light_indices( world_instance *world )
 
    float bound_radius = v3_length( cube_size );
 
-   for( int iz = 0; iz<icubes_count[2]; iz ++ ){
-      for( int iy = 0; iy<icubes_count[1]; iy++ ){
-         for( int ix = 0; ix<icubes_count[0]; ix++ ){
+   for( int iz = 0; iz<icubes_count[2]; iz ++ )
+   {
+      for( int iy = 0; iy<icubes_count[1]; iy++ )
+      {
+         for( int ix = 0; ix<icubes_count[0]; ix++ )
+         {
             boxf bbx;
             v3_div( (v3f){ ix, iy, iz }, world->ub_lighting.g_cube_inv_range, 
                   bbx[0] );
@@ -506,7 +505,8 @@ void world_gen_compute_light_indices( world_instance *world )
             float influences[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
             const int N = VG_ARRAY_LEN( influences );
 
-            for( u32 j=0; j<af_arrcount(&world->ent_light); j ++ ){
+            for( u32 j=0; j<af_arrcount(&world->ent_light); j ++ )
+            {
                ent_light *light = af_arritm( &world->ent_light, j );
                v3f closest;
                closest_point_aabb( light->transform.co, bbx, closest );
@@ -519,7 +519,8 @@ void world_gen_compute_light_indices( world_instance *world )
                f32 dist = sqrtf(dist2),
                    influence = 1.0f/(dist+1.0f);
 
-               if( light->type == k_light_type_spot){
+               if( light->type == k_light_type_spot)
+               {
                   v3f local;
                   m4x3_mulv( light->inverse_world, center, local );
 
@@ -534,8 +535,10 @@ void world_gen_compute_light_indices( world_instance *world )
                   if( influence > influences[k] )
                      best_pos = k;
 
-               if( best_pos < N ){
-                  for( int k=N-1; k>best_pos; k -- ){
+               if( best_pos < N )
+               {
+                  for( int k=N-1; k>best_pos; k -- )
+                  {
                      influences[k] = influences[k-1];
                      indices[k] = indices[k-1];
                   }
@@ -571,16 +574,16 @@ void world_gen_compute_light_indices( world_instance *world )
       }
    }
 
-   vg_async_dispatch( call, async_upload_light_indices );
+   vg_async_task_dispatch( task, async_upload_light_indices_task );
 }
 
 /*
  * Rendering pass needed to complete the world
  */
-void async_world_postprocess( void *payload, u32 _size )
+void async_world_postprocess( void *userdata )
 {
    /* create scene lighting buffer */
-   world_instance *world = payload;
+   world_instance *world = userdata;
 
    u32 size = VG_MAX(af_arrcount(&world->ent_light),1) * sizeof(float)*12;
    vg_info( "Upload %ubytes (lighting)\n", size );
@@ -598,14 +601,16 @@ void async_world_postprocess( void *payload, u32 _size )
     */
 
    v4f *light_dst = glMapBuffer( GL_TEXTURE_BUFFER, GL_WRITE_ONLY );
-   for( u32 i=0; i<af_arrcount(&world->ent_light); i++ ){
+   for( u32 i=0; i<af_arrcount(&world->ent_light); i++ )
+   {
       ent_light *light = af_arritm( &world->ent_light, i );
 
       /* colour  + night */
       v3_muls( light->colour, light->colour[3] * 2.0f, light_dst[i*3+0] );
       light_dst[i*3+0][3] = 2.0f;
 
-      if( !light->daytime ){
+      if( !light->daytime )
+      {
          u32 hash = (i * 29986577u) & 0xffu;
          float switch_on = hash;
                switch_on *= (1.0f/255.0f);
@@ -685,13 +690,13 @@ void async_world_postprocess( void *payload, u32 _size )
 
    /* upload full buffer */
    glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
-   glBufferSubData( GL_UNIFORM_BUFFER, 0, 
-                    sizeof(struct ub_world_lighting), &world->ub_lighting );
+   glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), &world->ub_lighting );
 
    /*
     * Allocate cubemaps
     */
-   for( u32 i=0; i<af_arrcount(&world->ent_cubemap); i++ ){
+   for( u32 i=0; i<af_arrcount(&world->ent_cubemap); i++ )
+   {
       ent_cubemap *cm = af_arritm(&world->ent_cubemap,i);
 
       glGenTextures( 1, &cm->texture_id );
@@ -702,9 +707,9 @@ void async_world_postprocess( void *payload, u32 _size )
                glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
                glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
 
-               for( u32 j=0; j<6; j ++ ) {
-                       glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, 0, GL_RGB, 
-                        WORLD_CUBEMAP_RES, WORLD_CUBEMAP_RES, 
+               for( u32 j=0; j<6; j ++ ) 
+      {
+                       glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, 0, GL_RGB, WORLD_CUBEMAP_RES, WORLD_CUBEMAP_RES, 
                         0, GL_RGB, GL_UNSIGNED_BYTE, NULL );
                }
 
@@ -712,17 +717,14 @@ void async_world_postprocess( void *payload, u32 _size )
                glBindFramebuffer( GL_FRAMEBUFFER, cm->framebuffer_id );
                glGenRenderbuffers(1, &cm->renderbuffer_id );
                glBindRenderbuffer( GL_RENDERBUFFER, cm->renderbuffer_id );
-               glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 
-                              WORLD_CUBEMAP_RES, WORLD_CUBEMAP_RES );
-               glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
-                                 GL_RENDERBUFFER, cm->renderbuffer_id );
+               glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, WORLD_CUBEMAP_RES, WORLD_CUBEMAP_RES );
+               glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cm->renderbuffer_id );
 
                glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
          GL_TEXTURE_CUBE_MAP_POSITIVE_X, cm->texture_id, 0 );
 
-               if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE ){
+               if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE )
          vg_error( "Cubemap framebuffer incomplete.\n" );
-      }
    }
 
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
index c6ffb9227f8f35eb87dc44f4d76883a1aff8f09a..8e65780fa1af85aff6623ea3a782cd22f149d907 100644 (file)
@@ -12,4 +12,4 @@ void world_init_blank( world_instance *world );
 void world_gen_load_surfaces( world_instance *world );
 void world_gen_generate_meshes( world_instance *world );
 void world_gen_compute_light_indices( world_instance *world );
-void async_world_postprocess( void *payload, u32 _size );
+void async_world_postprocess( void *userdata );
index 5ba1246bcbf7b8febd6360d80f8615c92237728d..c23357dc9d0f6aa69c3c9df66e5a8660caa2e489 100644 (file)
@@ -216,36 +216,47 @@ static void world_instance_load_mdl( world_instance *world, const char *path, vo
       ent_script_alloc( world, heap );
 
       vg_loader_set_user_information( "Postprocessing world" );
-      vg_async_call( async_world_postprocess, world, 0 );
-      vg_async_stall();
+      vg_async_call( &vg.main_tasks, async_world_postprocess, world );
    }
-
-   vg_loader_set_user_information( NULL );
 }
 
-static void async_world_loader_done( void *payload, u32 size )
+static void async_world_loader_done( void *userdata )
 {
-   _world.loader_state = k_world_loader_done;
+   THREAD_0;
+   _world.loader_state = k_world_loader_init;
    _world.loader_instance->complete = 1;
+
+   if( !_world.loader_preview_mode )
+      menu_on_world_change( _world.main.addon_id );
 }
 
-void skaterift_world_load_thread( void *_ )
+struct world_load_info
+{
+   bool OK;
+   char path[4096];
+};
+void skaterift_world_load_t1( vg_async_task *task )
 {
+   THREAD_1;
+   struct world_load_info *info = (void *)task->data;
+
+   if( !info->OK )
+      return;
+
    vg_loader_set_user_information( "Scanning world directory" );
 
-   addon_reg *reg = _world.loader_reg;
-   _world.loader_instance->addon = reg;
+   addon_reg *reg = addon_details( _world.load_addon );
+   _world.loader_instance->addon_id = _world.load_addon;
 
    char uid[ADDON_UID_MAX];
-   addon_alias_uid( &_world.loader_reg->alias, uid );
-   vg_info( "LOAD WORLD %s @%d\n", uid );
+   addon_alias_uid( &reg->alias, uid );
+   vg_info( "LOAD WORLD %s\n", uid );
 
-   char path_buf[4096];
+   char path_buf[ 4096 ];
    vg_str path;
-   vg_strnull( &path, path_buf, 4096 );
-
-   addon_get_content_folder( reg, &path, 1 );
-
+   vg_strnull( &path, path_buf, sizeof( path_buf ) );
+   vg_strcat( &path, info->path );
+   
    vg_str folder = path;
    if( !vg_strgood( &folder ) ) 
    {
@@ -320,26 +331,25 @@ void skaterift_world_load_thread( void *_ )
    }
 
    world_instance_load_mdl( _world.loader_instance, mdl_path, _world.loader_heap );
-
-   vg_async_call( async_world_loader_done, NULL, 0 );
-   vg_async_stall();
+   vg_async_call( &vg.main_tasks, async_world_loader_done, NULL );
 }
 
-struct world_savedata_thread_data
+struct world_savedata_info
 {
    savedata_file save;
    world_instance *instance;
 };
 
-void async_start_player_from_worldsave( void *payload, u32 size )
+void async_worldsave_go( vg_async_task *task )
 {
-   struct world_savedata_thread_data *data = payload;
+   THREAD_0;
+   struct world_savedata_info *info = (void *)task->data;
 
    vg_msg sav;
-   vg_msg_init( &sav, data->save.buf, data->save.len );
+   vg_msg_init( &sav, info->save.buf, info->save.len );
 
    /* start entities in the world */
-   world_entity_start( data->instance, &sav );
+   world_entity_start( info->instance, &sav );
 
    /* start player in the world */
    if( _world.travelled_through_nonlocal_gate )
@@ -352,7 +362,7 @@ void async_start_player_from_worldsave( void *payload, u32 size )
    {
       bool restored_player_position = 0;
 
-      vg_msg_init( &sav, data->save.buf, data->save.len );
+      vg_msg_init( &sav, info->save.buf, info->save.len );
       vg_msg player_frame = sav;
       if( vg_msg_seekframe( &player_frame, "player" ) )
       {
@@ -361,61 +371,52 @@ void async_start_player_from_worldsave( void *payload, u32 size )
       }
 
       if( !restored_player_position )
-         world_default_spawn_pos( data->instance, localplayer.rb.co );
+         world_default_spawn_pos( info->instance, localplayer.rb.co );
 
       player__reset();
    }
 
    network_send_item( k_netmsg_playeritem_world0 );
+   _world.loader_state = k_world_loader_done;
+   _world.load_addon = 0;
+   g_client.unreadyness --;
 }
 
-void load_player_from_world_savedata_thread( void *_ )
+void load_world_savedata_t1( void *userdata )
 {
-   vg_async_item *call = vg_async_alloc( sizeof(struct world_savedata_thread_data) );
-   struct world_savedata_thread_data *data = call->payload;
-
-   data->instance = _world.loader_instance;
-   skaterift_world_get_save_path( _world.loader_reg, data->save.path );
-   savedata_file_read( &data->save );
-
-   vg_async_dispatch( call, async_start_player_from_worldsave );
-   vg_async_stall();
+   THREAD_1;
+   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct world_savedata_info), 1 );
+   struct world_savedata_info *info = (void *)task->data;
+
+   info->instance = _world.loader_instance;
+   skaterift_world_get_save_path( _world.load_addon, info->save.path );
+   savedata_file_read( &info->save );
+   vg_async_task_dispatch( task, async_worldsave_go );
 }
 
-void async_world_switcher_done( void *payload, u32 size )
+vg_async_task *world_load_go(void)
 {
-   _world.loader_reg = NULL;
-
-   if( !_world.loader_preview_mode )
-      g_client.unreadyness --;
-}
-
-void world_switcher_thread( void *_ )
-{
-   skaterift_world_load_thread( NULL );
-   vg_async_stall();
-
-   if( !_world.loader_preview_mode )
-   {
-      load_player_from_world_savedata_thread( NULL );
-      vg_async_stall();
-   }
-
-   vg_async_call( async_world_switcher_done, NULL, 0 );
+   THREAD_0;
+   _world.loader_state = k_world_loader_loading;
+   vg_linear_clear( _world.loader_heap );
+   vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct world_load_info), 1 );
+   struct world_load_info *info = (void *)task->data;
+   vg_str folder_str;
+   vg_strnull( &folder_str, info->path, sizeof(info->path) );
+   info->OK = addon_get_content_folder( _world.load_addon, &folder_str );
+   return task;
 }
 
 void world_switcher_update(void)
 {
-   if( !_world.loader_reg )
+   if( !_world.load_addon )
       return;
 
    if( _world.loader_state == k_world_loader_saving_current )
    {
-      if( skaterift_write_all_savedata(1) )
-      {
-         _world.loader_state = k_world_loader_unloading_current;
-         vg_loader_set_user_information( "Unloading current world" );
-      }
+      skaterift_write_all_savedata(1);
+      _world.loader_state = k_world_loader_unloading_current;
+      vg_loader_set_user_information( "Unloading current world" );
    }
 
    /* pre-load step aka waiting for audio to end. */
@@ -432,18 +433,26 @@ void world_switcher_update(void)
 
    if( _world.loader_state == k_world_loader_ready )
    {
-      if( vg_loader_availible() )
-      {
-         _world.loader_state = k_world_loader_loading;
+      vg_async_task *task = world_load_go();
+      vg_async_task_dispatch( task, skaterift_world_load_t1 );
+   }
 
-         vg_linear_clear( vg_async.buffer );
-         vg_linear_clear( _world.loader_heap );
-         vg_loader_start( world_switcher_thread, NULL );
+   if( _world.loader_state == k_world_loader_init )
+   {
+      if( _world.loader_preview_mode )
+      {
+         _world.load_addon = 0;
+         _world.loader_state = k_world_loader_done;
+      }
+      else
+      {
+         _world.loader_state = k_world_loader_load_savedata;
+         vg_async_call( &vg.loader_tasks, load_world_savedata_t1, NULL );
       }
    }
 }
 
-void skaterift_load_world_start( addon_reg *reg, bool preview )
+void skaterift_load_world_start( addon_id addon_id, bool preview )
 {
    if( g_client.unreadyness )
    {
@@ -459,12 +468,10 @@ void skaterift_load_world_start( addon_reg *reg, bool preview )
 
    world_instance *world = preview? &_world.preview_instance: &_world.main;
 
-   if( !reg )
+   if( !addon_id )
    {
-      if( world->addon )
-      {
-         reg = world->addon;
-      }
+      if( world->addon_id )
+         addon_id = world->addon_id;
       else
       {
          vg_error( "Loaded world has no associated addon registration, can't reload this!\n" );
@@ -474,8 +481,8 @@ void skaterift_load_world_start( addon_reg *reg, bool preview )
    
    if( !preview )
    {
-      if( reg != world->addon )
-         _world.previous_world_addon = _world.main.addon;
+      if( addon_id != world->addon_id )
+         _world.previous_world_addon = _world.main.addon_id;
 
       g_client.unreadyness ++;
       _world.loader_state = k_world_loader_saving_current;
@@ -486,7 +493,7 @@ void skaterift_load_world_start( addon_reg *reg, bool preview )
       _world.loader_state = k_world_loader_ready;
 
    char buf[76];
-   addon_alias_uid( &reg->alias, buf );
+   addon_uid( addon_id, buf );
    vg_info( "loading world: %s %s\n", buf, preview? "(preview mode)": "" );
 
    vg_linear_clear( vg_mem.scratch ); /* ?? */
@@ -511,13 +518,15 @@ void skaterift_load_world_start( addon_reg *reg, bool preview )
    _world.loader_instance = world;
    _world.loader_heap = preview? _world.preview_heap: _world.heap;
    _world.loader_preview_mode = preview;
-   _world_loader_set_target_reg( reg );
+   _world_loader_set_addon( addon_id );
 }
 
-void _world_loader_set_target_reg( addon_reg *reg )
+void _world_loader_set_addon( addon_id addon_id )
 {
    strcpy( _world.loader_filename, "main.mdl" );
-   _world.loader_reg = reg;
+   _world.load_addon = addon_id;
+
+   addon_reg *reg = addon_details(addon_id);
    if( reg->flags & ADDON_REG_MTZERO )
    {
       u64 status = _skaterift_script_nugget_status( "ch2s5_view" );
@@ -538,7 +547,7 @@ int skaterift_load_world_command( int argc, const char *argv[] )
    {
       if( !strcmp( argv[0], "reload" ) )
       {
-         skaterift_load_world_start( NULL, 0 );
+         skaterift_load_world_start( 0, 0 );
          return 0;
       }
 
@@ -551,30 +560,28 @@ int skaterift_load_world_command( int argc, const char *argv[] )
       addon_alias q;
       addon_uid_to_alias( argv[0], &q );
 
-      u32 reg_id = addon_match( &q );
-      if( reg_id != 0xffffffff )
+      addon_id addon_id = _get_addon_by_alias( &q );
+      if( addon_id )
       {
-         addon_reg *reg = get_addon_from_index( k_addon_type_world, reg_id, 0,0 );
-         menu_on_world_change( reg );
-         skaterift_load_world_start( reg, 0 );
+         skaterift_load_world_start( addon_id, 0 );
       }
       else 
-      {
          vg_error( "Addon '%s' is not installed or not found.\n", argv[0] );
-      }
    }
    else 
    {
       vg_info( "worlds availible to load:\n" );
-         
-      for( int i=0; i<addon_count(k_addon_type_world,0,0); i ++ )
+
+      u32 count = _addon_filtered_count( k_addon_type_world,0,0 ); 
+      for( int i=0; i<count; i ++ )
       {
-         addon_reg *w = get_addon_from_index( k_addon_type_world, i, 0,0);
+         addon_id ai = _addon_get_filtered( k_addon_type_world, i, 0,0 );
+         addon_reg *reg = addon_details(ai);
 
          char buf[ADDON_UID_MAX];
-         addon_alias_uid( &w->alias, buf );
+         addon_alias_uid( &reg->alias, buf );
 
-         if( w->flags & ADDON_REG_HIDDEN )
+         if( reg->flags & ADDON_REG_HIDDEN )
             vg_info( "  %s [hidden]\n", buf );
          else
             vg_info( "  %s\n", buf );
index 361ce37906e0b46d57900025a7cafff3789b296c..76f98136773d54563501da46935614b95a03d432 100644 (file)
@@ -5,8 +5,9 @@
 #include "addon.h"
 
 int skaterift_load_world_command( int argc, const char *argv[] );
-void skaterift_load_world_start( addon_reg *reg, bool preview_mode );
-void _world_loader_set_target_reg( addon_reg *reg );
+void skaterift_load_world_start( addon_id addon, bool preview_mode );
+void _world_loader_set_addon( addon_id addon );
 void world_switcher_update(void);
-void world_switcher_thread( void *_ );
 void world_instance_free_graphics_data( world_instance *world );
+vg_async_task *world_load_go(void);
+void skaterift_world_load_t1( vg_async_task *task );
index 8dd0dd9aa2cd717ff9f2aad87378f1bd64f87e00..6253eee59ac47c3e68ba450dda8dd9760cf375b4 100644 (file)
@@ -713,7 +713,7 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
 
 
       title_text = menu.clicked_world_name? menu.clicked_world_name: "...";
-      subtitle_text = (menu.clicked_world_reg == _world.main.addon)? "Current Location": NULL;
+      subtitle_text = (menu.clicked_world_id == _world.main.addon_id)? "Current Location": NULL;
 
       ctx->font = &vgf_default_title;
       upper_title[2] = ui_text_line_width(ctx,title_text) + 24;
@@ -824,13 +824,13 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
 
       for( u32 i=0; i<menu.world_list_display_count; i ++ )
       {
-         addon_reg *reg = menu.world_list_entries[i];
-
+         addon_id addon_id = menu.world_list_entries[i];
          bool clickable = 1;
          
-         if( reg )
+         if( addon_id )
          {
-            bool selected = reg == menu.clicked_world_reg;
+            addon_reg *reg = addon_details( addon_id );
+            bool selected = addon_id == menu.clicked_world_id;
             if( selected )
             {
                ui_rect sel_box, _null;
@@ -840,13 +840,11 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
             clickable = !selected;
          }
          else
-         {
             clickable = 0;
-         }
 
          if( menu_button( ctx, panel, R == (page_base + i), clickable, menu.world_list_names[i] ) )
          {
-            menu.clicked_world_reg = reg;
+            menu.clicked_world_id = addon_id;
             menu.clicked_world_name = menu.world_list_names[i];
          }
       }
@@ -860,20 +858,20 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
          menu_update_world_list();
       }
 
-      if( (_world.loader_state == k_world_loader_done) && (menu.clicked_world_reg) )
+      if( (_world.loader_state == k_world_loader_done) && (menu.clicked_world_id) )
       {
          bool do_load = 0;
          
          if( _world.preview_instance.complete ) 
          {
-            if( _world.preview_instance.addon != menu.clicked_world_reg )
+            if( _world.preview_instance.addon_id != menu.clicked_world_id )
                do_load = 1;
          }
          else
             do_load = 1;
 
          if( do_load )
-            skaterift_load_world_start( menu.clicked_world_reg, 1 );
+            skaterift_load_world_start( menu.clicked_world_id, 1 );
       }
 
       ctx->font = &vgf_default_title;
@@ -891,16 +889,16 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
          vg_input_string( &enter_helper, input_button_list[k_srbind_mhub], 1 );
 
       bool enter_location = 0;
-      if( menu_button( ctx, enter_world_box, 0, menu.clicked_world_reg?1:0, buf ) )
+      if( menu_button( ctx, enter_world_box, 0, menu.clicked_world_id?1:0, buf ) )
          enter_location = 1;
 
       if( button_down( k_srbind_mhub ) )
          enter_location = 1;
 
-      if( enter_location && menu.clicked_world_reg )
+      if( enter_location && menu.clicked_world_id )
       {
-         if( menu.clicked_world_reg != _world.main.addon )
-            skaterift_load_world_start( menu.clicked_world_reg, 0 );
+         if( menu.clicked_world_id != _world.main.addon_id )
+            skaterift_load_world_start( menu.clicked_world_id, 0 );
 
          world_map.activity = k_map_activity_local_world;
          world_map.superworld_actual_world = world_map.superworld_list_selected;
index 2e42ba8e47a23099351f5c291e0fe5c791b77754..887f6ae9185e7c4ade32af9fe78a9b8be3968c26 100644 (file)
@@ -29,18 +29,15 @@ static int ccmd_set_time( int argc, const char *argv[] )
    return 0;
 }
 
-static void async_world_render_init( void *payload, u32 size )
+static void async_world_render_init( void *userdata )
 {
    vg_info( "Allocate uniform buffers\n" );
 
    world_instance *world = &_world.main;
    world->ubo_bind_point = 0;
-
    glGenBuffers( 1, &world->ubo_lighting );
    glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
-   glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting), 
-                 NULL, GL_DYNAMIC_DRAW );
-
+   glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting), NULL, GL_DYNAMIC_DRAW );
    glBindBufferBase( GL_UNIFORM_BUFFER, 0, world->ubo_lighting );
 }
 
@@ -86,8 +83,7 @@ void world_render_init(void)
       .attachment     = GL_COLOR_ATTACHMENT0
    };
    vg_framebuffer_create( world->heightmap );
-
-   vg_async_call( async_world_render_init, NULL, 0 );
+   vg_async_call( &vg.main_tasks, async_world_render_init, NULL );
 }
 
 /* 
@@ -1423,94 +1419,89 @@ void render_world_cubemaps( world_instance *world )
    }
 }
 
+// dev
 void render_world_portal_cubemaps(void)
 {
-   if( vg_loader_availible() ) // HACK? 
+   qoi_desc desc = 
    {
-      qoi_desc desc = 
-      {
-         .width = 512,
-         .height = 512*6,
-         .channels = 3,
-         .colorspace = 0
-      };
-
-      vg_linear_clear( vg_async.buffer );
-      u8 *src_image = vg_linear_alloc( vg_async.buffer, 512*512*3*6 );
-      u8 *compressed_image = vg_linear_alloc( vg_async.buffer, vg_query_qoi_storage_size( &desc ) );
-   
-      GLuint temp_tex, temp_fb, temp_rb;
+      .width = 512,
+      .height = 512*6,
+      .channels = 3,
+      .colorspace = 0
+   };
 
-      glGenFramebuffers( 1, &temp_fb );
-      glBindFramebuffer( GL_FRAMEBUFFER, temp_fb );
+   u8 *src_image = malloc( 512*512*3*6 );
+   u8 *compressed_image = malloc( vg_query_qoi_storage_size( &desc ) );
 
-      glGenRenderbuffers( 1, &temp_rb );
-      glBindRenderbuffer( GL_RENDERBUFFER, temp_rb );
-      glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 512, 512 );
-      glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, temp_rb );
+   GLuint temp_tex, temp_fb, temp_rb;
+   glGenFramebuffers( 1, &temp_fb );
+   glBindFramebuffer( GL_FRAMEBUFFER, temp_fb );
 
-      glGenTextures( 1, &temp_tex );
-      glBindTexture( GL_TEXTURE_2D, temp_tex );
-      glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL );
-      glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_tex, 0 );
+   glGenRenderbuffers( 1, &temp_rb );
+   glBindRenderbuffer( GL_RENDERBUFFER, temp_rb );
+   glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 512, 512 );
+   glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, temp_rb );
 
-               if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE )
-      {
-         vg_error( "Cubemap framebuffer incomplete.\n" );
-         return;
-      }
+   glGenTextures( 1, &temp_tex );
+   glBindTexture( GL_TEXTURE_2D, temp_tex );
+   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL );
+   glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_tex, 0 );
 
-      glViewport( 0, 0, 512, 512 );
-      vg_framebuffer temp_vg_framebuffer =
-      {
-         .display_name = NULL,
-         .resolution_div = 0,
-         .fixed_w = 512,
-         .fixed_h = 512,
-         .id = temp_fb,
-         .attachment_count = 0,
-         .attachments = NULL
-      };
+   if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE )
+   {
+      vg_error( "Cubemap framebuffer incomplete.\n" );
+      goto e0;
+   }
 
-      world_instance *world = &_world.main;
+   glViewport( 0, 0, 512, 512 );
+   vg_framebuffer temp_vg_framebuffer =
+   {
+      .display_name = NULL,
+      .resolution_div = 0,
+      .fixed_w = 512,
+      .fixed_h = 512,
+      .id = temp_fb,
+      .attachment_count = 0,
+      .attachments = NULL
+   };
 
-      for( u32 j=0; j<af_arrcount(&world->ent_gate); j ++ )
+   world_instance *world = &_world.main;
+   for( u32 j=0; j<af_arrcount(&world->ent_gate); j ++ )
+   {
+      ent_gate *gate = af_arritm( &world->ent_gate, j );
+      if( gate->flags & k_ent_gate_nonlocal )
       {
-         ent_gate *gate = af_arritm( &world->ent_gate, j );
-         if( gate->flags & k_ent_gate_nonlocal )
-         {
-            v3f co;
-            v3_add( gate->co[0], (v3f){0,2,0}, co );
+         v3f co;
+         v3_add( gate->co[0], (v3f){0,2,0}, co );
 
-            m3x3f rotation;
-            m3x3f correction = {{0,0,1},{0,1,0},{-1,0,0}};
-            m3x3_mul( correction, gate->to_world, rotation );
+         m3x3f rotation;
+         m3x3f correction = {{0,0,1},{0,1,0},{-1,0,0}};
+         m3x3_mul( correction, gate->to_world, rotation );
 
-            for( u32 i=0; i<6; i ++ )
-            {
-               glClear( GL_DEPTH_BUFFER_BIT );
-               render_cubemap_side( &_world.main, co, gate->to_world, i, &temp_vg_framebuffer );
+         for( u32 i=0; i<6; i ++ )
+         {
+            glClear( GL_DEPTH_BUFFER_BIT );
+            render_cubemap_side( &_world.main, co, gate->to_world, i, &temp_vg_framebuffer );
 
-               u8 *dest_side = src_image + i*512*512*3;
-               glReadBuffer( GL_COLOR_ATTACHMENT0 );
-               glReadPixels( 0,0, 512,512, GL_RGB, GL_UNSIGNED_BYTE, dest_side );
-            }
+            u8 *dest_side = src_image + i*512*512*3;
+            glReadBuffer( GL_COLOR_ATTACHMENT0 );
+            glReadPixels( 0,0, 512,512, GL_RGB, GL_UNSIGNED_BYTE, dest_side );
+         }
 
-            char path[256];
-            nonlocal_gate_cubemap_path( world->addon, af_str( &world->meta.af, gate->key ), path );
+         char path[256];
+         nonlocal_gate_cubemap_path( world->addon_id, af_str( &world->meta.af, gate->key ), path );
 
-            int file_size;
-            if( vg_encode_qoi2( src_image, &desc, compressed_image, &file_size ) )
-            {
-               vg_asset_write( path, compressed_image, file_size );
-            }
-         }
+         int file_size;
+         if( vg_encode_qoi2( src_image, &desc, compressed_image, &file_size ) )
+            vg_asset_write( path, compressed_image, file_size );
       }
-
-      glDeleteTextures( 1, &temp_tex );
-      glDeleteFramebuffers( 1, &temp_fb );
-      glDeleteRenderbuffers( 1, &temp_rb );
    }
+
+e0:glDeleteTextures( 1, &temp_tex );
+   glDeleteFramebuffers( 1, &temp_fb );
+   glDeleteRenderbuffers( 1, &temp_rb );
+   free( src_image );
+   free( compressed_image );
 }
 
 static int ccmd_render_portals( int argc, const char *argv[] )
index 940ff4b661e5b836cd151d3627a39cbcce782ef9..6df041205200fc518bdf2b8a60236d2a191bb28a 100644 (file)
@@ -129,15 +129,12 @@ static void world_routes_time_lap( world_instance *world, ent_route *route )
          }
       }
 
-      addon_alias *alias = &_world.main.addon->alias;
-
       char mod_uid[ ADDON_UID_MAX ];
-      addon_alias_uid( alias, mod_uid );
+      addon_uid( _world.main.addon_id, mod_uid );
       network_publish_laptime( mod_uid, af_str( &world->meta.af, route->pstr_name ), lap_time );
    }
 
    route->valid_checkpoints = valid_sections+1;
-
    vg_info( "valid sections: %u\n", valid_sections );
    vg_info( "----------------------------\n" );
 
@@ -509,12 +506,9 @@ struct world_surface *world_tri_index_surface( world_instance *world,
  */
 void world_gen_routes_generate( world_instance *world )
 {
+   THREAD_1;
    vg_info( "Generating route meshes\n" );
-   vg_async_stall();
-
-   vg_async_item *call_scene = scene_alloc_async( &world->scene_lines, 
-                                                  &world->mesh_route_lines,
-                                                  200000, 300000 );
+   vg_async_task *task = scene_alloc_async( &world->scene_lines, &world->mesh_route_lines, 200000, 300000 );
 
    for( u32 i=0; i<af_arrcount(&world->ent_gate); i++ )
    {
@@ -561,11 +555,10 @@ void world_gen_routes_generate( world_instance *world )
       }
    }
 
-   for( u32 i=0; i<af_arrcount(&world->ent_route); i++ ){
+   for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
       world_routes_gen_meshes( world, i, &world->scene_lines );
-   }
 
-   vg_async_dispatch( call_scene, async_scene_upload );
+   vg_async_task_dispatch( task, async_scene_upload );
    world_routes_clear( world );
 }
 
index ecc34181bd8b2cbdf4a3f0b5aae4d2de1fc5f46d..0efdf06960619b4593c5a875d0bd20d00b96ba96 100644 (file)
@@ -226,15 +226,12 @@ void world_sfd_update( world_instance *world, v3f pos )
          {
             board->cache_time = vg.time_real;
             ent_route *route = af_arritm( &world->ent_route, closest );
-            addon_reg *world_reg = _world.main.addon;
 
             char mod_uid[ ADDON_UID_MAX ];
-            addon_alias_uid( &world_reg->alias, mod_uid );
+            addon_uid( _world.main.addon_id, mod_uid );
 
-            network_request_scoreboard( 
-                  mod_uid, 
-                  af_str( &world->meta.af, route->pstr_name ),
-                  NETWORK_LEADERBOARD_ALLTIME_AND_CURRENT_WEEK, closest );
+            network_request_scoreboard( mod_uid, af_str( &world->meta.af, route->pstr_name ),
+                                        NETWORK_LEADERBOARD_ALLTIME_AND_CURRENT_WEEK, closest );
          }
       }
 
@@ -324,7 +321,7 @@ void world_sfd_init(void)
    mdl_load_mesh_block( &mscoreboard, vg_mem.scratch );
 
    scene_context *scene = &world_sfd.scene;
-   vg_async_item *call = scene_alloc_async( scene, &world_sfd.mesh_display, 3000, 8000 );
+   vg_async_task *task = scene_alloc_async( scene, &world_sfd.mesh_display, 3000, 8000 );
 
    mdl_submesh *sm_card = &mscoreboard.submeshes[ mdl_get_submesh_index( &mscoreboard, "score_card" ) ];
    world_sfd.sm_base = mscoreboard.submeshes[ mdl_get_submesh_index( &mscoreboard, "backer" ) ];
@@ -347,11 +344,8 @@ void world_sfd_init(void)
       }
    }
 
-   vg_async_dispatch( call, async_scene_upload );
-   vg_tex2d_load_qoi_async_file( "textures/scoretext.qoi", 
-                                 VG_TEX2D_CLAMP|VG_TEX2D_NEAREST,
-                                 &world_sfd.tex_scoretex );
-
+   vg_async_task_dispatch( task, async_scene_upload );
+   vg_tex2d_load_qoi_async_file( "textures/scoretext.qoi", VG_TEX2D_CLAMP|VG_TEX2D_NEAREST, &world_sfd.tex_scoretex );
    mdl_close( &mscoreboard );
 
    int w = 27,