X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=world_load.c;h=5a2861351c7d75956caebbf3bdfbc532f6392fc8;hb=refs%2Fheads%2Fmaster;hp=50a882c2fab5dc1f8907a87c051d189eb55fed62;hpb=d171c9ad5de05c9ac8563fcf9f23760b93fb50f8;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/world_load.c b/world_load.c deleted file mode 100644 index 50a882c..0000000 --- a/world_load.c +++ /dev/null @@ -1,457 +0,0 @@ -#ifndef WORLD_LOAD_C -#define WORLD_LOAD_C - -#include "world_load.h" -#include "world_routes.h" -#include "world_gate.h" -#include "ent_skateshop.h" -#include "addon.h" -#include "save.h" -#include "vg/vg_msg.h" -#include "network.h" -#include "player_remote.h" - -/* - * load the .mdl file located in path as a world instance - */ -static void world_instance_load_mdl( u32 instance_id, const char *path ){ - vg_rand_seed( 9001 ); - - world_instance *world = &world_static.instances[ instance_id ]; - world_init_blank( world ); - world->status = k_world_status_loading; - - vg_info( "Loading instance[%u]: %s\n", instance_id, path ); - - void *allocator = NULL; - if( instance_id == 0 ) allocator = world_static.heap; - else allocator = world_static.instances[instance_id-1].heap; - - u32 heap_availible = vg_linear_remaining( allocator ); - u32 min_overhead = sizeof(vg_linear_allocator); - - if( heap_availible < (min_overhead+1024) ){ - vg_fatal_error( "out of memory" ); - } - - u32 size = heap_availible - min_overhead; - void *heap = vg_create_linear_allocator( allocator, size, VG_MEMORY_SYSTEM ); - - world->heap = heap; - mdl_context *meta = &world->meta; - - mdl_open( meta, path, world->heap ); - mdl_load_metadata_block( meta, world->heap ); - mdl_load_animation_block( meta, world->heap ); - mdl_load_mesh_block( meta, world->heap ); - - /* TODO: Make this a table? */ - mdl_load_array( meta, &world->ent_gate, "ent_gate", heap ); - mdl_load_array( meta, &world->ent_camera, "ent_camera", heap ); - mdl_load_array( meta, &world->ent_spawn, "ent_spawn", heap ); - mdl_load_array( meta, &world->ent_light, "ent_light", heap ); - mdl_load_array( meta, &world->ent_route_node,"ent_route_node", heap ); - mdl_load_array( meta, &world->ent_path_index,"ent_path_index", heap ); - mdl_load_array( meta, &world->ent_checkpoint,"ent_checkpoint", heap ); - mdl_load_array( meta, &world->ent_route, "ent_route", heap ); - mdl_load_array( meta, &world->ent_water, "ent_water", heap ); - mdl_load_array( meta, &world->ent_audio_clip,"ent_audio_clip", heap ); - mdl_load_array( meta, &world->ent_audio, "ent_audio", heap ); - mdl_load_array( meta, &world->ent_volume, "ent_volume", heap ); - mdl_load_array( meta, &world->ent_traffic, "ent_traffic", heap ); - mdl_load_array( meta, &world->ent_marker, "ent_marker", heap ); - mdl_load_array( meta, &world->ent_skateshop, "ent_skateshop", heap ); - mdl_load_array( meta, &world->ent_swspreview,"ent_swspreview", heap ); - mdl_load_array( meta, &world->ent_ccmd, "ent_ccmd", heap ); - mdl_load_array( meta, &world->ent_objective, "ent_objective", heap ); - mdl_load_array( meta, &world->ent_challenge, "ent_challenge", heap ); - mdl_load_array( meta, &world->ent_relay, "ent_relay", heap ); - mdl_load_array( meta, &world->ent_cubemap, "ent_cubemap", heap ); - mdl_load_array( meta, &world->ent_miniworld, "ent_miniworld", heap ); - mdl_load_array( meta, &world->ent_prop, "ent_prop", heap ); - - mdl_array_ptr infos; - mdl_load_array( meta, &infos, "ent_worldinfo", vg_mem.scratch ); - - world->skybox = k_skybox_default; - if( mdl_arrcount(&infos) ){ - world->info = *((ent_worldinfo *)mdl_arritm(&infos,0)); - - if( world->meta.info.version >= 104 ){ - if( MDL_CONST_PSTREQ( &world->meta, world->info.pstr_skybox,"space")){ - world->skybox = k_skybox_space; - } - } - } - else{ - world->info.pstr_author = 0; - world->info.pstr_desc = 0; - world->info.pstr_name = 0; - world->info.timezone = 0.0f; - } - - 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); - - /* process resources from pack */ - world_gen_load_surfaces( world ); - world_gen_routes_ent_init( world ); - world_gen_entities_init( world ); - - /* main bulk */ - world_gen_generate_meshes( world ); - world_gen_routes_generate( instance_id ); - world_gen_compute_light_indices( world ); - mdl_close( meta ); - - /* init player position. - * - this is overriden by the save state when(if) it loads */ - ent_spawn *rp = world_find_spawn_by_name( world, "start" ); - if( !rp ) rp = world_find_closest_spawn( world, (v3f){0.0f,0.0f,0.0f} ); - - /* TODO: fallback to searching for a safe location using raycasts */ - assert(rp); - v3_copy( rp->transform.co, world->player_co ); - - /* allocate leaderboard buffers */ - u32 bs = mdl_arrcount(&world->ent_route)*sizeof(struct leaderboard_cache); - world->leaderboard_cache = vg_linear_alloc( heap, bs ); - - for( u32 i=0; ient_route ); i ++ ){ - struct leaderboard_cache *board = &world->leaderboard_cache[i]; - board->data = vg_linear_alloc( heap, NETWORK_REQUEST_MAX ); - board->status = k_request_status_client_error; - board->cache_time = 0.0; - board->data_len = 0; - } - - vg_async_call( async_world_postprocess, world, 0 ); - vg_async_stall(); -} - -struct world_load_complete_data{ - savedata_file save; - enum world_purpose purpose; -}; - -static void skaterift_world_load_done( void *payload, u32 size ){ - struct world_load_complete_data *data = payload; - - /* TODO(W2): Load player position from this save file */ - vg_msg sav; - vg_msg_init( &sav, data->save.buf, data->save.len ); - - world_instance *world = &world_static.instances[ data->purpose ]; - world_entity_start( world, &sav ); - world->status = k_world_status_loaded; - world_static.load_state = k_world_loader_none; -} - -struct world_load_args { - enum world_purpose purpose; - addon_reg *reg; -}; - -/* - * Does a complete world switch using the remaining free slots - */ -static void skaterift_world_load_thread( void *_args ){ - /* FIXME: we need to check all threads that take args. args can dissapear! */ - struct world_load_args args = *((struct world_load_args *)_args); - - addon_reg *reg = args.reg; - world_static.instance_addons[ args.purpose ] = reg; - - char uid[ADDON_UID_MAX]; - addon_alias_uid( ®->alias, uid ); - vg_info( "LOAD WORLD %s @%d\n", uid, args.purpose ); - - char path_buf[4096]; - vg_str path; - vg_strnull( &path, path_buf, 4096 ); - - assert( reg ); - addon_get_content_folder( reg, &path ); - - vg_str folder = path; - if( !vg_strgood( &folder ) ) { - vg_error( "Load target too long\n" ); - return; - } - - char worlds[k_world_max-1][4096]; - u32 i=0; - - vg_dir dir; - if( !vg_dir_open(&dir, folder.buffer) ){ - vg_error( "opendir('%s') failed\n", folder.buffer ); - return; - } - - while( vg_dir_next_entry(&dir) ){ - if( vg_dir_entry_type(&dir) == k_vg_entry_type_file ){ - const char *d_name = vg_dir_entry_name(&dir); - if( d_name[0] == '.' ) continue; - - vg_str file = folder; - vg_strcat( &file, "/" ); - vg_strcat( &file, d_name ); - if( !vg_strgood( &file ) ) continue; - - char *ext = vg_strch( &file, '.' ); - if( !ext ) continue; - if( strcmp(ext,".mdl") ) continue; - - if( i == k_world_max-1 ){ - vg_warn( "There are too many .mdl files in the map folder!(3)\n" ); - break; - } - - strcpy( worlds[i++], file.buffer ); - } - } - vg_dir_close(&dir); - - if( i == 0 ){ - vg_warn( "There are no .mdl files in the map folder.\n" ); - } - - u32 first_index = 0; - for( u32 j=0; jpayload; - data->purpose = args.purpose; - - skaterift_world_get_save_path( args.purpose, data->save.path ); - savedata_file_read( &data->save ); - - vg_async_dispatch( final_call, skaterift_world_load_done ); - vg_async_stall(); -} - -/* holding pattern before we can start loading the new world, since we might be - * waiting for audio to stop */ -static void skaterift_change_client_world_preupdate(void){ - for( u32 i=1; istatus == k_world_status_unloading ){ - if( world_freeable( inst ) ){ - world_free( inst ); - } - return; - } - } - - if( vg_loader_availible() ){ - vg_info( "worlds cleared, begining load\n" ); - world_static.load_state = k_world_loader_load; - - vg_linear_clear( vg_async.buffer ); - struct world_load_args *args = - vg_linear_alloc( vg_async.buffer, sizeof(struct world_load_args) ); - args->purpose = k_world_purpose_client; - args->reg = world_static.instance_addons[ k_world_purpose_client ]; - - /* this is replaces the already correct reg but we have to set it again - * TOO BAD */ - - /* finally can start the loader */ - vg_loader_start( skaterift_world_load_thread, args ); - } -} - -/* places all loaded worlds into unloading state */ -static void skaterift_change_world_start( addon_reg *reg ){ - if( world_static.active_instance != 0 ) - vg_error( "Cannot change worlds while in non-root world\n" ); - else{ - if( world_static.instance_addons[ k_world_purpose_client ] == reg ){ - vg_warn( "World is already loaded\n" ); - return; - } - - 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; - - vg_linear_clear( vg_mem.scratch ); /* ?? */ - vg_info( "unloading old worlds\n" ); - - for( u32 i=1; istatus == k_world_status_loaded ){ - inst->status = k_world_status_unloading; - world_fadeout_audio( inst ); - } - } - - world_static.instance_addons[ k_world_purpose_client ] = reg; - network_send_item( k_netmsg_playeritem_world1 ); - relink_all_remote_player_worlds(); - } -} - -/* console command for the above function */ -static int skaterift_load_world_command( int argc, const char *argv[] ){ - if( !vg_loader_availible() ) return 0; /* FIXME */ - - if( argc == 1 ){ - addon_alias q; - addon_uid_to_alias( argv[0], &q ); - - u32 reg_id = addon_match( &q ); - if( reg_id != 0xffffffff ){ - addon_reg *reg = get_addon_from_index( k_addon_type_world, reg_id ); - skaterift_change_world_start( reg ); - } - else { - vg_error( "Addon '%s' is not installed or not found.\n", argv[0] ); - } - } - else { - vg_info( "worlds availible to load:\n" ); - - for( int i=0; ialias, buf ); - vg_info( " %s\n", buf ); - } - } - - return 0; -} - -/* - * checks: - * 1. to see if all audios owned by the world have been stopped - * 2. that this is the least significant world - */ -static int world_freeable( world_instance *world ){ - if( world->status != k_world_status_unloading ) return 0; - u8 world_id = (world - world_static.instances) + 1; - - for( u32 i=world_id; iallocated && (ch->world_id == world_id)){ - if( !audio_channel_finished( ch ) ){ - freeable = 0; - break; - } - } - } - audio_unlock(); - return freeable; -} - -/* - * Free all resources for world instance - */ -static void world_free( world_instance *world ){ - 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. - * */ - glDeleteBuffers( 1, &world->tbo_light_entities ); - glDeleteTextures( 1, &world->tex_light_entities ); - glDeleteTextures( 1, &world->tex_light_cubes ); - - /* delete textures and meshes */ - glDeleteTextures( world->texture_count, world->textures ); - - u32 world_index = world - world_static.instances; - if( world_index ){ - vg_linear_del( world_static.instances[world_index-1].heap, - vg_linear_header(world->heap) ); - } - - for( u32 i=0; ient_cubemap); i++ ){ - ent_cubemap *cm = mdl_arritm(&world->ent_cubemap,i); - glDeleteTextures( 1, &cm->texture_id ); - glDeleteFramebuffers( 1, &cm->framebuffer_id ); - glDeleteRenderbuffers( 1, &cm->renderbuffer_id ); - } - - world->status = k_world_status_unloaded; -} - -/* - * reset the world structure without deallocating persistent buffers - * TODO: Make this a memset(0), and have persistent items live in a static loc - */ -static void world_init_blank( world_instance *world ){ - memset( &world->meta, 0, sizeof(mdl_context) ); - - world->textures = NULL; - world->texture_count = 0; - world->surfaces = NULL; - world->surface_count = 0; - - world->geo_bh = NULL; - world->entity_bh = NULL; - world->entity_list = NULL; - world->rendering_gate = NULL; - - world->water.enabled = 0; - world->time = 0.0; - - /* default lighting conditions - * -------------------------------------------------------------*/ - struct ub_world_lighting *state = &world->ub_lighting; - - state->g_light_preview = 0; - state->g_shadow_samples = 8; - state->g_water_fog = 0.04f; - - v4_zero( state->g_water_plane ); - v4_zero( state->g_depth_bounds ); - - state->g_shadow_length = 9.50f; - state->g_shadow_spread = 0.65f; - - v3_copy( (v3f){0.37f, 0.54f, 0.97f}, state->g_daysky_colour ); - v3_copy( (v3f){0.03f, 0.05f, 0.20f}, state->g_nightsky_colour ); - v3_copy( (v3f){1.00f, 0.32f, 0.01f}, state->g_sunset_colour ); - v3_copy( (v3f){0.13f, 0.17f, 0.35f}, state->g_ambient_colour ); - v3_copy( (v3f){0.25f, 0.17f, 0.51f}, state->g_sunset_ambient ); - v3_copy( (v3f){1.10f, 0.89f, 0.35f}, state->g_sun_colour ); -} - -#endif /* WORLD_LOAD_C */