Techneck/code/source-c/chunk_loading.c

325 lines
9.7 KiB
C
Raw Normal View History

2023-10-12 16:52:05 +00:00
#include "world.h"
#include <stdlib.h>
#include <stdio.h>
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