#include "world.h" #include #include void tc_on_each_chunkloader(tc_world_s *world, bool (*fn_do)(tc_chunkloader_s *loader, void *userdata), void *userdata) { for(uint32_t loader_index = 0; loader_index < world->num_loaders; ++loader_index) if(fn_do(&world->loaders[loader_index], userdata)) return; } void tc_on_each_loaded_chunk(tc_world_s *world, bool (*fn_do)(tc_chunk_s *chunk, void *userdata), void *userdata) { for(uint32_t loader_index = 0; loader_index < world->num_loaders; ++loader_index) for(uint32_t chunk_index = 0; chunk_index < world->loaders[loader_index].num_chunks; ++chunk_index) if(fn_do(world->loaders[loader_index].chunks[chunk_index], userdata)) return; } void tc_on_each_chunk_of_loader(tc_chunkloader_s *loader, bool (*fn_do)(tc_chunk_s *chunk, void *userdata), void *userdata) { uint32_t chunk_index = 0; while(chunk_index < loader->num_chunks) { if(fn_do(loader->chunks[chunk_index], userdata)) return; ++chunk_index; } } bool tc_coord_is_within_loaders_range(tc_chunkloader_s *loader, tc_vec3i_s coord) { if(coord.x < (loader->center.x - loader->extent.x / 2)) return false; if(coord.y < (loader->center.y - loader->extent.y / 2)) return false; if(coord.z < (loader->center.z - loader->extent.z / 2)) return false; if(coord.x > (loader->center.x + loader->extent.x / 2)) return false; if(coord.y > (loader->center.y + loader->extent.y / 2)) return false; if(coord.z > (loader->center.z + loader->extent.z / 2)) return false; return true; } tc_chunkloader_s * tc_get_corresponding_loader(tc_world_s *world, tc_vec3i_s coord) { for(uint32_t loader_index = 0; loader_index < world->num_loaders; ++loader_index) if(tc_coord_is_within_loaders_range(&world->loaders[loader_index], coord)) return &world->loaders[loader_index]; return NULL; } tc_chunk_s * tc_get_chunk_of_loader(tc_chunkloader_s *loader, tc_vec3i_s coord) { for(uint32_t chunk_index = 0; chunk_index < loader->num_chunks; ++chunk_index) if(tc_vec3i_equ(loader->chunks[chunk_index]->position, coord)) return loader->chunks[chunk_index]; return NULL; } tc_chunk_s * tc_get_loaded_chunk(tc_world_s *world, tc_vec3i_s coord) { tc_chunkloader_s *loader = tc_get_corresponding_loader(world, coord); if(loader == NULL) return NULL; return tc_get_chunk_of_loader(loader, coord); } tc_chunk_s * tc_load_chunk_of_loader(tc_chunkloader_s *loader, tc_vec3i_s coord) { tc_chunk_s *chunk = tc_get_chunk_of_loader(loader, coord); if(chunk == NULL) { chunk = tc_allocate_chunk(loader->world); chunk->position = coord; loader->world->worldgen->fn_generate_chunk(loader->world->worldgen, chunk); tc_upload_chunk(chunk); tc_add_chunk_to_loader(loader, chunk); } return chunk; } void tc_reload_chunk_of_loader(tc_chunkloader_s *loader, tc_vec3i_s coord) { tc_chunk_s *chunk = tc_get_chunk_of_loader(loader, coord); if(chunk == NULL) return; tc_meshize_chunk(chunk); tc_upload_chunk(chunk); } void tc_reload_chunk(tc_world_s *world, tc_vec3i_s coord) { tc_chunkloader_s *loader = tc_get_corresponding_loader(world, coord); if(loader == NULL) return; tc_reload_chunk_of_loader(loader, coord); } void tc_remove_loaders_chunk(tc_chunkloader_s *loader, uint32_t index) { tc_vec3i_s position = loader->chunks[index]->position; tc_free_chunk(loader->world, loader->chunks[index]); if(loader->num_chunks != 0) { // This is is NOT last element if((index+1) < loader->num_chunks) { loader->chunks[index] = loader->chunks[loader->num_chunks-1]; // move last chunk into gap } --loader->num_chunks; } } void tc_remove_unnecessary_chunks_of_loader(tc_chunkloader_s *loader) { for(uint32_t chunk_index = 0; chunk_index < loader->num_chunks; ++chunk_index) { tc_chunk_s *chunk = loader->chunks[chunk_index]; if(!tc_coord_is_within_loaders_range(loader, chunk->position)) { tc_remove_loaders_chunk(loader, chunk_index); } } } void tc_load_all_chunks_of_chunkloader(tc_chunkloader_s *loader) { for(int32_t x = 0; x < loader->extent.x; ++x) { for(int32_t y = 0; y < loader->extent.y; ++y) { for(int32_t z = 0; z < loader->extent.z; ++z) { tc_vec3i_s coords; coords.x = (loader->center.x - (x - ((int32_t) loader->extent.x)))-1; coords.y = (loader->center.y - (y - ((int32_t) loader->extent.y)))-1; coords.z = (loader->center.z - (z - ((int32_t) loader->extent.z)))-1; tc_load_chunk_of_loader(loader, coords); } } } } void tc_reload_chunkloader_zone(tc_chunkloader_s *loader) { tc_remove_unnecessary_chunks_of_loader(loader); tc_load_all_chunks_of_chunkloader(loader); } uint64_t world_update_tick = 0; void tc_update_world(tc_world_s *world) { if((world_update_tick % 512) == 0) { uint32_t chunkloader_index = 0; while(chunkloader_index < world->num_loaders) { if(world->loaders[chunkloader_index].needs_reload) { tc_reload_chunkloader_zone(&world->loaders[chunkloader_index]); } ++chunkloader_index; } } ++world_update_tick; } // TODO: Set center chunk