small compression
[carveJwlIkooP6JGAAIwe30JlM.git] / addon.c
diff --git a/addon.c b/addon.c
index 5c9578f67ac2f671c460acd50409662cfbf86d1e..ef92b0083ce4f1ba1c6a49a39d2a0e4c4a191aea 100644 (file)
--- a/addon.c
+++ b/addon.c
@@ -43,7 +43,11 @@ static u32 get_index_from_addon( enum addon_type type, addon_reg *a ){
 }
 
 static u32 addon_match( addon_alias *alias ){
-   u32 foldername_djb2 = vg_strdjb2( alias->foldername );
+   if( alias->type == k_addon_type_none ) return 0xffffffff;
+
+   u32 foldername_djb2 = 0;
+   if( !alias->workshop_id )
+      foldername_djb2 = vg_strdjb2( alias->foldername );
 
    u32 count = 0;
    for( u32 i=0; count<addon_system.registry_type_counts[alias->type]; i++ ){
@@ -69,7 +73,10 @@ static u32 addon_match( addon_alias *alias ){
    return 0xffffffff;
 }
 
-static void addon_alias_uid( addon_alias *alias, char buf[76] ){
+/*
+ * Create a string version of addon alias in buf
+ */
+static 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 );
@@ -80,6 +87,76 @@ static void addon_alias_uid( addon_alias *alias, char buf[76] ){
    }
 }
 
+/*
+ * equality check
+ */
+static int addon_alias_eq( addon_alias *a, addon_alias *b ){
+   if( a->type == b->type ){
+      if( a->workshop_id == b->workshop_id ){
+         if( a->workshop_id )
+            return 1;
+         else
+            return !strcmp( a->foldername, b->foldername );
+      }
+      else
+         return 0;
+   }
+   else return 0;
+}
+
+/*
+ * make alias represent NULL.
+ */
+static void invalidate_addon_alias( addon_alias *alias ){
+   alias->type = k_addon_type_none;
+   alias->workshop_id = 0;
+   alias->foldername[0] = '\0';
+}
+
+/*
+ * parse uid to alias. returns 1 if successful
+ */
+static int addon_uid_to_alias( char uid[ADDON_UID_MAX], addon_alias *alias ){
+/*           1
+ * 01234567890123
+ * sr&&&-@@@@@-#*
+ *    |    |   |
+ *  type   |   id
+ *         |
+ *     location
+ */
+   if( strlen(uid) < 13 ){
+      invalidate_addon_alias( alias );
+      return 0;
+   }
+   if( !((uid[0] == 's') && (uid[1] == 'r')) ){
+      invalidate_addon_alias( alias );
+      return 0;
+   }
+
+   char type[4];
+   memcpy( type, uid+2, 3 );
+   type[3] = '\0';
+   alias->type = atoi(type);
+
+   char location[6];
+   memcpy( location, uid+6, 5 );
+   location[5] = '\0';
+
+   if( !strcmp(location,"steam") )
+      alias->workshop_id = atoll( uid+12 );
+   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 );
+      return 0;
+   }
+
+   return 1;
+}
+
 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 );
@@ -123,7 +200,7 @@ static void addon_system_init( void ){
 /*
  * Reciever for scan completion. copies the registry counts back into main fred
  */
-VG_STATIC void async_addon_reg_update( void *data, u32 size )
+static void async_addon_reg_update( void *data, u32 size )
 {
    vg_info( "Registry update notify\n" );
    
@@ -137,7 +214,7 @@ VG_STATIC void async_addon_reg_update( void *data, u32 size )
    }
 }
 
-VG_STATIC void addon_set_foldername( addon_reg *reg, const char name[64] ){
+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 );
 }
@@ -145,7 +222,7 @@ VG_STATIC void addon_set_foldername( addon_reg *reg, const char name[64] ){
 /*
  * Create a new registry 
  */
-VG_STATIC addon_reg *addon_alloc_reg( PublishedFileId_t workshop_id,
+static addon_reg *addon_alloc_reg( PublishedFileId_t workshop_id,
                                       enum addon_type type ){
    if( addon_system.registry_count == ADDON_MOUNTED_MAX ){
       vg_error( "You have too many addons installed!\n" );
@@ -171,7 +248,7 @@ VG_STATIC addon_reg *addon_alloc_reg( PublishedFileId_t workshop_id,
 /*
  * If the addon.inf exists int the folder, load into the reg
  */
-VG_STATIC int addon_try_load_metadata( addon_reg *reg, vg_str folder_path ){
+static int addon_try_load_metadata( addon_reg *reg, vg_str folder_path ){
    vg_str meta_path = folder_path;
    vg_strcat( &meta_path, "/addon.inf" );
    if( !vg_strgood( &meta_path ) ){
@@ -198,7 +275,7 @@ VG_STATIC int addon_try_load_metadata( addon_reg *reg, vg_str folder_path ){
    return 1;
 }
 
-VG_STATIC void addon_print_info( addon_reg *reg ){
+static void addon_print_info( addon_reg *reg ){
    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 );
@@ -208,15 +285,17 @@ VG_STATIC void addon_print_info( addon_reg *reg ){
    vg_info( "}\n" );
 }
 
-VG_STATIC void addon_mount_finish( addon_reg *reg ){
+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
  */
-VG_STATIC addon_reg *addon_mount_workshop_folder( PublishedFileId_t workshop_id,
+static addon_reg *addon_mount_workshop_folder( PublishedFileId_t workshop_id,
                                                   vg_str folder_path )
 {
    addon_reg *reg = addon_alloc_reg( workshop_id, k_addon_type_none );
@@ -227,14 +306,11 @@ VG_STATIC addon_reg *addon_mount_workshop_folder( PublishedFileId_t workshop_id,
    }
 
    enum addon_type type = k_addon_type_none;
-   vg_msg root = {0};
-   root.buf = reg->metadata;
-   root.len = reg->metadata_len;
-   root.max = sizeof(reg->metadata);
+   vg_msg msg;
+   vg_msg_init( &msg, reg->metadata, reg->metadata_len );
 
-   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( vg_msg_seekframe( &msg, "workshop" )){
+      type = vg_msg_getkvu32( &msg, "type", 0 );
    }
 
    if( type == k_addon_type_none ){
@@ -250,7 +326,7 @@ VG_STATIC addon_reg *addon_mount_workshop_folder( PublishedFileId_t workshop_id,
 /*
  * Mount a local folder. may or may not have addon.inf
  */
-VG_STATIC addon_reg *addon_mount_local_addon( const char *folder,
+static addon_reg *addon_mount_local_addon( const char *folder,
                                               enum addon_type type,
                                               const char *content_ext )
 {
@@ -279,10 +355,8 @@ VG_STATIC addon_reg *addon_mount_local_addon( const char *folder,
 
    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);
+      vg_msg msg;
+      vg_msg_init( &msg, reg->metadata, sizeof(reg->metadata) );
 
       u32 content_count = 0;
 
@@ -315,7 +389,7 @@ VG_STATIC addon_reg *addon_mount_local_addon( const char *folder,
 
       if( !content_count ) return NULL;
       if( msg.error == k_vg_msg_error_OK )
-         reg->metadata_len = msg.cur;
+         reg->metadata_len = msg.cur.co;
       else{
          vg_error( "Error creating metadata: %d\n", msg.error );
          return NULL;
@@ -329,7 +403,7 @@ VG_STATIC addon_reg *addon_mount_local_addon( const char *folder,
 /*
  * Check all subscribed items
  */
-VG_STATIC void addon_mount_workshop_items(void){
+static void addon_mount_workshop_items(void){
    if( !steam_ready ) return;
    /*
     * Steam workshop scan
@@ -381,7 +455,7 @@ 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_content_folder( enum addon_type type,
+static void addon_mount_content_folder( enum addon_type type,
                                            const char *base_folder, 
                                            const char *content_ext )
 {
@@ -545,12 +619,10 @@ static int addon_cache_load_request( enum addon_type type, u16 id,
     * --------------------------------- */
    vg_str content_path = folder;
 
-   vg_msg root = {0};
-   root.buf = reg->metadata;
-   root.len = reg->metadata_len;
-   root.max = sizeof(reg->metadata);
+   vg_msg msg;
+   vg_msg_init( &msg, reg->metadata, reg->metadata_len );
 
-   const char *kv_content = vg_msg_seekkvstr( &root, "content", 0 );
+   const char *kv_content = vg_msg_getkvstr( &msg, "content" );
    if( kv_content ){
       vg_strcat( &content_path, "/" );
       vg_strcat( &content_path, kv_content );
@@ -676,6 +748,23 @@ static u16 addon_cache_create_viewer( enum addon_type type, u16 reg_id ){
    return cache_id;
 }
 
+static u16 addon_cache_create_viewer_from_uid( enum addon_type type,
+                                               char uid[ADDON_UID_MAX] ){
+   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 ){
+      vg_warn( "We dont have the addon '%s' installed.\n", uid );
+      return 0;
+   }
+   else {
+      return addon_cache_create_viewer( type, reg_id );
+   }
+}
+
 static void addon_cache_watch( enum addon_type type, u16 cache_id ){
    if( !cache_id ) return;