network: rework view_id

isolation_bkp/dynres
Dominik Madarász 2022-07-31 12:24:31 +02:00
parent 3b40354054
commit a2f76237f8
9 changed files with 80 additions and 84 deletions

View File

@ -110,6 +110,10 @@ void game_world_view_set_active(world_view *view) {
camera_set_follow(view->owner_id); camera_set_follow(view->owner_id);
} }
size_t game_world_view_count(void) {
return zpl_buffer_count(world_viewers);
}
void flecs_dash_init() { void flecs_dash_init() {
#if 0 #if 0
ECS_IMPORT(world_ecs(), FlecsDash); ECS_IMPORT(world_ecs(), FlecsDash);

View File

@ -26,6 +26,7 @@ void game_render();
//~ NOTE(zaklaus): world view management //~ NOTE(zaklaus): world view management
world_view *game_world_view_get_active(void); world_view *game_world_view_get_active(void);
world_view *game_world_view_get(uint16_t idx); 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_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(int8_t dir); void game_world_view_cycle_active(int8_t dir);

View File

@ -24,6 +24,7 @@ static ENetHost *host = NULL;
static ENetHost *server = NULL; static ENetHost *server = NULL;
static ENetPeer *peer = NULL; static ENetPeer *peer = NULL;
static librg_world *world = NULL; static librg_world *world = NULL;
static ecs_query_t *clientinfo_query = NULL;
int32_t network_init() { int32_t network_init() {
return enet_initialize() != 0; return enet_initialize() != 0;
@ -32,7 +33,6 @@ int32_t network_init() {
int32_t network_destroy() { int32_t network_destroy() {
enet_deinitialize(); enet_deinitialize();
return 0; return 0;
} }
//~ NOTE(zaklaus): client //~ NOTE(zaklaus): client
@ -40,61 +40,63 @@ int32_t network_destroy() {
int32_t network_client_connect(const char *hostname, uint16_t port) { int32_t network_client_connect(const char *hostname, uint16_t port) {
ENetAddress address = {0}; address.port = port; ENetAddress address = {0}; address.port = port;
enet_address_set_host(&address, hostname); enet_address_set_host(&address, hostname);
host = enet_host_create(NULL, 1, 2, 0, 0); host = enet_host_create(NULL, 1, 2, 0, 0);
peer = enet_host_connect(host, &address, 2, 0); peer = enet_host_connect(host, &address, 2, 0);
if (peer == NULL) { if (peer == NULL) {
zpl_printf("[ERROR] Cannot connect to specicied server: %s:%d\n", hostname, port); zpl_printf("[ERROR] Cannot connect to specicied server: %s:%d\n", hostname, port);
return 1; return 1;
} }
world = librg_world_create(); world = librg_world_create();
librg_world_userdata_set(world, peer); librg_world_userdata_set(world, peer);
return 0; return 0;
} }
int32_t network_client_disconnect() { int32_t network_client_disconnect() {
enet_peer_disconnect(peer, 0); enet_peer_disconnect(peer, 0);
enet_host_destroy(host); enet_host_destroy(host);
librg_world_destroy(world); librg_world_destroy(world);
peer = NULL; peer = NULL;
host = NULL; host = NULL;
world = NULL; world = NULL;
return 0; return 0;
} }
int32_t network_client_tick() { int32_t network_client_tick() {
ENetEvent event = {0}; ENetEvent event = {0};
while (enet_host_service(host, &event, 1) > 0) { while (enet_host_service(host, &event, 1) > 0) {
switch (event.type) { switch (event.type) {
case ENET_EVENT_TYPE_CONNECT: { case ENET_EVENT_TYPE_CONNECT: {
zpl_printf("[INFO] We connected to the server.\n"); 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; } break;
case ENET_EVENT_TYPE_DISCONNECT: case ENET_EVENT_TYPE_DISCONNECT:
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: { case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: {
zpl_printf("[INFO] We disconnected from server.\n"); zpl_printf("[INFO] We disconnected from server.\n");
} break; } break;
case ENET_EVENT_TYPE_RECEIVE: { case ENET_EVENT_TYPE_RECEIVE: {
if (!world_read(event.packet->data, (uint32_t)event.packet->dataLength, event.peer)) { if (!world_read(event.packet->data, (uint32_t)event.packet->dataLength, event.peer)) {
zpl_printf("[INFO] Server sent us an unsupported packet.\n"); zpl_printf("[INFO] Server sent us an unsupported packet.\n");
} }
/* Clean up the packet now that we're done using it. */ /* Clean up the packet now that we're done using it. */
enet_packet_destroy(event.packet); enet_packet_destroy(event.packet);
} break; } break;
case ENET_EVENT_TYPE_NONE: break; case ENET_EVENT_TYPE_NONE: break;
} }
} }
return 0; return 0;
} }
@ -105,59 +107,59 @@ network_client_stats
network_client_fetch_stats(void) { network_client_fetch_stats(void) {
if (!network_client_is_connected()) if (!network_client_is_connected())
return (network_client_stats){0}; return (network_client_stats){0};
network_client_stats stats = {0}; network_client_stats stats = {0};
stats.incoming_total = peer->incomingDataTotal; stats.incoming_total = peer->incomingDataTotal;
stats.total_received = peer->totalDataReceived; stats.total_received = peer->totalDataReceived;
stats.outgoing_total = peer->outgoingDataTotal; stats.outgoing_total = peer->outgoingDataTotal;
stats.total_sent = peer->totalDataSent; stats.total_sent = peer->totalDataSent;
static double next_measure = 0.0; static double next_measure = 0.0;
static float incoming_bandwidth = 0.0f; static float incoming_bandwidth = 0.0f;
static float outgoing_bandwidth = 0.0f; static float outgoing_bandwidth = 0.0f;
if (next_measure < zpl_time_rel()) { if (next_measure < zpl_time_rel()) {
#define MAX_RATE_SAMPLES 8 #define MAX_RATE_SAMPLES 8
static uint64_t last_total_sent = 0; static uint64_t last_total_sent = 0;
static uint64_t last_total_recv = 0; static uint64_t last_total_recv = 0;
static uint64_t rolling_counter = 0; static uint64_t rolling_counter = 0;
static uint64_t sent_buffer[MAX_RATE_SAMPLES] = {0}; static uint64_t sent_buffer[MAX_RATE_SAMPLES] = {0};
static uint64_t recv_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 sent_delta = stats.total_sent - last_total_sent;
uint64_t recv_delta = stats.total_received - last_total_recv; uint64_t recv_delta = stats.total_received - last_total_recv;
last_total_sent = stats.total_sent; last_total_sent = stats.total_sent;
last_total_recv = stats.total_received; last_total_recv = stats.total_received;
sent_buffer[rolling_counter % MAX_RATE_SAMPLES] = sent_delta; sent_buffer[rolling_counter % MAX_RATE_SAMPLES] = sent_delta;
recv_buffer[rolling_counter % MAX_RATE_SAMPLES] = recv_delta; recv_buffer[rolling_counter % MAX_RATE_SAMPLES] = recv_delta;
++rolling_counter; ++rolling_counter;
for (int i = 0; i < MAX_RATE_SAMPLES; i++) { for (int i = 0; i < MAX_RATE_SAMPLES; i++) {
stats.incoming_bandwidth += recv_buffer[i]; stats.incoming_bandwidth += recv_buffer[i];
stats.outgoing_bandwidth += sent_buffer[i]; stats.outgoing_bandwidth += sent_buffer[i];
} }
incoming_bandwidth = stats.incoming_bandwidth /= MAX_RATE_SAMPLES; incoming_bandwidth = stats.incoming_bandwidth /= MAX_RATE_SAMPLES;
outgoing_bandwidth = stats.outgoing_bandwidth /= MAX_RATE_SAMPLES; outgoing_bandwidth = stats.outgoing_bandwidth /= MAX_RATE_SAMPLES;
next_measure = zpl_time_rel() + 1.0; next_measure = zpl_time_rel() + 1.0;
} else { } else {
stats.incoming_bandwidth = incoming_bandwidth; stats.incoming_bandwidth = incoming_bandwidth;
stats.outgoing_bandwidth = outgoing_bandwidth; stats.outgoing_bandwidth = outgoing_bandwidth;
} }
stats.packets_sent = peer->totalPacketsSent; stats.packets_sent = peer->totalPacketsSent;
stats.packets_lost = peer->totalPacketsLost; stats.packets_lost = peer->totalPacketsLost;
if (stats.packets_sent > 0) { if (stats.packets_sent > 0) {
stats.packet_loss = stats.packets_lost / (float)stats.packets_sent; stats.packet_loss = stats.packets_lost / (float)stats.packets_sent;
} }
stats.ping = peer->roundTripTime; stats.ping = peer->roundTripTime;
stats.low_ping = peer->lowestRoundTripTime; stats.low_ping = peer->lowestRoundTripTime;
return stats; return stats;
} }
@ -165,19 +167,20 @@ network_client_fetch_stats(void) {
int32_t network_server_start(const char *host, uint16_t port) { int32_t network_server_start(const char *host, uint16_t port) {
(void)host; (void)host;
ENetAddress address = {0}; ENetAddress address = {0};
address.host = ENET_HOST_ANY; address.host = ENET_HOST_ANY;
address.port = port; address.port = port;
server = enet_host_create(&address, 8, 2, 0, 0); server = enet_host_create(&address, 8, 2, 0, 0);
if (server == NULL) { if (server == NULL) {
zpl_printf("[ERROR] An error occured while trying to create a server host.\n"); zpl_printf("[ERROR] An error occured while trying to create a server host.\n");
return 1; return 1;
} }
clientinfo_query = ecs_query_new(world_ecs(), "components.ClientInfo");
return 0; return 0;
} }
@ -197,41 +200,60 @@ int32_t network_server_tick(void) {
case ENET_EVENT_TYPE_DISCONNECT: case ENET_EVENT_TYPE_DISCONNECT:
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: { case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: {
zpl_printf("[INFO] A user %d disconnected.\n", event.peer->incomingPeerID); zpl_printf("[INFO] A user %d disconnected.\n", event.peer->incomingPeerID);
if (event.peer->data) { if (event.peer->data) {
player_despawn((ecs_entity_t)event.peer->data); network_server_despawn_viewers(event.peer);
event.peer->data = 0;
} }
} break; } break;
case ENET_EVENT_TYPE_RECEIVE: { case ENET_EVENT_TYPE_RECEIVE: {
if (!world_read(event.packet->data, (uint32_t)event.packet->dataLength, event.peer)) { 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); 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. */ /* Clean up the packet now that we're done using it. */
enet_packet_destroy(event.packet); enet_packet_destroy(event.packet);
} break; } break;
case ENET_EVENT_TYPE_NONE: break; case ENET_EVENT_TYPE_NONE: break;
} }
} }
return 0; return 0;
} }
void network_server_assign_entity(void *peer_id, uint64_t ent_id) { void network_server_despawn_viewers(void *peer_id) {
ENetPeer *peer = (ENetPeer *)peer_id; ecs_iter_t it = ecs_query_iter(clientinfo_query);
peer->data = (void*)ent_id;
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) { if (game_get_kind() == GAMEKIND_SINGLE) {
return (uint64_t)peer_id; return (uint64_t)peer_id;
} }
ENetPeer *peer = (ENetPeer *)peer_id;
ZPL_ASSERT(peer->data); ecs_iter_t it = ecs_query_iter(clientinfo_query);
return (uint64_t)peer->data;
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 //~ NOTE(zaklaus): messaging

View File

@ -39,8 +39,8 @@ network_client_fetch_stats(void);
int32_t network_server_start(const char *host, uint16_t port); int32_t network_server_start(const char *host, uint16_t port);
int32_t network_server_stop(void); int32_t network_server_stop(void);
int32_t network_server_tick(void); int32_t network_server_tick(void);
void network_server_assign_entity(void *peer_id, uint64_t ent_id); void network_server_despawn_viewers(void *peer_id);
uint64_t network_server_get_entity(void *peer_id); uint64_t network_server_get_entity(void *peer_id, uint16_t view_id);
// NOTE(zaklaus): messaging // NOTE(zaklaus): messaging
int32_t network_msg_send(void *peer_id, void *data, size_t datalen, uint16_t channel_id); int32_t network_msg_send(void *peer_id, void *data, size_t datalen, uint16_t channel_id);

View File

@ -34,7 +34,6 @@ int32_t pkt_00_init_handler(pkt_header *header) {
if (game_get_kind() == GAMEKIND_SINGLE) peer_id = ent_id; 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 }); 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()); pkt_01_welcome_send(world_seed(), peer_id, header->view_id, ent_id, world_chunk_size(), world_chunk_amount());

View File

@ -29,7 +29,7 @@ int32_t pkt_01_welcome_handler(pkt_header *header) {
world_view *view = game_world_view_get(header->view_id); 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); world_view_init(view, table.seed, table.ent_id, table.chunk_size, table.world_size);
game_world_view_set_active(view); game_world_view_set_active(view);
return 0; return 0;

View File

@ -33,7 +33,7 @@ size_t pkt_send_keystate_send(uint16_t view_id,
int32_t pkt_send_keystate_handler(pkt_header *header) { int32_t pkt_send_keystate_handler(pkt_header *header) {
pkt_send_keystate table; 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))); 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)) if (!world_entity_valid(e))
return 1; return 1;

View File

@ -26,6 +26,7 @@ static bool request_shutdown;
#include "gui/inventory.c" #include "gui/inventory.c"
void platform_init() { void platform_init() {
SetTraceLogLevel(LOG_ERROR);
InitWindow(screenWidth, screenHeight, "eco2d"); InitWindow(screenWidth, screenHeight, "eco2d");
SetWindowState(/*FLAG_WINDOW_UNDECORATED|*/FLAG_WINDOW_MAXIMIZED|FLAG_WINDOW_RESIZABLE|FLAG_MSAA_4X_HINT); SetWindowState(/*FLAG_WINDOW_UNDECORATED|*/FLAG_WINDOW_MAXIMIZED|FLAG_WINDOW_RESIZABLE|FLAG_MSAA_4X_HINT);

View File

@ -1,31 +0,0 @@
#include "platform.h"
#include <stdio.h>
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);
}