From: hgn Date: Tue, 15 Apr 2025 20:29:12 +0000 (+0100) Subject: King horrendous X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=6b3b4276ee1b24aad55794191bced3d6bdb69fbd;p=carveJwlIkooP6JGAAIwe30JlM.git King horrendous --- diff --git a/src/addon.c b/src/addon.c index 2ac69d1..c3221f7 100644 --- a/src/addon.c +++ b/src/addon.c @@ -8,7 +8,18 @@ #include "workshop.h" #include -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; typecountalias.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; typecountalias.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; typecountalias.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; counttype]; 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; typecache_count ) { @@ -257,59 +265,73 @@ void addon_system_init( void ) for( i32 j=0; jcache_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; ialias.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; ialias.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; jalias.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; icount; 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; iworkshop_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; icount; 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; typepool.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; typepool.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; typepool.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 ); } + diff --git a/src/addon.h b/src/addon.h index c65524b..2bfdc9c 100644 --- a/src/addon.h +++ b/src/addon.h @@ -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 ); diff --git a/src/addon_types.h b/src/addon_types.h index 5f50d61..2b6e8bb 100644 --- a/src/addon_types.h +++ b/src/addon_types.h @@ -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 diff --git a/src/board_maker.c b/src/board_maker.c index 35ab07a..40ac2a3 100644 --- a/src/board_maker.c +++ b/src/board_maker.c @@ -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 ) { diff --git a/src/client.c b/src/client.c index daedaa5..6d0dbd9 100644 --- a/src/client.c +++ b/src/client.c @@ -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) diff --git a/src/control_overlay.c b/src/control_overlay.c index d6963a2..735bb0b 100644 --- a/src/control_overlay.c +++ b/src/control_overlay.c @@ -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 ) diff --git a/src/ent_region.c b/src/ent_region.c index 35df0b1..94ea1ba 100644 --- a/src/ent_region.c +++ b/src/ent_region.c @@ -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 ) { diff --git a/src/ent_skateshop.c b/src/ent_skateshop.c index 076b3e1..23962f8 100644 --- a/src/ent_skateshop.c +++ b/src/ent_skateshop.c @@ -13,14 +13,11 @@ #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; icache_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; ient_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; ipool, 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 ); } diff --git a/src/ent_skateshop.h b/src/ent_skateshop.h index c3a869d..182bcd6 100644 --- a/src/ent_skateshop.h +++ b/src/ent_skateshop.h @@ -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; } diff --git a/src/entity.h b/src/entity.h index 5f85377..d91ad89 100644 --- a/src/entity.h +++ b/src/entity.h @@ -222,7 +222,7 @@ struct ent_gate{ union { u32 timing_version; - u32 addon_reg; + addon_id remote_addon_id; struct{ u8 ref_count; diff --git a/src/gameserver_database.c b/src/gameserver_database.c index d4ec092..deab245 100644 --- a/src/gameserver_database.c +++ b/src/gameserver_database.c @@ -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 ) diff --git a/src/gameserver_replay.c b/src/gameserver_replay.c index 3910c55..d744627 100644 --- a/src/gameserver_replay.c +++ b/src/gameserver_replay.c @@ -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) diff --git a/src/gameserver_requests.c b/src/gameserver_requests.c index 9d8c121..6699d32 100644 --- a/src/gameserver_requests.c +++ b/src/gameserver_requests.c @@ -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 ) diff --git a/src/menu.c b/src/menu.c index d381f62..77c82f0 100644 --- a/src/menu.c +++ b/src/menu.c @@ -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 ++; } } diff --git a/src/menu.h b/src/menu.h index 85cbe7b..40f24dd 100644 --- a/src/menu.h +++ b/src/menu.h @@ -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 ); diff --git a/src/metascene.c b/src/metascene.c index 20ca10f..437f42f 100644 --- a/src/metascene.c +++ b/src/metascene.c @@ -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 { diff --git a/src/model.c b/src/model.c index dea1bb8..f5a5370 100644 --- a/src/model.c +++ b/src/model.c @@ -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 { diff --git a/src/network.c b/src/network.c index df807fb..174903a 100644 --- a/src/network.c +++ b/src/network.c @@ -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( ®->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 ++; diff --git a/src/network.h b/src/network.h index cb3649c..07e8dd7 100644 --- a/src/network.h +++ b/src/network.h @@ -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, diff --git a/src/particle.c b/src/particle.c index 58bc3ed..d589679 100644 --- a/src/particle.c +++ b/src/particle.c @@ -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; iindices[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 ) diff --git a/src/player.c b/src/player.c index c868191..bc63268 100644 --- a/src/player.c +++ b/src/player.c @@ -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 ); diff --git a/src/player_remote.c b/src/player_remote.c index 76d0bf3..74a0cda 100644 --- a/src/player_remote.c +++ b/src/player_remote.c @@ -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, ¤t_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; jbone_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; diff --git a/src/player_render.c b/src/player_render.c index 9bbb6ca..700c600 100644 --- a/src/player_render.c +++ b/src/player_render.c @@ -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 ); diff --git a/src/player_skate.c b/src/player_skate.c index 84c5c37..9d2f5bb 100644 --- a/src/player_skate.c +++ b/src/player_skate.c @@ -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) && diff --git a/src/render.c b/src/render.c index 190c506..20beb4b 100644 --- a/src/render.c +++ b/src/render.c @@ -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 ); } /* diff --git a/src/replay2.c b/src/replay2.c index 8ce5132..6ab05d0 100644 --- a/src/replay2.c +++ b/src/replay2.c @@ -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( ¤t_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; diff --git a/src/replay2.h b/src/replay2.h index 879cec8..3b5ea93 100644 --- a/src/replay2.h +++ b/src/replay2.h @@ -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 } diff --git a/src/save.c b/src/save.c index af89885..5ae6efd 100644 --- a/src/save.c +++ b/src/save.c @@ -26,8 +26,6 @@ void savedata_file_write( savedata_file *file ) void savedata_group_write( savedata_group *group ) { - for( u32 i=0; ifile_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, ®->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", ®->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; ifile_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; ifile_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" ); } } diff --git a/src/save.h b/src/save.h index ba19ea9..39feea7 100644 --- a/src/save.h +++ b/src/save.h @@ -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); diff --git a/src/scene.c b/src/scene.c index 0834b56..e204006 100644 --- a/src/scene.c +++ b/src/scene.c @@ -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 */ diff --git a/src/scene.h b/src/scene.h index 8d6f57a..c2ba3a9 100644 --- a/src/scene.h +++ b/src/scene.h @@ -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 ); diff --git a/src/skaterift.c b/src/skaterift.c index e7762ee..d4e432c 100644 --- a/src/skaterift.c +++ b/src/skaterift.c @@ -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 ); diff --git a/src/trail.c b/src/trail.c index 376a009..20c83b5 100644 --- a/src/trail.c +++ b/src/trail.c @@ -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; icount; i ++ ){ + for( i32 i=0; icount; 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; icount; i ++ ){ + for( i32 i=0; icount; 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 ) diff --git a/src/utest.c b/src/utest.c index c28578c..7145bec 100644 --- a/src/utest.c +++ b/src/utest.c @@ -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" diff --git a/src/workshop.c b/src/workshop.c index cf8be7d..89d86c0 100644 --- a/src/workshop.c +++ b/src/workshop.c @@ -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; ibuffer[i] ); - if( state & k_EItemStateInstalled ){ - info->buffer[j ++] = info->buffer[i]; - } - } - - *info->len = j; -} +#endif diff --git a/src/workshop.h b/src/workshop.h index 14b2d23..c644fce 100644 --- a/src/workshop.h +++ b/src/workshop.h @@ -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 */ diff --git a/src/world.c b/src/world.c index 2cd84c1..ba08fd8 100644 --- a/src/world.c +++ b/src/world.c @@ -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 ) diff --git a/src/world.h b/src/world.h index bd46891..2c8cdcc 100644 --- a/src/world.h +++ b/src/world.h @@ -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; diff --git a/src/world_entity.c b/src/world_entity.c index 279667a..dbc7a48 100644 --- a/src/world_entity.c +++ b/src/world_entity.c @@ -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; jent_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 ] ); } diff --git a/src/world_gate.c b/src/world_gate.c index 1b6c9be..086aef4 100644 --- a/src/world_gate.c +++ b/src/world_gate.c @@ -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; jent_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; } } diff --git a/src/world_gate.h b/src/world_gate.h index 20f6042..135d856 100644 --- a/src/world_gate.h +++ b/src/world_gate.h @@ -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] ); diff --git a/src/world_gen.c b/src/world_gen.c index cd1e570..443096b 100644 --- a/src/world_gen.c +++ b/src/world_gen.c @@ -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; isurface_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; izub_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; jent_light); j ++ ){ + for( u32 j=0; jent_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; ient_light); i++ ){ + for( u32 i=0; ient_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; ient_cubemap); i++ ){ + for( u32 i=0; ient_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 ); diff --git a/src/world_gen.h b/src/world_gen.h index c6ffb92..8e65780 100644 --- a/src/world_gen.h +++ b/src/world_gen.h @@ -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 ); diff --git a/src/world_load.c b/src/world_load.c index 5ba1246..c23357d 100644 --- a/src/world_load.c +++ b/src/world_load.c @@ -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( ®->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( ®->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; ialias, buf ); + addon_alias_uid( ®->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 ); diff --git a/src/world_load.h b/src/world_load.h index 361ce37..76f9813 100644 --- a/src/world_load.h +++ b/src/world_load.h @@ -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 ); diff --git a/src/world_map.c b/src/world_map.c index 8dd0dd9..6253eee 100644 --- a/src/world_map.c +++ b/src/world_map.c @@ -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; ifont = &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; diff --git a/src/world_render.c b/src/world_render.c index 2e42ba8..887f6ae 100644 --- a/src/world_render.c +++ b/src/world_render.c @@ -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; jent_gate); j ++ ) + world_instance *world = &_world.main; + for( u32 j=0; jent_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[] ) diff --git a/src/world_routes.c b/src/world_routes.c index 940ff4b..6df0412 100644 --- a/src/world_routes.c +++ b/src/world_routes.c @@ -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; ient_gate); i++ ) { @@ -561,11 +555,10 @@ void world_gen_routes_generate( world_instance *world ) } } - for( u32 i=0; ient_route); i++ ){ + for( u32 i=0; ient_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 ); } diff --git a/src/world_sfd.c b/src/world_sfd.c index ecc3418..0efdf06 100644 --- a/src/world_sfd.c +++ b/src/world_sfd.c @@ -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,