fix MP support
parent
e5d45a8c67
commit
e85b15d5f1
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
Loading…
Reference in New Issue