#ifndef ENT_SKATESHOP_C
#define ENT_SKATESHOP_C
+#define VG_GAME
+#include "vg/vg.h"
+#include "vg/vg_steam_ugc.h"
#include "ent_skateshop.h"
#include "world.h"
#include "player.h"
reg->cache_ptr = NULL;
vg_strncpy( file.name, reg->filename, 64, k_strncpy_always_add_null );
+ vg_strncpy( file.name, reg->workshop.title,
+ 64, k_strncpy_always_add_null );
reg->filename_hash = hash;
reg->workshop_id = 0;
reg->state = k_registry_board_state_indexed;
+ reg->workshop.author = 0;
+ strcpy( reg->workshop.author_name, "custom" );
}
next_file: tinydir_next( &dir );
reg->workshop_id = id;
reg->state = k_registry_board_state_indexed;
+ workshop_file_info_clear( ®->workshop );
+ strcpy( reg->workshop.title, "Workshop file" );
+
+ /* load the metadata off the disk */
+ vg_async_item *call =
+ vg_async_alloc( sizeof(struct async_workshop_filepath_info) );
+
+ const char *meta_file = "/board.mdl.inf";
+ char path[ 1024 ];
+ struct async_workshop_filepath_info *info = call->payload;
+ info->buf = path;
+ info->id = reg->workshop_id;
+ info->len = vg_list_size(path) - strlen(meta_file)-1;
+ vg_async_dispatch( call, async_workshop_get_filepath );
+ vg_async_stall(); /* too bad! */
+
+ strcat( path, meta_file );
+ workshop_load_metadata( path, ®->workshop );
+
next_file_workshop:;
}
ptr->ref_count --;
}
+/*
+ * Callback handler for persona state changes,
+ * it sets the author names on the registries
+ */
+VG_STATIC void callback_persona_statechange( CallbackMsg_t *msg )
+{
+ PersonaStateChange_t *info = (PersonaStateChange_t *)msg->m_pubParam;
+ ISteamFriends *hSteamFriends = SteamAPI_SteamFriends();
+
+ if( info->m_nChangeFlags & k_EPersonaChangeName ){
+ for( u32 i=0; i<global_skateshop.registry_count; i++ ){
+ struct registry_board *reg = &global_skateshop.registry[i];
+ if( reg->workshop.author == info->m_ulSteamID ){
+ const char *name = SteamAPI_ISteamFriends_GetFriendPersonaName(
+ hSteamFriends, info->m_ulSteamID );
+ str_utf8_collapse( name, reg->workshop.author_name, 32 );
+ }
+ }
+ }
+}
+
/*
* VG event init
*/
board->last_use_time = -99999.9;
board->ref_count = 0;
}
+
+ if( steam_ready ){
+ steam_register_callback( k_iPersonaStateChange,
+ callback_persona_statechange );
+ }
}
VG_STATIC struct cache_board *skateshop_selected_cache_if_loaded(void)
}
if( moved ){
- vg_info( "Select registry: %u\n",
- global_skateshop.selected_registry_id );
global_skateshop.interaction_cooldown = 0.125f;
return;
}
mdl_transform_m4x3( &mark_info->transform, mtext );
mdl_transform_m4x3( &mark_rack->transform, mrack );
+#if 0
const char *text_title = "Fish - Title";
const char *text_author = "by Shaniqua";
+#endif
m4x3f mlocal, mmdl;
m4x3_identity( mlocal );
struct cache_board *cache_ptr = skateshop_selected_cache_if_loaded();
if( !cache_ptr ) return;
+ struct registry_board *reg =
+ &global_skateshop.registry[cache_ptr->registry_id];
+ struct workshop_file_info *info = ®->workshop;
+
/* Skin title
* ----------------------------------------------------------------- */
+ m3x3_zero( mlocal );
m3x3_setdiagonalv3( mlocal, (v3f){ scale, scale, thickness } );
- mlocal[3][0] = -font3d_string_width(&world_global.font,0,text_title);
+ mlocal[3][0] = -font3d_string_width( &world_global.font, 0, info->title );
mlocal[3][0] *= scale*0.5f;
mlocal[3][1] = 0.1f;
m4x3_mul( mtext, mlocal, mmdl );
- font3d_simple_draw( &world_global.font, 0, text_title, &main_camera, mmdl );
+ font3d_simple_draw( &world_global.font, 0, info->title, &main_camera, mmdl );
/* Author name
* ----------------------------------------------------------------- */
scale *= 0.4f;
m3x3_setdiagonalv3( mlocal, (v3f){ scale, scale, thickness } );
- mlocal[3][0] = -font3d_string_width(&world_global.font,0,text_author);
+ mlocal[3][0] = -font3d_string_width( &world_global.font, 0,
+ info->author_name );
mlocal[3][0] *= scale*0.5f;
mlocal[3][1] = 0.0f;
m4x3_mul( mtext, mlocal, mmdl );
- font3d_simple_draw( &world_global.font, 0, text_author, &main_camera, mmdl );
+ font3d_simple_draw( &world_global.font, 0,
+ info->author_name, &main_camera, mmdl );
}
/*
struct registry_board{
PublishedFileId_t workshop_id;
+
+ /* only for steam workshop files */
+ struct workshop_file_info workshop;
struct cache_board *cache_ptr;
char filename[64]; /* if workshop, string version of its published ID. */
u32 size = arr->item_size*arr->item_count;
return vg_align8(size);
}
- else
- return 0;
+ else return 0;
}
VG_STATIC const char *mdl_pstr( mdl_context *mdl, u32 pstr );
fseek( mdl->file, mdl->pack_base_offset+info->pack_offset, SEEK_SET );
u64 l = fread( dst, info->pack_size, 1, mdl->file );
- if( l != 1 )
- mdl_load_fatal_corrupt( mdl );
+ if( l != 1 ) mdl_load_fatal_corrupt( mdl );
}
/* TODO: Rename these */
-VG_STATIC
-void mdl_load_array_file_buffer( mdl_context *mdl, mdl_array *arr,
- void *buffer )
+VG_STATIC void mdl_load_array_file_buffer( mdl_context *mdl, mdl_array *arr,
+ void *buffer )
{
if( arr->item_count ){
fseek( mdl->file, arr->file_offset, SEEK_SET );
u64 l = fread( buffer, arr->item_size*arr->item_count, 1, mdl->file );
- if( l != 1 )
- mdl_load_fatal_corrupt( mdl );
+ if( l != 1 ) mdl_load_fatal_corrupt( mdl );
}
}
*/
char model_path[128];
-
struct player_board board_model;
/* what does the user want to do with the image preview? */
*/
struct workshop_package_thread_args{
PublishedFileId_t file_id;
+
+ u64_steamid steamid;
+ char username[32];
};
VG_STATIC void _workshop_package_thread( void *_args )
{
return;
}
+ /* write the metadata file */
+ struct workshop_file_info meta;
+ meta.author = args->steamid;
+ vg_strncpy( args->username, meta.author_name, vg_list_size(meta.author_name),
+ k_strncpy_always_add_null );
+ vg_strncpy( workshop_form.submission.title, meta.title,
+ vg_list_size(meta.title), k_strncpy_always_add_null );
+
+ char _path[1024];
+ vg_str path;
+ vg_strnull( &path, _path, vg_list_size( _path ) );
+ vg_strcat( &path, info->abs_content_file );
+ vg_strcat( &path, ".inf" );
+
+ if( vg_strgood( &path ) ){
+ FILE *fp = fopen( _path, "wb" );
+
+ if( fp ){
+ fwrite( &meta, sizeof(struct workshop_file_info), 1, fp );
+ fclose( fp );
+ }
+ else{
+ info->success = 0;
+ info->failure_reason = "Cant write .inf file";
+ vg_async_dispatch( call, workshop_form_async_package_complete );
+ }
+ }
+ else{
+ info->success = 0;
+ info->failure_reason = "Path too long";
+ vg_async_dispatch( call, workshop_form_async_package_complete );
+ return;
+ }
+
info->success = 1;
vg_async_dispatch( call, workshop_form_async_package_complete );
}
vg_linear_alloc( vg_mem.scratch,
sizeof(struct workshop_package_thread_args));
+ ISteamFriends *hSteamFriends = SteamAPI_SteamFriends();
+ ISteamUser *hSteamUser = SteamAPI_SteamUser();
+
+ args->steamid = SteamAPI_ISteamUser_GetSteamID( hSteamUser );
+
+ const char *username = SteamAPI_ISteamFriends_GetPersonaName(hSteamFriends);
+ str_utf8_collapse( username, args->username, vg_list_size( args->username ));
+ vg_info( "Steamid: "PRINTF_U64", Name: %s(%s)\n",
+ args->steamid, username, args->username );
+
args->file_id = file_id;
vg_loader_start( _workshop_package_thread, args );
}
workshop_end_op();
}
+/*
+ * Reciever for failure to load
+ */
+VG_STATIC void workshop_form_loadmodel_async_error( void *payload, u32 size )
+{
+ workshop_end_op();
+}
+
/*
* Thread which loads the model from the disk
*/
VG_STATIC void _workshop_form_load_thread( void *data )
{
- player_board_load( &workshop_form.board_model, workshop_form.model_path );
- vg_async_call( workshop_form_loadmodel_async_complete, NULL, 0 );
+ FILE *test = fopen( workshop_form.model_path, "rb" );
+ if( test ){
+ fclose( test );
+ player_board_load( &workshop_form.board_model, workshop_form.model_path );
+ vg_async_call( workshop_form_loadmodel_async_complete, NULL, 0 );
+ }
+ else{
+ vg_error( "workshop async load failed: file not found\n" );
+ vg_async_call( workshop_form_loadmodel_async_error, NULL, 0 );
+ }
}
/*
.change = workshop_changed_description
};
ui_rect desc_entry;
- /* TODO: Tommora, new split_px_gap and split_px() */
ui_split( content, k_ui_axis_h, 8, 0, null, content );
ui_split( content, k_ui_axis_h, 28, 0, label, content );
ui_split( content, k_ui_axis_h, 28*4, 0, desc_entry, content );
char buf[32];
strcpy( buf, "page " );
int i = 5;
-
- /* TODO: for what it is, this code is getting a bit.. special */
i += highscore_intl( buf+i, workshop_form.view_published_page_id+1, 4 );
buf[ i ++ ] = '/';
i += highscore_intl( buf+i, workshop_form.view_published_page_count, 4 );
*info->len = j;
}
+VG_STATIC void vg_strsan_ascii( char *buf, u32 len )
+{
+ for( u32 i=0; i<len-1; i ++ ){
+ if( buf[i] == 0 ) return;
+
+ if( buf[i] < 32 || buf[i] > 126 ){
+ buf[i] = '?';
+ }
+ }
+ buf[len-1] = '\0';
+}
+
+#define VG_STRSAN_ASCII( X ) vg_strsan_ascii( X, vg_list_size(X) )
+
+VG_STATIC void workshop_load_metadata( const char *path,
+ struct workshop_file_info *info )
+{
+ FILE *fp = fopen( path, "rb" );
+
+ if( fp ){
+ if( fread( info, sizeof( struct workshop_file_info ), 1, fp ) ){
+ VG_STRSAN_ASCII( info->author_name );
+ VG_STRSAN_ASCII( info->title );
+ }
+ fclose( fp );
+ }
+}
+
#endif /* WORKSHOP_C */
}
static workshop;
+struct workshop_file_info{
+ u64 author;
+ char author_name[32];
+ char title[64];
+};
+
struct async_workshop_filepath_info{
PublishedFileId_t id;
char *buf;
u32 *len; /* inout */
};
+struct async_workshop_metadata_info{
+ struct workshop_file_info *info;
+ const char *path;
+};
+
+VG_STATIC void workshop_file_info_clear( struct workshop_file_info *info )
+{
+ info->author = 0ul;
+ info->author_name[0] = '\0';
+ info->title[0] = '\0';
+}
+
VG_STATIC void async_workshop_get_filepath( void *data, u32 len );
VG_STATIC void async_workshop_get_installed_files( void *data, u32 len );
+VG_STATIC void workshop_load_metadata( const char *path,
+ struct workshop_file_info *info );
/*
* Start a new operation and crash if we are already running one.