diff --git a/CMakeLists.txt b/CMakeLists.txt index d310dec..873d290 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,5 +19,5 @@ add_subdirectory(code/common) add_subdirectory(code/vendors) add_subdirectory(code/apps/client) -add_subdirectory(code/apps/server) -add_subdirectory(code/apps/playground) +#add_subdirectory(code/apps/server) +#add_subdirectory(code/apps/playground) diff --git a/code/apps/client/CMakeLists.txt b/code/apps/client/CMakeLists.txt index e707f6d..ffa6701 100644 --- a/code/apps/client/CMakeLists.txt +++ b/code/apps/client/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(client-common STATIC source/main.c source/camera.c source/entity_view.c + source/world_view.c source/utils/options.c diff --git a/code/apps/client/header/entity_view.h b/code/apps/client/header/entity_view.h index 8e19444..ddef911 100644 --- a/code/apps/client/header/entity_view.h +++ b/code/apps/client/header/entity_view.h @@ -11,11 +11,11 @@ typedef struct entity_view { ZPL_TABLE_DECLARE(, entity_view_tbl, entity_view_tbl_, entity_view); -void entity_view_init(void); -void entity_view_free(void); +void entity_view_init(entity_view_tbl *map); +void entity_view_free(entity_view_tbl *map); -void entity_view_update_or_create(uint64_t ent_id, entity_view data); -void entity_view_destroy(uint64_t ent_id); +void entity_view_update_or_create(entity_view_tbl *map, uint64_t ent_id, entity_view data); +void entity_view_destroy(entity_view_tbl *map, uint64_t ent_id); -entity_view *entity_view_get(uint64_t ent_id); -void entity_view_map(void (*map_proc)(uint64_t key, entity_view value)); +entity_view *entity_view_get(entity_view_tbl *map, uint64_t ent_id); +void entity_view_map(entity_view_tbl *map, void (*map_proc)(uint64_t key, entity_view value)); diff --git a/code/apps/client/header/world_view.h b/code/apps/client/header/world_view.h new file mode 100644 index 0000000..611ff0a --- /dev/null +++ b/code/apps/client/header/world_view.h @@ -0,0 +1,14 @@ +#pragma once +#include "system.h" +#include "entity_view.h" +#include "world/world.h" + +typedef struct { + uint64_t owner_id; + entity_view_tbl entities; + librg_world *tracker; +} world_view; + +world_view world_view_create(void); +void world_view_init(world_view *view, uint64_t ent_id, uint16_t block_size, uint16_t chunk_size, uint16_t world_size); +void world_view_destroy(world_view *view); diff --git a/code/apps/client/source/camera.c b/code/apps/client/source/camera.c index 2af9030..f4d7dee 100644 --- a/code/apps/client/source/camera.c +++ b/code/apps/client/source/camera.c @@ -1,6 +1,7 @@ #include "zpl.h" #include "camera.h" #include "entity_view.h" +#include "game.h" static camera main_camera; @@ -12,7 +13,7 @@ void camera_reset(void) { void camera_update(void) { switch (main_camera.mode) { case CAMERA_MODE_FOLLOW: { - entity_view *view = entity_view_get(main_camera.ent_id); + entity_view *view = entity_view_get(game_world_view_get_active(), main_camera.ent_id); if (!view) break; main_camera.x = view->x; diff --git a/code/apps/client/source/entity_view.c b/code/apps/client/source/entity_view.c index d54aaab..7c6c0b5 100644 --- a/code/apps/client/source/entity_view.c +++ b/code/apps/client/source/entity_view.c @@ -2,29 +2,26 @@ ZPL_TABLE_DEFINE(entity_view_tbl, entity_view_tbl_, entity_view); -static entity_view_tbl cli_entities = {0}; - - -void entity_view_init(void) { - entity_view_tbl_init(&cli_entities, zpl_heap()); +void entity_view_init(entity_view_tbl *map) { + entity_view_tbl_init(map, zpl_heap()); } -void entity_view_free(void) { - entity_view_tbl_destroy(&cli_entities); +void entity_view_free(entity_view_tbl *map) { + entity_view_tbl_destroy(map); } -void entity_view_update_or_create(uint64_t ent_id, entity_view data) { - entity_view_tbl_set(&cli_entities, ent_id, data); +void entity_view_update_or_create(entity_view_tbl *map, uint64_t ent_id, entity_view data) { + entity_view_tbl_set(map, ent_id, data); } -void entity_view_destroy(uint64_t ent_id) { - entity_view_tbl_remove(&cli_entities, ent_id); +void entity_view_destroy(entity_view_tbl *map, uint64_t ent_id) { + entity_view_tbl_remove(map, ent_id); } -entity_view *entity_view_get(uint64_t ent_id) { - return entity_view_tbl_get(&cli_entities, ent_id); +entity_view *entity_view_get(entity_view_tbl *map, uint64_t ent_id) { + return entity_view_tbl_get(map, ent_id); } -void entity_view_map(void (*map_proc)(uint64_t key, entity_view value)) { - entity_view_tbl_map(&cli_entities, map_proc); +void entity_view_map(entity_view_tbl *map, void (*map_proc)(uint64_t key, entity_view value)) { + entity_view_tbl_map(map, map_proc); } diff --git a/code/apps/client/source/game.c b/code/apps/client/source/game.c index 6ca8a15..0f4c272 100644 --- a/code/apps/client/source/game.c +++ b/code/apps/client/source/game.c @@ -1,9 +1,11 @@ #include "game.h" +#include "zpl.h" #include "platform.h" #include "world/world.h" #include "packet.h" #include "signal_handling.h" #include "network.h" +#include "world_view.h" #include "entity_view.h" #include "camera.h" @@ -12,14 +14,18 @@ #include "flecs/flecs_systems_civetweb.h" #include "flecs/flecs_os_api_stdcpp.h" +#include "packets/pkt_00_init.h" #include "packets/pkt_01_welcome.h" static int8_t is_networked_play; -static uint64_t sp_player; + +static world_view *world_viewers; +static world_view *active_viewer; static WORLD_PKT_READER(pkt_reader) { pkt_header header = {0}; uint32_t ok = pkt_header_decode(&header, data, datalen); + header.udata = udata; if (ok && header.ok) { return pkt_handlers[header.id].handler(&header) >= 0; @@ -30,7 +36,7 @@ static WORLD_PKT_READER(pkt_reader) { } static WORLD_PKT_WRITER(sp_pkt_writer) { - return world_read(pkt->data, pkt->datalen, NULL); + return world_read(pkt->data, pkt->datalen, 0); } static WORLD_PKT_WRITER(mp_pkt_writer) { @@ -42,33 +48,57 @@ static WORLD_PKT_WRITER(mp_pkt_writer) { } } -void game_init(int8_t play_mode, int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size) { +void world_viewers_init(uint32_t num_viewers) { + zpl_buffer_init(world_viewers, zpl_heap(), num_viewers); + + for (uint32_t i = 0; i < num_viewers; i++) { + world_viewers[i] = world_view_create(); + } +} + +void world_viewers_destroy() { + for (uint32_t i = 0; i < zpl_buffer_count(world_viewers); i++) { + world_view_destroy(&world_viewers[i]); + } + zpl_buffer_free(world_viewers); +} + +world_view *game_world_view_get(uint16_t idx) { + return &world_viewers[idx]; +} + +world_view *game_world_view_get_active(void) { + return active_viewer; +} + +void flecs_dash_init() { + ECS_IMPORT(world_ecs(), FlecsDash); + ECS_IMPORT(world_ecs(), FlecsSystemsCivetweb); + + ecs_set(world_ecs(), 0, EcsDashServer, {.port = 27001}); + ecs_set_target_fps(world_ecs(), 60); +} + +void game_init(int8_t play_mode, uint32_t num_viewers, int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size) { is_networked_play = play_mode; platform_init(); - entity_view_init(); + world_viewers_init(num_viewers); + active_viewer = &world_viewers[0]; camera_reset(); if (is_networked_play) { - world_init_minimal(0, 0, 0, pkt_reader, mp_pkt_writer); + world_setup_pkt_handlers(pkt_reader, mp_pkt_writer); network_init(); network_client_connect("127.0.0.1", 27000); } else { stdcpp_set_os_api(); - world_init(seed, block_size, chunk_size, world_size, pkt_reader, sp_pkt_writer); - - /* server dashboard */ - { - ECS_IMPORT(world_ecs(), FlecsDash); - ECS_IMPORT(world_ecs(), FlecsSystemsCivetweb); - - ecs_set(world_ecs(), 0, EcsDashServer, {.port = 27001}); - ecs_set_target_fps(world_ecs(), 60); - } - - sp_player = player_spawn("unnamed"); - - pkt_01_welcome table = {.ent_id = 0, .block_size = block_size, .chunk_size = chunk_size, .world_size = world_size}; - pkt_world_write(MSG_ID_01_WELCOME, pkt_01_welcome_encode(&table), 1, NULL); + world_setup_pkt_handlers(pkt_reader, sp_pkt_writer); + world_init(seed, block_size, chunk_size, world_size); + flecs_dash_init(); + } + + for (uint32_t i = 0; i < num_viewers; i++) { + pkt_00_init_send(i); } } @@ -77,13 +107,12 @@ int8_t game_is_networked() { } void game_shutdown() { - entity_view_free(); + world_viewers_destroy(); if (is_networked_play) { network_client_disconnect(); network_destroy(); } else { - player_despawn(sp_player); world_destroy(); } } diff --git a/code/apps/client/source/main.c b/code/apps/client/source/main.c index 19f3211..89df8a0 100644 --- a/code/apps/client/source/main.c +++ b/code/apps/client/source/main.c @@ -16,6 +16,7 @@ int main(int argc, char** argv) zpl_opts_add(&opts, "?", "help", "the HELP section", ZPL_OPTS_FLAG); zpl_opts_add(&opts, "s", "single-player", "play single-player game.", ZPL_OPTS_FLAG); + zpl_opts_add(&opts, "c", "viewer-count", "number of viewers (detachable clients)", ZPL_OPTS_INT); zpl_opts_add(&opts, "p", "preview-map", "draw world preview", 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); @@ -33,6 +34,7 @@ int main(int argc, char** argv) int8_t is_networked_play = !zpl_opts_has_arg(&opts, "single-player"); int32_t seed = zpl_opts_integer(&opts, "seed", DEFAULT_WORLD_SEED); + uint16_t num_viewers = zpl_opts_integer(&opts, "viewer-count", 1); 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 world_size = zpl_opts_integer(&opts, "world-size", DEFAULT_WORLD_SIZE); @@ -50,7 +52,7 @@ int main(int argc, char** argv) } sighandler_register(); - game_init(is_networked_play, seed, block_size, chunk_size, world_size); + game_init(is_networked_play, num_viewers, seed, block_size, chunk_size, world_size); while (game_is_running()) { game_input(); diff --git a/code/apps/client/source/network.c b/code/apps/client/source/network.c index 6bfd535..0a9a7de 100644 --- a/code/apps/client/source/network.c +++ b/code/apps/client/source/network.c @@ -26,6 +26,7 @@ int32_t network_destroy() { } + int32_t network_client_connect(const char *hostname, uint16_t port) { ENetAddress address = {0}; address.port = port; enet_address_set_host(&address, hostname); diff --git a/code/apps/client/source/platform_raylib.c b/code/apps/client/source/platform_raylib.c index 03013fa..e48190f 100644 --- a/code/apps/client/source/platform_raylib.c +++ b/code/apps/client/source/platform_raylib.c @@ -40,7 +40,7 @@ void platform_render() { ClearBackground(BLACK); BeginMode2D(render_camera); DrawRectangleV((Vector2){0,0}, (Vector2){40,40}, RED); - entity_view_map(DEBUG_draw_entities); + entity_view_map(&game_world_view_get_active()->entities, DEBUG_draw_entities); EndMode2D(); display_conn_status(); EndDrawing(); diff --git a/code/apps/client/source/world_view.c b/code/apps/client/source/world_view.c new file mode 100644 index 0000000..b9a057e --- /dev/null +++ b/code/apps/client/source/world_view.c @@ -0,0 +1,56 @@ +#include "world_view.h" +#include "librg.h" + +int32_t tracker_read_create(librg_world *w, librg_event *e) { + int64_t owner_id = librg_event_owner_get(w, e); + int64_t entity_id = librg_event_entity_get(w, e); + zpl_printf("[INFO] An entity %d was created for owner: %d\n", (int)entity_id, (int)owner_id); + world_view *view = (world_view*)librg_world_userdata_get(w); + + // TODO(zaklaus): receive real data + entity_view_update_or_create(&view->entities, entity_id, (entity_view){0}); + return 0; +} + +int32_t tracker_read_remove(librg_world *w, librg_event *e) { + int64_t owner_id = librg_event_owner_get(w, e); + int64_t entity_id = librg_event_entity_get(w, e); + zpl_printf("[INFO] An entity %d was removed for owner: %d\n", (int)entity_id, (int)owner_id); + world_view *view = (world_view*)librg_world_userdata_get(w); + + entity_view_destroy(&view->entities, entity_id); + return 0; +} + +int32_t tracker_read_update(librg_world *w, librg_event *e) { + // int64_t entity_id = librg_event_entity_get(w, e); + size_t actual_length = librg_event_size_get(w, e); + char *buffer = librg_event_buffer_get(w, e); + + // TODO(zaklaus): update real data + return 0; +} + +world_view world_view_create(void) { + world_view view = {0}; + view.tracker = librg_world_create(); + entity_view_init(&view.entities); + return view; +} + +void world_view_init(world_view *view, uint64_t ent_id, uint16_t block_size, uint16_t chunk_size, uint16_t world_size) { + view->owner_id = ent_id; + librg_config_chunksize_set(view->tracker, block_size * chunk_size, block_size * chunk_size, 1); + librg_config_chunkamount_set(view->tracker, world_size, world_size, 1); + librg_config_chunkoffset_set(view->tracker, LIBRG_OFFSET_MID, LIBRG_OFFSET_MID, 0); + + librg_event_set(view->tracker, LIBRG_READ_CREATE, tracker_read_create); + librg_event_set(view->tracker, LIBRG_READ_REMOVE, tracker_read_remove); + librg_event_set(view->tracker, LIBRG_READ_UPDATE, tracker_read_update); + librg_world_userdata_set(view->tracker, view); +} + +void world_view_destroy(world_view *view) { + librg_world_destroy(view->tracker); + entity_view_free(&view->entities); +} diff --git a/code/common/game.h b/code/common/game.h index b48f63a..6b528f3 100644 --- a/code/common/game.h +++ b/code/common/game.h @@ -1,7 +1,8 @@ #pragma once #include "system.h" +#include "world_view.h" -void game_init(int8_t play_mode, int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size); +void game_init(int8_t play_mode, uint32_t num_viewers, int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size); void game_shutdown(); uint8_t game_is_running(); int8_t game_is_networked(); @@ -9,3 +10,6 @@ int8_t game_is_networked(); void game_input(); void game_update(); void game_render(); + +world_view *game_world_view_get_active(void); +world_view *game_world_view_get(uint16_t idx); \ No newline at end of file diff --git a/code/common/packet.c b/code/common/packet.c index 18e9963..3fa8e03 100644 --- a/code/common/packet.c +++ b/code/common/packet.c @@ -4,23 +4,26 @@ // NOTE(zaklaus): packets +#include "packets/pkt_00_init.h" #include "packets/pkt_01_welcome.h" #include "packets/pkt_send_keystate.h" #include "packets/pkt_send_librg_update.h" -#define PKT_HEADER_ELEMENTS 2 +#define PKT_HEADER_ELEMENTS 3 pkt_handler pkt_handlers[] = { + {.id = MSG_ID_00_INIT, .handler = pkt_00_init_handler}, {.id = MSG_ID_01_WELCOME, .handler = pkt_01_welcome_handler}, {.id = MSG_ID_LIBRG_UPDATE, .handler = pkt_send_librg_update_handler}, }; uint8_t pkt_buffer[PKT_BUFSIZ]; -int32_t pkt_header_encode(pkt_messages id, void *data, size_t datalen) { +int32_t pkt_header_encode(pkt_messages id, uint16_t view_id, void *data, size_t datalen) { cw_pack_context pc = {0}; pkt_pack_msg(&pc, PKT_HEADER_ELEMENTS); cw_pack_unsigned(&pc, id); + cw_pack_unsigned(&pc, view_id); cw_pack_bin(&pc, data, datalen); return pkt_pack_msg_size(&pc); } @@ -35,12 +38,20 @@ int32_t pkt_header_decode(pkt_header *table, void *data, size_t datalen) { } uint16_t pkt_id = (uint16_t)uc.item.as.u64; - + + cw_unpack_next(&uc); + if (uc.item.type != CWP_ITEM_POSITIVE_INTEGER || uc.item.as.u64 > UINT16_MAX) { + return -1; // invalid view id + } + + uint16_t view_id = (uint16_t)uc.item.as.u64; + 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; diff --git a/code/common/packet.h b/code/common/packet.h index fb879ee..023f2cd 100644 --- a/code/common/packet.h +++ b/code/common/packet.h @@ -4,6 +4,7 @@ #define PKT_BUFSIZ 4096 typedef enum { + MSG_ID_00_INIT, MSG_ID_01_WELCOME, MSG_ID_LIBRG_UPDATE, MSG_ID_SEND_KEYSTATE, @@ -13,10 +14,12 @@ typedef enum { typedef struct pkt_header { uint16_t id; uint16_t sender; + uint16_t view_id; uint8_t *data; uint32_t datalen; int8_t is_reliable; int8_t ok; + void* udata; } pkt_header; #define PKT_HANDLER_PROC(name) int32_t name(pkt_header *header) @@ -27,7 +30,7 @@ typedef struct { pkt_handler_proc *handler; } pkt_handler; -int32_t pkt_header_encode(pkt_messages id, void *data, size_t datalen); +int32_t pkt_header_encode(pkt_messages id, uint16_t view_id, void *data, size_t datalen); int32_t pkt_header_decode(pkt_header *table, void *data, size_t datalen); extern pkt_handler pkt_handlers[]; diff --git a/code/common/packet_utils.h b/code/common/packet_utils.h index bdf0374..3d2dfbc 100644 --- a/code/common/packet_utils.h +++ b/code/common/packet_utils.h @@ -39,13 +39,14 @@ inline size_t pkt_pack_msg_size(cw_pack_context *pc) { return pc->current - pc->start; // NOTE(zaklaus): length } -inline int32_t pkt_prep_msg(pkt_header *pkt, pkt_messages id, size_t pkt_size, int8_t is_reliable) { +inline int32_t pkt_prep_msg(pkt_header *pkt, pkt_messages id, uint16_t view_id, size_t pkt_size, int8_t is_reliable) { zpl_zero_item(pkt); static uint8_t pkt_data[PKT_BUFSIZ] = {0}; zpl_memcopy(pkt_data, pkt_buffer, pkt_size); pkt->data = pkt_buffer; - pkt->datalen = pkt_header_encode(id, pkt_data, pkt_size); + pkt->view_id = view_id; + pkt->datalen = pkt_header_encode(id, view_id, pkt_data, pkt_size); pkt->is_reliable = is_reliable; pkt->id = id; return 0; @@ -53,9 +54,9 @@ inline int32_t pkt_prep_msg(pkt_header *pkt, pkt_messages id, size_t pkt_size, i extern int32_t world_write(pkt_header *pkt, void *udata); -inline int32_t pkt_world_write(pkt_messages id, size_t pkt_size, int8_t is_reliable, void *udata) { +inline int32_t pkt_world_write(pkt_messages id, size_t pkt_size, int8_t is_reliable, uint16_t view_id, void *udata) { pkt_header pkt; - PKT_IF(pkt_prep_msg(&pkt, id, pkt_size, is_reliable)); + PKT_IF(pkt_prep_msg(&pkt, id, view_id, pkt_size, is_reliable)); return world_write(&pkt, udata); } diff --git a/code/common/packets/pkt_00_init.c b/code/common/packets/pkt_00_init.c new file mode 100644 index 0000000..a874a10 --- /dev/null +++ b/code/common/packets/pkt_00_init.c @@ -0,0 +1,38 @@ +#include "packets/pkt_00_init.h" +#include "packets/pkt_01_welcome.h" +#include "packet.h" +#include "world/world.h" +#include "game.h" +#include "entity_view.h" +#include "camera.h" + +#include "modules/net.h" + +pkt_desc pkt_00_init_desc[] = { + { PKT_FIELD(CWP_ITEM_POSITIVE_INTEGER, pkt_00_init, view_id) }, + { PKT_END }, +}; + +size_t pkt_00_init_encode(pkt_00_init *table) { + cw_pack_context pc = {0}; + pkt_pack_msg(&pc, pkt_pack_desc_args(pkt_00_init_desc)); + pkt_pack_struct(&pc, pkt_00_init_desc, PKT_STRUCT_PTR(table)); + return pkt_pack_msg_size(&pc); +} + +size_t pkt_00_init_send(uint16_t view_id) { + pkt_00_init table = {.view_id = view_id }; + return pkt_world_write(MSG_ID_00_INIT, pkt_00_init_encode(&table), 1, view_id, NULL); +} + +int32_t pkt_00_init_handler(pkt_header *header) { + ECS_IMPORT(world_ecs(), Net); + pkt_00_init table; + PKT_IF(pkt_msg_decode(header, pkt_00_init_desc, pkt_pack_desc_args(pkt_00_init_desc), PKT_STRUCT_PTR(&table))); + + uint64_t peer_id = (uint64_t)header->udata; + uint64_t ent_id = player_spawn(zpl_bprintf("client_%d", peer_id)); + ecs_set(world_ecs(), ent_id, ClientInfo, {.peer = ent_id, .view_id = header->view_id }); + pkt_01_welcome_send(peer_id, header->view_id, ent_id, world_block_size(), world_chunk_size(), world_world_size()); + return 0; +} diff --git a/code/common/packets/pkt_00_init.h b/code/common/packets/pkt_00_init.h new file mode 100644 index 0000000..43d3967 --- /dev/null +++ b/code/common/packets/pkt_00_init.h @@ -0,0 +1,14 @@ +#pragma once +#include "system.h" +#include "packet_utils.h" + +typedef struct { + uint16_t view_id; +} pkt_00_init; + +size_t pkt_00_init_encode(pkt_00_init *table); +size_t pkt_00_init_send(uint16_t view_id); +pkt_desc pkt_00_init_desc[]; + +PKT_HANDLER_PROC(pkt_00_init_handler); + diff --git a/code/common/packets/pkt_01_welcome.c b/code/common/packets/pkt_01_welcome.c index ce55858..4da27c2 100644 --- a/code/common/packets/pkt_01_welcome.c +++ b/code/common/packets/pkt_01_welcome.c @@ -2,11 +2,8 @@ #include "packet.h" #include "world/world.h" #include "game.h" - -#ifdef CLIENT #include "entity_view.h" #include "camera.h" -#endif pkt_desc pkt_01_welcome_desc[] = { { PKT_FIELD(CWP_ITEM_POSITIVE_INTEGER, pkt_01_welcome, ent_id) }, @@ -22,19 +19,23 @@ size_t pkt_01_welcome_encode(pkt_01_welcome *table) { pkt_pack_struct(&pc, pkt_01_welcome_desc, PKT_STRUCT_PTR(table)); return pkt_pack_msg_size(&pc); } +size_t pkt_01_welcome_send(uint64_t peer_id, + uint16_t view_id, + uint64_t ent_id, + uint16_t block_size, + uint16_t chunk_size, + uint16_t world_size) { + pkt_01_welcome table = {.ent_id = ent_id, .block_size = block_size, .chunk_size = chunk_size, .world_size = world_size}; + return pkt_world_write(MSG_ID_01_WELCOME, pkt_01_welcome_encode(&table), 1, view_id, (void*)peer_id); +} int32_t pkt_01_welcome_handler(pkt_header *header) { pkt_01_welcome table; PKT_IF(pkt_msg_decode(header, pkt_01_welcome_desc, pkt_pack_desc_args(pkt_01_welcome_desc), PKT_STRUCT_PTR(&table))); - - #ifdef CLIENT - if (game_is_networked()) { - zpl_printf("[INFO] initializing read-only world view ...\n"); - world_init_minimal(table.block_size, table.chunk_size, table.world_size, NULL, NULL); - } - entity_view_update_or_create(table.ent_id, (entity_view){0}); - camera_set_follow(table.ent_id); - #endif + world_view *view = game_world_view_get(header->view_id); + + zpl_printf("[INFO] initializing read-only world view ...\n"); + world_view_init(view, table.ent_id, table.block_size, table.chunk_size, table.world_size); return 0; } diff --git a/code/common/packets/pkt_01_welcome.h b/code/common/packets/pkt_01_welcome.h index 6fe0847..c684929 100644 --- a/code/common/packets/pkt_01_welcome.h +++ b/code/common/packets/pkt_01_welcome.h @@ -9,6 +9,12 @@ typedef struct { uint16_t world_size; } pkt_01_welcome; +size_t pkt_01_welcome_send(uint64_t peer_id, + uint16_t view_id, + uint64_t ent_id, + uint16_t block_size, + uint16_t chunk_size, + uint16_t world_size); size_t pkt_01_welcome_encode(pkt_01_welcome *table); pkt_desc pkt_01_welcome_desc[]; diff --git a/code/common/packets/pkt_send_librg_update.c b/code/common/packets/pkt_send_librg_update.c index 8d477d3..0834040 100644 --- a/code/common/packets/pkt_send_librg_update.c +++ b/code/common/packets/pkt_send_librg_update.c @@ -1,6 +1,7 @@ #include "packet_utils.h" #include "packets/pkt_send_librg_update.h" #include "world/world.h" +#include "game.h" size_t pkt_send_librg_update_encode(void *data, int32_t data_length) { cw_pack_context pc = {0}; @@ -17,7 +18,9 @@ int32_t pkt_send_librg_update_handler(pkt_header *header) { if (uc.item.type != CWP_ITEM_BIN) return -1; - int32_t state = librg_world_read(world_tracker(), 1, uc.item.as.bin.start, uc.item.as.bin.length, NULL); + world_view *view = game_world_view_get(header->view_id); + + int32_t state = librg_world_read(view->tracker, header->view_id, uc.item.as.bin.start, uc.item.as.bin.length, NULL); if (state < 0) zpl_printf("[ERROR] world read error: %d\n", state); return state; diff --git a/code/common/world/world.c b/code/common/world/world.c index 25bb436..a3ad9af 100644 --- a/code/common/world/world.c +++ b/code/common/world/world.c @@ -29,32 +29,9 @@ static world_data world = {0}; int32_t world_gen(); -int32_t tracker_read_create(librg_world *w, librg_event *e) { - int64_t owner_id = librg_event_owner_get(w, e); - int64_t entity_id = librg_event_entity_get(w, e); - zpl_printf("[INFO] An entity %d was created for owner: %d\n", (int)entity_id, (int)owner_id); - return 0; -} - -int32_t tracker_read_remove(librg_world *w, librg_event *e) { - int64_t owner_id = librg_event_owner_get(w, e); - int64_t entity_id = librg_event_entity_get(w, e); - zpl_printf("[INFO] An entity %d was removed for owner: %d\n", (int)entity_id, (int)owner_id); - return 0; -} - -int32_t tracker_read_update(librg_world *w, librg_event *e) { - // int64_t entity_id = librg_event_entity_get(w, e); - size_t actual_length = librg_event_size_get(w, e); - char *buffer = librg_event_buffer_get(w, e); - - return 0; -} - int32_t tracker_write_create(librg_world *w, librg_event *e) { int64_t owner_id = librg_event_owner_get(w, e); int64_t entity_id = librg_event_entity_get(w, e); - zpl_printf("let's add prtint here\n"); return 0; } @@ -74,11 +51,19 @@ int32_t tracker_write_update(librg_world *w, librg_event *e) { return 0; } -int32_t world_init_minimal(uint16_t block_size, uint16_t chunk_size, uint16_t world_size, world_pkt_reader_proc *reader_proc, world_pkt_writer_proc *writer_proc) { +void world_setup_pkt_handlers(world_pkt_reader_proc *reader_proc, world_pkt_writer_proc *writer_proc) { + world.reader_proc = reader_proc; + world.writer_proc = writer_proc; +} + +int32_t world_init(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size) { + if (world.data) { + return 0; + } + + world.seed = seed; world.chunk_size = chunk_size; world.world_size = world_size; - if (reader_proc) world.reader_proc = reader_proc; - if (writer_proc) world.writer_proc = writer_proc; world.width = chunk_size * world_size; world.height = chunk_size * world_size; @@ -88,7 +73,7 @@ int32_t world_init_minimal(uint16_t block_size, uint16_t chunk_size, uint16_t wo if (world.tracker == NULL) { world.tracker = librg_world_create(); } - + if (world.tracker == NULL) { zpl_printf("[ERROR] An error occurred while trying to create a server world.\n"); return WORLD_ERROR_TRACKER_FAILED; @@ -99,24 +84,10 @@ int32_t world_init_minimal(uint16_t block_size, uint16_t chunk_size, uint16_t wo librg_config_chunkamount_set(world.tracker, world_size, world_size, 1); librg_config_chunkoffset_set(world.tracker, LIBRG_OFFSET_MID, LIBRG_OFFSET_MID, 0); - librg_event_set(world.tracker, LIBRG_READ_CREATE, tracker_read_create); - librg_event_set(world.tracker, LIBRG_READ_REMOVE, tracker_read_remove); - librg_event_set(world.tracker, LIBRG_READ_UPDATE, tracker_read_update); - librg_event_set(world.tracker, LIBRG_WRITE_CREATE, tracker_write_create); librg_event_set(world.tracker, LIBRG_WRITE_REMOVE, tracker_write_remove); librg_event_set(world.tracker, LIBRG_WRITE_UPDATE, tracker_write_update); - return 0; -} - -int32_t world_init(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size, world_pkt_reader_proc *reader_proc, world_pkt_writer_proc *writer_proc) { - if (world.data) { - return 0; - } - - world.seed = seed; - world_init_minimal(block_size, chunk_size, world_size, reader_proc, writer_proc); world.data = zpl_malloc(sizeof(uint8_t)*world.size); world.tracker_update = 0; @@ -129,11 +100,11 @@ int32_t world_init(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint1 ECS_IMPORT(world.ecs, General); - for (int i = 0; i < chunk_size * chunk_size; ++i) { + for (int i = 0; i < world_size * world_size; ++i) { ecs_entity_t e = ecs_new(world.ecs, 0); ecs_set(world.ecs, e, Chunk, { - .x = i % chunk_size, - .y = i / chunk_size, + .x = i % world_size, + .y = i / world_size, }); librg_entity_track(world.tracker, e); @@ -162,15 +133,14 @@ static void world_tracker_update(void) { ecs_query_t *query = ecs_query_new(world.ecs, "Net.ClientInfo"); ecs_iter_t it = ecs_query_iter(query); - static char buffer[16000] = {0}; - static int32_t datalen = 16000; + char buffer[8096] = {0}; while (ecs_query_next(&it)) { ClientInfo *p = ecs_column(&it, ClientInfo, 1); for (int i = 0; i < it.count; i++) { - datalen = 16000; - int32_t result = librg_world_write(world_tracker(), it.entities[i], buffer, &datalen, NULL); + size_t datalen = 8096; + 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); @@ -178,7 +148,7 @@ static void world_tracker_update(void) { zpl_printf("[error] an error happened writing the world %d\n", result); } - pkt_world_write(MSG_ID_LIBRG_UPDATE, pkt_send_librg_update_encode(buffer, datalen), 1, p[i].peer); + pkt_world_write(MSG_ID_LIBRG_UPDATE, pkt_send_librg_update_encode(buffer, datalen), 1, p[i].view_id, p[i].peer); } } } diff --git a/code/common/world/world.h b/code/common/world/world.h index 7f31cb0..74b7ac4 100644 --- a/code/common/world/world.h +++ b/code/common/world/world.h @@ -17,8 +17,8 @@ typedef WORLD_PKT_READER(world_pkt_reader_proc); #define WORLD_PKT_WRITER(name) int32_t name(pkt_header *pkt, void *udata) typedef WORLD_PKT_WRITER(world_pkt_writer_proc); -int32_t world_init_minimal(uint16_t block_size, uint16_t chunk_size, uint16_t world_size, world_pkt_reader_proc *reader_proc, world_pkt_writer_proc *writer_proc); -int32_t world_init(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size, world_pkt_reader_proc *reader_proc, world_pkt_writer_proc *writer_proc); +void world_setup_pkt_handlers(world_pkt_reader_proc *reader_proc, world_pkt_writer_proc *writer_proc); +int32_t world_init(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size); int32_t world_destroy(void); int32_t world_update(void); int32_t world_read(void* data, uint32_t datalen, void *udata); diff --git a/code/modules/modules/net.h b/code/modules/modules/net.h index 3fb0709..6a6becb 100644 --- a/code/modules/modules/net.h +++ b/code/modules/modules/net.h @@ -4,6 +4,7 @@ ECS_STRUCT(ClientInfo, { uintptr_t peer; + uint16_t view_id; }); typedef struct {