#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); }