From: hgn Date: Thu, 18 May 2023 01:57:52 +0000 (+0100) Subject: semantics and world reloading X-Git-Url: https://skaterift.com/git/?a=commitdiff_plain;h=a8ba9cc44e1ae9aeca62fb579a3105c625e59133;p=carveJwlIkooP6JGAAIwe30JlM.git semantics and world reloading --- diff --git a/audio.h b/audio.h index e6e76bd..c07f0d1 100644 --- a/audio.h +++ b/audio.h @@ -173,12 +173,12 @@ enum audio_sprite_type VG_STATIC void audio_ambient_sprite_play( v3f co, audio_clip *clip ) { audio_lock(); - u32 channel_id = 31342352; - audio_channel *ch = audio_get_group_idle_channel( channel_id, 4 ); + u16 group_id = 0xfff0; + audio_channel *ch = audio_get_group_idle_channel( group_id, 4 ); if( ch ){ audio_channel_init( ch, clip, AUDIO_FLAG_SPACIAL_3D ); - audio_channel_group( ch, channel_id ); + audio_channel_group( ch, group_id ); audio_channel_set_spacial( ch, co, 80.0f ); audio_channel_edit_volume( ch, 1.0f, 1 ); ch = audio_relinquish_channel( ch ); diff --git a/blender_export.py b/blender_export.py index 3e6bb10..cc51987 100644 --- a/blender_export.py +++ b/blender_export.py @@ -186,6 +186,7 @@ class ent_gate(Structure): #{ _fields_ = [("type",c_uint32), ("target", c_uint32), + ("key",c_uint32), ("dimensions", c_float*3), ("co", (c_float*3)*2), ("q", (c_float*4)*2), @@ -1567,7 +1568,8 @@ def sr_compile( collection ): #} #} elif obj_data.tipo == 'nonlocal':#{ - gate.target = sr_compile_string(obj_data.key) + gate.target = 0 + gate.key = sr_compile_string(obj_data.key) gate.type = 2 #} else: gate.type = 0 diff --git a/ent_skateshop.c b/ent_skateshop.c index fb9db29..9438c00 100644 --- a/ent_skateshop.c +++ b/ent_skateshop.c @@ -104,7 +104,7 @@ VG_STATIC void skateshop_update_viewpage(void) /* generic reciever */ VG_STATIC void workshop_async_any_complete( void *data, u32 size ) { - workshop_end_op(); + skaterift_end_op(); } /* @@ -348,7 +348,7 @@ next_file: tinydir_next( &dir ); */ VG_STATIC void workshop_op_item_scan(void) { - workshop_begin_op( k_workshop_op_item_scan ); + skaterift_begin_op( k_workshop_op_item_scan ); vg_loader_start( workshop_scan_thread, NULL ); } @@ -747,6 +747,7 @@ VG_STATIC void ent_skateshop_call( world_instance *world, ent_call *call ) vg_info( "skateshop_call\n" ); if( menu.active ) return; + if( skaterift.async_op != k_async_op_none ) return; if( call->function == k_ent_function_trigger ){ if( localplayer.subsystem != k_player_subsystem_walk ){ diff --git a/entity.h b/entity.h index a14314a..867c74c 100644 --- a/entity.h +++ b/entity.h @@ -98,7 +98,8 @@ enum gate_type{ struct ent_gate{ u32 type, - target; + target, + key; v3f dimensions, co[2]; diff --git a/maps_src/mp_gridmap.mdl b/maps_src/mp_gridmap.mdl index ea3174f..c4763cc 100644 Binary files a/maps_src/mp_gridmap.mdl and b/maps_src/mp_gridmap.mdl differ diff --git a/maps_src/mp_mtzero.mdl b/maps_src/mp_mtzero.mdl index 9b119a2..7de53a9 100644 Binary files a/maps_src/mp_mtzero.mdl and b/maps_src/mp_mtzero.mdl differ diff --git a/maps_src/mp_spawn.mdl b/maps_src/mp_spawn.mdl index 9a8e526..8e3042a 100644 Binary files a/maps_src/mp_spawn.mdl and b/maps_src/mp_spawn.mdl differ diff --git a/skaterift.c b/skaterift.c index 9c7da4f..2edd7dc 100644 --- a/skaterift.c +++ b/skaterift.c @@ -15,6 +15,7 @@ #define SR_NETWORKED #define VG_DEVWINDOW + #include "common.h" #include "conf.h" #include "steam.h" @@ -27,14 +28,14 @@ #include "entity.c" #include "workshop.c" -VG_STATIC struct player_avatar localplayer_avatar; -VG_STATIC struct player_model localplayer_models[3]; -VG_STATIC int skaterift_status = 0; - #include "network.h" #include "menu.h" #include "vehicle.h" +static struct player_avatar localplayer_avatar; +static struct player_model localplayer_models[3]; + + int main( int argc, char *argv[] ) { vg_mem.use_libc_malloc = 0; @@ -80,12 +81,6 @@ VG_STATIC void load_playermodels(void) player_model_load( &localplayer_models[0], "models/ch_new.mdl" ); player_model_load( &localplayer_models[1], "models/ch_outlaw.mdl" ); player_model_load( &localplayer_models[2], "models/ch_jordan.mdl" ); - - /* load default board */ -#if 0 - player_board_load( &localplayer_boards[0], - "models/boards/skaterift_fish.mdl" ); -#endif /* FIXME: hack */ shader_model_character_view_register(); @@ -99,14 +94,16 @@ void temp_update_playermodel(void){ VG_STATIC void async_skaterift_complete( void *payload, u32 size ) { - skaterift_status = 1; - localplayer.viewable_world = get_active_world(); localplayer_cmd_respawn( 1, (const char *[]){ "start" } ); + + skaterift_end_op(); } VG_STATIC void vg_load(void) { + vg_console_reg_cmd( "changeworld", skaterift_change_world_command, NULL ); + vg_loader_step( render_init, NULL ); vg_loader_step( menu_init, NULL ); vg_loader_step( world_init, NULL ); @@ -128,7 +125,6 @@ VG_STATIC void vg_load(void) player_avatar_load( &localplayer_avatar, "models/ch_new.mdl" ); player__use_avatar( &localplayer, &localplayer_avatar ); player__use_model( &localplayer, &localplayer_models[cl_playermdl_id] ); - //localplayer.board = &localplayer_boards[0]; player__bind( &localplayer ); /* --------------------- */ @@ -137,10 +133,8 @@ VG_STATIC void vg_load(void) vg_loader_step( audio_init, audio_free ); /* 'systems' are completely loaded now */ - /* load home world */ - + /* load home/permanent world */ world_load( 0, "maps/mp_spawn.mdl" ); - world_load( 1, "maps/mp_mtzero.mdl" ); vg_console_load_autos(); menu_link(); @@ -155,64 +149,65 @@ VG_STATIC void draw_origin_axis(void) vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff ); } +static void skaterift_change_world_preupdate(void); VG_STATIC void vg_update(void) { steam_update(); - skaterift_preupdate_inputs(); + if( skaterift.async_op == k_async_op_clientloading ) return; + if( skaterift.async_op == k_async_op_world_preloading ){ + skaterift_change_world_preupdate(); + } - if( skaterift_status == 1 ){ - draw_origin_axis(); - network_update(); - - player__pre_update( &localplayer ); - global_skateshop_preupdate(); + draw_origin_axis(); + network_update(); + + player__pre_update( &localplayer ); + global_skateshop_preupdate(); - world_update( get_active_world(), localplayer.rb.co ); - audio_ambient_sprites_update( get_active_world(), localplayer.rb.co ); - //gui_helper_action( localplayer.input_use, "\x7f Hello \x1f""A \x1e\x84" ); - } + world_update( get_active_world(), localplayer.rb.co ); + audio_ambient_sprites_update( get_active_world(), localplayer.rb.co ); + //gui_helper_action( localplayer.input_use, "\x7f Hello \x1f""A \x1e\x84" ); } VG_STATIC void vg_update_fixed(void) { - if( skaterift_status == 1 ){ - world_routes_fixedupdate( get_active_world() ); + if( skaterift.async_op == k_async_op_clientloading ) return; - player__update( &localplayer ); - vehicle_update_fixed(); - } + world_routes_fixedupdate( get_active_world() ); + player__update( &localplayer ); + vehicle_update_fixed(); } VG_STATIC void vg_update_post(void) { - if( skaterift_status == 1 ){ - player__post_update( &localplayer ); + if( skaterift.async_op == k_async_op_clientloading ) return; - float dist; - int sample_index; - world_audio_sample_distances( localplayer.rb.co, &sample_index, &dist ); + player__post_update( &localplayer ); - audio_lock(); - vg_dsp.echo_distances[sample_index] = dist; + float dist; + int sample_index; + world_audio_sample_distances( localplayer.rb.co, &sample_index, &dist ); - v3f ears = { 1.0f,0.0f,0.0f }; - m3x3_mulv( main_camera.transform, ears, ears ); - v3_copy( ears, vg_audio.external_listener_ears ); - v3_copy( main_camera.transform[3], vg_audio.external_listener_pos ); + audio_lock(); + vg_dsp.echo_distances[sample_index] = dist; - if( localplayer.gate_waiting ){ - m4x3_mulv( localplayer.gate_waiting->transport, - vg_audio.external_listener_pos, - vg_audio.external_listener_pos ); - } + v3f ears = { 1.0f,0.0f,0.0f }; + m3x3_mulv( main_camera.transform, ears, ears ); + v3_copy( ears, vg_audio.external_listener_ears ); + v3_copy( main_camera.transform[3], vg_audio.external_listener_pos ); - v3_copy( localplayer.rb.v, vg_audio.external_lister_velocity ); - audio_unlock(); - - vg.time_rate = 1.0f-menu.factive; - vehicle_update_post(); + if( localplayer.gate_waiting ){ + m4x3_mulv( localplayer.gate_waiting->transport, + vg_audio.external_listener_pos, + vg_audio.external_listener_pos ); } + + v3_copy( localplayer.rb.v, vg_audio.external_lister_velocity ); + audio_unlock(); + + vg.time_rate = 1.0f-menu.factive; + vehicle_update_post(); } VG_STATIC void vg_framebuffer_resize( int w, int h ) @@ -359,7 +354,7 @@ VG_STATIC void render_main_game(void) VG_STATIC void vg_render(void) { - if( skaterift_status == 0 ){ + if( skaterift.async_op == k_async_op_clientloading ){ _vg_loader_render(); return; } @@ -387,9 +382,7 @@ VG_STATIC void vg_render(void) VG_STATIC void vg_gui(void) { - if( skaterift_status == 0 ){ - return; - } + if( skaterift.async_op == k_async_op_clientloading ) return; menu_update(); if( menu.active ){ @@ -406,6 +399,78 @@ VG_STATIC void vg_gui(void) render_view_framebuffer_ui(); } +static void async_skaterift_world_loaded( void *payload, u32 size ) +{ + skaterift_end_op(); +} + +static void skaterift_world_changer_thread( void *data ) +{ + const char *path = data; + world_load( 1, world_global.load_target ); + vg_async_call( async_skaterift_world_loaded, NULL, 0 ); +} + +/* holding pattern before we can start loading the new world, since we might be + * waiting for audio to stop */ +static void skaterift_change_world_preupdate(void) +{ + for( u32 i=1; istatus == k_world_status_unloading ){ + if( world_freeable( inst ) ){ + world_free( inst ); + } + return; + } + } + + vg_info( "worlds cleared, begining load\n" ); + skaterift_shift_op( k_async_op_world_loading ); + + /* finally can start the loader */ + vg_loader_start( skaterift_world_changer_thread, NULL ); +} + +/* places all loaded worlds into unloading state */ +static void skaterift_change_world( const char *world_path ) +{ + vg_info( "switching to %s\n", world_path ); + + if( world_global.active_world != 0 ){ + vg_error( "Cannot change worlds while in non-root world\n" ); + } + else{ + skaterift_begin_op( k_async_op_world_preloading ); + + vg_linear_clear( vg_mem.scratch ); + world_global.load_target = vg_linear_alloc( vg_mem.scratch, 1024 ); + vg_strncpy( world_path, world_global.load_target, + 1024, k_strncpy_overflow_fatal ); + + vg_info( "unloading old worlds\n" ); + world_unlink_nonlocal( &world_global.worlds[0] ); + + for( u32 i=1; istatus == k_world_status_loaded ){ + inst->status = k_world_status_unloading; + world_fadeout_audio( inst ); + } + } + } +} + +static int skaterift_change_world_command( int argc, const char *argv[] ) +{ + if( argc == 1 ) + skaterift_change_world( argv[0] ); + + return 0; +} + #else #include "skaterift_imgui_dev.c" diff --git a/skaterift.h b/skaterift.h new file mode 100644 index 0000000..b2d208c --- /dev/null +++ b/skaterift.h @@ -0,0 +1,69 @@ +#ifndef SKATERIFT_H +#define SKATERIFT_H + +#include "common.h" + +struct{ + enum async_operation{ + k_async_op_none, + k_async_op_clientloading, + k_async_op_world_preloading, + k_async_op_world_loading, + k_workshop_form_op_loading_model, + k_workshop_form_op_downloading_submission, + k_workshop_form_op_publishing_update, + k_workshop_op_item_scan, + k_workshop_op_item_load + } + async_op; +} +static skaterift = { .async_op = k_async_op_clientloading }; + + +/* Skaterift api */ + +static void skaterift_change_world( const char *world_path ); +static int skaterift_change_world_command( int argc, const char *argv[] ); + + + + + +/* + * Start a new operation or crash if we are already running one. you can avoid + * crashing the game by checking the async status yourself before calling. + */ +VG_STATIC void skaterift_begin_op( enum async_operation op ) +{ + if( skaterift.async_op != k_async_op_none ){ + vg_fatal_error( "Async executing op(%d), tried to start op(%d)\n", + skaterift.async_op, op ); + } + + skaterift.async_op = op; + vg_info( "Starting op( %d )\n", op ); +} + +/* + * Switch operation for those who have multiple parts + */ +VG_STATIC void skaterift_shift_op( enum async_operation op ) +{ + if( skaterift.async_op == k_async_op_none ){ + vg_fatal_error( "No current op, cannot shift operation (%d)\n", op ); + } + + skaterift.async_op = op; + vg_info( "Shifting to op( %d )\n", op ); +} + +/* + * Finished operation, otheres can now run + */ +VG_STATIC void skaterift_end_op(void) +{ + vg_info( "Finishing op( %d )\n", skaterift.async_op ); + skaterift.async_op = k_async_op_none; +} + +#endif /* SKATERIFT_H */ diff --git a/workshop.c b/workshop.c index 30aaf7a..d5eb820 100644 --- a/workshop.c +++ b/workshop.c @@ -111,7 +111,7 @@ static struct ui_dropdown_opt workshop_form_visibility_opts[] = { */ VG_STATIC void workshop_quit_form(void) { - workshop_begin_op( k_workshop_form_op_none ); /* safeguard */ + skaterift_begin_op( k_async_op_none ); /* safeguard */ player_board_unload( &workshop_form.board_model ); workshop_form.file_intent = k_workshop_form_file_intent_none; @@ -124,7 +124,7 @@ VG_STATIC void workshop_quit_form(void) } workshop_form.page = k_workshop_form_hidden; - workshop_end_op(); + skaterift_end_op(); } /* @@ -224,7 +224,7 @@ VG_STATIC void on_workshop_update_result( void *data, void *user ) vg_error( "Error with the submitted file (%d)\n", result->m_eResult ); } - workshop_end_op(); + skaterift_end_op(); } struct workshop_package_info { @@ -248,7 +248,7 @@ VG_STATIC void workshop_form_async_package_complete( void *data, u32 size ) if( !info->success ){ workshop_form.page = k_workshop_form_closing_bad; workshop_form.failure_or_success_string = info->failure_reason; - workshop_end_op(); + skaterift_end_op(); return; } @@ -432,7 +432,7 @@ VG_STATIC void on_workshop_createitem( void *data, void *user ) workshop_form.page = k_workshop_form_closing_bad; workshop_form.failure_or_success_string = errstr; - workshop_end_op(); + skaterift_end_op(); } } @@ -535,7 +535,7 @@ VG_STATIC void workshop_op_submit(void) } } - workshop_begin_op( k_workshop_form_op_publishing_update ); + skaterift_begin_op( k_workshop_form_op_publishing_update ); player_board_unload( &workshop_form.board_model ); workshop_form.file_intent = k_workshop_form_file_intent_none; @@ -560,7 +560,7 @@ VG_STATIC void workshop_form_loadmodel_async_complete( void *payload, u32 size ) workshop_form.file_intent = k_workshop_form_file_intent_new; vg_success( "workshop async load complete\n" ); - workshop_end_op(); + skaterift_end_op(); } /* @@ -568,7 +568,7 @@ VG_STATIC void workshop_form_loadmodel_async_complete( void *payload, u32 size ) */ VG_STATIC void workshop_form_loadmodel_async_error( void *payload, u32 size ) { - workshop_end_op(); + skaterift_end_op(); } /* @@ -593,7 +593,7 @@ VG_STATIC void _workshop_form_load_thread( void *data ) */ VG_STATIC void workshop_op_load_model(void) { - workshop_begin_op( k_workshop_form_op_loading_model ); + skaterift_begin_op( k_workshop_form_op_loading_model ); vg_loader_start( _workshop_form_load_thread, NULL ); } @@ -619,7 +619,7 @@ VG_STATIC void workshop_form_async_imageload( void *data, u32 len ) vg_success( "Loaded workshop preview image\n" ); } - workshop_end_op(); + skaterift_end_op(); } struct workshop_loadpreview_info { @@ -670,7 +670,7 @@ VG_STATIC void on_workshop_download_ugcpreview( void *data, void *user ) else{ vg_error( "Error while donwloading UGC preview( %d )\n", result->m_eResult ); - workshop_end_op(); + skaterift_end_op(); } } @@ -687,7 +687,7 @@ VG_STATIC void workshop_op_download_and_view_submission( int result_index ) result_index, &details ) ) { - workshop_begin_op( k_workshop_form_op_downloading_submission ); + skaterift_begin_op( k_workshop_form_op_downloading_submission ); workshop_reset_submission_data(); workshop_form.submission.submit_description = 0; workshop_form.submission.submit_file_and_image = 0; @@ -721,7 +721,7 @@ VG_STATIC void workshop_op_download_and_view_submission( int result_index ) if( details.m_hPreviewFile == 0 ){ vg_error( "m_hPreviewFile is 0\n" ); - workshop_end_op(); + skaterift_end_op(); } else{ /* Now need to begin downloading the image so we can display it */ @@ -747,7 +747,7 @@ VG_STATIC void workshop_op_download_and_view_submission( int result_index ) } else{ vg_error( "GetQueryUGCResult: Index out of range\n" ); - workshop_end_op(); + skaterift_end_op(); } } @@ -1297,7 +1297,7 @@ VG_STATIC void workshop_form_gui(void) ui_rect quit_button; ui_split( title, k_ui_axis_v, title[2]-title[3], 2, title, quit_button ); - if( workshop.operation == k_workshop_form_op_none ){ + if( skaterift.async_op == k_async_op_none ){ if( ui_button_text( quit_button, "X", 1 ) ){ workshop_quit_form(); return; @@ -1310,11 +1310,11 @@ VG_STATIC void workshop_form_gui(void) * escapes here and we show them a basic string */ - if( workshop.operation != k_workshop_form_op_none ){ + if( skaterift.async_op != k_async_op_none ){ const char *op_string = "The programmer has not bothered to describe " "the current operation that is running."; - switch(workshop.operation){ + switch( skaterift.async_op ){ case k_workshop_form_op_loading_model: op_string = "Operation in progress: Loading model file."; break; diff --git a/workshop.h b/workshop.h index 4a0f8b2..6418339 100644 --- a/workshop.h +++ b/workshop.h @@ -4,19 +4,7 @@ #define VG_GAME #include "vg/vg.h" #include "vg/vg_steam_remote_storage.h" - -struct workshop{ - enum workshop_operation{ - k_workshop_form_op_none, - k_workshop_form_op_loading_model, - k_workshop_form_op_downloading_submission, - k_workshop_form_op_publishing_update, - k_workshop_op_item_scan, - k_workshop_op_item_load - } - operation; -} -static workshop; +#include "skaterift.h" struct workshop_file_info{ u64 author; @@ -52,29 +40,4 @@ 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. - */ -VG_STATIC int workshop_begin_op( enum workshop_operation op ) -{ - if( workshop.operation != k_workshop_form_op_none ){ - vg_error( "Workshop form currently executing op(%d), tried to " - "start op(%d)\n", workshop.operation, op ); - return 0; - } - - workshop.operation = op; - vg_info( "Starting op( %d )\n", op ); - return 1; -} - -/* - * Finished operation, otheres can now run - */ -VG_STATIC void workshop_end_op(void) -{ - vg_info( "Finishing op( %d )\n", workshop.operation ); - workshop.operation = k_workshop_form_op_none; -} - #endif /* WORKSHOP_H */ diff --git a/world.h b/world.h index 68c3f2b..66b3b28 100644 --- a/world.h +++ b/world.h @@ -62,11 +62,11 @@ struct world_instance { */ void *heap; - char world_name[ 64 ]; enum world_status{ k_world_status_unloaded = 0, k_world_status_loading = 1, - k_world_status_loaded = 2 + k_world_status_loaded = 2, + k_world_status_unloading = 3 /* dont spawn sounds and stuff */ } status; @@ -127,7 +127,6 @@ struct world_instance { float probabilities[3]; v3i light_cubes; - struct framebuffer heightmap; /* @@ -206,6 +205,7 @@ struct world_global{ * -------------------------------------------------------------------------- */ void *heap; + char *load_target; /* rendering */ glmesh skydome; @@ -239,8 +239,6 @@ struct world_global{ v3f render_gate_pos; int in_volume; - int switching_to_new_world; - world_instance worlds[4]; u32 active_world; @@ -441,6 +439,12 @@ VG_STATIC void ent_volume_call( world_instance *world, ent_call *call ) VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ) { + if( world->status == k_world_status_unloading ){ + vg_warn( "cannot modify audio while unloading world\n" ); + return; + } + + u8 world_id = (world - world_global.worlds) + 1; u32 index = mdl_entity_id_id( call->id ); ent_audio *audio = mdl_arritm( &world->ent_audio, index ); @@ -468,7 +472,6 @@ VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ) bar += p; if( chance < bar ){ - audio_lock(); if( audio->behaviour == k_channel_behaviour_unlimited ){ @@ -484,6 +487,7 @@ VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ) if( ch ){ audio_channel_init( ch, &clip->clip, audio->flags ); audio_channel_group( ch, audio->group ); + audio_channel_world( ch, world_id ); audio_channel_set_spacial( ch, sound_co, audio->transform.s[0] ); audio_channel_edit_volume( ch, audio->volume, 1 ); ch = audio_relinquish_channel( ch ); @@ -515,6 +519,7 @@ VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ) if( ch ){ audio_channel_init( ch, &clip->clip, audio->flags ); audio_channel_group( ch, audio->group ); + audio_channel_world( ch, world_id ); audio_channel_fadein( ch, audio->crossfade ); ch = audio_relinquish_channel( ch ); } @@ -526,6 +531,28 @@ VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ) } } +/* finds any active playing in world and fades them out, we can only do this + * while unloading */ +VG_STATIC void world_fadeout_audio( world_instance *world ) +{ + if( world->status != k_world_status_unloading ){ + vg_fatal_error( "World status must be set to 'unloading', to fadeout" + " audio.\n" ); + } + + u8 world_id = (world - world_global.worlds) + 1; + + audio_lock(); + for( u32 i=0; iallocated && (ch->world_id == world_id) ){ + ch = audio_channel_fadeout( ch, 1.0f ); + } + } + audio_unlock(); +} + VG_STATIC void world_update( world_instance *world, v3f pos ) { world_global.sky_time += world_global.sky_rate * vg.time_delta; diff --git a/world_gate.h b/world_gate.h index 469f736..b409c51 100644 --- a/world_gate.h +++ b/world_gate.h @@ -5,6 +5,7 @@ #ifndef WORLD_GATE_H #define WORLD_GATE_H +#include "skaterift.h" #include "common.h" #include "model.h" #include "entity.h" @@ -229,6 +230,13 @@ VG_STATIC ent_gate *world_intersect_gates( world_instance *world, gate->type == k_gate_type_nonlocal_unlinked ) continue; + if( gate->type == k_gate_type_nonlocel ){ + if( skaterift.async_op == k_async_op_world_loading || + skaterift.async_op == k_async_op_world_preloading ){ + continue; + } + } + if( gate_intersect( gate, pos, last ) ){ return gate; } diff --git a/world_gen.h b/world_gen.h index 2bada3a..6cae853 100644 --- a/world_gen.h +++ b/world_gen.h @@ -596,15 +596,15 @@ VG_STATIC void world_process_resources( world_instance *world ) } } -#if 0 VG_STATIC void world_free( world_instance *world ) { - vg_acquire_thread_sync(); + vg_info( "Free world @%p\n", world ); /* free meshes */ mesh_free( &world->mesh_route_lines ); mesh_free( &world->mesh_geo ); mesh_free( &world->mesh_no_collide ); + mesh_free( &world->mesh_water ); /* glDeleteBuffers silently ignores 0's and names that do not correspond to * existing buffer objects. @@ -616,11 +616,46 @@ VG_STATIC void world_free( world_instance *world ) /* delete textures and meshes */ glDeleteTextures( world->texture_count, world->textures ); - vg_release_thread_sync(); + u32 world_index = world - world_global.worlds; + if( world_index ){ + vg_linear_del( world_global.worlds[world_index-1].heap, + vg_linear_header(world->heap) ); + } world->status = k_world_status_unloaded; } -#endif + +/* + * checks: + * 1. to see if all audios owned by the world have been stopped + * 2. that this is the least significant world + */ +VG_STATIC int world_freeable( world_instance *world ) +{ + if( world->status != k_world_status_unloading ) return 0; + u8 world_id = (world - world_global.worlds) + 1; + + for( u32 i=world_id; iallocated && (ch->world_id == world_id)){ + if( !audio_channel_finished( ch ) ){ + freeable = 0; + break; + } + } + } + audio_unlock(); + return freeable; +} VG_STATIC void world_init_blank( world_instance *world ) { @@ -661,32 +696,29 @@ VG_STATIC void world_init_blank( world_instance *world ) v3_copy( (v3f){1.10f, 0.89f, 0.35f}, state->g_sun_colour ); } -VG_STATIC void world_entities_init( u32 world_id ) +/* detatches any nonlocal gates */ +VG_STATIC void world_unlink_nonlocal( world_instance *world ) { - world_instance *world = &world_global.worlds[world_id]; - - /* lights */ - for( u32 j=0; jent_light); j ++ ){ - ent_light *light = mdl_arritm( &world->ent_light, j ); - - m4x3f to_world; - q_m3x3( light->transform.q, to_world ); - v3_copy( light->transform.co, to_world[3] ); - m4x3_invert_affine( to_world, light->inverse_world ); + for( u32 j=0; jent_gate); j ++ ){ + ent_gate *gate = mdl_arritm( &world->ent_gate, j ); - light->angle_sin_cos[0] = sinf( light->angle * 0.5f ); - light->angle_sin_cos[1] = cosf( light->angle * 0.5f ); + if( gate->type == k_gate_type_nonlocel ){ + gate->type = k_gate_type_nonlocal_unlinked; + } } +} + +/* attatches nonlocal gates, to be called from main thread ONLY! */ +VG_STATIC void world_link_nonlocal_async( void *payload, u32 size ) +{ + world_instance *world = payload; + u32 world_id = world - world_global.worlds; - /* gates */ for( u32 j=0; jent_gate); j ++ ){ ent_gate *gate = mdl_arritm( &world->ent_gate, j ); - if( gate->type == k_gate_type_teleport ){ - gate_transform_update( gate ); - } - else if( gate->type == k_gate_type_nonlocal_unlinked ){ - const char *key = mdl_pstr( &world->meta, gate->target ); + if( gate->type == k_gate_type_nonlocal_unlinked ){ + const char *key = mdl_pstr( &world->meta, gate->key ); vg_info( "key: %s\n", key ); for( u32 i=0; ient_gate, j ); if( gate2->type != k_gate_type_nonlocal_unlinked ) continue; - const char *key2 = mdl_pstr( &other->meta, gate2->target ); + const char *key2 = mdl_pstr( &other->meta, gate2->key ); vg_info( " key2: %s\n", key2 ); if( strcmp( key, key2 ) ) continue; @@ -731,6 +763,34 @@ VG_STATIC void world_entities_init( u32 world_id ) matched:; } } +} + +VG_STATIC void world_entities_init( u32 world_id ) +{ + world_instance *world = &world_global.worlds[world_id]; + + /* lights */ + for( u32 j=0; jent_light); j ++ ){ + ent_light *light = mdl_arritm( &world->ent_light, j ); + + m4x3f to_world; + q_m3x3( light->transform.q, to_world ); + v3_copy( light->transform.co, to_world[3] ); + m4x3_invert_affine( to_world, light->inverse_world ); + + light->angle_sin_cos[0] = sinf( light->angle * 0.5f ); + light->angle_sin_cos[1] = cosf( light->angle * 0.5f ); + } + + /* gates */ + for( u32 j=0; jent_gate); j ++ ){ + ent_gate *gate = mdl_arritm( &world->ent_gate, j ); + + if( gate->type == k_gate_type_teleport ){ + gate_transform_update( gate ); + } + } + vg_async_call( world_link_nonlocal_async, world, 0 ); /* water */ for( u32 j=0; jent_water); j++ ){ @@ -811,8 +871,7 @@ VG_STATIC void world_load( u32 index, const char *path ) } u32 size = heap_availible - min_overhead; - void *heap = vg_create_linear_allocator( allocator, size, - VG_MEMORY_SYSTEM ); + void *heap = vg_create_linear_allocator( allocator, size, VG_MEMORY_SYSTEM ); world->heap = heap; mdl_context *meta = &world->meta; @@ -872,7 +931,6 @@ VG_STATIC void world_load( u32 index, const char *path ) world_post_process( world ); mdl_close( meta ); - world->status = k_world_status_loaded; } diff --git a/world_render.h b/world_render.h index ef5946e..10e4163 100644 --- a/world_render.h +++ b/world_render.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved + * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved */ #ifndef WORLD_RENDER_H @@ -405,8 +405,11 @@ VG_STATIC void render_world_gates( world_instance *world, camera *cam, render_gate( world, gate, cam, layer_depth ); } else if( gate->type == k_gate_type_nonlocel ){ - world_instance *dest_world = &world_global.worlds[ gate->target ]; - render_gate( dest_world, gate, cam, layer_depth ); + if( skaterift.async_op != k_async_op_world_loading && + skaterift.async_op != k_async_op_world_preloading ){ + world_instance *dest_world = &world_global.worlds[ gate->target ]; + render_gate( dest_world, gate, cam, layer_depth ); + } } else world->rendering_gate = NULL;