fix MP support

isolation_bkp/dynres
Dominik Madarász 2021-05-04 21:22:55 +02:00
parent e5d45a8c67
commit e85b15d5f1
11 changed files with 140 additions and 131 deletions

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "system.h" #include "system.h"
void game_init(); void game_init(int8_t play_mode, int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size);
void game_shutdown(); void game_shutdown();
uint8_t game_is_running(); uint8_t game_is_running();

View File

@ -9,3 +9,6 @@ int32_t network_client_disconnect(void);
int32_t network_client_tick(void); int32_t network_client_tick(void);
void network_client_update(void *data); void network_client_update(void *data);
bool network_client_is_connected(); bool network_client_is_connected();
int32_t network_msg_send(void *data, size_t datalen);
int32_t network_msg_send_unreliable(void *data, size_t datalen);

View File

@ -1,12 +1,75 @@
#include "game.h" #include "game.h"
#include "platform.h" #include "platform.h"
#include "world/world.h"
#include "packets/packet.h"
#include "signal_handling.h"
#include "network.h"
void game_init() { #include "flecs/flecs.h"
#include "flecs/flecs_dash.h"
#include "flecs/flecs_systems_civetweb.h"
#include "flecs/flecs_os_api_stdcpp.h"
static int8_t is_networked_play;
static WORLD_PKT_READER(pkt_reader) {
pkt_header header = {0};
uint32_t ok = pkt_header_decode(&header, data, datalen);
if (ok && header.ok) {
return pkt_handlers[header.id].handler(&header) >= 0;
} else {
zpl_printf("[warn] unknown packet id %d (header %d data %d)\n", header.id, ok, header.ok);
}
return -1;
}
static WORLD_PKT_WRITER(sp_pkt_writer) {
return world_read(pkt->data, pkt->datalen, NULL);
}
static WORLD_PKT_WRITER(mp_pkt_writer) {
if (pkt->is_reliable) {
return network_msg_send(pkt->data, pkt->datalen);
}
else {
return network_msg_send_unreliable(pkt->data, pkt->datalen);
}
}
void game_init(int8_t play_mode, int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size) {
is_networked_play = play_mode;
platform_init(); platform_init();
if (is_networked_play) {
world_init_minimal(0, 0, 0, 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);
}
pkt_01_welcome table = {.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);
}
} }
void game_shutdown() { void game_shutdown() {
// if (is_networked_play) {
network_client_disconnect();
network_destroy();
} else {
world_destroy();
}
} }
uint8_t game_is_running() { uint8_t game_is_running() {
@ -18,7 +81,8 @@ void game_input() {
} }
void game_update() { void game_update() {
if (is_networked_play) network_client_tick();
else world_update();
} }
void game_render() { void game_render() {

View File

@ -2,47 +2,12 @@
#include "zpl.h" #include "zpl.h"
#include "system.h" #include "system.h"
#include "game.h" #include "game.h"
#include "world/world.h"
#include "packets/packet.h"
#include "signal_handling.h"
#include "network.h"
#include "flecs/flecs.h"
#include "flecs/flecs_dash.h"
#include "flecs/flecs_systems_civetweb.h"
#include "flecs/flecs_os_api_stdcpp.h"
#define DEFAULT_WORLD_SEED 302097 #define DEFAULT_WORLD_SEED 302097
#define DEFAULT_BLOCK_SIZE 64 /* amount of units within a block (single axis) */ #define DEFAULT_BLOCK_SIZE 64 /* amount of units within a block (single axis) */
#define DEFAULT_CHUNK_SIZE 3 /* amount of blocks within a chunk (single axis) */ #define DEFAULT_CHUNK_SIZE 3 /* amount of blocks within a chunk (single axis) */
#define DEFAULT_WORLD_SIZE 8 /* amount of chunks within a world (single axis) */ #define DEFAULT_WORLD_SIZE 8 /* amount of chunks within a world (single axis) */
static WORLD_PKT_READER(pkt_reader) {
pkt_header header = {0};
uint32_t ok = pkt_header_decode(&header, data, datalen);
if (ok && header.ok) {
return pkt_handlers[header.id].handler(&header);
} else {
zpl_printf("[warn] unknown packet id %d (header %d data %d)\n", header.id, ok, header.ok);
}
return -1;
}
static WORLD_PKT_WRITER(sp_pkt_writer) {
return world_read(pkt->data, pkt->datalen);
}
static WORLD_PKT_WRITER(mp_pkt_writer) {
return 0; // TODO(zaklaus): enet send packet
}
inline int32_t pkt_world_write(pkt_messages id, size_t pkt_size, int8_t is_reliable) {
pkt_header pkt;
PKT_IF(pkt_prep_msg(&pkt, id, pkt_size, is_reliable));
return world_write(&pkt);
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
zpl_opts opts={0}; zpl_opts opts={0};
@ -64,7 +29,7 @@ int main(int argc, char** argv)
return -1; return -1;
} }
uint8_t is_networked_play = !zpl_opts_has_arg(&opts, "single-player"); int8_t is_networked_play = !zpl_opts_has_arg(&opts, "single-player");
int32_t seed = zpl_opts_integer(&opts, "seed", DEFAULT_WORLD_SEED); int32_t seed = zpl_opts_integer(&opts, "seed", DEFAULT_WORLD_SEED);
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);
@ -78,48 +43,18 @@ int main(int argc, char** argv)
} }
sighandler_register(); sighandler_register();
stdcpp_set_os_api(); game_init(is_networked_play, seed, block_size, chunk_size, world_size);
game_init();
if (is_networked_play) {
world_init_minimal(0, 0, 0, pkt_reader, mp_pkt_writer);
network_init();
network_client_connect("127.0.0.1", 27000);
} else {
world_init(seed, block_size, chunk_size, world_size, pkt_reader, sp_pkt_writer);
pkt_01_welcome table = {.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);
}
/* 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);
}
while (game_is_running()) while (game_is_running())
{ {
game_input(); game_input();
game_update(); game_update();
game_render(); game_render();
if (is_networked_play) network_client_tick();
else world_update();
} }
game_shutdown(); game_shutdown();
sighandler_unregister(); sighandler_unregister();
if (is_networked_play) {
network_client_disconnect();
network_destroy();
} else {
world_destroy();
}
zpl_opts_free(&opts); zpl_opts_free(&opts);
return 0; return 0;
} }

View File

@ -96,7 +96,6 @@ int32_t network_client_disconnect() {
int32_t network_client_tick() { int32_t network_client_tick() {
ENetEvent event = {0}; ENetEvent event = {0};
#define ID 0
while (enet_host_service(host, &event, 1) > 0) { while (enet_host_service(host, &event, 1) > 0) {
switch (event.type) { switch (event.type) {
@ -109,12 +108,7 @@ int32_t network_client_tick() {
} break; } break;
case ENET_EVENT_TYPE_RECEIVE: { case ENET_EVENT_TYPE_RECEIVE: {
pkt_header header = {0}; if (!world_read(event.packet->data, event.packet->dataLength, NULL)) {
uint32_t ok = pkt_header_decode(&header, event.packet->data, event.packet->dataLength);
if (ok && header.ok) {
pkt_handlers[header.id].handler(&header);
} else {
zpl_printf("[INFO] Server sent us an unsupported packet.\n"); zpl_printf("[INFO] Server sent us an unsupported packet.\n");
} }
@ -163,15 +157,15 @@ bool network_client_is_connected() {
return peer ? enet_peer_get_state(peer) == ENET_PEER_STATE_CONNECTED : false; return peer ? enet_peer_get_state(peer) == ENET_PEER_STATE_CONNECTED : false;
} }
static int32_t network_msg_send_raw(uint16_t peer_id, void *data, size_t datalen, uint32_t flags) { static int32_t network_msg_send_raw(uint16_t peer_id, void *data, size_t datalen, uint32_t flags) {
ENetPacket *packet = enet_packet_create(data, datalen, flags); ENetPacket *packet = enet_packet_create(data, datalen, flags);
enet_peer_send(peer, 0, packet); return enet_peer_send(peer, 0, packet);
} }
int32_t network_msg_send(uint16_t peer_id, void *data, size_t datalen) { int32_t network_msg_send(void *data, size_t datalen) {
network_msg_send_raw(0, data, datalen, ENET_PACKET_FLAG_RELIABLE); return network_msg_send_raw(0, data, datalen, ENET_PACKET_FLAG_RELIABLE);
} }
int32_t network_msg_send_unreliable(uint16_t peer_id, void *data, size_t datalen) { int32_t network_msg_send_unreliable(void *data, size_t datalen) {
network_msg_send_raw(0, data, datalen, 0); return network_msg_send_raw(0, data, datalen, 0);
} }

View File

@ -8,8 +8,10 @@ int32_t network_server_stop(void);
int32_t network_server_tick(void); int32_t network_server_tick(void);
void network_server_update(void *data); void network_server_update(void *data);
uint64_t network_client_create(uint16_t peer_id); uint64_t network_client_create(void *peer);
void network_client_destroy(uint64_t ent_id); void network_client_destroy(uint64_t ent_id);
int32_t network_msg_send(uint16_t peer_id, void *data, size_t datalen); int32_t network_msg_send(void *peer, void *data, size_t datalen);
int32_t network_msg_send_unreliable(uint16_t peer_id, void *data, size_t datalen); int32_t network_msg_send_unreliable(void *peer, void *data, size_t datalen);
WORLD_PKT_WRITER(mp_pkt_writer);

View File

@ -2,8 +2,8 @@
#include "zpl.h" #include "zpl.h"
#include "system.h" #include "system.h"
#include "network.h"
#include "world/world.h" #include "world/world.h"
#include "network.h"
#include "utils/options.h" #include "utils/options.h"
#include "signal_handling.h" #include "signal_handling.h"
@ -25,12 +25,14 @@
} while (0) } while (0)
static WORLD_PKT_READER(mp_pkt_reader) { static WORLD_PKT_READER(mp_pkt_reader) {
// TODO(zaklaus): implement this pkt_header header = {0};
return -1; uint32_t ok = pkt_header_decode(&header, data, datalen);
}
static WORLD_PKT_WRITER(mp_pkt_writer) { if (ok && header.ok) {
// TODO(zaklaus): implement this return pkt_handlers[header.id].handler(&header) >= 0;
} else {
zpl_printf("[warn] unknown packet id %d (header %d data %d)\n", header.id, ok, header.ok);
}
return -1; return -1;
} }

View File

@ -24,6 +24,15 @@
static ENetHost *server = NULL; static ENetHost *server = NULL;
static zpl_timer nettimer = {0}; static zpl_timer nettimer = {0};
WORLD_PKT_WRITER(mp_pkt_writer) {
if (pkt->is_reliable) {
return network_msg_send(udata, pkt->data, pkt->datalen);
}
else {
return network_msg_send_unreliable(udata, pkt->data, pkt->datalen);
}
}
int32_t network_init(void) { int32_t network_init(void) {
zpl_timer_set(&nettimer, NETWORK_UPDATE_DELAY, -1, network_server_update); zpl_timer_set(&nettimer, NETWORK_UPDATE_DELAY, -1, network_server_update);
return enet_initialize() != 0; return enet_initialize() != 0;
@ -74,6 +83,9 @@ int32_t network_server_tick(void) {
uint64_t ent_id = network_client_create(event.peer); uint64_t ent_id = network_client_create(event.peer);
// TODO: Make sure ent_id does not get truncated with large entity numbers. // TODO: Make sure ent_id does not get truncated with large entity numbers.
event.peer->data = (void*)((uint32_t)ent_id); event.peer->data = (void*)((uint32_t)ent_id);
pkt_01_welcome table = {.block_size = world_block_size(), .chunk_size = world_chunk_size(), .world_size = world_world_size()};
pkt_world_write(MSG_ID_01_WELCOME, pkt_01_welcome_encode(&table), 1, event.peer);
} break; } break;
case ENET_EVENT_TYPE_DISCONNECT: case ENET_EVENT_TYPE_DISCONNECT:
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: { case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: {
@ -83,18 +95,12 @@ int32_t network_server_tick(void) {
} break; } break;
case ENET_EVENT_TYPE_RECEIVE: { case ENET_EVENT_TYPE_RECEIVE: {
pkt_header header = {0}; if (!world_read(event.packet->data, event.packet->dataLength, event.peer)) {
uint32_t ok = pkt_header_decode(&header, event.packet->data, event.packet->dataLength);
if (ok && header.ok) {
pkt_handlers[header.id].handler(&header);
} else {
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);
ecs_entity_t e = (ecs_entity_t)((uint32_t)event.peer->data); ecs_entity_t e = (ecs_entity_t)((uint32_t)event.peer->data);
network_client_destroy(e); network_client_destroy(e);
} }
// /* handle a newly received event */ // /* handle a newly received event */
// librg_world_read( // librg_world_read(
// world_tracker(), // world_tracker(),
@ -143,18 +149,18 @@ void network_server_update(void *data) {
// } // }
} }
uint64_t network_client_create(uint16_t peer_id) { uint64_t network_client_create(ENetPeer *peer) {
ECS_IMPORT(world_ecs(), General); ECS_IMPORT(world_ecs(), General);
ECS_IMPORT(world_ecs(), Controllers); ECS_IMPORT(world_ecs(), Controllers);
ECS_IMPORT(world_ecs(), Net); ECS_IMPORT(world_ecs(), Net);
ecs_entity_t e = ecs_new(world_ecs(), 0); ecs_entity_t e = ecs_new(world_ecs(), 0);
ecs_add(world_ecs(), e, EcsClient); ecs_add(world_ecs(), e, EcsClient);
ecs_set(world_ecs(), e, ClientInfo, {peer_id}); ecs_set(world_ecs(), e, ClientInfo, {peer});
ecs_set(world_ecs(), e, EcsName, {.alloc_value = zpl_bprintf("client_%d", peer_id) }); ecs_set(world_ecs(), e, EcsName, {.alloc_value = zpl_bprintf("client_%d", peer->incomingPeerID) });
librg_entity_track(world_tracker(), e); librg_entity_track(world_tracker(), e);
librg_entity_owner_set(world_tracker(), e, peer_id); librg_entity_owner_set(world_tracker(), e, (int64_t)peer);
librg_entity_radius_set(world_tracker(), e, 2); /* 2 chunk radius visibility */ librg_entity_radius_set(world_tracker(), e, 2); /* 2 chunk radius visibility */
// librg_entity_chunk_set(world_tracker(), e, 1); // librg_entity_chunk_set(world_tracker(), e, 1);
@ -166,25 +172,15 @@ void network_client_destroy(uint64_t ent_id) {
ecs_delete(world_ecs(), ent_id); ecs_delete(world_ecs(), ent_id);
} }
static ENetPeer *network_enet_find_by_id(uint16_t peer_id) { static int32_t network_msg_send_raw(ENetPeer *peer, void *data, size_t datalen, uint32_t flags) {
for (size_t i = 0; i < server->peerCount; ++i) {
ENetPeer *peer = &server->peers[i];
if (enet_peer_get_id(peer) == peer_id)
return peer;
}
return NULL;
}
static int32_t network_msg_send_raw(uint16_t peer_id, void *data, size_t datalen, uint32_t flags) {
ENetPacket *packet = enet_packet_create(data, datalen, flags); ENetPacket *packet = enet_packet_create(data, datalen, flags);
enet_peer_send(network_enet_find_by_id(peer_id), 0, packet); return enet_peer_send(peer, 0, packet);
} }
int32_t network_msg_send(uint16_t peer_id, void *data, size_t datalen) { int32_t network_msg_send(ENetPeer *peer, void *data, size_t datalen) {
network_msg_send_raw(peer_id, data, datalen, ENET_PACKET_FLAG_RELIABLE); return network_msg_send_raw(peer, data, datalen, ENET_PACKET_FLAG_RELIABLE);
} }
int32_t network_msg_send_unreliable(uint16_t peer_id, void *data, size_t datalen) { int32_t network_msg_send_unreliable(ENetPeer *peer, void *data, size_t datalen) {
network_msg_send_raw(peer_id, data, datalen, 0); return network_msg_send_raw(peer, data, datalen, 0);
} }

View File

@ -51,6 +51,14 @@ inline int32_t pkt_prep_msg(pkt_header *pkt, pkt_messages id, size_t pkt_size, i
return 0; return 0;
} }
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) {
pkt_header pkt;
PKT_IF(pkt_prep_msg(&pkt, id, pkt_size, is_reliable));
return world_write(&pkt, udata);
}
#ifndef PKT_OFFSETOF #ifndef PKT_OFFSETOF
#if defined(_MSC_VER) || defined(ZPL_COMPILER_TINYC) #if defined(_MSC_VER) || defined(ZPL_COMPILER_TINYC)
# define PKT_OFFSETOF(Type, element) ((size_t) & (((Type *)0)->element)) # define PKT_OFFSETOF(Type, element) ((size_t) & (((Type *)0)->element))

