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
#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();
uint8_t game_is_running();

View File

@ -9,3 +9,6 @@ int32_t network_client_disconnect(void);
int32_t network_client_tick(void);
void network_client_update(void *data);
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 "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();
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() {
//
if (is_networked_play) {
network_client_disconnect();
network_destroy();
} else {
world_destroy();
}
}
uint8_t game_is_running() {
@ -18,7 +81,8 @@ void game_input() {
}
void game_update() {
if (is_networked_play) network_client_tick();
else world_update();
}
void game_render() {

View File

@ -2,47 +2,12 @@
#include "zpl.h"
#include "system.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_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_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)
{
zpl_opts opts={0};
@ -64,7 +29,7 @@ int main(int argc, char** argv)
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);
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);
@ -78,48 +43,18 @@ int main(int argc, char** argv)
}
sighandler_register();
stdcpp_set_os_api();
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);
}
game_init(is_networked_play, seed, block_size, chunk_size, world_size);
while (game_is_running())
{
game_input();
game_update();
game_render();
if (is_networked_play) network_client_tick();
else world_update();
}
game_shutdown();
sighandler_unregister();
if (is_networked_play) {
network_client_disconnect();
network_destroy();
} else {
world_destroy();
}
zpl_opts_free(&opts);
return 0;
}

View File

@ -96,7 +96,6 @@ int32_t network_client_disconnect() {
int32_t network_client_tick() {
ENetEvent event = {0};
#define ID 0
while (enet_host_service(host, &event, 1) > 0) {
switch (event.type) {
@ -109,12 +108,7 @@ int32_t network_client_tick() {
} break;
case ENET_EVENT_TYPE_RECEIVE: {
pkt_header header = {0};
uint32_t ok = pkt_header_decode(&header, event.packet->data, event.packet->dataLength);
if (ok && header.ok) {
pkt_handlers[header.id].handler(&header);
} else {
if (!world_read(event.packet->data, event.packet->dataLength, NULL)) {
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;
}
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);
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) {
network_msg_send_raw(0, data, datalen, ENET_PACKET_FLAG_RELIABLE);
int32_t network_msg_send(void *data, size_t datalen) {
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) {
network_msg_send_raw(0, data, datalen, 0);
int32_t network_msg_send_unreliable(void *data, size_t datalen) {
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);
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);
int32_t network_msg_send(uint16_t peer_id, 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(void *peer, 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 "system.h"
#include "network.h"
#include "world/world.h"
#include "network.h"
#include "utils/options.h"
#include "signal_handling.h"
@ -25,12 +25,14 @@
} while (0)
static WORLD_PKT_READER(mp_pkt_reader) {
// TODO(zaklaus): implement this
return -1;
}
pkt_header header = {0};
uint32_t ok = pkt_header_decode(&header, data, datalen);
static WORLD_PKT_WRITER(mp_pkt_writer) {
// TODO(zaklaus): implement this
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;
}

View File

@ -24,6 +24,15 @@
static ENetHost *server = NULL;
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) {
zpl_timer_set(&nettimer, NETWORK_UPDATE_DELAY, -1, network_server_update);
return enet_initialize() != 0;
@ -74,6 +83,9 @@ int32_t network_server_tick(void) {
uint64_t ent_id = network_client_create(event.peer);
// TODO: Make sure ent_id does not get truncated with large entity numbers.
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;
case ENET_EVENT_TYPE_DISCONNECT:
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: {
@ -83,18 +95,12 @@ int32_t network_server_tick(void) {
} break;
case ENET_EVENT_TYPE_RECEIVE: {
pkt_header header = {0};
uint32_t ok = pkt_header_decode(&header, event.packet->data, event.packet->dataLength);
if (ok && header.ok) {
pkt_handlers[header.id].handler(&header);
} else {
if (!world_read(event.packet->data, event.packet->dataLength, event.peer)) {
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);
network_client_destroy(e);
}
// /* handle a newly received event */
// librg_world_read(
// 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(), Controllers);
ECS_IMPORT(world_ecs(), Net);
ecs_entity_t e = ecs_new(world_ecs(), 0);
ecs_add(world_ecs(), e, EcsClient);
ecs_set(world_ecs(), e, ClientInfo, {peer_id});
ecs_set(world_ecs(), e, EcsName, {.alloc_value = zpl_bprintf("client_%d", peer_id) });
ecs_set(world_ecs(), e, ClientInfo, {peer});
ecs_set(world_ecs(), e, EcsName, {.alloc_value = zpl_bprintf("client_%d", peer->incomingPeerID) });
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_chunk_set(world_tracker(), e, 1);
@ -166,25 +172,15 @@ void network_client_destroy(uint64_t ent_id) {
ecs_delete(world_ecs(), ent_id);
}
static ENetPeer *network_enet_find_by_id(uint16_t peer_id) {
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) {
static int32_t network_msg_send_raw(ENetPeer *peer, void *data, size_t datalen, uint32_t 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) {
network_msg_send_raw(peer_id, data, datalen, ENET_PACKET_FLAG_RELIABLE);
int32_t network_msg_send(ENetPeer *peer, void *data, size_t datalen) {
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) {
network_msg_send_raw(peer_id, data, datalen, 0);
int32_t network_msg_send_unreliable(ENetPeer *peer, void *data, size_t datalen) {
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;
}
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
#if defined(_MSC_VER) || defined(ZPL_COMPILER_TINYC)
# define PKT_OFFSETOF(Type, element) ((size_t) & (((Type *)0)->element))

View File

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

View File

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