PKT: chunk block streaming + pkt enhancements
parent
e056395f8f
commit
ee794495e9
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 },
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue