added basic prediction + pkt_dump_struct
parent
c5df24cefc
commit
7d1e5c1d61
|
@ -6,6 +6,7 @@ add_library(client-common STATIC
|
||||||
source/game.c
|
source/game.c
|
||||||
source/camera.c
|
source/camera.c
|
||||||
source/world_view.c
|
source/world_view.c
|
||||||
|
source/prediction.c
|
||||||
|
|
||||||
source/utils/options.c
|
source/utils/options.c
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
#include "entity_view.h"
|
||||||
|
|
||||||
|
float smooth_val(float cur, float tgt, float dt);
|
||||||
|
void predict_receive_update(entity_view *d, entity_view *data);
|
|
@ -86,6 +86,10 @@ void game_world_view_set_active_by_idx(uint16_t idx) {
|
||||||
game_world_view_set_active(&world_viewers[idx]);
|
game_world_view_set_active(&world_viewers[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game_world_view_active_entity_map(void (*map_proc)(uint64_t key, entity_view value)) {
|
||||||
|
entity_view_map(&active_viewer->entities, map_proc);
|
||||||
|
}
|
||||||
|
|
||||||
void game_world_view_set_active(world_view *view) {
|
void game_world_view_set_active(world_view *view) {
|
||||||
active_viewer = view;
|
active_viewer = view;
|
||||||
camera_set_follow(view->owner_id);
|
camera_set_follow(view->owner_id);
|
||||||
|
@ -146,12 +150,13 @@ void game_input() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_update() {
|
void game_update() {
|
||||||
if (is_viewer_only) network_client_tick();
|
if (is_viewer_only) {
|
||||||
|
network_client_tick();
|
||||||
|
}
|
||||||
else world_update();
|
else world_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_render() {
|
void game_render() {
|
||||||
camera_update();
|
|
||||||
platform_render();
|
platform_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ int main(int argc, char** argv)
|
||||||
zpl_opts_add(&opts, "bs", "block-size", "amount of units within a block (single axis)", ZPL_OPTS_INT);
|
zpl_opts_add(&opts, "bs", "block-size", "amount of units within a block (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, "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, "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);
|
||||||
|
|
||||||
uint32_t ok = zpl_opts_compile(&opts, argc, argv);
|
uint32_t ok = zpl_opts_compile(&opts, argc, argv);
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ int main(int argc, char** argv)
|
||||||
uint16_t block_size = zpl_opts_integer(&opts, "block-size", DEFAULT_BLOCK_SIZE);
|
uint16_t block_size = zpl_opts_integer(&opts, "block-size", DEFAULT_BLOCK_SIZE);
|
||||||
uint16_t chunk_size = zpl_opts_integer(&opts, "chunk-size", DEFAULT_CHUNK_SIZE);
|
uint16_t chunk_size = zpl_opts_integer(&opts, "chunk-size", DEFAULT_CHUNK_SIZE);
|
||||||
uint16_t world_size = zpl_opts_integer(&opts, "world-size", DEFAULT_WORLD_SIZE);
|
uint16_t world_size = zpl_opts_integer(&opts, "world-size", DEFAULT_WORLD_SIZE);
|
||||||
|
uint32_t npc_count = zpl_opts_integer(&opts, "npc-count", 100);
|
||||||
|
|
||||||
if (zpl_opts_has_arg(&opts, "random-seed")) {
|
if (zpl_opts_has_arg(&opts, "random-seed")) {
|
||||||
zpl_random rnd={0};
|
zpl_random rnd={0};
|
||||||
|
@ -72,7 +74,7 @@ int main(int argc, char** argv)
|
||||||
ECS_IMPORT(world_ecs(), Controllers);
|
ECS_IMPORT(world_ecs(), Controllers);
|
||||||
ECS_IMPORT(world_ecs(), Physics);
|
ECS_IMPORT(world_ecs(), Physics);
|
||||||
uint16_t half_world_dim = world_dim() / 2;
|
uint16_t half_world_dim = world_dim() / 2;
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < npc_count; i++) {
|
||||||
uint64_t e = entity_spawn(NULL);
|
uint64_t e = entity_spawn(NULL);
|
||||||
ecs_add(world_ecs(), e, EcsDemoNPC);
|
ecs_add(world_ecs(), e, EcsDemoNPC);
|
||||||
Position *pos = ecs_get_mut(world_ecs(), e, Position, NULL);
|
Position *pos = ecs_get_mut(world_ecs(), e, Position, NULL);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "entity_view.h"
|
#include "entity_view.h"
|
||||||
|
#include "prediction.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ void DrawRectangleEco(int posX, int posY, int width, int height, Color color)
|
||||||
|
|
||||||
void platform_init() {
|
void platform_init() {
|
||||||
InitWindow(screenWidth, screenHeight, "eco2d - client");
|
InitWindow(screenWidth, screenHeight, "eco2d - client");
|
||||||
SetWindowState(FLAG_WINDOW_UNDECORATED|FLAG_WINDOW_HIGHDPI|FLAG_WINDOW_MAXIMIZED|FLAG_WINDOW_RESIZABLE);
|
SetWindowState(FLAG_WINDOW_UNDECORATED|FLAG_WINDOW_MAXIMIZED|FLAG_WINDOW_RESIZABLE);
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
|
|
||||||
screenWidth = GetScreenWidth();
|
screenWidth = GetScreenWidth();
|
||||||
|
@ -61,6 +62,17 @@ void platform_init() {
|
||||||
render_camera.offset = (Vector2){screenWidth/2.0f, screenHeight/2.0f};
|
render_camera.offset = (Vector2){screenWidth/2.0f, screenHeight/2.0f};
|
||||||
render_camera.rotation = 0.0f;
|
render_camera.rotation = 0.0f;
|
||||||
render_camera.zoom = 4.0f/GFX_WORLD_SCALE;
|
render_camera.zoom = 4.0f/GFX_WORLD_SCALE;
|
||||||
|
|
||||||
|
// NOTE(zaklaus): Paint the screen before we load the game
|
||||||
|
// TODO(zaklaus): Render a cool loading screen background maybe? :wink: :wink:
|
||||||
|
|
||||||
|
BeginDrawing();
|
||||||
|
ClearBackground(GetColor(0x222034));
|
||||||
|
|
||||||
|
char const *loading_text = "zpl.eco2d is loading...";
|
||||||
|
int text_w = MeasureText(loading_text, 120);
|
||||||
|
DrawText(loading_text, GetScreenWidth()-text_w-15, GetScreenHeight()-135, 120, RAYWHITE);
|
||||||
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform_shutdown() {
|
void platform_shutdown() {
|
||||||
|
@ -122,15 +134,20 @@ void display_conn_status();
|
||||||
void DEBUG_draw_entities(uint64_t key, entity_view data);
|
void DEBUG_draw_entities(uint64_t key, entity_view data);
|
||||||
void DEBUG_draw_ground(uint64_t key, entity_view data);
|
void DEBUG_draw_ground(uint64_t key, entity_view data);
|
||||||
|
|
||||||
|
void lerp_entity_positions(uint64_t key, entity_view data);
|
||||||
|
|
||||||
void platform_render() {
|
void platform_render() {
|
||||||
|
game_world_view_active_entity_map(lerp_entity_positions);
|
||||||
|
camera_update();
|
||||||
|
|
||||||
camera game_camera = camera_get();
|
camera game_camera = camera_get();
|
||||||
render_camera.target = (Vector2){game_camera.x * GFX_WORLD_SCALE, game_camera.y * GFX_WORLD_SCALE};
|
render_camera.target = (Vector2){game_camera.x * GFX_WORLD_SCALE, game_camera.y * GFX_WORLD_SCALE};
|
||||||
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(BLACK);
|
ClearBackground(GetColor(0x222034));
|
||||||
BeginMode2D(render_camera);
|
BeginMode2D(render_camera);
|
||||||
entity_view_map(&game_world_view_get_active()->entities, DEBUG_draw_ground);
|
game_world_view_active_entity_map(DEBUG_draw_ground);
|
||||||
entity_view_map(&game_world_view_get_active()->entities, DEBUG_draw_entities);
|
game_world_view_active_entity_map(DEBUG_draw_entities);
|
||||||
EndMode2D();
|
EndMode2D();
|
||||||
display_conn_status();
|
display_conn_status();
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
|
@ -164,6 +181,7 @@ void DEBUG_draw_ground(uint64_t key, entity_view data) {
|
||||||
|
|
||||||
double x = data.x * size + offset;
|
double x = data.x * size + offset;
|
||||||
double y = data.y * size + offset;
|
double y = data.y * size + offset;
|
||||||
|
DrawRectangleEco((int)x-offset, (int)y-offset, size+offset, size+offset, BLACK);
|
||||||
DrawRectangleEco((int)x, (int)y, size-offset, size-offset, LIME);
|
DrawRectangleEco((int)x, (int)y, size-offset, size-offset, LIME);
|
||||||
|
|
||||||
for (uint16_t i = 0; i < chunk_size*chunk_size; i++) {
|
for (uint16_t i = 0; i < chunk_size*chunk_size; i++) {
|
||||||
|
@ -210,4 +228,15 @@ void DEBUG_draw_entities(uint64_t key, entity_view data) {
|
||||||
}break;
|
}break;
|
||||||
default:break;
|
default:break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lerp_entity_positions(uint64_t key, entity_view data) {
|
||||||
|
world_view *view = game_world_view_get_active();
|
||||||
|
|
||||||
|
if (data.flag == EFLAG_INTERP) {
|
||||||
|
entity_view *e = entity_view_get(&view->entities, key);
|
||||||
|
|
||||||
|
e->x = smooth_val(e->x, e->tx, 0);
|
||||||
|
e->y = smooth_val(e->y, e->ty, 0);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include "zpl.h"
|
||||||
|
#include "prediction.h"
|
||||||
|
#include "world/world.h"
|
||||||
|
|
||||||
|
#define PREDICT_SMOOTH_FACTOR_LO 0.8
|
||||||
|
#define PREDICT_SMOOTH_FACTOR_HI 0.12
|
||||||
|
|
||||||
|
float smooth_val(float cur, float tgt, float dt) {
|
||||||
|
#if 0
|
||||||
|
return zpl_lerp(cur, tgt, zpl_lerp(PREDICT_SMOOTH_FACTOR_HI, PREDICT_SMOOTH_FACTOR_LO, zpl_unlerp(dt, WORLD_TRACKER_UPDATE_FAST_MS, WORLD_TRACKER_UPDATE_SLOW_MS)));
|
||||||
|
#endif
|
||||||
|
return zpl_lerp(cur, tgt, PREDICT_SMOOTH_FACTOR_HI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void predict_receive_update(entity_view *d, entity_view *data) {
|
||||||
|
if (d && data->flag & EFLAG_INTERP) {
|
||||||
|
// NOTE(zaklaus): store target pos but keep x,y unchanged
|
||||||
|
float tx = data->x;
|
||||||
|
float ty = data->y;
|
||||||
|
data->x = d->x;
|
||||||
|
data->y = d->y;
|
||||||
|
data->tx = tx;
|
||||||
|
data->ty = ty;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
#include "world_view.h"
|
#include "world_view.h"
|
||||||
|
#include "entity_view.h"
|
||||||
|
#include "prediction.h"
|
||||||
#include "librg.h"
|
#include "librg.h"
|
||||||
#include "zpl.h"
|
#include "zpl.h"
|
||||||
|
|
||||||
|
@ -19,6 +21,8 @@ int32_t tracker_read_update(librg_world *w, librg_event *e) {
|
||||||
world_view *view = (world_view*)librg_world_userdata_get(w);
|
world_view *view = (world_view*)librg_world_userdata_get(w);
|
||||||
|
|
||||||
entity_view data = entity_view_unpack_struct(buffer, actual_length);
|
entity_view data = entity_view_unpack_struct(buffer, actual_length);
|
||||||
|
entity_view *d = entity_view_get(&view->entities, entity_id);
|
||||||
|
predict_receive_update(d, &data);
|
||||||
entity_view_update_or_create(&view->entities, entity_id, data);
|
entity_view_update_or_create(&view->entities, entity_id, data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +36,10 @@ int32_t tracker_read_create(librg_world *w, librg_event *e) {
|
||||||
world_view *view = (world_view*)librg_world_userdata_get(w);
|
world_view *view = (world_view*)librg_world_userdata_get(w);
|
||||||
|
|
||||||
entity_view data = entity_view_unpack_struct(buffer, actual_length);
|
entity_view data = entity_view_unpack_struct(buffer, actual_length);
|
||||||
|
if (data.flag & EFLAG_INTERP) {
|
||||||
|
data.tx = data.x;
|
||||||
|
data.ty = data.y;
|
||||||
|
}
|
||||||
entity_view_update_or_create(&view->entities, entity_id, data);
|
entity_view_update_or_create(&view->entities, entity_id, data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,11 @@ ZPL_TABLE_DEFINE(entity_view_tbl, entity_view_tbl_, entity_view);
|
||||||
|
|
||||||
pkt_desc pkt_entity_view_desc[] = {
|
pkt_desc pkt_entity_view_desc[] = {
|
||||||
{ PKT_UINT(entity_view, kind) },
|
{ PKT_UINT(entity_view, kind) },
|
||||||
{ PKT_REAL(entity_view, x) },
|
{ PKT_UINT(entity_view, flag) },
|
||||||
{ PKT_REAL(entity_view, y) },
|
{ PKT_HALF(entity_view, x) },
|
||||||
|
{ PKT_HALF(entity_view, y) },
|
||||||
|
{ PKT_HALF(entity_view, vx) },
|
||||||
|
{ PKT_HALF(entity_view, vy) },
|
||||||
{ PKT_END },
|
{ PKT_END },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,6 +26,7 @@ entity_view entity_view_unpack_struct(void *data, size_t len) {
|
||||||
|
|
||||||
entity_view view = {0};
|
entity_view view = {0};
|
||||||
pkt_unpack_struct(&uc, pkt_entity_view_desc, PKT_STRUCT_PTR(&view));
|
pkt_unpack_struct(&uc, pkt_entity_view_desc, PKT_STRUCT_PTR(&view));
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,16 +7,26 @@
|
||||||
#include "packet_utils.h"
|
#include "packet_utils.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EKIND_PLAYER,
|
EKIND_PLAYER = 0,
|
||||||
EKIND_THING,
|
EKIND_THING,
|
||||||
EKIND_CHUNK,
|
EKIND_CHUNK,
|
||||||
FORCE_EKIND_UINT16 = UINT16_MAX
|
FORCE_EKIND_UINT16 = UINT16_MAX
|
||||||
} entity_kind;
|
} entity_kind;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EFLAG_INTERP = (1 << 0),
|
||||||
|
FORCE_EFLAG_UINT16 = UINT16_MAX
|
||||||
|
} entity_flag;
|
||||||
|
|
||||||
typedef struct entity_view {
|
typedef struct entity_view {
|
||||||
entity_kind kind;
|
entity_kind kind;
|
||||||
|
entity_flag flag;
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
|
float vx;
|
||||||
|
float vy;
|
||||||
|
float tx;
|
||||||
|
float ty;
|
||||||
} entity_view;
|
} entity_view;
|
||||||
|
|
||||||
ZPL_TABLE_DECLARE(, entity_view_tbl, entity_view_tbl_, entity_view);
|
ZPL_TABLE_DECLARE(, entity_view_tbl, entity_view_tbl_, entity_view);
|
||||||
|
|
|
@ -18,6 +18,7 @@ world_view *game_world_view_get(uint16_t idx);
|
||||||
void game_world_view_set_active_by_idx(uint16_t idx);
|
void game_world_view_set_active_by_idx(uint16_t idx);
|
||||||
void game_world_view_set_active(world_view *view);
|
void game_world_view_set_active(world_view *view);
|
||||||
void game_world_view_cycle_active(uint8_t dir);
|
void game_world_view_cycle_active(uint8_t dir);
|
||||||
|
void game_world_view_active_entity_map(void (*map_proc)(uint64_t key, entity_view value));
|
||||||
|
|
||||||
//~ NOTE(zaklaus): viewer -> host actions
|
//~ NOTE(zaklaus): viewer -> host actions
|
||||||
void game_action_send_keystate(float x, float y, uint8_t use, uint8_t sprint);
|
void game_action_send_keystate(float x, float y, uint8_t use, uint8_t sprint);
|
|
@ -135,3 +135,33 @@ int32_t pkt_pack_struct(cw_pack_context *pc, pkt_desc *desc, void *raw_blob, uin
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
zpl_printf(" \"%s\": ", field->name);
|
||||||
|
switch (field->type) {
|
||||||
|
case CWP_ITEM_BIN: {
|
||||||
|
// TODO(zaklaus): print memory dump as array of hex bytes
|
||||||
|
}break;
|
||||||
|
case CWP_ITEM_POSITIVE_INTEGER: {
|
||||||
|
zpl_printf("%u\n", *(uint64_t*)(blob + field->offset));
|
||||||
|
}break;
|
||||||
|
case CWP_ITEM_NEGATIVE_INTEGER: {
|
||||||
|
zpl_printf("%d\n", *(int64_t*)(blob + field->offset));
|
||||||
|
}break;
|
||||||
|
case CWP_ITEM_FLOAT: {
|
||||||
|
zpl_printf("%f\n", *(float*)(blob + field->offset));
|
||||||
|
}break;
|
||||||
|
case CWP_ITEM_DOUBLE: {
|
||||||
|
zpl_printf("%f\n", *(double*)(blob + field->offset));
|
||||||
|
}break;
|
||||||
|
default: {
|
||||||
|
zpl_printf("[WARN] unsupported pkt field type %lld !\n", field->type);
|
||||||
|
return; // unsupported field
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zpl_printf("}\n");
|
||||||
|
}
|
|
@ -74,27 +74,27 @@ static inline int32_t pkt_world_write(pkt_messages id, size_t pkt_size, int8_t i
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PKT_FIELD
|
#ifndef PKT_FIELD
|
||||||
#define PKT_FIELD(k, t, a) .type = k, .offset = PKT_OFFSETOF(t, a), .size = PKT_FIELD_SIZEOF(t,a), .it_size = PKT_FIELD_SIZEOF(t,a)
|
#define PKT_FIELD(k, t, a) .type = k, .offset = PKT_OFFSETOF(t, a), .size = PKT_FIELD_SIZEOF(t,a), .it_size = PKT_FIELD_SIZEOF(t,a), .name = #a
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PKT_UINT
|
#ifndef PKT_UINT
|
||||||
#define PKT_UINT(t, a) .type = CWP_ITEM_POSITIVE_INTEGER, .offset = PKT_OFFSETOF(t, a), .size = PKT_FIELD_SIZEOF(t,a), .it_size = PKT_FIELD_SIZEOF(t,a)
|
#define PKT_UINT(t, a) .type = CWP_ITEM_POSITIVE_INTEGER, .offset = PKT_OFFSETOF(t, a), .size = PKT_FIELD_SIZEOF(t,a), .it_size = PKT_FIELD_SIZEOF(t,a), .name = #a
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PKT_SINT
|
#ifndef PKT_SINT
|
||||||
#define PKT_SINT(t, a) .type = CWP_ITEM_NEGATIVE_INTEGER, .offset = PKT_OFFSETOF(t, a), .size = PKT_FIELD_SIZEOF(t,a), .it_size = PKT_FIELD_SIZEOF(t,a)
|
#define PKT_SINT(t, a) .type = CWP_ITEM_NEGATIVE_INTEGER, .offset = PKT_OFFSETOF(t, a), .size = PKT_FIELD_SIZEOF(t,a), .it_size = PKT_FIELD_SIZEOF(t,a), .name = #a
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PKT_REAL
|
#ifndef PKT_REAL
|
||||||
#define PKT_REAL(t, a) .type = CWP_ITEM_DOUBLE, .offset = PKT_OFFSETOF(t, a), .size = PKT_FIELD_SIZEOF(t,a), .it_size = PKT_FIELD_SIZEOF(t,a)
|
#define PKT_REAL(t, a) .type = CWP_ITEM_DOUBLE, .offset = PKT_OFFSETOF(t, a), .size = PKT_FIELD_SIZEOF(t,a), .it_size = PKT_FIELD_SIZEOF(t,a), .name = #a
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PKT_HALF
|
#ifndef PKT_HALF
|
||||||
#define PKT_HALF(t, a) .type = CWP_ITEM_FLOAT, .offset = PKT_OFFSETOF(t, a), .size = PKT_FIELD_SIZEOF(t,a), .it_size = PKT_FIELD_SIZEOF(t,a)
|
#define PKT_HALF(t, a) .type = CWP_ITEM_FLOAT, .offset = PKT_OFFSETOF(t, a), .size = PKT_FIELD_SIZEOF(t,a), .it_size = PKT_FIELD_SIZEOF(t,a), .name = #a
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PKT_ARRAY
|
#ifndef PKT_ARRAY
|
||||||
#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])
|
#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
|
#endif
|
||||||
|
|
||||||
#ifndef PKT_END
|
#ifndef PKT_END
|
||||||
|
@ -106,6 +106,7 @@ static inline int32_t pkt_world_write(pkt_messages id, size_t pkt_size, int8_t i
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct pkt_desc {
|
typedef struct pkt_desc {
|
||||||
|
const char *name;
|
||||||
cwpack_item_types type;
|
cwpack_item_types type;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
@ -127,3 +128,5 @@ static inline size_t pkt_pack_desc_args(pkt_desc *desc) {
|
||||||
for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field, ++cnt) {}
|
for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field, ++cnt) {}
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pkt_dump_struct(pkt_desc *desc, void* raw_blob, uint32_t blob_size);
|
|
@ -2,6 +2,7 @@
|
||||||
#include "librg.h"
|
#include "librg.h"
|
||||||
#include "modules/general.h"
|
#include "modules/general.h"
|
||||||
#include "modules/net.h"
|
#include "modules/net.h"
|
||||||
|
#include "modules/physics.h"
|
||||||
#include "world/world.h"
|
#include "world/world.h"
|
||||||
#include "entity_view.h"
|
#include "entity_view.h"
|
||||||
|
|
||||||
|
@ -24,14 +25,11 @@ typedef struct {
|
||||||
|
|
||||||
static world_data world = {0};
|
static world_data world = {0};
|
||||||
|
|
||||||
#define WORLD_TRACKER_UPDATE_FAST_MS 10
|
|
||||||
#define WORLD_TRACKER_UPDATE_NORMAL_MS 100
|
|
||||||
#define WORLD_TRACKER_UPDATE_SLOW_MS 800
|
|
||||||
|
|
||||||
int32_t world_gen();
|
int32_t world_gen();
|
||||||
|
|
||||||
entity_view world_build_entity_view(int64_t e) {
|
entity_view world_build_entity_view(int64_t e) {
|
||||||
ECS_IMPORT(world_ecs(), General);
|
ECS_IMPORT(world_ecs(), General);
|
||||||
|
ECS_IMPORT(world_ecs(), Physics);
|
||||||
ECS_IMPORT(world_ecs(), Net);
|
ECS_IMPORT(world_ecs(), Net);
|
||||||
entity_view view = {0};
|
entity_view view = {0};
|
||||||
|
|
||||||
|
@ -41,7 +39,13 @@ entity_view world_build_entity_view(int64_t e) {
|
||||||
view.kind = ecs_has(world_ecs(), e, EcsClient) ? EKIND_PLAYER : EKIND_THING;
|
view.kind = ecs_has(world_ecs(), e, EcsClient) ? EKIND_PLAYER : EKIND_THING;
|
||||||
view.x = pos->x;
|
view.x = pos->x;
|
||||||
view.y = pos->y;
|
view.y = pos->y;
|
||||||
return view;
|
}
|
||||||
|
|
||||||
|
const Velocity *vel = ecs_get(world_ecs(), e, Velocity);
|
||||||
|
if (vel) {
|
||||||
|
view.flag |= EFLAG_INTERP;
|
||||||
|
view.vx = vel->x;
|
||||||
|
view.vy = vel->y;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Chunk *chpos = ecs_get(world_ecs(), e, Chunk);
|
const Chunk *chpos = ecs_get(world_ecs(), e, Chunk);
|
||||||
|
@ -49,7 +53,6 @@ entity_view world_build_entity_view(int64_t e) {
|
||||||
view.kind = EKIND_CHUNK;
|
view.kind = EKIND_CHUNK;
|
||||||
view.x = chpos->x;
|
view.x = chpos->x;
|
||||||
view.y = chpos->y;
|
view.y = chpos->y;
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
|
@ -91,7 +94,7 @@ int32_t world_init(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint1
|
||||||
world.chunk_amount = chunk_amount;
|
world.chunk_amount = chunk_amount;
|
||||||
|
|
||||||
world.block_size = block_size;
|
world.block_size = block_size;
|
||||||
world.dim = (world.chunk_size * world.chunk_amount);;
|
world.dim = (world.chunk_size * world.chunk_amount);
|
||||||
world.size = world.dim * world.dim;
|
world.size = world.dim * world.dim;
|
||||||
|
|
||||||
if (world.tracker == NULL) {
|
if (world.tracker == NULL) {
|
||||||
|
@ -104,8 +107,8 @@ int32_t world_init(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint1
|
||||||
}
|
}
|
||||||
|
|
||||||
/* config our world grid */
|
/* config our world grid */
|
||||||
librg_config_chunksize_set(world.tracker, block_size * chunk_size, block_size * chunk_size, 0);
|
librg_config_chunksize_set(world.tracker, block_size * world.chunk_size, block_size * world.chunk_size, 0);
|
||||||
librg_config_chunkamount_set(world.tracker, chunk_amount, chunk_amount, 0);
|
librg_config_chunkamount_set(world.tracker, world.chunk_amount, world.chunk_amount, 0);
|
||||||
librg_config_chunkoffset_set(world.tracker, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG, 0);
|
librg_config_chunkoffset_set(world.tracker, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG, 0);
|
||||||
|
|
||||||
librg_event_set(world.tracker, LIBRG_WRITE_CREATE, tracker_write_create);
|
librg_event_set(world.tracker, LIBRG_WRITE_CREATE, tracker_write_create);
|
||||||
|
@ -120,10 +123,12 @@ int32_t world_init(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint1
|
||||||
|
|
||||||
world.ecs = ecs_init();
|
world.ecs = ecs_init();
|
||||||
ecs_set_entity_range(world.ecs, 0, UINT32_MAX);
|
ecs_set_entity_range(world.ecs, 0, UINT32_MAX);
|
||||||
|
int32_t world_build_status = world_gen();
|
||||||
|
ZPL_ASSERT(world_build_status >= 0);
|
||||||
|
|
||||||
ECS_IMPORT(world.ecs, General);
|
ECS_IMPORT(world.ecs, General);
|
||||||
|
|
||||||
for (int i = 0; i < chunk_amount * chunk_amount; ++i) {
|
for (int i = 0; i < world.chunk_amount * world.chunk_amount; ++i) {
|
||||||
ecs_entity_t e = ecs_new(world.ecs, 0);
|
ecs_entity_t e = ecs_new(world.ecs, 0);
|
||||||
Chunk *chunk = ecs_get_mut(world.ecs, e, Chunk, NULL);
|
Chunk *chunk = ecs_get_mut(world.ecs, e, Chunk, NULL);
|
||||||
librg_entity_track(world.tracker, e);
|
librg_entity_track(world.tracker, e);
|
||||||
|
@ -133,7 +138,7 @@ int32_t world_init(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint1
|
||||||
|
|
||||||
zpl_printf("[INFO] Created a new server world\n");
|
zpl_printf("[INFO] Created a new server world\n");
|
||||||
|
|
||||||
return world_gen();
|
return world_build_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t world_destroy(void) {
|
int32_t world_destroy(void) {
|
||||||
|
@ -181,8 +186,8 @@ static void world_tracker_update(uint8_t ticker, uint8_t freq, uint8_t radius) {
|
||||||
int32_t world_update() {
|
int32_t world_update() {
|
||||||
ecs_progress(world.ecs, 0);
|
ecs_progress(world.ecs, 0);
|
||||||
|
|
||||||
world_tracker_update(0, WORLD_TRACKER_UPDATE_FAST_MS, 2);
|
//world_tracker_update(0, WORLD_TRACKER_UPDATE_FAST_MS, 2);
|
||||||
//world_tracker_update(1, WORLD_TRACKER_UPDATE_NORMAL_MS, 4);
|
world_tracker_update(1, WORLD_TRACKER_UPDATE_NORMAL_MS, 4);
|
||||||
//world_tracker_update(2, WORLD_TRACKER_UPDATE_SLOW_MS, 6);
|
//world_tracker_update(2, WORLD_TRACKER_UPDATE_SLOW_MS, 6);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
#define WORLD_ERROR_INVALID_BUFFER -0x0004
|
#define WORLD_ERROR_INVALID_BUFFER -0x0004
|
||||||
#define WORLD_ERROR_TRACKER_FAILED -0x0005
|
#define WORLD_ERROR_TRACKER_FAILED -0x0005
|
||||||
|
|
||||||
|
#define WORLD_TRACKER_UPDATE_FAST_MS 10
|
||||||
|
#define WORLD_TRACKER_UPDATE_NORMAL_MS 100
|
||||||
|
#define WORLD_TRACKER_UPDATE_SLOW_MS 800
|
||||||
|
|
||||||
#define WORLD_PKT_READER(name) int32_t name(void* data, uint32_t datalen, void *udata)
|
#define WORLD_PKT_READER(name) int32_t name(void* data, uint32_t datalen, void *udata)
|
||||||
typedef WORLD_PKT_READER(world_pkt_reader_proc);
|
typedef WORLD_PKT_READER(world_pkt_reader_proc);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "flecs/flecs.h"
|
#include "flecs/flecs.h"
|
||||||
#include "flecs/flecs_meta.h"
|
#include "flecs/flecs_meta.h"
|
||||||
|
#include "world/world.h"
|
||||||
|
|
||||||
ECS_STRUCT(Vector2D, {
|
ECS_STRUCT(Vector2D, {
|
||||||
float x;
|
float x;
|
||||||
|
@ -10,6 +11,7 @@ ECS_STRUCT(Vector2D, {
|
||||||
ECS_STRUCT(Chunk, {
|
ECS_STRUCT(Chunk, {
|
||||||
int16_t x;
|
int16_t x;
|
||||||
int16_t y;
|
int16_t y;
|
||||||
|
ecs_vector(uint8_t) blocks;
|
||||||
});
|
});
|
||||||
|
|
||||||
ECS_STRUCT(Drawable, {
|
ECS_STRUCT(Drawable, {
|
||||||
|
|
Loading…
Reference in New Issue