179 lines
6.0 KiB
C
179 lines
6.0 KiB
C
#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;
|
|
}
|
|
}
|
|
|
|
|
|
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)
|
|
{
|
|
printf("Creating chunk at: %d %d %d\n", coord.x, coord.y, coord.z);
|
|
|
|
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_free_chunk(loader->world, loader->chunks[index]);
|
|
|
|
// 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))
|
|
{
|
|
printf("Chunk at %d %d %d isn't in range\n", chunk->position.x, chunk->position.y, chunk->position.z);
|
|
tc_remove_loaders_chunk(loader, chunk_index);
|
|
}
|
|
}
|
|
}
|
|
|
|
void tc_load_all_chunks_of_chunkloader(tc_chunkloader_s *loader)
|
|
{
|
|
for(uint32_t x = 0; x < loader->extent.x; ++x)
|
|
{
|
|
for(uint32_t y = 0; y < loader->extent.y; ++y)
|
|
{
|
|
for(uint32_t z = 0; z < loader->extent.z; ++z)
|
|
{
|
|
tc_vec3i_s coords;
|
|
/*
|
|
coords.x = ((x + loader->center.x) - (loader->extent.x / 2)) + loader->extent.x;
|
|
coords.y = ((y + loader->center.y) - (loader->extent.y / 2)) + loader->extent.y;
|
|
coords.z = ((z + loader->center.z) - (loader->extent.z / 2)) + loader->extent.z;
|
|
*/
|
|
coords.x = loader->center.x + (x - (loader->extent.x / 2));
|
|
coords.y = loader->center.y + (y - (loader->extent.y / 2));
|
|
coords.z = loader->center.z + (z - (loader->extent.z / 2));
|
|
|
|
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);
|
|
}
|
|
|
|
void tc_update_world(tc_world_s *world)
|
|
{
|
|
world->loaders[0].center.x = world->loading_center.x;
|
|
world->loaders[0].center.y = world->loading_center.y;
|
|
world->loaders[0].center.z = world->loading_center.z;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
// TODO: Set center chunk
|