218 lines
7 KiB
C
218 lines
7 KiB
C
#include "pxl8_sys.h"
|
|
#include "pxl8_log.h"
|
|
#include "pxl8_mem.h"
|
|
#include "pxl8_script.h"
|
|
|
|
#include "demo3d_net.h"
|
|
#include "demo3d_world.h"
|
|
|
|
static const char* demo3d_ffi_cdefs =
|
|
"typedef struct demo3d_bsp demo3d_bsp;\n"
|
|
"\n"
|
|
"u32 demo3d_bsp_face_count(const demo3d_bsp* bsp);\n"
|
|
"pxl8_vec3 demo3d_bsp_face_normal(const demo3d_bsp* bsp, u32 face_id);\n"
|
|
"void demo3d_bsp_face_set_material(demo3d_bsp* bsp, u32 face_id, u16 material_id);\n"
|
|
"u8 demo3d_bsp_light_at(const demo3d_bsp* bsp, f32 x, f32 y, f32 z, u8 ambient);\n"
|
|
"\n"
|
|
"typedef struct demo3d_chunk {\n"
|
|
" u32 id;\n"
|
|
" u32 version;\n"
|
|
" demo3d_bsp* bsp;\n"
|
|
"} demo3d_chunk;\n"
|
|
"\n"
|
|
"typedef struct demo3d_world demo3d_world;\n"
|
|
"\n"
|
|
"typedef struct pxl8_ray {\n"
|
|
" pxl8_vec3 normal;\n"
|
|
" pxl8_vec3 point;\n"
|
|
" float fraction;\n"
|
|
" bool hit;\n"
|
|
"} pxl8_ray;\n"
|
|
"\n"
|
|
"demo3d_world* demo3d_get_world(pxl8* sys);\n"
|
|
"demo3d_chunk* demo3d_world_active_chunk(demo3d_world* world);\n"
|
|
"bool demo3d_world_point_solid(const demo3d_world* world, float x, float y, float z);\n"
|
|
"pxl8_ray demo3d_world_ray(const demo3d_world* world, pxl8_vec3 from, pxl8_vec3 to);\n"
|
|
"pxl8_ray demo3d_world_sweep(const demo3d_world* world, pxl8_vec3 from, pxl8_vec3 to, float radius);\n"
|
|
"void demo3d_world_render(demo3d_world* world, pxl8_gfx* gfx, pxl8_vec3 camera_pos);\n"
|
|
"void demo3d_world_set_bsp_material(demo3d_world* world, u16 material_id, const pxl8_gfx_material* material);\n"
|
|
"\n"
|
|
"typedef struct demo3d_sim_entity {\n"
|
|
" pxl8_vec3 pos;\n"
|
|
" pxl8_vec3 vel;\n"
|
|
" f32 yaw;\n"
|
|
" f32 pitch;\n"
|
|
" u32 flags;\n"
|
|
" u16 kind;\n"
|
|
" u16 _pad;\n"
|
|
"} demo3d_sim_entity;\n"
|
|
"\n"
|
|
"void demo3d_world_init_local_player(demo3d_world* world, f32 x, f32 y, f32 z);\n"
|
|
"void demo3d_world_set_look(demo3d_world* world, f32 yaw, f32 pitch);\n"
|
|
"demo3d_sim_entity* demo3d_world_local_player(demo3d_world* world);\n"
|
|
"\n"
|
|
"typedef struct demo3d_input_msg {\n"
|
|
" u32 buttons;\n"
|
|
" f32 look_dx;\n"
|
|
" f32 look_dy;\n"
|
|
" f32 move_x;\n"
|
|
" f32 move_y;\n"
|
|
" f32 yaw;\n"
|
|
" u64 tick;\n"
|
|
" u64 timestamp;\n"
|
|
"} demo3d_input_msg;\n"
|
|
"\n"
|
|
"typedef struct demo3d_sim_config {\n"
|
|
" f32 move_speed;\n"
|
|
" f32 ground_accel;\n"
|
|
" f32 air_accel;\n"
|
|
" f32 stop_speed;\n"
|
|
" f32 friction;\n"
|
|
" f32 gravity;\n"
|
|
" f32 jump_velocity;\n"
|
|
" f32 player_radius;\n"
|
|
" f32 player_height;\n"
|
|
" f32 max_pitch;\n"
|
|
"} demo3d_sim_config;\n"
|
|
"\n"
|
|
"typedef struct demo3d_sim_world {\n"
|
|
" const demo3d_bsp* chunks[9];\n"
|
|
" i32 center_cx;\n"
|
|
" i32 center_cz;\n"
|
|
" f32 chunk_size;\n"
|
|
"} demo3d_sim_world;\n"
|
|
"\n"
|
|
"void demo3d_sim_move_player(demo3d_sim_entity* ent, const demo3d_input_msg* input, const demo3d_sim_world* world, const demo3d_sim_config* cfg, f32 dt);\n"
|
|
"void demo3d_sim_integrate(demo3d_sim_entity* ent, const demo3d_sim_world* world, const demo3d_sim_config* cfg, f32 dt);\n"
|
|
"pxl8_vec3 demo3d_sim_trace(const demo3d_sim_world* world, pxl8_vec3 from, pxl8_vec3 to, f32 radius, f32 height);\n"
|
|
"bool demo3d_sim_check_ground(const demo3d_sim_world* world, pxl8_vec3 pos, f32 radius);\n"
|
|
"\n"
|
|
"demo3d_sim_world demo3d_world_sim_world(const demo3d_world* world, pxl8_vec3 pos);\n"
|
|
"void demo3d_world_set_sim_config(demo3d_world* world, const demo3d_sim_config* config);\n"
|
|
"void demo3d_world_push_input(demo3d_world* world, const demo3d_input_msg* input);\n"
|
|
"\n"
|
|
"typedef struct demo3d_net demo3d_net;\n"
|
|
"\n"
|
|
"typedef struct demo3d_entity_state {\n"
|
|
" u64 entity_id;\n"
|
|
" u8 userdata[56];\n"
|
|
"} demo3d_entity_state;\n"
|
|
"\n"
|
|
"typedef struct demo3d_snapshot_header {\n"
|
|
" u16 entity_count;\n"
|
|
" u16 event_count;\n"
|
|
" u64 player_id;\n"
|
|
" u64 tick;\n"
|
|
" f32 time;\n"
|
|
"} demo3d_snapshot_header;\n"
|
|
"\n"
|
|
"demo3d_net* demo3d_get_net(pxl8* sys);\n"
|
|
"bool demo3d_net_connected(const demo3d_net* ng);\n"
|
|
"i32 demo3d_net_spawn(demo3d_net* ng, f32 x, f32 y, f32 z, f32 yaw, f32 pitch);\n"
|
|
"bool demo3d_net_has_chunk(const demo3d_net* ng);\n"
|
|
"i32 demo3d_net_chunk_cx(const demo3d_net* ng);\n"
|
|
"i32 demo3d_net_chunk_cz(const demo3d_net* ng);\n"
|
|
"const demo3d_entity_state* demo3d_net_entities(const demo3d_net* ng);\n"
|
|
"u64 demo3d_net_player_id(const demo3d_net* ng);\n"
|
|
"const u8* demo3d_net_entity_userdata(const demo3d_net* ng, u64 entity_id);\n"
|
|
"const u8* demo3d_net_entity_prev_userdata(const demo3d_net* ng, u64 entity_id);\n"
|
|
"f32 demo3d_net_lerp_alpha(const demo3d_net* ng);\n"
|
|
"const demo3d_snapshot_header* demo3d_net_snapshot(const demo3d_net* ng);\n"
|
|
;
|
|
|
|
typedef struct demo3d_state {
|
|
demo3d_net* net;
|
|
demo3d_world* world;
|
|
} demo3d_state;
|
|
|
|
static pxl8_result demo3d_init(pxl8_game* game, void* userdata) {
|
|
(void)userdata;
|
|
demo3d_state* state = pxl8_calloc(1, sizeof(demo3d_state));
|
|
if (!state) return PXL8_ERROR_INITIALIZATION_FAILED;
|
|
game->userdata = state;
|
|
|
|
pxl8_script_add_ffi(game->script, demo3d_ffi_cdefs);
|
|
|
|
state->world = demo3d_world_create();
|
|
if (!state->world) {
|
|
pxl8_error("failed to create world");
|
|
return PXL8_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
|
|
pxl8_net_config net_cfg = { .address = "127.0.0.1", .port = 7777 };
|
|
state->net = demo3d_net_create(&net_cfg);
|
|
if (state->net) {
|
|
demo3d_net_set_chunk_cache(state->net, demo3d_world_get_chunk_cache(state->world));
|
|
demo3d_net_set_world(state->net, state->world);
|
|
demo3d_net_connect(state->net);
|
|
}
|
|
|
|
#ifdef PXL8_ASYNC_THREADS
|
|
if (state->net) {
|
|
demo3d_net_start_thread(state->net);
|
|
}
|
|
if (state->world) {
|
|
demo3d_world_start_sim_thread(state->world, state->net);
|
|
}
|
|
#endif
|
|
|
|
return PXL8_OK;
|
|
}
|
|
|
|
static void demo3d_update(pxl8_game* game, f32 dt, void* userdata) {
|
|
(void)userdata;
|
|
demo3d_state* state = (demo3d_state*)game->userdata;
|
|
|
|
#ifdef PXL8_ASYNC_THREADS
|
|
demo3d_net_update(state->net, dt);
|
|
#else
|
|
if (state->net) {
|
|
while (demo3d_net_poll(state->net)) {}
|
|
demo3d_net_update(state->net, dt);
|
|
demo3d_world_sync(state->world, state->net);
|
|
}
|
|
demo3d_world_update(state->world, dt);
|
|
#endif
|
|
}
|
|
|
|
static void demo3d_quit(pxl8_game* game, void* userdata) {
|
|
(void)userdata;
|
|
demo3d_state* state = (demo3d_state*)game->userdata;
|
|
if (!state) return;
|
|
|
|
#ifdef PXL8_ASYNC_THREADS
|
|
if (state->world) {
|
|
demo3d_world_stop_sim_thread(state->world);
|
|
}
|
|
if (state->net) {
|
|
demo3d_net_stop_thread(state->net);
|
|
}
|
|
#endif
|
|
|
|
if (state->net) demo3d_net_destroy(state->net);
|
|
if (state->world) demo3d_world_destroy(state->world);
|
|
|
|
pxl8_free(state);
|
|
game->userdata = NULL;
|
|
}
|
|
|
|
demo3d_net* demo3d_get_net(pxl8* sys) {
|
|
pxl8_game* game = pxl8_get_game(sys);
|
|
if (!game || !game->userdata) return NULL;
|
|
return ((demo3d_state*)game->userdata)->net;
|
|
}
|
|
|
|
demo3d_world* demo3d_get_world(pxl8* sys) {
|
|
pxl8_game* game = pxl8_get_game(sys);
|
|
if (!game || !game->userdata) return NULL;
|
|
return ((demo3d_state*)game->userdata)->world;
|
|
}
|
|
|
|
void pxl8_register_game(pxl8* sys) {
|
|
pxl8_game_hooks hooks = {
|
|
.init = demo3d_init,
|
|
.update = demo3d_update,
|
|
.quit = demo3d_quit,
|
|
};
|
|
pxl8_set_game_hooks(sys, hooks);
|
|
}
|