2025-11-13 07:15:41 -06:00
|
|
|
#include "pxl8_world.h"
|
|
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
#include <stdio.h>
|
2025-10-07 10:32:48 -05:00
|
|
|
|
2025-12-02 11:02:23 -06:00
|
|
|
#include "pxl8_log.h"
|
2026-01-21 23:19:50 -06:00
|
|
|
#include "pxl8_mem.h"
|
2025-10-07 10:32:48 -05:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
#define PXL8_WORLD_ENTITY_CAPACITY 256
|
|
|
|
|
|
2025-10-07 10:32:48 -05:00
|
|
|
struct pxl8_world {
|
2026-01-25 09:26:30 -06:00
|
|
|
pxl8_chunk* active_chunk;
|
|
|
|
|
pxl8_block_registry* block_registry;
|
|
|
|
|
pxl8_chunk_cache* chunk_cache;
|
|
|
|
|
pxl8_entity_pool* entities;
|
2025-10-07 10:32:48 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pxl8_world* pxl8_world_create(void) {
|
2026-01-25 09:26:30 -06:00
|
|
|
pxl8_world* world = pxl8_calloc(1, sizeof(pxl8_world));
|
|
|
|
|
if (!world) return NULL;
|
|
|
|
|
|
|
|
|
|
world->block_registry = pxl8_block_registry_create();
|
|
|
|
|
world->chunk_cache = pxl8_chunk_cache_create();
|
|
|
|
|
world->entities = pxl8_entity_pool_create(PXL8_WORLD_ENTITY_CAPACITY);
|
|
|
|
|
|
|
|
|
|
if (!world->block_registry || !world->chunk_cache || !world->entities) {
|
|
|
|
|
pxl8_world_destroy(world);
|
2025-10-07 10:32:48 -05:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return world;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pxl8_world_destroy(pxl8_world* world) {
|
|
|
|
|
if (!world) return;
|
|
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
pxl8_block_registry_destroy(world->block_registry);
|
|
|
|
|
pxl8_chunk_cache_destroy(world->chunk_cache);
|
|
|
|
|
pxl8_entity_pool_destroy(world->entities);
|
2026-01-21 23:19:50 -06:00
|
|
|
pxl8_free(world);
|
2025-10-07 10:32:48 -05:00
|
|
|
}
|
|
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
pxl8_chunk_cache* pxl8_world_chunk_cache(pxl8_world* world) {
|
|
|
|
|
if (!world) return NULL;
|
|
|
|
|
return world->chunk_cache;
|
2025-11-11 21:24:53 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
pxl8_chunk* pxl8_world_active_chunk(pxl8_world* world) {
|
|
|
|
|
if (!world) return NULL;
|
|
|
|
|
return world->active_chunk;
|
2025-11-21 16:44:42 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
void pxl8_world_set_active_chunk(pxl8_world* world, pxl8_chunk* chunk) {
|
|
|
|
|
if (!world) return;
|
|
|
|
|
world->active_chunk = chunk;
|
2025-11-21 16:44:42 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
pxl8_block_registry* pxl8_world_block_registry(pxl8_world* world) {
|
|
|
|
|
if (!world) return NULL;
|
|
|
|
|
return world->block_registry;
|
|
|
|
|
}
|
2025-11-11 21:24:53 -06:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
pxl8_entity_pool* pxl8_world_entities(pxl8_world* world) {
|
|
|
|
|
if (!world) return NULL;
|
|
|
|
|
return world->entities;
|
|
|
|
|
}
|
2025-11-09 06:30:17 -06:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
pxl8_entity pxl8_world_spawn(pxl8_world* world) {
|
|
|
|
|
if (!world || !world->entities) return PXL8_ENTITY_INVALID;
|
|
|
|
|
return pxl8_entity_spawn(world->entities);
|
2025-11-09 06:30:17 -06:00
|
|
|
}
|
|
|
|
|
|
2025-11-21 16:44:42 -06:00
|
|
|
bool pxl8_world_check_collision(const pxl8_world* world, pxl8_vec3 pos, f32 radius) {
|
2026-01-25 09:26:30 -06:00
|
|
|
(void)radius;
|
2025-11-21 16:44:42 -06:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
if (!world || !world->active_chunk) return false;
|
2025-11-21 16:44:42 -06:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
if (world->active_chunk->type == PXL8_CHUNK_BSP && world->active_chunk->bsp) {
|
|
|
|
|
return pxl8_bsp_point_solid(world->active_chunk->bsp, pos);
|
2025-10-07 10:32:48 -05:00
|
|
|
}
|
|
|
|
|
|
2025-11-21 16:44:42 -06:00
|
|
|
return false;
|
|
|
|
|
}
|
2025-10-07 10:32:48 -05:00
|
|
|
|
2025-11-21 16:44:42 -06:00
|
|
|
pxl8_vec3 pxl8_world_resolve_collision(const pxl8_world* world, pxl8_vec3 from, pxl8_vec3 to, f32 radius) {
|
2026-01-25 09:26:30 -06:00
|
|
|
if (!world || !world->active_chunk) return to;
|
2025-11-21 16:44:42 -06:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
if (world->active_chunk->type == PXL8_CHUNK_BSP && world->active_chunk->bsp) {
|
|
|
|
|
return pxl8_bsp_trace(world->active_chunk->bsp, from, to, radius);
|
2025-10-07 10:32:48 -05:00
|
|
|
}
|
|
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
return to;
|
|
|
|
|
}
|
2025-10-07 10:32:48 -05:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
void pxl8_world_update(pxl8_world* world, f32 dt) {
|
|
|
|
|
(void)dt;
|
|
|
|
|
if (!world) return;
|
2025-11-21 16:44:42 -06:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
pxl8_chunk_cache_tick(world->chunk_cache);
|
|
|
|
|
}
|
2025-11-21 16:44:42 -06:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
void pxl8_world_render(pxl8_world* world, pxl8_gfx* gfx, pxl8_vec3 camera_pos) {
|
|
|
|
|
if (!world || !gfx || !world->active_chunk) return;
|
2025-11-21 16:44:42 -06:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
if (world->active_chunk->type == PXL8_CHUNK_BSP && world->active_chunk->bsp) {
|
|
|
|
|
pxl8_bsp_render(gfx, world->active_chunk->bsp, camera_pos);
|
2025-11-21 16:44:42 -06:00
|
|
|
}
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
2025-11-21 16:44:42 -06:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
void pxl8_world_sync(pxl8_world* world, pxl8_net* net) {
|
|
|
|
|
if (!world || !net) return;
|
2025-11-21 16:44:42 -06:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
u8 chunk_type = pxl8_net_chunk_type(net);
|
|
|
|
|
u32 chunk_id = pxl8_net_chunk_id(net);
|
2025-11-21 16:44:42 -06:00
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
if (chunk_type == PXL8_CHUNK_TYPE_BSP && chunk_id != 0) {
|
|
|
|
|
pxl8_chunk* chunk = pxl8_chunk_cache_get_bsp(world->chunk_cache, chunk_id);
|
|
|
|
|
if (chunk && chunk->bsp) {
|
|
|
|
|
if (world->active_chunk != chunk) {
|
|
|
|
|
world->active_chunk = chunk;
|
|
|
|
|
pxl8_debug("[CLIENT] Synced BSP chunk id=%u as active (verts=%u faces=%u)",
|
|
|
|
|
chunk_id, chunk->bsp->num_vertices, chunk->bsp->num_faces);
|
2025-11-21 16:44:42 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-10-07 10:32:48 -05:00
|
|
|
}
|