View File

@ -134,16 +134,16 @@ int32_t world_update() {
return 0; return 0;
} }
int32_t world_read(void* data, uint32_t datalen) { int32_t world_read(void* data, uint32_t datalen, void *udata) {
if (world.reader_proc) { if (world.reader_proc) {
return world.reader_proc(data, datalen); return world.reader_proc(data, datalen, udata);
} }
return -1; return -1;
} }
int32_t world_write(pkt_header *pkt) { int32_t world_write(pkt_header *pkt, void *udata) {
if (world.writer_proc) { if (world.writer_proc) {
return world.writer_proc(pkt); return world.writer_proc(pkt, udata);
} }
return -1; return -1;
} }
@ -164,11 +164,15 @@ librg_world * world_tracker() {
return world.tracker; return world.tracker;
} }
uint16_t world_block_size(void) {
return world.block_size;
}
uint16_t world_chunk_size(void) { uint16_t world_chunk_size(void) {
return world.chunk_size; return world.chunk_size;
} }
uint16_t world_chunk_amount(void) { uint16_t world_world_size(void) {
return world.world_size; return world.world_size;
} }

View File

@ -11,22 +11,23 @@
#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_PKT_READER(name) int32_t name(void* data, uint32_t datalen) #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);
#define WORLD_PKT_WRITER(name) int32_t name(pkt_header *pkt) #define WORLD_PKT_WRITER(name) int32_t name(pkt_header *pkt, void *udata)
typedef WORLD_PKT_WRITER(world_pkt_writer_proc); 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_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); 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);
int32_t world_destroy(void); int32_t world_destroy(void);
int32_t world_update(void); int32_t world_update(void);
int32_t world_read(void* data, uint32_t datalen); int32_t world_read(void* data, uint32_t datalen, void *udata);
int32_t world_write(pkt_header *pkt); int32_t world_write(pkt_header *pkt, void *udata);
uint32_t world_buf(uint8_t const **ptr, uint32_t *width); uint32_t world_buf(uint8_t const **ptr, uint32_t *width);
ecs_world_t * world_ecs(void); ecs_world_t * world_ecs(void);
librg_world * world_tracker(void); librg_world * world_tracker(void);
uint16_t world_block_size(void);
uint16_t world_chunk_size(void); uint16_t world_chunk_size(void);
uint16_t world_chunk_amount(void); uint16_t world_world_size(void);