#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; } } // TODO: Create and use vectors typedef struct tc_chunk_grid_distance { int32_t x; int32_t y; int32_t z; } tc_chunk_grid_distance_s; tc_chunk_grid_distance_s tc_chunk_distance_to( int32_t first_x, int32_t first_y, int32_t first_z, int32_t last_x, int32_t last_y, int32_t last_z ) { tc_chunk_grid_distance_s distance; distance.x = last_x - first_x; distance.y = last_y - first_y; distance.z = last_z - first_z; return distance; } bool tc_chunk_coordinate_is_within_loaded_zone(tc_world_s *world, int32_t x, int32_t y, int32_t z) { if((world->loading_center.x + world->load_radius) < x) return false; if((world->loading_center.y + world->load_radius) < y) return false; if((world->loading_center.z + world->load_radius) < z) return false; if((world->loading_center.x - world->load_radius) > x) return false; if((world->loading_center.y - world->load_radius) > y) return false; if((world->loading_center.z - world->load_radius) > z) return false; return true; } bool tc_chunk_exists(tc_world_s *world, int32_t x, int32_t y, int32_t z) { uint32_t loader_index = 0; while(loader_index < world->num_loaders) { tc_chunkloader_s *loader = &world->loaders[loader_index]; for(uint32_t chunk_index = 0; chunk_index < loader->num_chunks; ++chunk_index) { tc_chunk_s *chunk = loader->chunks[chunk_index]; if(chunk->position.x != x) continue; if(chunk->position.y != y) continue; if(chunk->position.z != z) continue; return true; } ++loader_index; } return false; } bool tc_chunk_is_loaded(tc_world_s *world, int32_t x, int32_t y, int32_t z) { // TODO: Further checks if(!tc_chunk_coordinate_is_within_loaded_zone(world, x, y, z)) return false; if(!tc_chunk_exists(world, x, y, z)) return false; printf("Checked for a chunk at %d:%d:%d and found it!\n", x, y, z); return true; } bool tc_check_chunk_coordinate_equality_for_getting_a_loaded_chunk(tc_chunk_s *chunk, void *userdata) { struct payload { int32_t x; int32_t y; int32_t z; tc_chunk_s *result; } *payload = userdata; if(chunk->position.x != payload->x) return false; if(chunk->position.y != payload->y) return false; if(chunk->position.z != payload->z) return false; payload->result = chunk; return true; } tc_chunk_s * tc_get_loaded_chunk_at(tc_world_s *world, int32_t x, int32_t y, int32_t z) { struct payload { int32_t x; int32_t y; int32_t z; tc_chunk_s *result; } payload; payload.x = x; payload.y = y; payload.z = z; payload.result = NULL; tc_on_each_loaded_chunk(world, &tc_check_chunk_coordinate_equality_for_getting_a_loaded_chunk, &payload); return payload.result; } /* tc_chunk_s *chunk = tc_chunk_at_south_east_bottom(world); tc_chunk_grid_distance_s distance = tc_chunk_distance_to( chunk->position.x, chunk->position.y, chunk->position.z, x, y, z ); while(distance.x > 0) { chunk = chunk->east; --distance.x; } while(distance.y > 0) { chunk = chunk->top; --distance.y; } while(distance.z > 0) { chunk = chunk->north; --distance.z; } return chunk; void tc_reassociate_surrounding_chunks(tc_chunk_s *old_chunk, tc_chunk_s *chunk) { if(old_chunk->top != NULL) old_chunk->top->bottom = chunk; if(old_chunk->bottom != NULL) old_chunk->bottom->top = chunk; if(old_chunk->east != NULL) old_chunk->east->west = chunk; if(old_chunk->west != NULL) old_chunk->west->east = chunk; if(old_chunk->north != NULL) old_chunk->north->south = chunk; if(old_chunk->south != NULL) old_chunk->south->north = chunk; } */ void tc_place_chunk_at(tc_world_s *world, tc_chunk_s *chunk, int32_t x, int32_t y, int32_t z) { tc_chunk_s *old_chunk = tc_get_loaded_chunk_at(world, x, y, z); // tc_reassociate_surrounding_chunks(old_chunk, chunk); tc_free_chunk(world, old_chunk); } tc_chunk_s * tc_create_chunk_at(tc_world_s *world, int32_t x, int32_t y, int32_t z) { tc_chunk_s *chunk = tc_allocate_chunk(world); chunk->position.x = x; chunk->position.y = y; chunk->position.z = z; world->worldgen->fn_generate_chunk(world->worldgen, chunk); tc_upload_chunk(chunk); tc_place_chunk_at(world, chunk, x, y, z); return chunk; } tc_chunk_s * tc_load_chunk_at(tc_world_s *world, int32_t x, int32_t y, int32_t z) { if(!tc_chunk_is_loaded(world, x, y, z)) { return tc_create_chunk_at(world, x, y, z); } return tc_get_loaded_chunk_at(world, x, y, z); } // Creates & Generates a chunk and provides a pointer to it tc_chunk_s * tc_new_chunk(tc_world_s *world, int32_t x, int32_t y, int32_t z) { tc_chunk_s *chunk = tc_allocate_chunk(world); chunk->position.x = x; chunk->position.y = y; chunk->position.z = z; world->worldgen->fn_generate_chunk(world->worldgen, chunk); return chunk; } /*c_ void tc_shift_chunks_on_axis_x(tc_world_s *world, int32_t difference) { } void tc_shift_chunks_on_axis_y(tc_world_s *world, int32_t difference) { } // Go one further west with loading void tc_shift_loading_one_west(tc_world_s *world) { tc_chunk_s *north_eastern = world->center_chunk; while(north_eastern->east != NULL) north_eastern = north_eastern->east; while(north_eastern->north != NULL) north_eastern = north_eastern->north; tc_chunk_s *north_western = world->center_chunk; while(north_western->west != NULL) north_western = north_western->west; while(north_western->north != NULL) north_western = north_western->north; tc_chunk_s *eastern_edge = north_eastern; while((eastern_edge != NULL) && (western_edge != NULL)) { eastern_west = western_edge; eastern_edge = eastern_edge->south; western_edge = western_edge->south; } // Load new row while(north_eastern != NULL) { north_ north_eastern = north_eastern->south; } tc_load_chunk(); } void tc_shift_chunks_on_axis_z(tc_world_s *world, int32_t difference) { if(difference > 0) { for(; difference > 0; --difference) tc_shift_one_west(world); } if(difference < 0) { for(; difference < 0; ++difference) tc_shift_one_east(world); } } */ tc_chunk_s * tc_reload_chunk_of_loader(tc_chunkloader_s *loader, int32_t x, int32_t y, int32_t z) { } void tc_reload_chunkloader_zone(tc_world_s *world, tc_chunkloader_s *chunkloader) { int32_t last_x = chunkloader->center_x + chunkloader->width; int32_t last_y = chunkloader->center_y + chunkloader->height; int32_t last_z = chunkloader->center_z + chunkloader->depth; int32_t chunk_x = chunkloader->center_x - chunkloader->width; while(chunk_x < last_x) { int32_t chunk_y = chunkloader->center_y - chunkloader->height; while(chunk_y < last_y) { int32_t chunk_z = chunkloader->center_z - chunkloader->depth; while(chunk_z < last_z) { tc_chunk_s *chunk = tc_get_loaded_chunk_at(world, chunk_x, chunk_y, chunk_z); if(chunk == NULL) { chunk = tc_allocate_chunk(world); chunk->position.x = chunk_x; chunk->position.y = chunk_y; chunk->position.z = chunk_z; tc_add_chunk_to_loader(chunkloader, world); } ++chunk_z; } ++chunk_y; } ++chunk_x; } } void tc_update_world(tc_world_s *world) { uint32_t chunkloader_index = 0; while(chunkloader_index < world->num_loaders) { if(world->loaders[chunkloader_index].needs_reload) { tc_reload_chunkloader_zone(world, &world->loaders[chunkloader_index]); } ++chunkloader_index; } } // TODO: Set center chunk