From a2f76237f81d24f6b019a276a9e5d1a8dad29d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Sun, 31 Jul 2022 12:24:31 +0200 Subject: [PATCH] network: rework view_id --- code/game/src/game.c | 4 + code/game/src/game.h | 1 + code/game/src/network.c | 118 +++++++++++++--------- code/game/src/network.h | 4 +- code/game/src/packets/pkt_00_init.c | 1 - code/game/src/packets/pkt_01_welcome.c | 2 +- code/game/src/packets/pkt_send_keystate.c | 2 +- code/game/src/platform_raylib.c | 1 + code/game/src/platform_text.c | 31 ------ 9 files changed, 80 insertions(+), 84 deletions(-) delete mode 100644 code/game/src/platform_text.c diff --git a/code/game/src/game.c b/code/game/src/game.c index 087fbac..50da9b8 100644 --- a/code/game/src/game.c +++ b/code/game/src/game.c @@ -110,6 +110,10 @@ void game_world_view_set_active(world_view *view) { camera_set_follow(view->owner_id); } +size_t game_world_view_count(void) { + return zpl_buffer_count(world_viewers); +} + void flecs_dash_init() { #if 0 ECS_IMPORT(world_ecs(), FlecsDash); diff --git a/code/game/src/game.h b/code/game/src/game.h index c6a26a3..11949bb 100644 --- a/code/game/src/game.h +++ b/code/game/src/game.h @@ -26,6 +26,7 @@ void game_render(); //~ NOTE(zaklaus): world view management world_view *game_world_view_get_active(void); world_view *game_world_view_get(uint16_t idx); +size_t game_world_view_count(void); void game_world_view_set_active_by_idx(uint16_t idx); void game_world_view_set_active(world_view *view); void game_world_view_cycle_active(int8_t dir); diff --git a/code/game/src/network.c b/code/game/src/network.c index 5ef6f33..07a5a06 100644 --- a/code/game/src/network.c +++ b/code/game/src/network.c @@ -24,6 +24,7 @@ static ENetHost *host = NULL; static ENetHost *server = NULL; static ENetPeer *peer = NULL; static librg_world *world = NULL; +static ecs_query_t *clientinfo_query = NULL; int32_t network_init() { return enet_initialize() != 0; @@ -32,7 +33,6 @@ int32_t network_init() { int32_t network_destroy() { enet_deinitialize(); return 0; - } //~ NOTE(zaklaus): client @@ -40,61 +40,63 @@ 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); - + host = enet_host_create(NULL, 1, 2, 0, 0); peer = enet_host_connect(host, &address, 2, 0); - + if (peer == NULL) { zpl_printf("[ERROR] Cannot connect to specicied server: %s:%d\n", hostname, port); return 1; } - + world = librg_world_create(); librg_world_userdata_set(world, peer); - + return 0; } int32_t network_client_disconnect() { enet_peer_disconnect(peer, 0); enet_host_destroy(host); - + librg_world_destroy(world); - + peer = NULL; host = NULL; world = NULL; - + return 0; } int32_t network_client_tick() { ENetEvent event = {0}; - + while (enet_host_service(host, &event, 1) > 0) { switch (event.type) { case ENET_EVENT_TYPE_CONNECT: { zpl_printf("[INFO] We connected to the server.\n"); - pkt_00_init_send(0); + for (uint32_t i = 0; i < game_world_view_count(); i++) { + pkt_00_init_send(i); + } } break; case ENET_EVENT_TYPE_DISCONNECT: case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: { zpl_printf("[INFO] We disconnected from server.\n"); } break; - + case ENET_EVENT_TYPE_RECEIVE: { if (!world_read(event.packet->data, (uint32_t)event.packet->dataLength, event.peer)) { zpl_printf("[INFO] Server sent us an unsupported packet.\n"); } - + /* Clean up the packet now that we're done using it. */ enet_packet_destroy(event.packet); } break; - + case ENET_EVENT_TYPE_NONE: break; } } - + return 0; } @@ -105,59 +107,59 @@ network_client_stats network_client_fetch_stats(void) { if (!network_client_is_connected()) return (network_client_stats){0}; - + network_client_stats stats = {0}; - + stats.incoming_total = peer->incomingDataTotal; stats.total_received = peer->totalDataReceived; stats.outgoing_total = peer->outgoingDataTotal; stats.total_sent = peer->totalDataSent; - + static double next_measure = 0.0; static float incoming_bandwidth = 0.0f; static float outgoing_bandwidth = 0.0f; - + if (next_measure < zpl_time_rel()) { #define MAX_RATE_SAMPLES 8 static uint64_t last_total_sent = 0; static uint64_t last_total_recv = 0; static uint64_t rolling_counter = 0; - static uint64_t sent_buffer[MAX_RATE_SAMPLES] = {0}; - static uint64_t recv_buffer[MAX_RATE_SAMPLES] = {0}; - + static uint64_t sent_buffer[MAX_RATE_SAMPLES] = {0}; + static uint64_t recv_buffer[MAX_RATE_SAMPLES] = {0}; + uint64_t sent_delta = stats.total_sent - last_total_sent; uint64_t recv_delta = stats.total_received - last_total_recv; last_total_sent = stats.total_sent; last_total_recv = stats.total_received; - + sent_buffer[rolling_counter % MAX_RATE_SAMPLES] = sent_delta; recv_buffer[rolling_counter % MAX_RATE_SAMPLES] = recv_delta; ++rolling_counter; - + for (int i = 0; i < MAX_RATE_SAMPLES; i++) { stats.incoming_bandwidth += recv_buffer[i]; stats.outgoing_bandwidth += sent_buffer[i]; } - + incoming_bandwidth = stats.incoming_bandwidth /= MAX_RATE_SAMPLES; outgoing_bandwidth = stats.outgoing_bandwidth /= MAX_RATE_SAMPLES; - + next_measure = zpl_time_rel() + 1.0; } else { stats.incoming_bandwidth = incoming_bandwidth; stats.outgoing_bandwidth = outgoing_bandwidth; } - + stats.packets_sent = peer->totalPacketsSent; stats.packets_lost = peer->totalPacketsLost; - + if (stats.packets_sent > 0) { stats.packet_loss = stats.packets_lost / (float)stats.packets_sent; } - + stats.ping = peer->roundTripTime; stats.low_ping = peer->lowestRoundTripTime; - + return stats; } @@ -165,19 +167,20 @@ network_client_fetch_stats(void) { int32_t network_server_start(const char *host, uint16_t port) { (void)host; - + ENetAddress address = {0}; - + address.host = ENET_HOST_ANY; address.port = port; - + server = enet_host_create(&address, 8, 2, 0, 0); - + if (server == NULL) { zpl_printf("[ERROR] An error occured while trying to create a server host.\n"); return 1; } - + + clientinfo_query = ecs_query_new(world_ecs(), "components.ClientInfo"); return 0; } @@ -197,41 +200,60 @@ int32_t network_server_tick(void) { case ENET_EVENT_TYPE_DISCONNECT: case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: { zpl_printf("[INFO] A user %d disconnected.\n", event.peer->incomingPeerID); - + if (event.peer->data) { - player_despawn((ecs_entity_t)event.peer->data); - event.peer->data = 0; + network_server_despawn_viewers(event.peer); } } break; - + case ENET_EVENT_TYPE_RECEIVE: { if (!world_read(event.packet->data, (uint32_t)event.packet->dataLength, event.peer)) { zpl_printf("[INFO] User %d sent us a malformed packet.\n", event.peer->incomingPeerID); } - + /* Clean up the packet now that we're done using it. */ enet_packet_destroy(event.packet); } break; - + case ENET_EVENT_TYPE_NONE: break; } } - + return 0; } -void network_server_assign_entity(void *peer_id, uint64_t ent_id) { - ENetPeer *peer = (ENetPeer *)peer_id; - peer->data = (void*)ent_id; +void network_server_despawn_viewers(void *peer_id) { + ecs_iter_t it = ecs_query_iter(clientinfo_query); + + while (ecs_query_next(&it)) { + ClientInfo *p = ecs_column(&it, ClientInfo, 1); + + for (int i = 0; i < it.count; i++) { + if (p[i].peer == (uintptr_t)peer_id) { + player_despawn(it.entities[i]); + } + } + } } -uint64_t network_server_get_entity(void *peer_id) { +uint64_t network_server_get_entity(void *peer_id, uint16_t view_id) { if (game_get_kind() == GAMEKIND_SINGLE) { return (uint64_t)peer_id; } - ENetPeer *peer = (ENetPeer *)peer_id; - ZPL_ASSERT(peer->data); - return (uint64_t)peer->data; + + ecs_iter_t it = ecs_query_iter(clientinfo_query); + + while (ecs_query_next(&it)) { + ClientInfo *p = ecs_column(&it, ClientInfo, 1); + + for (int i = 0; i < it.count; i++) { + if (p[i].peer == (uintptr_t)peer_id && p[i].view_id == view_id) { + return it.entities[i]; + } + } + } + + return 0; } //~ NOTE(zaklaus): messaging diff --git a/code/game/src/network.h b/code/game/src/network.h index 909910f..e02bac5 100644 --- a/code/game/src/network.h +++ b/code/game/src/network.h @@ -39,8 +39,8 @@ network_client_fetch_stats(void); int32_t network_server_start(const char *host, uint16_t port); int32_t network_server_stop(void); int32_t network_server_tick(void); -void network_server_assign_entity(void *peer_id, uint64_t ent_id); -uint64_t network_server_get_entity(void *peer_id); +void network_server_despawn_viewers(void *peer_id); +uint64_t network_server_get_entity(void *peer_id, uint16_t view_id); // NOTE(zaklaus): messaging int32_t network_msg_send(void *peer_id, void *data, size_t datalen, uint16_t channel_id); diff --git a/code/game/src/packets/pkt_00_init.c b/code/game/src/packets/pkt_00_init.c index 2409b6c..de37555 100644 --- a/code/game/src/packets/pkt_00_init.c +++ b/code/game/src/packets/pkt_00_init.c @@ -34,7 +34,6 @@ int32_t pkt_00_init_handler(pkt_header *header) { if (game_get_kind() == GAMEKIND_SINGLE) peer_id = ent_id; - else network_server_assign_entity(header->udata, ent_id); ecs_set(world_ecs(), ent_id, ClientInfo, {.peer = peer_id, .view_id = header->view_id }); pkt_01_welcome_send(world_seed(), peer_id, header->view_id, ent_id, world_chunk_size(), world_chunk_amount()); diff --git a/code/game/src/packets/pkt_01_welcome.c b/code/game/src/packets/pkt_01_welcome.c index 1b0d6ac..b92a969 100644 --- a/code/game/src/packets/pkt_01_welcome.c +++ b/code/game/src/packets/pkt_01_welcome.c @@ -29,7 +29,7 @@ int32_t pkt_01_welcome_handler(pkt_header *header) { world_view *view = game_world_view_get(header->view_id); - zpl_printf("[INFO] initializing read-only world view ...\n"); + zpl_printf("[INFO] initializing read-only world view id: %d...\n", header->view_id); world_view_init(view, table.seed, table.ent_id, table.chunk_size, table.world_size); game_world_view_set_active(view); return 0; diff --git a/code/game/src/packets/pkt_send_keystate.c b/code/game/src/packets/pkt_send_keystate.c index d4a11de..6440ad9 100644 --- a/code/game/src/packets/pkt_send_keystate.c +++ b/code/game/src/packets/pkt_send_keystate.c @@ -33,7 +33,7 @@ size_t pkt_send_keystate_send(uint16_t view_id, int32_t pkt_send_keystate_handler(pkt_header *header) { pkt_send_keystate table; PKT_IF(pkt_msg_decode(header, pkt_send_keystate_desc, pkt_pack_desc_args(pkt_send_keystate_desc), PKT_STRUCT_PTR(&table))); - ecs_entity_t e = network_server_get_entity(header->udata); + ecs_entity_t e = network_server_get_entity(header->udata, header->view_id); if (!world_entity_valid(e)) return 1; diff --git a/code/game/src/platform_raylib.c b/code/game/src/platform_raylib.c index 430cf36..0f9450c 100644 --- a/code/game/src/platform_raylib.c +++ b/code/game/src/platform_raylib.c @@ -26,6 +26,7 @@ static bool request_shutdown; #include "gui/inventory.c" void platform_init() { + SetTraceLogLevel(LOG_ERROR); InitWindow(screenWidth, screenHeight, "eco2d"); SetWindowState(/*FLAG_WINDOW_UNDECORATED|*/FLAG_WINDOW_MAXIMIZED|FLAG_WINDOW_RESIZABLE|FLAG_MSAA_4X_HINT); diff --git a/code/game/src/platform_text.c b/code/game/src/platform_text.c deleted file mode 100644 index dd59586..0000000 --- a/code/game/src/platform_text.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "platform.h" -#include - -uint8_t is_running; - -void platform_init() { - printf("eco2d-cli\n"); - is_running = 1; -} - -void platform_shutdown() { - printf("\nBye!\n"); - is_running = 0; -} - -void platform_input() { - -} - -uint8_t platform_is_running() { - return is_running; -} - -float platform_frametime() { - return 1.0f; -} - -void platform_render() { - zpl_printf("o"); - zpl_sleep_ms(1000); -}