void vg_build_scripts(void)
{
+ if( vg_long_opt( "qt", "quick test stuff" ) )
+ {
+ c8 formatted[ 1024 ];
+ vg_str value_str;
+ vg_strnull( &value_str, formatted, sizeof(formatted) );
+ vg_strcatf64( &value_str, 0.008f, 10, 5 );
+ vg_strcatch( &value_str, ' ' );
+ vg_strcatf64( &value_str, 2.008f, 10, 5 );
+ vg_info( "Formatted: %s\n", formatted );
+ }
+
if( vg_long_opt( "skaterift", "Make skaterift" ) )
{
struct vg_project proj;
--- /dev/null
+{
+ "rdocCaptureSettings": 1,
+ "settings": {
+ "autoStart": false,
+ "commandLine": "--no-steam --noauth",
+ "environment": [
+ {
+ "separator": "Platform style",
+ "type": "Set",
+ "value": "/usr/lib/gcc/x86_64-linux-gnu/12/libasan.so:./libworkaround-27653.so",
+ "variable": "LD_PRELOAD"
+ }
+ ],
+ "executable": "/home/harry/source/skaterift/bin/skaterift/skaterift",
+ "inject": false,
+ "numQueuedFrames": 0,
+ "options": {
+ "allowFullscreen": true,
+ "allowVSync": true,
+ "apiValidation": false,
+ "captureAllCmdLists": false,
+ "captureCallstacks": false,
+ "captureCallstacksOnlyDraws": false,
+ "debugOutputMute": true,
+ "delayForDebugger": 0,
+ "hookIntoChildren": false,
+ "refAllResources": false,
+ "verifyBufferAccess": false
+ },
+ "queuedFrameCap": 0,
+ "workingDir": ""
+ }
+}
{
char uid[ ADDON_UID_MAX ];
addon_make_uid( id, uid );
- snprintf( out_buf, 256, "savedata/%s.bkv", uid );
+ snprintf( out_buf, 256, "savedata/%s.kv", uid );
}
u32 addon_uid_get_custom_part( const char *uid, char out_cpart[ ADDON_CPART_MAX ] )
}
else
{
+ bool ok = 0;
u32 size;
- void *legacy_msg_buf = vg_file_read( NULL, path_buf, &size, 0 );
-
- if( legacy_msg_buf )
+ u32 temp_frame = _vg_start_temp_frame();
{
- vg_kvs_append_from_legacy_msg2( ®->metadata, 0, legacy_msg_buf, size );
- vg_free( legacy_msg_buf );
- return 1;
+ void *legacy_msg_buf = vg_file_read( _vg_temp_stack(), path_buf, &size, 0 );
+
+ if( legacy_msg_buf )
+ {
+ vg_kvs_append_from_legacy_msg2( ®->metadata, 0, legacy_msg_buf, size );
+ ok = 1;
+ }
}
- else return 0;
+ _vg_end_temp_frame( temp_frame );
+ return ok;
}
}
else if( info->type == k_vg_event_init )
{
_vg_loader_set_user_information( "Initializing subsystems" );
+ _vg_loader_increment( +2 );
- _vg_async_context_push_groups( SKATERIFT_LOAD_GROUP );
+ _vg_async_context_push_groups( SKATERIFT_LOAD_GROUP, 0 );
_demo_check_init();
_render_init();
_remote_players_init();
_user_profile_init();
_particles_init();
_addon_system_init();
+ _savedata_init();
_player_init();
_player_render_init();
}
else if( info->type == k_vg_event_pre_update )
{
+ if( _vg_async_group_count( SKATERIFT_LOAD_GROUP ) )
+ return;
-#if 0
- if( co_step( co, 1 ) )
+ if( skaterift.main_save_handle == 0 )
+ {
+ _vg_loader_set_user_information( "Loading savedata" );
+ skaterift.main_save_handle = _savedata_handle( 0 );
+ _vg_loader_increment( -1 );
+ }
+
+ if( !skaterift.loaded_mainsave )
+ {
+ if( _savefile_state( skaterift.main_save_handle ) == k_savefile_ready )
{
- /* initializing / loading world. */
- vg_loader_set_user_information( "Loading savedata" );
- skaterift_load_mainsave();
+ addon_id world_to_load = _world.default_hub_addon;
- if( skaterift.override_load_world )
- _world.load_addon = _addon_mount_from_folder_path( skaterift.override_load_world, k_addon_type_world, ".mdl" );
+ vg_kvs *kvs = _savefile_kvs( skaterift.main_save_handle );
+ u32 player_block = vg_kv_find( kvs, 0, "player" );
+ if( player_block )
+ {
+ const c8 *location = vg_kv_read_string( kvs, player_block, "location", NULL );
+ if( location )
+ {
+ /* do do do parsing the location thingy! */
+ }
+ }
_world.loader_instance = &_world.main;
_world.loader_preview_mode = 0;
- _world.loader_stack = _world.stack;
+ _world.loader_stack = &_world.stack;
+ _world_loader_set_addon( world_to_load );
+ _world.loader_state = k_world_loader_ready;
- if( !_world.load_addon )
- {
- vg_warn( "Falling back to default hub world...\n" );
- _world.load_addon = _world.default_hub_addon;
- }
-
- _world_loader_set_addon( _world.load_addon );
+ skaterift.loaded_mainsave = 1;
}
+ }
+
+#if 0
+ if( skaterift.override_load_world )
+ _world.load_addon = _addon_mount_from_folder_path( skaterift.override_load_world, k_addon_type_world, ".mdl" );
#endif
skaterift_preupdate_inputs();
world_switcher_update();
- if( !skaterift.ready_to_show_game )
+ if( _vg_loader_visible() )
return;
//draw_origin_axis();
}
else if( info->type == k_vg_event_fixed_update )
{
- if( !skaterift.ready_to_show_game )
+ if( _vg_loader_visible() )
return;
world_routes_fixedupdate( &_world.main );
}
else if( info->type == k_vg_event_post_update )
{
- if( !skaterift.ready_to_show_game )
+ if( _vg_loader_visible() )
return;
player__post_update();
}
else if( info->type == k_vg_event_render )
{
- if( !skaterift.ready_to_show_game )
- return;
-
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glViewport( 0,0, _vg_window.w, _vg_window.h );
glDisable( GL_DEPTH_TEST );
glDisable( GL_BLEND );
- glClearColor( 1.0f, 0.0f, 0.0f, 0.0f );
+ glClearColor( 0.1f, 0.0f, 0.3f, 0.0f );
glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
+ if( _vg_loader_visible() )
+ return;
+
/* RENDER main game
* ------------------------------------------------------------------------------------------------------------ */
+ if( (_cutscene.state >= k_cutscene_state_ready) && _cutscene.player_binding )
{
- if( (_cutscene.state >= k_cutscene_state_ready) && _cutscene.player_binding )
- {
- struct cs_instance *inst = _cutscene.player_binding;
- ms_skeleton *sk = &localplayer.skeleton;
- for( u32 i=0; i<sk->bone_count; i ++ )
- m4x3_copy( inst->skinning_data[i], localplayer.final_mtx[i] );
- }
- else if( skaterift.activity == k_skaterift_replay ){}
- else
- {
- player__animate();
- _replay2_record_local_frame();
- }
-
- animate_remote_players();
- player__pre_render();
+ struct cs_instance *inst = _cutscene.player_binding;
+ ms_skeleton *sk = &localplayer.skeleton;
+ for( u32 i=0; i<sk->bone_count; i ++ )
+ m4x3_copy( inst->skinning_data[i], localplayer.final_mtx[i] );
+ }
+ else if( skaterift.activity == k_skaterift_replay ){}
+ else
+ {
+ player__animate();
+ _replay2_record_local_frame();
+ }
+ animate_remote_players();
+ player__pre_render();
- /* world entity driven camera
- * ------------------------------------------------------------------------------ */
- if( _world.entity_set_camera )
- {
- _world.entity_set_camera = 0;
- _world.entity_camera_modulate = vg_minf( 1.0f, _world.entity_camera_modulate+vg.time_frame_delta );
- }
- 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 );
- /* replay camera
- * ------------------------------------------------------------------ */
- if( skaterift.activity == k_skaterift_replay )
- {
- _replay2_get_camera( &g_render.cam );
- }
+ /* world entity driven camera
+ * ------------------------------------------------------------------------------ */
+ if( _world.entity_set_camera )
+ {
+ _world.entity_set_camera = 0;
+ _world.entity_camera_modulate = vg_minf( 1.0f, _world.entity_camera_modulate+vg.time_frame_delta );
+ }
+ else
+ {
+ _world.entity_camera_modulate = vg_maxf( 0.0f, _world.entity_camera_modulate-vg.time_frame_delta );
+ }
- if( skaterift.activity == k_skaterift_spectate )
- {
- _network_get_spectate_cam( &g_render.cam );
- }
+ vg_camera_lerp( &localplayer.cam, &_world.entity_driven_camera,
+ vg_smoothstepf(_world.entity_camera_modulate), &g_render.cam );
- g_render.cam.nearz = 0.1f;
- g_render.cam.farz = 2100.0f;
+ /* replay camera
+ * ------------------------------------------------------------------ */
+ if( skaterift.activity == k_skaterift_replay )
+ {
+ _replay2_get_camera( &g_render.cam );
+ }
- /* menu override camera
- * -------------------------------------------------------------------- */
- if( (skaterift.activity == k_skaterift_menu) && menu.bg_cam )
- {
- ent_camera_unpack( menu.bg_cam, &g_render.cam );
- }
+ if( skaterift.activity == k_skaterift_spectate )
+ {
+ _network_get_spectate_cam( &g_render.cam );
+ }
- /* cutscene camera TODO: Fix the action camera
- * ---------------------------------------------------------------- */
- ent_camera *cs_cam = _cutscene_active_camera();
- if( cs_cam )
- ent_camera_unpack( cs_cam, &g_render.cam );
+ g_render.cam.nearz = 0.1f;
+ g_render.cam.farz = 2100.0f;
- world_map_get_transition_cam( &g_render.cam );
+ /* menu override camera
+ * -------------------------------------------------------------------- */
+ if( (skaterift.activity == k_skaterift_menu) && menu.bg_cam )
+ {
+ ent_camera_unpack( menu.bg_cam, &g_render.cam );
+ }
- vg_camera_update_transform( &g_render.cam );
+ /* cutscene camera TODO: Fix the action camera
+ * ---------------------------------------------------------------- */
+ ent_camera *cs_cam = _cutscene_active_camera();
+ if( cs_cam )
+ ent_camera_unpack( cs_cam, &g_render.cam );
- vg_camera_update_view( &g_render.cam );
- vg_camera_update_projection( &g_render.cam, _vg_window.w, _vg_window.h );
- vg_camera_finalize( &g_render.cam );
+ world_map_get_transition_cam( &g_render.cam );
+ vg_camera_update_transform( &g_render.cam );
+ vg_camera_update_view( &g_render.cam );
+ vg_camera_update_projection( &g_render.cam, _vg_window.w, _vg_window.h );
+ vg_camera_finalize( &g_render.cam );
+ bool render_actual_game = !menu_viewing_map();
+ bool render_stenciled = 0;
+ if( render_actual_game )
+ {
+ world_instance *world = &_world.main;
+ render_world_cubemaps( world );
+ }
+ /* variable res target */
+ vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
+ glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+ glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
- bool render_actual_game = !menu_viewing_map();
- bool render_stenciled = 0;
+ if( !render_actual_game )
+ {
+ render_world_map();
- if( render_actual_game )
+ if( world_map_get_transition_cam(NULL) )
{
- world_instance *world = &_world.main;
- render_world_cubemaps( world );
+ glEnable( GL_STENCIL_TEST );
+ glDisable( GL_DEPTH_TEST );
+ glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
+ glStencilFunc( GL_ALWAYS, 1, 0xFF );
+ glStencilMask( 0xFF );
+
+ shader_blit_transition_use();
+ shader_blit_transition_uInverseRatio( (v2f){1.0f,1.0f} );
+ shader_blit_transition_uT( -(sqrtf(2)+0.5f) * world_map.spawn_timer );
+ render_fsquad();
+ render_stenciled = 1;
+ render_actual_game = 1;
}
+ }
- /* variable res target */
- vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
- glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
- glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
-
- if( !render_actual_game )
- {
- render_world_map();
-
- if( world_map_get_transition_cam(NULL) )
- {
- glEnable( GL_STENCIL_TEST );
- glDisable( GL_DEPTH_TEST );
- glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
- glStencilFunc( GL_ALWAYS, 1, 0xFF );
- glStencilMask( 0xFF );
-
- shader_blit_transition_use();
- shader_blit_transition_uInverseRatio( (v2f){1.0f,1.0f} );
- shader_blit_transition_uT( -(sqrtf(2)+0.5f) * world_map.spawn_timer );
- render_fsquad();
- render_stenciled = 1;
- render_actual_game = 1;
- }
- }
+ if( render_actual_game )
+ {
+ /* Draw world */
+ glEnable( GL_DEPTH_TEST );
+ world_prerender( &_world.main );
- if( render_actual_game )
- {
- /* Draw world */
- glEnable( GL_DEPTH_TEST );
- world_prerender( &_world.main );
+ render_world( &_world.main, &g_render.cam, render_stenciled, 0, 1, 1, _vg_render.fb_main );
- render_world( &_world.main, &g_render.cam, render_stenciled, 0, 1, 1, _vg_render.fb_main );
+ particle_system_update( &particles_grind, vg.time_delta );
+ //particle_system_debug( &particles_grind );
+ particle_system_prerender( &particles_grind );
+ particle_system_render( &particles_grind, &g_render.cam );
+
+ ent_tornado_pre_update();
+ particle_system_update( &particles_env, vg.time_delta );
+ particle_system_prerender( &particles_env );
+ particle_system_render( &particles_env, &g_render.cam );
- particle_system_update( &particles_grind, vg.time_delta );
- //particle_system_debug( &particles_grind );
- particle_system_prerender( &particles_grind );
- particle_system_render( &particles_grind, &g_render.cam );
-
- ent_tornado_pre_update();
- particle_system_update( &particles_env, vg.time_delta );
- particle_system_prerender( &particles_env );
- particle_system_render( &particles_env, &g_render.cam );
+ player_glide_render_effects( &g_render.cam );
+ }
- player_glide_render_effects( &g_render.cam );
- }
+ glEnable( GL_DEPTH_TEST );
- glEnable( GL_DEPTH_TEST );
+ /* full res target */
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ glViewport( 0,0, _vg_window.w, _vg_window.h );
- /* full res target */
- glBindFramebuffer( GL_FRAMEBUFFER, 0 );
- glViewport( 0,0, _vg_window.w, _vg_window.h );
+ if( render_actual_game && !render_stenciled )
+ {
+ bool render_player_transparent = 1;
- if( render_actual_game && !render_stenciled )
+ if( (skaterift.activity == k_skaterift_menu) &&
+ (menu.page == k_menu_page_main) &&
+ (menu.main_index == k_menu_main_guide) )
{
- bool render_player_transparent = 1;
-
- if( (skaterift.activity == k_skaterift_menu) &&
- (menu.page == k_menu_page_main) &&
- (menu.main_index == k_menu_main_guide) )
- {
- render_player_transparent = 0;
- }
+ render_player_transparent = 0;
+ }
- if( skaterift.activity == k_skaterift_replay )
- render_player_transparent = 0;
+ if( skaterift.activity == k_skaterift_replay )
+ render_player_transparent = 0;
- if( render_player_transparent )
- {
- static vg_camera small_cam; /* DOES NOT NEED TO BE STATIC BUT MINGW
- SAIS OTHERWISE */
+ if( render_player_transparent )
+ {
+ static vg_camera small_cam; /* DOES NOT NEED TO BE STATIC BUT MINGW
+ SAIS OTHERWISE */
- m4x3_copy( g_render.cam.transform, small_cam.transform );
+ m4x3_copy( g_render.cam.transform, small_cam.transform );
- small_cam.fov = g_render.cam.fov;
- small_cam.nearz = 0.05f;
- small_cam.farz = 60.0f;
+ small_cam.fov = g_render.cam.fov;
+ small_cam.nearz = 0.05f;
+ small_cam.farz = 60.0f;
- vg_camera_update_view( &small_cam );
- vg_camera_update_projection( &small_cam, _vg_window.w, _vg_window.h );
- vg_camera_finalize( &small_cam );
+ vg_camera_update_view( &small_cam );
+ vg_camera_update_projection( &small_cam, _vg_window.w, _vg_window.h );
+ vg_camera_finalize( &small_cam );
- /* Draw player to window buffer and blend background ontop */
- player__render( &small_cam );
- }
-
- /* continue with variable rate */
- vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
- render_world_gates( &_world.main, &g_render.cam, _vg_render.fb_main );
+ /* Draw player to window buffer and blend background ontop */
+ player__render( &small_cam );
}
- /* composite */
- if( (skaterift.activity == k_skaterift_menu) && menu.bg_blur )
- v2_muls( (v2f){ 0.04f, 0.001f }, 1.0f-skaterift.time_rate, g_render.blur_override );
- else
- v2_zero( g_render.blur_override );
+ /* continue with variable rate */
+ vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
+ render_world_gates( &_world.main, &g_render.cam, _vg_render.fb_main );
+ }
- vg_postprocess_to_screen( _vg_render.fb_main );
- _cutscene_render_fadeout();
+ /* composite */
+ if( (skaterift.activity == k_skaterift_menu) && menu.bg_blur )
+ v2_muls( (v2f){ 0.04f, 0.001f }, 1.0f-skaterift.time_rate, g_render.blur_override );
+ else
+ v2_zero( g_render.blur_override );
- if( !_gui_helpers_active() )
- control_overlay_render();
- }
+ vg_postprocess_to_screen( _vg_render.fb_main );
+ _cutscene_render_fadeout();
+ if( !_gui_helpers_active() )
+ control_overlay_render();
m4x4_copy( g_render.cam.mtx.pv, vg.pv );
}
else if( info->type == k_vg_event_gui )
{
- if( !skaterift.ready_to_show_game )
+ if( _vg_loader_visible() )
return;
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
f32 boost_scale;
bool no_save_location;
+ u16 main_save_handle;
- bool ready_to_show_game;
+ bool loaded_mainsave;
}
extern skaterift;
for( u32 i=0; i<prop_count; i ++ )
{
editer_property *prop = af_arritm( &model->editer_property, i );
- const char *alias = af_str( &model->model.packed_strings, prop->pstr_alias );
+ const char *alias = af_str( model->model.packed_strings, prop->pstr_alias );
if( prop->ui_type == k_editer_type_toggle )
{
array_file_ptr v106_data;
array_file_ptr v110_data;
-#if (VG_MODEL_VERSION_MIN <= 105)
if( ctx->model->version <= 105 )
+#if (VG_MODEL_VERSION_MIN <= 105)
af_load_array( &ctx->af, &v101_materials, "mdl_material", _vg_temp_stack(), sizeof(struct mdl_material_v101) );
- else
+#else
+ vg_fatal_error( "Unsupported model version (%u)\n", ctx->model->version );
#endif
- if( ctx->model->version <= 109 )
+ else if( ctx->model->version <= 109 )
+ {
af_load_array( &ctx->af, &v106_data, "shader_data", _vg_temp_stack(), 1 );
+ vg_mem_dumphex( stdout, v106_data.data, 0, v106_data.count );
+ }
else
af_load_array( &ctx->af, &v110_data, "shader_props", _vg_temp_stack(), 1 );
vg_kvs_init( &kvs, _vg_temp_stack() );
/* step1 ----------------------------- */
-#if (VG_MODEL_VERSION_MIN <= 105)
if( ctx->model->version <= 105 )
{
+#if (VG_MODEL_VERSION_MIN <= 105)
for( u32 i=0; i<ctx->model->material_count; i ++ )
{
mdl_material *mat = &ctx->model->materials[ i ];
vg_kv_append_vf32( &kvs, mat->props.kv_root, "deep_colour", old->colour1, 4 );
}
}
- }
-
- else
+#else
+ VG_ASSERT(0);
#endif
-
- if( ctx->model->version <= 109 )
+ }
+ else if( ctx->model->version <= 109 )
{
for( u32 i=0; i<ctx->model->material_count; i ++ )
{
mdl_material *mat = &ctx->model->materials[ i ];
- mat->props.kv_root = vg_kv_append( &kvs, 0, NULL, NULL );
- vg_kv_append( &kvs, mat->props.kv_root, "version", "106" );
+ u32 root = vg_kv_append( &kvs, 0, NULL, NULL );
+ vg_kv_append( &kvs, root, "version", "106" );
void *buffer = NULL;
if( v106_data.data )
buffer = v106_data.data + mat->props.kvs.offset;
- vg_kvs_append_from_legacy_msg2( &kvs, mat->props.kv_root, buffer, mat->props.kvs.size );
+ vg_kvs_append_from_legacy_msg2( &kvs, root, buffer, mat->props.kvs.size );
+ mat->props.kv_root = root;
}
}
else
for( u32 i=0; i<ctx->model->material_count; i ++ )
{
mdl_material *mat = &ctx->model->materials[ i ];
- mat->props.kv_root = vg_kv_append( &kvs, 0, NULL, NULL );
- vg_kv_append( &kvs, mat->props.kv_root, "version", "110" );
+ u32 root = vg_kv_append( &kvs, 0, NULL, NULL );
+ vg_kv_append( &kvs, root, "version", "110" );
const c8 *buffer = NULL;
if( v110_data.data )
vg_buffer_stream_open( &kv_stream, buffer, mat->props.kvs.size, VG_STREAM_READ );
vg_kv_parser parser;
- vg_kv_parser_init( &parser, &kvs, mat->props.kv_root );
+ vg_kv_parser_init( &parser, &kvs, root );
vg_kv_parse_stream( &parser, &kv_stream );
+ mat->props.kv_root = root;
}
}
- vg_kv_write wtest = { .fp = stdout, .depth = 0 };
- vg_kv_print_tree( &wtest, &kvs, 0 );
-
/* step2 ----------------------------- */
for( u32 i=0; i<ctx->model->material_count; i ++ )
{
u32 root = mat->props.kv_root;
union shader_props *props = &ctx->model->shader_props[ i ];
+ vg_stream stream = { .flags=VG_STREAM_FILE|VG_STREAM_WRITE, .fp = stdout };
+ vg_kv_write writer;
+ vg_kv_write_init( &writer, &stream );
+ vg_kv_write_tree( &writer, &kvs, root );
+
if( mat->shader == k_shader_standard ||
mat->shader == k_shader_standard_cutout ||
mat->shader == k_shader_foliage ||
vg_low( "Reference skeleton has a bone called '%s', retargetee has no such bone..\n", sb->name );
}
+ vg_model_stream_textures_gpu( &ctx );
vg_model_stream_meshes_gpu( &ctx, fixup_table );
vg_model_stream_close( &ctx );
}
// In the future
// #define MAX_SAVE_SLOTS 4
-VG_API void _skaterift_autosave_post_update( void )
-{
- VG_ASSERT(0);
-}
-
-#if 0
-
struct
{
struct savefile
{
- bool ready;
+ enum savefile_state state;
vg_stack_allocator stack;
vg_kvs kvs;
u16 addon_id; /* 0 for main save */
+ u16 reference_count;
}
files[ MAX_SAVE_FILES ];
- vg_pool pool;
- vg_pool_chain inactive, active;
}
_savedata;
-void _savedata_init(void)
-{
- vg_pool_init( &_savedata.pool, &_savedata.inactive, MAX_SAVE_FILES, &vg.rtmem );
-}
-
-
-// Loading
-while( ... )
-{
- if( stage == init )
- {
- world->savefile = savedata_handle( world->addon );
- if( world->savefile )
- stage = read_save;
- }
- else if( stage == read_save )
- {
- if( savedata_loaded( world->savefile ) )
- {
- // read save
- stage = ready;
- }
- }
-}
-
-
-// Game loop
-if( autosave_timer() )
+VG_API void _savedata_init(void)
{
- world_autosave(); -> savedata_sync( world->savefile );
+ for( u32 i=0; i<MAX_SAVE_FILES; i ++ )
+ vg_stack_init( &_savedata.files[i].stack, VG_STACK_USE_HEAP, VG_KB(64), "Savedata KVs" );
}
-// Unload
-savedata_sync( world->savefile );
-savedata_release_handle( world->addon );
-
-
-
-
-
-
-
-static u16 _savedata_handle_fork( u16 save_handle )
+VG_API void _skaterift_autosave_post_update( void )
{
- VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
- if( vg_pool_reference( &_savedata.pool, save_handle, 1 ) == 1 )
- vg_pool_switch( &_savedata.pool, &_savedata.inactive, &_savedata.active );
-
- return save_handle;
}
-void _savedata_handle_release( u16 save_handle )
+struct savedata_task
{
- VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
- if( vg_pool_reference( &_savedata.pool, save_handle, 0 ) == 0 )
- vg_pool_switch( &_savedata.pool, &_savedata.active, &_savedata.inactive );
-}
+ u16 savefile_id;
+ bool read;
-struct savedata_async_info
-{
- u16 save_handle;
+ u32 buffer_length;
+ c8 buffer[];
};
-static savedata_async( vg_async_queue *queue, void( *fn )(u16), u16 handle )
-{
- vg_async_task *task = vg_allocate_async_task( queue, sizeof(struct savedata_async_info), 1 );
- struct savedata_async_info *info = (void *)complete_task->data;
- info->save_handle = handle;
- vg_async_task_dispatch( task, savedata_load );
-}
-
-static savedata_task_complete( vg_async_task *task )
+static void _savedata_complete_task( struct savedata_task *in_args, vg_async_info *async )
{
VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
- struct savedata_async_info *info = (void *)task->data;
- struct savefile *sf = &_savedata.files[ vg_pool_index( &_savedata.pool, info->save_handle ) ];
- sf->ready = 1;
- _savedata_handle_release( info->save_handle );
+ VG_ASSERT( in_args->savefile_id );
+ struct savefile *save = &_savedata.files[ in_args->savefile_id-1 ];
+ save->state = k_savefile_ready;
+ save->reference_count --;
}
-
-void savedata_load( vg_async_task *task )
+static void _savedata_readwrite_task( struct savedata_task *in_args, vg_async_info *async )
{
VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
- struct savedata_async_info *info = (void *)task->data;
- struct savefile *sf = &_savedata.files[ vg_pool_index( &_savedata.pool, info->save_handle ) ];
+ VG_ASSERT( in_args->savefile_id );
+ struct savefile *save = &_savedata.files[ in_args->savefile_id-1 ];
- vg_stack_clear( &sf->stack );
- vg_kvs_init( &sf->kvs, &sf->stack );
-
- c8 path[ 256 ];
- addon_make_savedata_path( sf->addon_id, path );
+ c8 save_path[ 256 ];
+ if( save->addon_id )
+ addon_make_savedata_path( save->addon_id, save_path );
+ else
+ strcpy( save_path, "savedata/game.kv" );
- vg_file file;
- if( vg_file_stream_open( &file, path ) )
+ if( in_args->read )
{
- vg_kv_parser parser;
- vg_kv_parser_init( &parser, &sf->kvs, 0 );
-
- c8 chunk[ 1024 ];
-read_more:;
- u32 l = vg_file_stream( &file, chunk, sizeof(chunk) );
- vg_kv_parse_buffer( &parser, chunk, l );
-
- if( l == sizeof(chunk) )
- goto read_more;
+ vg_info( "Reading savefile.. '%s'\n", save_path );
- vg_file_stream_close( &file );
+ if( !vg_kv_read_file( &save->kvs, save_path, &save->stack ) )
+ vg_kvs_init( &save->kvs, &save->stack );
}
else
- vg_low( "Savefile '%s' did not exist yet. Creating.\n" );
+ {
+ vg_stream stream;
+ VG_ASSERT( vg_file_stream_open( &stream, save_path, VG_STREAM_WRITE ) );
+ vg_stream_write( &stream, in_args->buffer, in_args->buffer_length );
+ vg_file_stream_close( &stream );
+ }
- vg_async_task *complete_task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct savedata_async_info), 1 );
- struct savedata_async_info *info = (void *)complete_task->data;
- info->save_handle = info->save
- vg_async_task_dispatch( load_task, savedata_load );
+ struct savedata_task *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof(struct savedata_task) );
+ out_args->savefile_id = in_args->savefile_id;
+ _vg_async_send( out_args, (vg_async_fn)_savedata_complete_task );
}
-u16 _savedata_handle( addon_id addon )
+VG_API u16 _savedata_handle( addon_id addon )
{
VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
- u16 save_handle = _savedata.active.head;
- while( save_handle )
+ u16 unused_save = 0;
+ for( u16 i=0; i<MAX_SAVE_FILES; i ++ )
{
- if( _savedata.files[ vg_pool_index( &_savedata.pool, save_handle ) ].addon_id == addon )
- return _savedata_handle_fork( save_handle );
-
- save_handle = vg_pool_next( &_savedata.pool, save_handle, 1 );
+ struct savefile *save = &_savedata.files[i];
+ if( (save->addon_id == addon) && (save->state != k_savefile_not_init) )
+ {
+ save->reference_count ++;
+ return i+1;
+ }
+ else if( save->reference_count == 0 )
+ unused_save = i+1;
}
- save_handle = _savedata.inactive.tail;
- if( save_handle )
- {
- vg_async_task *load_task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct savedata_async_info), 1 );
- struct savedata_async_info *info = (void *)load_task->data;
- info->save_handle = _savedata_handle_fork( save_handle );
- vg_async_task_dispatch( load_task, savedata_load );
- return _savedata_handle_fork( save_handle );
- }
+ VG_ASSERT( unused_save );
- return 0;
+ struct savefile *save = &_savedata.files[unused_save-1];
+ save->reference_count ++; // for me
+ save->reference_count ++; // for load task
+ save->state = k_savefile_loading;
+ save->addon_id = addon;
+ vg_stack_clear( &save->stack );
+
+ struct savedata_task *out_args = _vg_async_alloc( VG_THREAD_ASYNC_ID, sizeof(struct savedata_task) );
+ out_args->savefile_id = unused_save;
+ out_args->read = 1;
+ _vg_async_send( out_args, (vg_async_fn)_savedata_readwrite_task );
+ return unused_save;
}
-bool _savedata_ready( u16 save_handle )
+VG_API void savedata_release_handle( u16 save_handle )
{
- VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
- return _savedata.files[ vg_pool_index( &_savedata.pool, save_handle ) ].ready;
+ VG_ASSERT( save_handle );
+ struct savefile *save = &_savedata.files[save_handle-1];
+ VG_ASSERT( save->reference_count );
+ save->reference_count --;
+}
+
+VG_API enum savefile_state _savefile_state( u16 save_handle )
+{
+ VG_ASSERT( save_handle );
+ return _savedata.files[ save_handle-1 ].state;
}
-#endif
+VG_API vg_kvs *_savefile_kvs( u16 save_handle )
+{
+ VG_ASSERT( save_handle );
+ struct savefile *save = &_savedata.files[save_handle-1];
+ VG_ASSERT( save->state == k_savefile_ready );
+ return &save->kvs;
+}
+
+VG_API void _savedata_write( u16 save_handle )
+{
+ VG_ASSERT( save_handle );
+ struct savefile *save = &_savedata.files[save_handle-1];
+ save->reference_count ++;
+
+ struct savedata_task *out_args = _vg_async_alloc( VG_THREAD_ASYNC_ID, sizeof(struct savedata_task) + VG_KB(128) );
+ out_args->savefile_id = save_handle;
+ out_args->read = 0;
+
+ vg_stream stream;
+ vg_buffer_stream_open( &stream, out_args->buffer, VG_KB(128), VG_STREAM_WRITE );
+ vg_kv_write writer;
+ vg_kv_write_init( &writer, &stream );
+ vg_kv_write_tree( &writer, &save->kvs, 0 );
+ out_args->buffer_length = stream.byte_count;
+
+ _vg_async_send( out_args, (vg_async_fn)_savedata_readwrite_task );
+}
# include "src/save2.c"
#else
+enum savefile_state
+{
+ k_savefile_not_init,
+ k_savefile_loading,
+ k_savefile_ready
+};
+
+VG_API void _savedata_init(void);
VG_API void _skaterift_autosave_post_update( void );
+VG_API u16 _savedata_handle( addon_id addon );
+VG_API enum savefile_state _savefile_state( u16 save_handle );
+VG_API vg_kvs *_savefile_kvs( u16 save_handle );
+
#endif
ctx->scene.vertex_count ++;
}
-VG_TIER_0 void scene_builder_get_submesh( scene_builder_context *ctx, mdl_submesh *sm )
+VG_TIER_0 void scene_builder_copy_submesh_indices( scene_builder_context *ctx, mdl_submesh *sm )
{
- vg_zero_mem( sm, sizeof(mdl_submesh) );
sm->indice_start = ctx->current_submesh.indice_start;
sm->indice_count = ctx->scene.indice_count - sm->indice_start;
sm->vertex_start = ctx->current_submesh.vertex_start;
out_args->scene.vertex_count = ctx->scene.vertex_count;
out_args->scene.indice_count = ctx->scene.indice_count;
out_args->out_mesh = out_mesh;
- memcpy( out_args->scene.vertex_buffer, ctx->scene.vertex_buffer, sizeof(scene_vert) * ctx->scene.vertex_count );
- memcpy( out_args->scene.indice_buffer, ctx->scene.indice_buffer, sizeof(u32) * ctx->scene.indice_count );
+ memcpy( out_args->scene.vertex_buffer, vg_stack_pointer( &ctx->vertex_stack, 0 ), sizeof(scene_vert) * ctx->scene.vertex_count );
+ memcpy( out_args->scene.indice_buffer, vg_stack_pointer( &ctx->indice_stack, 0 ), sizeof(u32) * ctx->scene.indice_count );
_vg_async_send( out_args, (vg_async_fn)scene_upload_task );
}
VG_TIER_0 void scene_builder_add_model_submesh( scene_builder_context *ctx, vg_model *model, mdl_submesh *sm, m4x3f transform );
VG_TIER_0 void scene_builder_push_tri( scene_builder_context *ctx, u32 tri[3] );
VG_TIER_0 void scene_builder_push_vert( scene_builder_context *ctx, scene_vert *v );
-VG_TIER_0 void scene_builder_get_submesh( scene_builder_context *ctx, mdl_submesh *sm );
+VG_TIER_0 void scene_builder_copy_submesh_indices( scene_builder_context *ctx, mdl_submesh *sm );
VG_TIER_0 void scene_builder_set_vertex_flags( scene_builder_context *ctx, u32 start, u32 count, u16 flags );
VG_TIER_2 void scene_builder_upload_async( scene_builder_context *ctx, scene_mesh *out_mesh );
VG_TIER_0 void scene_builder_save_scene( scene_builder_context *ctx, vg_scene *out_scene );
#define WORLD_SURFACE_HAS_TRAFFIC 0x1
#define WORLD_SURFACE_HAS_PROPS 0x2
+/* TODO: Break this down into main/preview world structures. So that world instances no longer exist finally,
+ * and _world referes to the actual loaded world, not possibly anything else. */
+
struct world_instance
{
bool complete;
*/
vg_stack_allocator stack, preview_stack;
+ u16 save_handle;
+
u32 current_run_version;
f64 last_gate_hit_time;
m4x3f identity;
m4x3_identity( identity );
scene_builder_add_model_submesh( builder, &world->meta, sm, identity );
- scene_builder_get_submesh( builder, sm );
+ scene_builder_copy_submesh_indices( builder, sm );
sm->flags |= k_submesh_flag_consumed;
}
if( surf->info.flags & k_material_flag_collision )
world_add_all_if_material( midentity, &geo_ctx, &world->meta, i );
- scene_builder_get_submesh( &geo_ctx, &surf->sm_geo );
+ scene_builder_copy_submesh_indices( &geo_ctx, &surf->sm_geo );
scene_builder_set_vertex_flags( &geo_ctx,
surf->sm_geo.vertex_start,
surf->sm_geo.vertex_count,
if( !_world.loader_preview_mode )
if( surf->info.flags & k_material_flag_grow_grass )
world_apply_procedural_foliage( world, &trans_ctx, surf );
- scene_builder_get_submesh( &trans_ctx, &surf->sm_no_collide );
+ scene_builder_copy_submesh_indices( &trans_ctx, &surf->sm_no_collide );
}
if( _world.loader_preview_mode )
world->surface_count = world->meta.material_count+1;
world->surfaces = vg_stack_allocate( world->stack, sizeof(struct world_surface)*world->surface_count, 8, "Surfaces" );
+ vg_zero_mem( world->surfaces, sizeof(struct world_surface)*world->surface_count );
- /* error material */
- struct world_surface *errmat = &world->surfaces[0];
- memset( errmat, 0, sizeof(struct world_surface) );
-
for( u32 i=0; i<world->meta.material_count; i++ )
{
struct world_surface *surf = &world->surfaces[i+1];
*/
static void world_instance_load_mdl( world_instance *world, const char *path, vg_stack_allocator *stack )
{
- _vg_loader_set_user_information( "Loading world data" );
+ //_vg_loader_set_user_information( "Loading world data" );
world_init_blank( world );
world->stack = stack;
}
_vg_end_temp_frame( temp_frame );
- _vg_loader_set_user_information( "Compiling world details" );
+ //_vg_loader_set_user_information( "Compiling world details" );
time_t seconds = time(NULL) % ((u32)vg_maxf(1.0f,k_day_length)*60);
world->time = ((f64)(seconds)/(k_day_length*60.0));
world->time += (world->info.timezone/24.0);
world->routes_ui = vg_stack_allocate( stack, sizeof(struct route_ui)*af_arrcount(&world->ent_route), 8, "Route UI buffer" );
ent_script_alloc( world, stack );
- _vg_loader_set_user_information( "Postprocessing world" );
+ //_vg_loader_set_user_information( "Postprocessing world" );
_vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)async_world_postprocess );
}
}
if( !in_args->OK )
return;
- _vg_loader_set_user_information( "Scanning world directory" );
-
addon_reg *reg = addon_details( _world.load_addon );
_world.loader_instance->addon_id = _world.load_addon;
_vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)async_world_loader_done );
}
-struct world_savedata_info
-{
- //savedata_file save;
- world_instance *instance;
-};
-
-void async_worldsave_go( struct world_savedata_info *in_args, vg_async_info *async )
-{
- VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
- VG_ASSERT( 0 );
-
- // FIXME FIXME FIXME
-
-#if 0
- struct world_savedata_info *info = (void *)task->data;
-
- /* start entities in the world */
- world_entity_start( info->instance, &info->save.kvs );
-
- /* start player in the world */
- if( _world.travelled_through_nonlocal_gate )
- {
- player__transport( _world.copy_of_nonlocal_sender.transport );
- _world.travelled_through_nonlocal_gate = 0;
- vg_success( "Successfuly consumed linked non-local gates composite transport matrix.\n" );
- }
- else
- {
- bool restored_player_position = 0;
-
- u32 player_block = vg_kv_find( &info->save.kvs, 0, "player" );
- if( player_block )
- {
- if( vg_kv_read_vf32( &info->save.kvs, player_block, "co", NULL, localplayer.rb.co, 3 ) )
- restored_player_position = 1;
- }
-
- if( !restored_player_position )
- 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;
- menu_on_world_change( _world.main.addon_id );
- relink_all_remote_player_worlds();
-
- vg_audio_lock();
- vg_audio_oneshot( &audio_ui[2], 1.0f, 0.0f, 0, 0 );
- vg_audio_unlock();
-#endif
-}
-
-void load_world_savedata_t1( void *_, vg_async_info *async )
-{
- VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
- VG_ASSERT( 0 );
- // FIXME FIXME
-#if 0
- 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;
-
- addon_make_savedata_path( _world.load_addon, info->save.path );
- savedata_file_read( &info->save );
- vg_async_task_dispatch( task, async_worldsave_go );
-#endif
-}
-
void world_switcher_update(void)
{
if( !_world.load_addon )
if( _world.loader_state == k_world_loader_ready )
{
+ _vg_loader_set_user_information( "Loading world..." );
_world.loader_state = k_world_loader_loading;
vg_stack_clear( _world.loader_stack );
else
{
_world.loader_state = k_world_loader_load_savedata;
- _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)load_world_savedata_t1 );
+ _vg_loader_set_user_information( "Loading world savedata..." );
+ _world.save_handle = _savedata_handle( _world.load_addon );
+ }
+ }
+
+ if( _world.loader_state == k_world_loader_load_savedata )
+ {
+ if( _savefile_state( _world.save_handle ) == k_savefile_ready )
+ {
+ _world.loader_state = k_world_loader_done;
+
+ vg_kvs *kvs = _savefile_kvs( _world.save_handle );
+ world_entity_start( &_world.main, kvs );
+
+ /* start player in the world */
+ if( _world.travelled_through_nonlocal_gate )
+ {
+ player__transport( _world.copy_of_nonlocal_sender.transport );
+ _world.travelled_through_nonlocal_gate = 0;
+ vg_success( "Successfuly consumed linked non-local gates composite transport matrix.\n" );
+ }
+ else
+ {
+ bool restored_player_position = 0;
+
+ u32 player_block = vg_kv_find( kvs, 0, "player" );
+ if( player_block )
+ {
+ if( vg_kv_read_vf32( kvs, player_block, "co", NULL, localplayer.rb.co, 3 ) )
+ restored_player_position = 1;
+ }
+
+ if( !restored_player_position )
+ world_default_spawn_pos( &_world.main, localplayer.rb.co );
+
+ player__reset();
+ }
+
+ network_send_item( k_netmsg_playeritem_world0 );
+ menu_on_world_change( _world.main.addon_id );
+ relink_all_remote_player_worlds();
+
+ vg_audio_lock();
+ vg_audio_oneshot( &audio_ui[2], 1.0f, 0.0f, 0, 0 );
+ vg_audio_unlock();
+ _vg_loader_increment( -1 );
}
}
}
}
}
- scene_builder_get_submesh( builder, &route->sm );
+ scene_builder_copy_submesh_indices( builder, &route->sm );
}
-struct world_surface *world_tri_index_surface( world_instance *world,
- u32 index );
-
/*
* Create the strips of colour that run through the world along course paths
*/
struct world_sfd world_sfd;
-static f32 sfd_encode_glyph( char c ){
+static f32 sfd_encode_glyph( char c )
+{
int value = 0;
if( c >= 'a' && c <= 'z' )
value = c-'a'+11;
return (float)value;
}
-static void sfd_clear( u32 row ){
+static void sfd_clear( u32 row )
+{
u32 row_h = world_sfd.h -1 -row;
- for( int i=0; i<world_sfd.w; i++ ){
+ for( int i=0; i<world_sfd.w; i++ )
+ {
u32 idx = (world_sfd.w*row_h + i) * 2;
world_sfd.buffer[idx] = 0.0f;
}
void world_sfd_compile_active_scores(void)
{
+#if 0
world_instance *world = &_world.main;
struct leaderboard_cache *board = NULL;
sfd_encode( (v2i){-1,4}, "No records", k_world_sfd_center );
}
#endif
+#endif
}
void world_sfd_update( world_instance *world, v3f pos )
{
+#if 0
if( af_arrcount( &world->ent_route ) )
{
u32 closest = 0;
else
*cur = *target;
}
+#endif
}
void bind_terrain_noise(void);
VG_API void _world_sfd_init(void)
{
+#if 0
VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
_vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_world_sfd_load_content );
for( i32 i=0; i<w*h*2; i++ )
world_sfd.buffer[i] = 0.0f;
+#endif
}