X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=addon.c;h=d408654100b3d5c5a8a0d66c7e7a45993c59fe08;hb=fdd41609e59c7df548682b25001f0015dc1acbea;hp=c2ad38c0d929f34ab96c48da70a155b221d3715b;hpb=badfa88dd109bbae5628f58504402f4707569f73;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/addon.c b/addon.c index c2ad38c..d408654 100644 --- a/addon.c +++ b/addon.c @@ -4,6 +4,8 @@ #include "addon.h" #include "vg/vg_msg.h" #include "steam.h" +#include "workshop_types.h" +#include "workshop.h" static u32 addon_count( enum workshop_file_type type ){ return addon_system.registry_type_counts[ type ]; @@ -40,6 +42,34 @@ static u32 get_index_from_addon( enum workshop_file_type type, addon_reg *a ){ return 0xffffffff; } +static u32 addon_match( enum workshop_file_type type, + u64 workshop_id, const char *foldername ){ + u32 foldername_djb2 = vg_strdjb2( foldername ); + + u32 count = 0; + for( u32 i=0; counttype == type ){ + + if( workshop_id ){ + if( workshop_id == reg->workshop_id ) + return count; + } + else{ + if( reg->foldername_hash == foldername_djb2 ){ + if( !strcmp( reg->foldername, foldername ) ){ + return count; + } + } + } + + count ++; + } + } + + return 0xffffffff; +} + static void addon_system_init( void ){ u32 reg_size = sizeof(addon_reg)*ADDON_MOUNTED_MAX; addon_system.registry = vg_linear_alloc( vg_mem.rtmemory, reg_size ); @@ -127,7 +157,7 @@ VG_STATIC int addon_try_load_metadata( addon_reg *reg, vg_str folder_path ){ return 1; } -VG_STATIC void addon_mount_finish( addon_reg *reg ){ +VG_STATIC void addon_print_info( addon_reg *reg ){ vg_info( "addon_reg #%u{\n", addon_system.registry_count ); vg_info( " type: %d\n", reg->type ); vg_info( " workshop_id: " PRINTF_U64 "\n", reg->workshop_id ); @@ -135,49 +165,124 @@ VG_STATIC void addon_mount_finish( addon_reg *reg ){ vg_info( " metadata_len: %u\n", reg->metadata_len ); vg_info( " userdata: %p\n", reg->userdata ); vg_info( "}\n" ); +} +VG_STATIC void addon_mount_finish( addon_reg *reg ){ + addon_print_info( reg ); addon_system.registry_count ++; } /* * Mount a fully packaged addon, one that certainly has a addon.inf */ -VG_STATIC void addon_mount_workshop_folder( PublishedFileId_t workshop_id, - vg_str folder_path ) +VG_STATIC addon_reg *addon_mount_workshop_folder( PublishedFileId_t workshop_id, + vg_str folder_path ) { addon_reg *reg = addon_alloc_reg( workshop_id, k_workshop_file_type_none ); - if( !reg ) return; + if( !reg ) return NULL; if( !addon_try_load_metadata( reg, folder_path ) ){ - return; + return NULL; } enum workshop_file_type type = k_workshop_file_type_none; - vg_msg msg; - vg_msg_init( &msg, reg->metadata, reg->metadata_len ); - vg_msg_cmd cmd; - while( vg_msg_next( &msg, &cmd ) ){ - if( (msg.depth == 1) && (cmd.code == k_vg_msg_code_frame) ){ - if( VG_STRDJB2_EQ( "workshop", cmd.key, cmd.key_djb2 ) ){ - u32 depth = msg.depth; - while( (msg.depth == depth) && vg_msg_next( &msg, &cmd ) ){ - if( cmd.code & k_vg_msg_code_unsigned ){ - if( VG_STRDJB2_EQ( "type", cmd.key, cmd.key_djb2 ) ){ - type = cmd.value._u32; - } - } - } - } - } + vg_msg root = {0}; + root.buf = reg->metadata; + root.len = reg->metadata_len; + root.max = sizeof(reg->metadata); + + vg_msg workshop = root; + if( vg_msg_seekframe( &workshop, "workshop", k_vg_msg_first )){ + type = vg_msg_seekkvu32( &workshop, "type", k_vg_msg_first ); } if( type == k_workshop_file_type_none ){ vg_error( "Cannot determine addon type\n" ); - return; + return NULL; } reg->type = type; addon_mount_finish( reg ); + return reg; +} + +/* + * Mount a local folder. may or may not have addon.inf + */ +VG_STATIC addon_reg *addon_mount_local_addon( const char *folder, + enum workshop_file_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; + u32 folder_hash = vg_strdjb2(folder_name); + for( u32 i=0; itype == type) && (reg->foldername_hash == folder_hash) ){ + if( !strcmp( reg->foldername, folder_name ) ){ + reg->state = k_addon_state_indexed; + return NULL; + } + } + } + + addon_reg *reg = addon_alloc_reg( 0, type ); + if( !reg ) return NULL; + addon_set_foldername( reg, folder_name ); + addon_try_load_metadata( reg, folder_path ); + + if( reg->metadata_len == 0 ){ + /* create our own content commands */ + vg_msg msg = {0}; + msg.buf = reg->metadata; + msg.len = 0; + msg.max = sizeof(reg->metadata); + + u32 content_count = 0; + + vg_strcat( &folder_path, "" ); + vg_warn( "Creating own metadata for: %s\n", folder_path.buffer ); + + vg_dir subdir; + if( !vg_dir_open(&subdir, folder_path.buffer) ){ + vg_error( "Failed to open '%s'\n", folder_path.buffer ); + return NULL; + } + + 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_msg_wkvstr( &msg, "content", fname ); + content_count ++; + } + } + vg_dir_close(&subdir); + + if( !content_count ) return NULL; + if( msg.error == k_vg_msg_error_OK ) + reg->metadata_len = msg.cur; + else{ + vg_error( "Error creating metadata: %d\n", msg.error ); + return NULL; + } + } + + addon_mount_finish( reg ); + return reg; } /* @@ -213,8 +318,6 @@ VG_STATIC void addon_mount_workshop_items(void){ } } - /* new one, lets find out what type it is - * ---------------------------------------------------------------*/ vg_async_item *call1 = vg_async_alloc( sizeof(struct async_workshop_filepath_info) ); @@ -237,9 +340,9 @@ 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. */ -VG_STATIC void addon_mount_local_folder( enum workshop_file_type type, - const char *base_folder, - const char *content_ext ) +VG_STATIC void addon_mount_content_folder( enum workshop_file_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 ); @@ -263,8 +366,6 @@ VG_STATIC void addon_mount_local_folder( enum workshop_file_type type, const char *d_name = vg_dir_entry_name(&dir); vg_str folder = path; - char *folder_name = folder.buffer+folder.i; - if( strlen( d_name ) > ADDON_FOLDERNAME_MAX ){ vg_warn( "folder too long: %s\n", d_name ); continue; @@ -273,97 +374,41 @@ VG_STATIC void addon_mount_local_folder( enum workshop_file_type type, vg_strcat( &folder, d_name ); if( !vg_strgood( &folder ) ) continue; - int present = 0; - u32 folder_hash = vg_strdjb2(folder_name); - for( u32 i=0; itype == type) && (reg->foldername_hash == folder_hash) ){ - if( !strcmp( reg->foldername, folder_name ) ){ - reg->state = k_addon_state_indexed; - present = 1; - break; - } - } - } - - if( !present ){ - addon_reg *reg = addon_alloc_reg( 0, type ); - if( !reg ) continue; - addon_set_foldername( reg, folder_name ); - addon_try_load_metadata( reg, folder ); - - if( reg->metadata_len == 0 ){ - /* create our own content commands */ - vg_msg msg; - vg_msg_init( &msg, reg->metadata, sizeof(reg->metadata) ); - - u32 content_count = 0; - - vg_strcat( &folder, "" ); - vg_warn( "Creating own metadata for: %s\n", folder.buffer ); - - vg_dir subdir; - if( !vg_dir_open(&subdir, folder.buffer) ){ - vg_error( "Failed to open '%s'\n", folder.buffer ); - continue; - } - - 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; - 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_msg_wkvstr( &msg, "content", fname ); - content_count ++; - } - } - vg_dir_close(&subdir); - - if( !content_count ){ - continue; - } - - if( msg.error == k_vg_msg_error_OK ) - reg->metadata_len = msg.cur; - else{ - vg_error( "Error creating metadata: %d\n", msg.error ); - continue; - } - } - - addon_mount_finish( reg ); - } + addon_mount_local_addon( folder.buffer, type, content_ext ); } } vg_dir_close(&dir); } -#if 0 -/* - * Async thread which scans local files for addons, as well as scheduling - * synchronous calls to the workshop - * - * Call this from in the loader thread. - */ -VG_STATIC void addon_system_scan_all(void){ - for( u32 i=0; istate = k_addon_state_indexed_absent; +static int addon_get_content_folder( addon_reg *reg, vg_str *folder ){ + if( reg->workshop_id ){ + vg_async_item *call = + vg_async_alloc( sizeof(struct async_workshop_filepath_info) ); + struct async_workshop_filepath_info *info = call->payload; + info->buf = folder->buffer; + info->id = reg->workshop_id; + info->len = folder->len; + vg_async_dispatch( call, async_workshop_get_filepath ); + vg_async_stall(); /* too bad! */ + if( info->buf[0] == '\0' ){ + vg_error( "Failed SteamAPI_GetItemInstallInfo(" PRINTF_U64 ")\n", + reg->workshop_id ); + return 0; + } + folder->i = strlen( folder->buffer ); + return 1; + } + else{ + folder->i = 0; + if( reg->type == k_workshop_file_type_board ) + vg_strcat( folder, "boards/" ); + else if( reg->type == k_workshop_file_type_world ) + vg_strcat( folder, "maps/" ); + else return 0; + + vg_strcat( folder, reg->foldername ); + return 1; } - - if( steam_ready ) addon_mount_workshop_items(); - - vg_async_call( addon_async_reg_update, NULL, 0 ); - vg_async_stall(); } -#endif #endif /* ADDON_C */