From c77e15a8dc7b976371a473bc8794cb55601d82f6 Mon Sep 17 00:00:00 2001 From: hgn Date: Mon, 24 Jul 2023 08:05:34 +0100 Subject: [PATCH] revision of savedata --- addon.h | 2 +- build.c | 1 + ent_skateshop.c | 2 +- save.c | 133 +++++++++++++++++++++++++++++++++++++----------- save.h | 28 ++++++---- skaterift.c | 14 +++-- skaterift.h | 2 + world.c | 15 ++++++ world.h | 9 ++++ world_entity.c | 27 ++++++++-- world_entity.h | 5 +- world_load.c | 29 +++++------ 12 files changed, 200 insertions(+), 67 deletions(-) diff --git a/addon.h b/addon.h index 691046d..6dda8a8 100644 --- a/addon.h +++ b/addon.h @@ -73,7 +73,7 @@ static addon_system; static void addon_system_init( void ); static u32 addon_count( enum addon_type type ); -static addon_reg *get_addon_from_index(enum addon_type type, u32 index); +static addon_reg *get_addon_from_index( enum addon_type type, u32 index ); static u32 get_index_from_addon( enum addon_type type, addon_reg *a ); static int addon_get_content_folder( addon_reg *reg, vg_str *folder ); diff --git a/build.c b/build.c index 154c474..f504e10 100644 --- a/build.c +++ b/build.c @@ -81,6 +81,7 @@ void build_game( enum compiler compiler ) vg_build_symbolic_link( "sound_src", "sound" ); vg_build_symbolic_link( "playermodels_src", "playermodels" ); vg_build_syscall( "mkdir -p %s/cfg", vg_compiler.build_dir ); + vg_build_syscall( "mkdir -p %s/savedata", vg_compiler.build_dir ); vg_build_syscall( "mkdir -p %s/tools", vg_compiler.build_dir ); vg_build_syscall( "cp blender_export.py %s/tools/", vg_compiler.build_dir ); diff --git a/ent_skateshop.c b/ent_skateshop.c index 44a669a..1b10153 100644 --- a/ent_skateshop.c +++ b/ent_skateshop.c @@ -252,7 +252,7 @@ VG_STATIC void global_skateshop_preupdate(void){ localplayer.board_view_slot = cache_id; global_skateshop_exit(); - skaterift_write_main_savedata(); + skaterift_autosave(1); return; } } diff --git a/save.c b/save.c index 094095c..ed869e6 100644 --- a/save.c +++ b/save.c @@ -2,29 +2,39 @@ #define SAVE_C #include "save.h" +#include "addon.h" #include "vg/vg_msg.h" +#include "vg/vg_log.h" +#include "world.h" -static void savedata_write_thread( void *file ){ - struct savedata *sav = file; +static void savedata_file_write( savedata_file *file ){ + savedata_file *sav = file; FILE *fp = fopen( sav->path, "wb" ); if( fp ){ fwrite( sav->buf, sav->len, 1, fp ); fclose( fp ); + vg_success( "savedata written to '%s'\n", sav->path ); } else { vg_error( "Error writing savedata (%s)\n", sav->path ); } } -static void savedata_read( struct savedata *sav ){ - FILE *fp = fopen( sav->path, "rb" ); +static void savedata_group_write( savedata_group *group ){ + for( u32 i=0; ifile_count; i++ ){ + savedata_file_write( &group->files[i] ); + } +} + +static void savedata_file_read( savedata_file *file ){ + FILE *fp = fopen( file->path, "rb" ); if( fp ){ - sav->len = fread( sav->buf, 1, sizeof(sav->buf), fp ); + file->len = fread( file->buf, 1, sizeof(file->buf), fp ); fclose( fp ); } else{ - sav->len = 0; - vg_warn( "Error reading savedata (%s)\n", sav->path ); + file->len = 0; + vg_warn( "Error reading savedata (%s)\n", file->path ); } } @@ -51,7 +61,6 @@ static void skaterift_write_viewslot( vg_msg *msg, const char *key, static void skaterift_read_addon_alias( vg_msg *msg, const char *key, enum addon_type type, addon_alias *alias ){ - alias->foldername[0] = '\0'; alias->workshop_id = 0; alias->type = type; @@ -65,47 +74,109 @@ static void skaterift_read_addon_alias( vg_msg *msg, const char *key, alias->workshop_id = vg_msg_read_as_u64( &kv ); } -static void skaterift_write_main_savedata(void){ - if( !vg_loader_availible() ) return; +static void skaterift_populate_world_savedata( savedata_file *file, + enum world_purpose which ){ + file->path[0] = '\0'; + file->len = 0; + addon_reg *reg = NULL; + if( which == k_world_purpose_hub ) reg = world_static.addon_hub; + else reg = world_static.addon_client; + + if( !reg ){ + vg_error( "Tried to save unspecified world (reg was null)\n" ); + return; + } - vg_linear_clear( vg_async.buffer ); - struct savedata *sav = vg_linear_alloc( vg_async.buffer, - vg_align8(sizeof(struct savedata)) ); + skaterift_world_get_save_path( which, file->path ); + + vg_msg sav = {0}; + sav.buf = file->buf; + sav.max = sizeof(file->buf); + + if( which == k_world_purpose_hub ){ + if( world_static.instances[0].status == k_world_status_loaded ) + world_entity_serialize( &world_static.instances[0], &sav ); + } + else { + for( u32 i=1; istatus == k_world_status_loaded ){ + world_entity_serialize( instance, &sav ); + } + } + } + + file->len = sav.len; +} - strcpy( sav->path, "save.bkv" ); +static void skaterift_populate_main_savedata( savedata_file *file ){ + strcpy( file->path, str_skaterift_main_save ); - vg_msg kvsav = {0}; - kvsav.buf = sav->buf; - kvsav.max = sizeof(sav->buf); + vg_msg sav = {0}; + sav.buf = file->buf; + sav.max = sizeof(file->buf); - vg_msg_frame( &kvsav, "player" ); + vg_msg_frame( &sav, "player" ); { - skaterift_write_viewslot( &kvsav, "board", k_addon_type_board, + skaterift_write_viewslot( &sav, "board", k_addon_type_board, localplayer.board_view_slot ); - skaterift_write_viewslot( &kvsav, "playermodel", k_addon_type_player, + skaterift_write_viewslot( &sav, "playermodel", k_addon_type_player, localplayer.playermodel_view_slot ); } - vg_msg_end_frame( &kvsav ); + vg_msg_end_frame( &sav ); - vg_msg_frame( &kvsav, "world" ); + vg_msg_frame( &sav, "world" ); { addon_reg *reg = world_static.addon_client; if( reg && (world_static.active_instance > 0) ){ - skaterift_write_addon_alias( &kvsav, "alias", ®->alias ); - vg_msg_wkvu32( &kvsav, "index", world_static.active_instance ); - vg_msg_wkvnum( &kvsav, "position", k_vg_msg_float|k_vg_msg_32b, 3, + skaterift_write_addon_alias( &sav, "alias", ®->alias ); + vg_msg_wkvu32( &sav, "index", world_static.active_instance ); + vg_msg_wkvnum( &sav, "position", k_vg_msg_float|k_vg_msg_32b, 3, localplayer.rb.co ); } } - vg_msg_end_frame( &kvsav ); + vg_msg_end_frame( &sav ); + + file->len = sav.len; +} + +static int skaterift_autosave( int async ){ + if( async ) + if( !vg_loader_availible() ) return 0; + + u32 save_files = 2; + if( world_static.addon_client ) + save_files ++; + + vg_linear_clear( vg_async.buffer ); + u32 size = sizeof(savedata_group) + sizeof(savedata_file) * save_files; + + savedata_group *group; + if( async ){ + size = vg_align8( size ); + group = vg_linear_alloc( vg_async.buffer, size ); + } + else + group = alloca( size ); + + group->file_count = save_files; + skaterift_populate_main_savedata( &group->files[0] ); + skaterift_populate_world_savedata( &group->files[1], k_world_purpose_hub ); + + if( world_static.addon_client ) + skaterift_populate_world_savedata( &group->files[2], + k_world_purpose_client ); + + if( async ) + vg_loader_start( (void *)savedata_group_write, group ); + else + savedata_group_write( group ); - sav->len = kvsav.len; - vg_loader_start( savedata_write_thread, sav ); + return 1; } -static void skaterift_read_main_savedata( struct savedata *sav ){ - strcpy( sav->path, "save.bkv" ); - savedata_read( sav ); +static void skaterift_autosave_synchronous(void){ + skaterift_autosave(0); } #endif /* SAVE_C */ diff --git a/save.h b/save.h index 25b9548..941dd12 100644 --- a/save.h +++ b/save.h @@ -3,17 +3,27 @@ #include "vg/vg_stdint.h" -struct savedata { - char path[128]; - u8 buf[1024]; - u32 len; +static const char *str_skaterift_main_save = "save.bkv"; +static f64 skaterift_last_autosave = 0.0; + +typedef struct savedata_file savedata_file; +typedef struct savedata_group savedata_group; + +struct savedata_group { + u32 file_count; + struct savedata_file { + char path[128]; + u8 buf[1024]; + u32 len; + } + files[]; }; -#include "ent_skateshop.h" +static void savedata_file_read( savedata_file *file ); +static void savedata_file_write( savedata_file *file ); +static void savedata_group_write( savedata_group *group ); -static void savedata_read( struct savedata *sav ); -static void savedata_write_thread( void *file ); +//static void skaterift_read_main_save( savedata_file *sav ); +static int skaterift_autosave(int async); -static void skaterift_read_main_savedata( struct savedata *sav ); -static void skaterift_write_main_savedata(void); #endif /* SAVE_H */ diff --git a/skaterift.c b/skaterift.c index c9afd0b..5804a3d 100644 --- a/skaterift.c +++ b/skaterift.c @@ -95,8 +95,10 @@ static void async_call_ready( void *payload, u32 size ){ } static void skaterift_restore_state(void){ - struct savedata sav; - skaterift_read_main_savedata( &sav ); + savedata_file sav; + strcpy( sav.path, str_skaterift_main_save ); + savedata_file_read( &sav ); + vg_msg kvsav = {0}; kvsav.buf = sav.buf; kvsav.len = sav.len; @@ -257,7 +259,7 @@ VG_STATIC void vg_load(void){ /* and now */ skaterift_restore_state(); - vg_loader_step( NULL, skaterift_write_main_savedata ); + vg_loader_step( NULL, skaterift_autosave_synchronous ); board_processview_thread(NULL); vg_async_call( async_call_ready, NULL, 0 ); @@ -337,6 +339,12 @@ VG_STATIC void vg_post_update(void){ audio_unlock(); vehicle_update_post(); + + if( vg.time - skaterift.last_autosave > 20.0 ){ + if( skaterift_autosave(1) ){ + skaterift.last_autosave = vg.time; + } + } } /* diff --git a/skaterift.h b/skaterift.h index 319efa5..fd59537 100644 --- a/skaterift.h +++ b/skaterift.h @@ -52,6 +52,8 @@ struct{ k_skaterift_menu = 0x04 } activity; + + f64 last_autosave; } static skaterift = { .op = k_async_op_clientloading, .time_rate = 1.0f }; diff --git a/world.c b/world.c index 0612644..c3b5516 100644 --- a/world.c +++ b/world.c @@ -26,6 +26,21 @@ static void world_init(void) VG_MEMORY_SYSTEM ); } +static void skaterift_world_get_save_path( enum world_purpose which, + char buf[128] ){ + addon_reg *reg; + + if( which == k_world_purpose_hub ) reg = world_static.addon_hub; + else reg = world_static.addon_client; + + assert( reg ); + + char id[76]; + addon_alias_uid( ®->alias, id ); + snprintf( buf, 128, "savedata/%s.bkv", id ); +} + + #include "world_entity.c" #include "world_gate.c" #include "world_gen.c" diff --git a/world.h b/world.h index c412a88..4da3791 100644 --- a/world.h +++ b/world.h @@ -16,8 +16,17 @@ enum world_geo_type{ k_world_geo_type_water = 2 }; +enum world_purpose{ + k_world_purpose_hub, + k_world_purpose_client +} +purpose; + typedef struct world_instance world_instance; +static void skaterift_world_get_save_path( enum world_purpose which, + char buf[128] ); + /* submodule headers */ #include "world_entity.h" #include "world_gate.h" diff --git a/world_entity.c b/world_entity.c index 7ffa1d6..b95961d 100644 --- a/world_entity.c +++ b/world_entity.c @@ -6,6 +6,7 @@ #include "world.h" #include "world_load.h" #include "save.h" +#include "vg/vg_msg.h" VG_STATIC void world_gen_entities_init( world_instance *world ){ /* lights */ @@ -439,8 +440,7 @@ VG_STATIC void entity_bh_closest( void *user, u32 item_index, v3f point, } } -VG_STATIC void world_entity_start( world_instance *world, - struct savedata *sav ){ +VG_STATIC void world_entity_start( world_instance *world, vg_msg *sav ){ vg_info( "Start instance %p\n", world ); world->probabilities[ k_probability_curve_constant ] = 1.0f; @@ -454,10 +454,31 @@ VG_STATIC void world_entity_start( world_instance *world, entity_call( world, &call ); } } + + /* read savedata + * ----------------------------------------------------------------------- */ + + for( u32 i=0; ient_unlock); i++ ){ + ent_unlock *unlock = mdl_arritm( &world->ent_unlock, i ); + const char *alias = mdl_pstr( &world->meta, unlock->pstr_alias ); + + if( vg_msg_seekkvu32( sav, alias, k_vg_msg_first ) ){ + ent_call call; + call.data = NULL; + call.function = 0; + call.id = mdl_entity_id( k_ent_unlock, i ); + entity_call( world, &call ); + } + } } -VG_STATIC void async_world_entity_start( void *payload, u32 size ){ +VG_STATIC void world_entity_serialize( world_instance *world, vg_msg *sav ){ + for( u32 i=0; ient_unlock); i++ ){ + ent_unlock *unlock = mdl_arritm(&world->ent_unlock,i); + const char *alias = mdl_pstr(&world->meta,unlock->pstr_alias); + vg_msg_wkvu32( sav, alias, unlock->status ); + } } #endif /* WORLD_ENTITY_C */ diff --git a/world_entity.h b/world_entity.h index 63cab47..c3af72a 100644 --- a/world_entity.h +++ b/world_entity.h @@ -5,14 +5,15 @@ #include "entity.h" #include "bvh.h" #include "save.h" +#include "vg/vg_msg.h" VG_STATIC void world_gen_entities_init( world_instance *world ); VG_STATIC ent_spawn *world_find_spawn_by_name( world_instance *world, const char *name ); VG_STATIC ent_spawn *world_find_closest_spawn( world_instance *world, v3f position ); -VG_STATIC void world_entity_start( world_instance *world, - struct savedata *sav ); +VG_STATIC void world_entity_start( world_instance *world, vg_msg *sav ); +VG_STATIC void world_entity_serialize( world_instance *world, vg_msg *sav ); VG_STATIC void ent_volume_call( world_instance *world, ent_call *call ); VG_STATIC void ent_audio_call( world_instance *world, ent_call *call ); diff --git a/world_load.c b/world_load.c index 0b96ad8..25d5b04 100644 --- a/world_load.c +++ b/world_load.c @@ -7,6 +7,7 @@ #include "ent_skateshop.h" #include "addon.h" #include "save.h" +#include "vg/vg_msg.h" /* * load the .mdl file located in path as a world instance @@ -99,27 +100,28 @@ VG_STATIC void world_instance_load_mdl( u32 instance_id, const char *path ){ struct world_load_complete_data{ - struct savedata save; + savedata_file save; u32 instance_start, instance_count; }; static void skaterift_world_load_done( void *payload, u32 size ){ struct world_load_complete_data *data = payload; + vg_msg sav = {0}; + sav.buf = data->save.buf; + sav.len = data->save.len; + sav.max = data->save.len; + for( u32 i=0; iinstance_count; i++ ){ world_instance *world = &world_static.instances[ data->instance_start+i ]; - world_entity_start( world, &data->save ); + world_entity_start( world, &sav ); } world_static.load_state = k_world_loader_none; } struct world_load_args { - enum world_purpose{ - k_world_purpose_hub, - k_world_purpose_client - } - purpose; + enum world_purpose purpose; addon_reg *reg; }; @@ -218,9 +220,9 @@ static void skaterift_world_load_thread( void *_args ){ struct world_load_complete_data *data = final_call->payload; data->instance_start = instance_start; data->instance_count = instance_count; - strcpy( data->save.path, "temp_fuckyou.bkv" ); - savedata_read( &data->save ); + skaterift_world_get_save_path( purpose, data->save.path ); + savedata_file_read( &data->save ); vg_async_dispatch( final_call, skaterift_world_load_done ); vg_async_stall(); @@ -266,6 +268,7 @@ static void skaterift_change_world_start( addon_reg *reg ){ char buf[76]; addon_alias_uid( ®->alias, buf ); vg_info( "switching to: %s\n", buf ); + skaterift_autosave(1); world_static.load_state = k_world_loader_preload; @@ -279,8 +282,6 @@ static void skaterift_change_world_start( addon_reg *reg ){ if( inst->status == k_world_status_loaded ){ inst->status = k_world_status_unloading; world_fadeout_audio( inst ); - - /* TODO: THIS IS WHERE A SAVE SHOULD BE DONE */ } } @@ -311,12 +312,6 @@ static int skaterift_change_world_command( int argc, const char *argv[] ){ return 0; } -#if 0 -static world_instance *world_loading_instance(void){ - return &world_static.instances[ world_loader.world_index ]; -} -#endif - /* * checks: * 1. to see if all audios owned by the world have been stopped -- 2.25.1