diff --git a/code/game/header/entity_view.h b/code/game/header/entity_view.h index d78593e..b8cb745 100644 --- a/code/game/header/entity_view.h +++ b/code/game/header/entity_view.h @@ -35,6 +35,10 @@ typedef struct entity_view { float tx; float ty; + // TODO(zaklaus): Find a way to stream dynamic arrays + uint8_t blocks_used; + uint8_t blocks[256]; + // NOTE(zaklaus): internals uint8_t layer_id; uint64_t last_update; diff --git a/code/game/header/packet_utils.h b/code/game/header/packet_utils.h index 60ea95c..43b9cd6 100644 --- a/code/game/header/packet_utils.h +++ b/code/game/header/packet_utils.h @@ -97,6 +97,10 @@ static inline int32_t pkt_world_write(pkt_messages id, size_t pkt_size, int8_t i #define PKT_ARRAY(t, a) .type = CWP_ITEM_BIN, .offset = PKT_OFFSETOF(t, a), .size = PKT_FIELD_SIZEOF(t,a), .it_size = PKT_FIELD_SIZEOF(t,a[0]), .name = #a #endif +#ifndef PKT_SKIP_IF +#define PKT_SKIP_IF(t, a, e, n) .skip_count = n, .offset = PKT_OFFSETOF(t, a), .skip_eq = e, .name = #a +#endif + #ifndef PKT_END #define PKT_END .type = CWP_NOT_AN_ITEM #endif @@ -111,8 +115,10 @@ typedef struct pkt_desc { size_t offset; size_t size; size_t it_size; + size_t skip_count; + uint8_t skip_eq; } pkt_desc; - + int32_t pkt_unpack_struct(cw_unpack_context *uc, pkt_desc *desc, void *raw_blob, uint32_t blob_size); int32_t pkt_pack_struct(cw_pack_context *pc, pkt_desc *desc, void *raw_blob, uint32_t blob_size); diff --git a/code/game/source/debug_ui.c b/code/game/source/debug_ui.c index 8aaa05c..b9fe4ff 100644 --- a/code/game/source/debug_ui.c +++ b/code/game/source/debug_ui.c @@ -185,16 +185,16 @@ void debug_draw(void) { color = RED; is_handle_ctrl_held = 1; } - + if (is_handle_ctrl_held) { debug_xpos = xpos = GetMouseX() - DBG_CTRL_HANDLE_DIM/2; debug_ypos = ypos = GetMouseY() - DBG_CTRL_HANDLE_DIM/2; - + if (area == DAREA_PRESS) { is_handle_ctrl_held = 0; } } - + DrawRectangle(xpos, ypos, DBG_CTRL_HANDLE_DIM, DBG_CTRL_HANDLE_DIM, color); } diff --git a/code/game/source/entity_view.c b/code/game/source/entity_view.c index 172e7d3..a77e8f7 100644 --- a/code/game/source/entity_view.c +++ b/code/game/source/entity_view.c @@ -10,6 +10,8 @@ pkt_desc pkt_entity_view_desc[] = { { PKT_HALF(entity_view, y) }, { PKT_HALF(entity_view, vx) }, { PKT_HALF(entity_view, vy) }, + { PKT_SKIP_IF(entity_view, blocks_used, 0, 1) }, + { PKT_ARRAY(entity_view, blocks) }, { PKT_END }, }; diff --git a/code/game/source/main.c b/code/game/source/main.c index cab296d..a81ec2c 100644 --- a/code/game/source/main.c +++ b/code/game/source/main.c @@ -31,7 +31,7 @@ int main(int argc, char** argv) { zpl_opts_add(&opts, "ed", "enable-dash", "enables flecs dash", ZPL_OPTS_FLAG); zpl_opts_add(&opts, "s", "seed", "world seed", ZPL_OPTS_INT); zpl_opts_add(&opts, "r", "random-seed", "generate random world seed", ZPL_OPTS_FLAG); - zpl_opts_add(&opts, "cs", "chunk-size", "amount of blocks within a chunk (single axis)", ZPL_OPTS_INT); + //zpl_opts_add(&opts, "cs", "chunk-size", "amount of blocks within a chunk (single axis)", ZPL_OPTS_INT); zpl_opts_add(&opts, "ws", "world-size", "amount of chunks within a world (single axis)", ZPL_OPTS_INT); zpl_opts_add(&opts, "n", "npc-count", "amount of demo npcs to spawn", ZPL_OPTS_INT); @@ -47,7 +47,7 @@ int main(int argc, char** argv) { int8_t is_dash_enabled = zpl_opts_has_arg(&opts, "enable-dash"); int32_t seed = zpl_opts_integer(&opts, "seed", DEFAULT_WORLD_SEED); uint16_t num_viewers = zpl_opts_integer(&opts, "viewer-count", 1); - uint16_t chunk_size = zpl_opts_integer(&opts, "chunk-size", DEFAULT_CHUNK_SIZE); + uint16_t chunk_size = DEFAULT_CHUNK_SIZE; //zpl_opts_integer(&opts, "chunk-size", DEFAULT_CHUNK_SIZE); uint16_t world_size = zpl_opts_integer(&opts, "world-size", DEFAULT_WORLD_SIZE); uint32_t npc_count = zpl_opts_integer(&opts, "npc-count", 1000); diff --git a/code/game/source/packet.c b/code/game/source/packet.c index d31de97..f031fcb 100644 --- a/code/game/source/packet.c +++ b/code/game/source/packet.c @@ -32,12 +32,12 @@ int32_t pkt_header_encode(pkt_messages id, uint16_t view_id, void *data, size_t int32_t pkt_header_decode(pkt_header *table, void *data, size_t datalen) { cw_unpack_context uc = {0}; pkt_unpack_msg_raw(&uc, data, datalen, PKT_HEADER_ELEMENTS); - + cw_unpack_next(&uc); if (uc.item.type != CWP_ITEM_POSITIVE_INTEGER || uc.item.as.u64 > UINT16_MAX) { return -1; // invalid packet id } - + uint16_t pkt_id = (uint16_t)uc.item.as.u64; cw_unpack_next(&uc); @@ -50,13 +50,13 @@ int32_t pkt_header_decode(pkt_header *table, void *data, size_t datalen) { cw_unpack_next(&uc); const void *packed_blob = uc.item.as.bin.start; uint32_t packed_size = uc.item.as.bin.length; - + table->id = pkt_id; table->view_id = view_id; table->data = packed_blob; table->datalen = packed_size; table->ok = 1; - + return pkt_validate_eof_msg(&uc) != -1; } @@ -64,6 +64,11 @@ int32_t pkt_unpack_struct(cw_unpack_context *uc, pkt_desc *desc, void *raw_blob, uint8_t *blob = (uint8_t*)raw_blob; for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field) { cw_unpack_next(uc); + if (field->skip_count) { + if (uc->item.type != CWP_ITEM_POSITIVE_INTEGER) return -1; // unexpected field + field += uc->item.as.u64; + continue; + } if (uc->item.type != field->type) return -1; // unexpected field if (blob + field->offset + field->size > blob + blob_size) return -1; // field does not fit switch (field->type) { @@ -99,6 +104,18 @@ int32_t pkt_unpack_struct(cw_unpack_context *uc, pkt_desc *desc, void *raw_blob, int32_t pkt_pack_struct(cw_pack_context *pc, pkt_desc *desc, void *raw_blob, uint32_t blob_size) { uint8_t *blob = (uint8_t*)raw_blob; for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field) { + if (field->skip_count) { + uint8_t val = *(uint8_t*)(blob + field->offset); + if (val == field->skip_eq) { + field += field->skip_count; + cw_pack_unsigned(pc, field->skip_count); + } else { + cw_pack_unsigned(pc, 0); + } + + continue; + } + switch (field->type) { case CWP_ITEM_BIN: { if (field->size >= PKT_BUFSIZ) return -1; // bin blob too big @@ -140,6 +157,14 @@ void pkt_dump_struct(pkt_desc *desc, void* raw_blob, uint32_t blob_size) { uint8_t *blob = (uint8_t*)raw_blob; zpl_printf("{\n"); for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field) { + if (field->skip_count) { + uint8_t val = *(uint8_t*)(blob + field->offset); + if (val == field->skip_eq) { + field += field->skip_count; + } + + continue; + } zpl_printf(" \"%s\": ", field->name); switch (field->type) { case CWP_ITEM_BIN: { diff --git a/code/game/source/platform_raylib.c b/code/game/source/platform_raylib.c index bca70ee..424fc73 100644 --- a/code/game/source/platform_raylib.c +++ b/code/game/source/platform_raylib.c @@ -56,7 +56,7 @@ void platform_shutdown() { assets_destroy(); CloseWindow(); } - + uint8_t platform_is_running() { return !WindowShouldClose(); } @@ -123,11 +123,11 @@ void platform_render() { } render_camera.zoom = zpl_lerp(render_camera.zoom, target_zoom, 0.18); camera_update(); - + camera game_camera = camera_get(); render_camera.target = (Vector2){game_camera.x, game_camera.y}; zoom_overlay_tran = zpl_lerp(zoom_overlay_tran, (target_zoom <= CAM_OVERLAY_ZOOM_LEVEL) ? 1.0f : 0.0f, GetFrameTime()*2.0f); - + BeginDrawing(); profile (PROF_RENDER) { ClearBackground(GetColor(0x222034)); @@ -167,7 +167,7 @@ void DEBUG_draw_ground(uint64_t key, entity_view * data) { float x = data->x * size + offset; float y = data->y * size + offset; - + DrawRectangleEco(x, y, size-offset, size-offset, ColorAlpha(LIME, data->tran_time)); #if 0 @@ -182,11 +182,11 @@ void DEBUG_draw_ground(uint64_t key, entity_view * data) { DrawRectangleEco(bx, by, block_size, block_size, GREEN); } #endif - + if (zoom_overlay_tran > 0.02f) { DrawRectangleEco(x, y, size-offset, size-offset, ColorAlpha(ColorFromHSV(key*x, 0.13f, 0.89f), data->tran_time*zoom_overlay_tran)); - DrawTextEco(TextFormat("%d %d", (int)data->x, (int)data->y), (int16_t)x+15, (int16_t)y+15, 65 , ColorAlpha(BLACK, data->tran_time*zoom_overlay_tran), 0.0); + DrawTextEco(TextFormat("%d %d", (int)data->x, (int)data->y), (int16_t)x+15, (int16_t)y+15, 200 , ColorAlpha(BLACK, data->tran_time*zoom_overlay_tran), 0.0); } }break; diff --git a/code/game/source/world/world.c b/code/game/source/world/world.c index 0d2f46b..f5c72ce 100644 --- a/code/game/source/world/world.c +++ b/code/game/source/world/world.c @@ -39,6 +39,11 @@ entity_view world_build_entity_view(int64_t e) { view.kind = EKIND_CHUNK; view.x = chpos->x; view.y = chpos->y; + view.blocks_used = 1; + + for (int i = 0; i < world.chunk_size*world.chunk_size; i += 1) { + view.blocks[i] = *ecs_vector_get(chpos->blocks, uint8_t, i); + } } return view; @@ -134,10 +139,10 @@ int32_t world_init(int32_t seed, uint16_t chunk_size, uint16_t chunk_amount) { ECS_IMPORT(world.ecs, General); ECS_IMPORT(world.ecs, Net); world.ecs_update = ecs_query_new(world.ecs, "net.ClientInfo, general.Position"); - + int32_t world_build_status = worldgen_test(&world); ZPL_ASSERT(world_build_status >= 0); - + for (int i = 0; i < world.chunk_amount * world.chunk_amount; ++i) { ecs_entity_t e = ecs_new(world.ecs, 0); Chunk *chunk = ecs_get_mut(world.ecs, e, Chunk, NULL); @@ -146,13 +151,17 @@ int32_t world_init(int32_t seed, uint16_t chunk_size, uint16_t chunk_amount) { librg_chunk_to_chunkpos(world.tracker, i, &chunk->x, &chunk->y, NULL); chunk->blocks = NULL; - // TODO(zaklaus): populate chunks from worldgen - for (int j = 0; j < world.chunk_size * world.chunk_size; j += 1) { - uint8_t *c = ecs_vector_add(&chunk->blocks, uint8_t); - *c = 0; + for (int y = 0; y < world.chunk_size; y += 1) { + for (int x = 0; x < world.chunk_size; x += 1) { + int chk = world.chunk_size * i; + int chk_x = chk % world.chunk_amount; + int chk_y = chk / world.chunk_amount; + uint8_t *c = ecs_vector_add(&chunk->blocks, uint8_t); + *c = world.data[(chk_y+y)*world.chunk_amount + (chk_x+x)]; + } } } - + zpl_printf("[INFO] Created a new server world\n"); return world_build_status; @@ -171,36 +180,36 @@ int32_t world_destroy(void) { static void world_tracker_update(uint8_t ticker, uint32_t freq, uint8_t radius) { if (world.tracker_update[ticker] > zpl_time_rel_ms()) return; - world.tracker_update[ticker] = zpl_time_rel_ms() + freq; + world.tracker_update[ticker] = zpl_time_rel_ms() + freq; profile(PROF_WORLD_WRITE) { ECS_IMPORT(world.ecs, General); ECS_IMPORT(world.ecs, Net); - + ecs_iter_t it = ecs_query_iter(world.ecs_update); static char buffer[WORLD_LIBRG_BUFSIZ] = {0}; world.active_layer_id = ticker; - + while (ecs_query_next(&it)) { ClientInfo *p = ecs_column(&it, ClientInfo, 1); - + for (int i = 0; i < it.count; i++) { size_t datalen = WORLD_LIBRG_BUFSIZ; - + // TODO(zaklaus): SUPER TEMPORARY HOT !!! simulate variable radius queries { librg_entity_radius_set(world_tracker(), p[i].peer, radius); } - + // TODO(zaklaus): push radius once librg patch comes in int32_t result = librg_world_write(world_tracker(), p[i].peer, buffer, &datalen, NULL); - + if (result > 0) { zpl_printf("[info] buffer size was not enough, please increase it by at least: %d\n", result); } else if (result < 0) { zpl_printf("[error] an error happened writing the world %d\n", result); } - + pkt_send_librg_update((uint64_t)p[i].peer, p[i].view_id, ticker, buffer, datalen); } } @@ -212,7 +221,7 @@ int32_t world_update() { profile (PROF_UPDATE_SYSTEMS) { ecs_progress(world.ecs, 0.0f); } - + world_tracker_update(0, WORLD_TRACKER_UPDATE_FAST_MS, 2); world_tracker_update(1, WORLD_TRACKER_UPDATE_NORMAL_MS, 4); world_tracker_update(2, WORLD_TRACKER_UPDATE_SLOW_MS, 6); diff --git a/code/modules/modules/controllers.h b/code/modules/modules/controllers.h index 001042f..bb26e95 100644 --- a/code/modules/modules/controllers.h +++ b/code/modules/modules/controllers.h @@ -3,11 +3,11 @@ #include "flecs/flecs_meta.h" ECS_STRUCT(Input, { - float x; - float y; - uint8_t use; - uint8_t sprint; -}); + float x; + float y; + uint8_t use; + uint8_t sprint; + }); typedef struct { ECS_DECLARE_COMPONENT(Input); @@ -22,14 +22,14 @@ typedef struct { } Controllers; #define ControllersImportHandles(handles)\ - ECS_IMPORT_COMPONENT(handles, Input);\ - ECS_IMPORT_TYPE(handles, Player);\ - ECS_IMPORT_TYPE(handles, Builder);\ - ECS_IMPORT_ENTITY(handles, EcsActor);\ - ECS_IMPORT_ENTITY(handles, EcsPlayer);\ - ECS_IMPORT_ENTITY(handles, EcsBuilder);\ - ECS_IMPORT_ENTITY(handles, EcsDemoNPC);\ - ECS_IMPORT_ENTITY(handles, MovementImpulse);\ - ECS_IMPORT_ENTITY(handles, DemoNPCMoveAround);\ +ECS_IMPORT_COMPONENT(handles, Input);\ +ECS_IMPORT_TYPE(handles, Player);\ +ECS_IMPORT_TYPE(handles, Builder);\ +ECS_IMPORT_ENTITY(handles, EcsActor);\ +ECS_IMPORT_ENTITY(handles, EcsPlayer);\ +ECS_IMPORT_ENTITY(handles, EcsBuilder);\ +ECS_IMPORT_ENTITY(handles, EcsDemoNPC);\ +ECS_IMPORT_ENTITY(handles, MovementImpulse);\ +ECS_IMPORT_ENTITY(handles, DemoNPCMoveAround);\ void ControllersImport(ecs_world_t *ecs); diff --git a/code/modules/source/controllers.c b/code/modules/source/controllers.c index 1f06bb4..3631d78 100644 --- a/code/modules/source/controllers.c +++ b/code/modules/source/controllers.c @@ -35,13 +35,13 @@ void DemoNPCMoveAround(ecs_iter_t *it) { void ControllersImport(ecs_world_t *ecs) { ECS_MODULE(ecs, Controllers); ecs_set_name_prefix(ecs, "Controllers"); - + ECS_IMPORT(ecs, General); ECS_IMPORT(ecs, Physics); ECS_IMPORT(ecs, FlecsMeta); - + ECS_META(ecs, Input); - + ECS_TAG(ecs, EcsActor); ECS_TAG(ecs, EcsPlayer); ECS_TAG(ecs, EcsBuilder); @@ -49,11 +49,11 @@ void ControllersImport(ecs_world_t *ecs) { ECS_SYSTEM(ecs, MovementImpulse, EcsOnUpdate, Input, physics.Velocity); ECS_SYSTEM(ecs, DemoNPCMoveAround, EcsOnUpdate, physics.Velocity, EcsDemoNPC); - + ECS_PREFAB(ecs, Base, general.Position, physics.Velocity, Input, EcsActor); ECS_TYPE(ecs, Player, INSTANCEOF | Base, SWITCH | physics.Movement, CASE | physics.Walking, EcsActor, EcsPlayer); ECS_TYPE(ecs, Builder, INSTANCEOF | Base, SWITCH | physics.Movement, CASE | physics.Flying, EcsActor, EcsBuilder); - + ECS_SET_COMPONENT(Input); ECS_SET_ENTITY(EcsActor); ECS_SET_ENTITY(EcsPlayer); @@ -61,5 +61,4 @@ void ControllersImport(ecs_world_t *ecs) { ECS_SET_ENTITY(EcsDemoNPC); ECS_SET_TYPE(Builder); ECS_SET_TYPE(Player); - ECS_SET_ENTITY(MovementImpulse); } diff --git a/code/modules/source/physics.c b/code/modules/source/physics.c index 34fa36a..6ea45dc 100644 --- a/code/modules/source/physics.c +++ b/code/modules/source/physics.c @@ -7,7 +7,7 @@ void MoveWalk(ecs_iter_t *it) { Position *p = ecs_column(it, Position, 1); Velocity *v = ecs_column(it, Velocity, 2); - + for (int i = 0; i < it->count; i++) { p[i].x += v[i].x * it->delta_time; p[i].y += v[i].y * it->delta_time; @@ -18,7 +18,6 @@ void MoveWalk(ecs_iter_t *it) { void HandleCollisions(ecs_iter_t *it) { Position *p = ecs_column(it, Position, 1); - //Velocity *v = ecs_column(it, Velocity, 2); for (int i = 0; i < it->count; i++) { // NOTE(zaklaus): world bounds @@ -45,13 +44,13 @@ void PhysicsImport(ecs_world_t *ecs) { ECS_TAG(ecs, Walking); ECS_TAG(ecs, Flying); ECS_TYPE(ecs, Movement, Walking, Flying); - + ECS_META(ecs, Velocity); - + ECS_SYSTEM(ecs, MoveWalk, EcsOnUpdate, general.Position, Velocity); ECS_SYSTEM(ecs, HandleCollisions, EcsOnValidate, general.Position, Velocity); ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, general.Position); - + ECS_SET_TYPE(Movement); ECS_SET_ENTITY(Walking); ECS_SET_ENTITY(Flying);