pxl8/demo3d/client/demo3d.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);
}