Implement networking layer
parent
096bf8c706
commit
d35b4381ec
|
@ -42,7 +42,6 @@ In the abstract sense, we call the Server the game master hosting all gameplay r
|
||||||
|
|
||||||
## Major things to do
|
## Major things to do
|
||||||
* More believable world generation.
|
* More believable world generation.
|
||||||
* Networking implementation, the communication part is done, but there's currently no way to start a headless server or connect to it anyhow.
|
|
||||||
* Improved rendering - the current world structure does not allow for layered blocks, but it's something worth looking into.
|
* Improved rendering - the current world structure does not allow for layered blocks, but it's something worth looking into.
|
||||||
* UI and visual effects
|
* UI and visual effects
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "debug_draw.h"
|
#include "debug_draw.h"
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
static debug_draw_queue draw_queue = {0};
|
static debug_draw_queue draw_queue = {0};
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ bool debug_draw_state(void) {
|
||||||
|
|
||||||
inline void debug_push_entry(debug_draw_entry entry) {
|
inline void debug_push_entry(debug_draw_entry entry) {
|
||||||
if (!draw_is_enabled) return;
|
if (!draw_is_enabled) return;
|
||||||
|
if (game_get_kind() == GAMEKIND_HEADLESS) return;
|
||||||
ZPL_ASSERT(draw_queue.num_entries < DEBUG_DRAW_MAX_ENTRIES);
|
ZPL_ASSERT(draw_queue.num_entries < DEBUG_DRAW_MAX_ENTRIES);
|
||||||
draw_queue.entries[draw_queue.num_entries++] = entry;
|
draw_queue.entries[draw_queue.num_entries++] = entry;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ typedef struct debug_item {
|
||||||
struct {
|
struct {
|
||||||
struct debug_item *items;
|
struct debug_item *items;
|
||||||
uint8_t is_collapsed;
|
uint8_t is_collapsed;
|
||||||
|
uint8_t is_sp_only;
|
||||||
} list;
|
} list;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -118,7 +119,8 @@ static debug_item items[] = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ .kind = DITEM_END },
|
{ .kind = DITEM_END },
|
||||||
}
|
},
|
||||||
|
.is_sp_only = true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -153,7 +155,8 @@ static debug_item items[] = {
|
||||||
{ .kind = DITEM_BUTTON, .name = "save as...", .on_click = ActReplaySaveAs },
|
{ .kind = DITEM_BUTTON, .name = "save as...", .on_click = ActReplaySaveAs },
|
||||||
|
|
||||||
{ .kind = DITEM_END },
|
{ .kind = DITEM_END },
|
||||||
}
|
},
|
||||||
|
.is_sp_only = true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -209,6 +212,7 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
|
||||||
UIDrawText(it->name, xpos, ypos, DBG_FONT_SIZE, color);
|
UIDrawText(it->name, xpos, ypos, DBG_FONT_SIZE, color);
|
||||||
ypos += DBG_FONT_SPACING;
|
ypos += DBG_FONT_SPACING;
|
||||||
if (it->list.is_collapsed) break;
|
if (it->list.is_collapsed) break;
|
||||||
|
if (it->list.is_sp_only && game_get_kind() != GAMEKIND_SINGLE) break;
|
||||||
debug_draw_result res = debug_draw_list(it->list.items, xpos+DBG_LIST_XPOS_OFFSET, ypos, is_shadow);
|
debug_draw_result res = debug_draw_list(it->list.items, xpos+DBG_LIST_XPOS_OFFSET, ypos, is_shadow);
|
||||||
ypos = res.y;
|
ypos = res.y;
|
||||||
}break;
|
}break;
|
||||||
|
|
|
@ -47,12 +47,21 @@ static WORLD_PKT_WRITER(sp_pkt_writer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static WORLD_PKT_WRITER(mp_pkt_writer) {
|
static WORLD_PKT_WRITER(mp_pkt_writer) {
|
||||||
(void)udata;
|
|
||||||
if (pkt->is_reliable) {
|
if (pkt->is_reliable) {
|
||||||
return network_msg_send(pkt->data, pkt->datalen);
|
return network_msg_send(udata, pkt->data, pkt->datalen);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return network_msg_send_unreliable(pkt->data, pkt->datalen);
|
return network_msg_send_unreliable(udata, pkt->data, pkt->datalen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static WORLD_PKT_WRITER(mp_cli_pkt_writer) {
|
||||||
|
(void)udata;
|
||||||
|
if (pkt->is_reliable) {
|
||||||
|
return network_msg_send(0, pkt->data, pkt->datalen);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return network_msg_send_unreliable(0, pkt->data, pkt->datalen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,17 +139,25 @@ void game_init(game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game_mode == GAMEKIND_CLIENT) {
|
if (game_mode == GAMEKIND_CLIENT) {
|
||||||
world_setup_pkt_handlers(pkt_reader, mp_pkt_writer);
|
world_setup_pkt_handlers(pkt_reader, mp_cli_pkt_writer);
|
||||||
|
#ifndef _DEBUG
|
||||||
|
network_client_connect("lab.zakto.pw", 27000);
|
||||||
|
#else
|
||||||
network_client_connect("127.0.0.1", 27000);
|
network_client_connect("127.0.0.1", 27000);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
stdcpp_set_os_api();
|
stdcpp_set_os_api();
|
||||||
world_setup_pkt_handlers(pkt_reader, sp_pkt_writer);
|
world_setup_pkt_handlers(pkt_reader, game_mode == GAMEKIND_SINGLE ? sp_pkt_writer : mp_pkt_writer);
|
||||||
world_init(seed, chunk_size, chunk_amount);
|
world_init(seed, chunk_size, chunk_amount);
|
||||||
if (is_dash_enabled) flecs_dash_init();
|
if (is_dash_enabled) flecs_dash_init();
|
||||||
//ecs_set_target_fps(world_ecs(), 60);
|
//ecs_set_target_fps(world_ecs(), 60);
|
||||||
|
|
||||||
|
if (game_mode == GAMEKIND_HEADLESS) {
|
||||||
|
network_server_start(0, 27000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game_mode != GAMEKIND_HEADLESS) {
|
if (game_mode == GAMEKIND_SINGLE) {
|
||||||
for (uint32_t i = 0; i < num_viewers; i++) {
|
for (uint32_t i = 0; i < num_viewers; i++) {
|
||||||
pkt_00_init_send(i);
|
pkt_00_init_send(i);
|
||||||
}
|
}
|
||||||
|
@ -157,6 +174,10 @@ void game_shutdown() {
|
||||||
network_client_disconnect();
|
network_client_disconnect();
|
||||||
} else {
|
} else {
|
||||||
world_destroy();
|
world_destroy();
|
||||||
|
|
||||||
|
if (game_mode == GAMEKIND_HEADLESS) {
|
||||||
|
network_server_stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game_mode != GAMEKIND_SINGLE) {
|
if (game_mode != GAMEKIND_SINGLE) {
|
||||||
|
@ -187,7 +208,13 @@ void game_update() {
|
||||||
if (game_mode == GAMEKIND_CLIENT) {
|
if (game_mode == GAMEKIND_CLIENT) {
|
||||||
network_client_tick();
|
network_client_tick();
|
||||||
}
|
}
|
||||||
else world_update();
|
else {
|
||||||
|
world_update();
|
||||||
|
|
||||||
|
if (game_mode == GAMEKIND_HEADLESS) {
|
||||||
|
network_server_tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (game_mode != GAMEKIND_HEADLESS) {
|
if (game_mode != GAMEKIND_HEADLESS) {
|
||||||
game_world_cleanup_entities();
|
game_world_cleanup_entities();
|
||||||
|
|
|
@ -11,10 +11,13 @@
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "world/world.h"
|
#include "world/world.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
#define NETWORK_UPDATE_DELAY 0.100
|
#define NETWORK_UPDATE_DELAY 0.100
|
||||||
|
|
||||||
static ENetHost *host = NULL;
|
static ENetHost *host = NULL;
|
||||||
|
static ENetHost *server = NULL;
|
||||||
static ENetPeer *peer = NULL;
|
static ENetPeer *peer = NULL;
|
||||||
static librg_world *world = NULL;
|
static librg_world *world = NULL;
|
||||||
|
|
||||||
|
@ -28,6 +31,7 @@ int32_t network_destroy() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//~ NOTE(zaklaus): client
|
||||||
|
|
||||||
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;
|
||||||
|
@ -44,12 +48,6 @@ int32_t network_client_connect(const char *hostname, uint16_t port) {
|
||||||
world = librg_world_create();
|
world = librg_world_create();
|
||||||
librg_world_userdata_set(world, peer);
|
librg_world_userdata_set(world, peer);
|
||||||
|
|
||||||
#if 0
|
|
||||||
librg_event_set(world, LIBRG_READ_CREATE, client_read_create);
|
|
||||||
librg_event_set(world, LIBRG_READ_UPDATE, client_read_update);
|
|
||||||
librg_event_set(world, LIBRG_READ_REMOVE, client_read_remove);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +71,7 @@ int32_t network_client_tick() {
|
||||||
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);
|
||||||
} break;
|
} break;
|
||||||
case ENET_EVENT_TYPE_DISCONNECT:
|
case ENET_EVENT_TYPE_DISCONNECT:
|
||||||
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: {
|
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: {
|
||||||
|
@ -80,7 +79,7 @@ int32_t network_client_tick() {
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_RECEIVE: {
|
case ENET_EVENT_TYPE_RECEIVE: {
|
||||||
if (!world_read(event.packet->data, event.packet->dataLength, NULL)) {
|
if (!world_read(event.packet->data, 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,15 +98,91 @@ 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) {
|
//~ NOTE(zaklaus): server
|
||||||
|
|
||||||
|
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, 100, 2, 0, 0);
|
||||||
|
|
||||||
|
if (server == NULL) {
|
||||||
|
zpl_printf("[ERROR] An error occured while trying to create a server host.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t network_server_stop(void) {
|
||||||
|
enet_host_destroy(server);
|
||||||
|
server = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t network_server_tick(void) {
|
||||||
|
ENetEvent event = {0};
|
||||||
|
while (enet_host_service(server, &event, 1) > 0) {
|
||||||
|
switch (event.type) {
|
||||||
|
case ENET_EVENT_TYPE_CONNECT: {
|
||||||
|
zpl_printf("[INFO] A new user %d connected.\n", event.peer->incomingPeerID);
|
||||||
|
} break;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ENET_EVENT_TYPE_RECEIVE: {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t network_server_get_entity(void *peer_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//~ NOTE(zaklaus): messaging
|
||||||
|
|
||||||
|
static int32_t network_msg_send_raw(ENetPeer *peer_id, void *data, size_t datalen, uint32_t flags) {
|
||||||
|
if (peer_id == 0) peer_id = peer;
|
||||||
ENetPacket *packet = enet_packet_create(data, datalen, flags);
|
ENetPacket *packet = enet_packet_create(data, datalen, flags);
|
||||||
return enet_peer_send(peer, 0, packet);
|
return enet_peer_send(peer_id, 0, packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t network_msg_send(void *data, size_t datalen) {
|
int32_t network_msg_send(void *peer_id, void *data, size_t datalen) {
|
||||||
return network_msg_send_raw(0, data, datalen, ENET_PACKET_FLAG_RELIABLE);
|
return network_msg_send_raw(peer_id, data, datalen, ENET_PACKET_FLAG_RELIABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t network_msg_send_unreliable(void *data, size_t datalen) {
|
int32_t network_msg_send_unreliable(void *peer_id, void *data, size_t datalen) {
|
||||||
return network_msg_send_raw(0, data, datalen, 0);
|
return network_msg_send_raw(peer_id, data, datalen, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,20 @@
|
||||||
int32_t network_init(void);
|
int32_t network_init(void);
|
||||||
int32_t network_destroy(void);
|
int32_t network_destroy(void);
|
||||||
|
|
||||||
|
// NOTE(zaklaus): client
|
||||||
int32_t network_client_connect(const char *host, uint16_t port);
|
int32_t network_client_connect(const char *host, uint16_t port);
|
||||||
int32_t network_client_disconnect(void);
|
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);
|
// NOTE(zaklaus): server
|
||||||
int32_t network_msg_send_unreliable(void *data, size_t datalen);
|
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);
|
||||||
|
|
||||||
|
// NOTE(zaklaus): messaging
|
||||||
|
int32_t network_msg_send(void *peer_id, void *data, size_t datalen);
|
||||||
|
int32_t network_msg_send_unreliable(void *peer_id, void *data, size_t datalen);
|
||||||
|
|
|
@ -109,10 +109,6 @@ static inline int32_t pkt_world_write(pkt_messages id, size_t pkt_size, int8_t i
|
||||||
#define PKT_END .type = CWP_NOT_AN_ITEM
|
#define PKT_END .type = CWP_NOT_AN_ITEM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PKT_GET_ENT
|
|
||||||
#define PKT_GET_ENT(h) (ecs_entity_t)(h->udata)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct pkt_desc {
|
typedef struct pkt_desc {
|
||||||
const char *name;
|
const char *name;
|
||||||
cwpack_item_types type;
|
cwpack_item_types type;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "world/world.h"
|
#include "world/world.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
#include "network.h"
|
||||||
#include "entity_view.h"
|
#include "entity_view.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
@ -33,7 +34,16 @@ int32_t pkt_00_init_handler(pkt_header *header) {
|
||||||
|
|
||||||
uint64_t peer_id = (uint64_t)header->udata;
|
uint64_t peer_id = (uint64_t)header->udata;
|
||||||
uint64_t ent_id = player_spawn(NULL);
|
uint64_t ent_id = player_spawn(NULL);
|
||||||
ecs_set(world_ecs(), ent_id, ClientInfo, {.peer = ent_id, .view_id = header->view_id });
|
|
||||||
|
Position *pos = ecs_get_mut(world_ecs(), ent_id, Position, NULL);
|
||||||
|
pos->x = world_dim()/2.0f + rand()%15*15.0f;
|
||||||
|
pos->y = world_dim()/2.0f + rand()%15*15.0f;
|
||||||
|
|
||||||
|
|
||||||
|
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());
|
pkt_01_welcome_send(world_seed(), peer_id, header->view_id, ent_id, world_chunk_size(), world_chunk_amount());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "packet_utils.h"
|
#include "packet_utils.h"
|
||||||
|
#include "network.h"
|
||||||
#include "packets/pkt_send_keystate.h"
|
#include "packets/pkt_send_keystate.h"
|
||||||
#include "modules/components.h"
|
#include "modules/components.h"
|
||||||
#include "modules/systems.h"
|
#include "modules/systems.h"
|
||||||
|
@ -49,7 +50,10 @@ size_t pkt_send_keystate_encode(pkt_send_keystate *table) {
|
||||||
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 = PKT_GET_ENT(header);
|
ecs_entity_t e = network_server_get_entity(header->udata);
|
||||||
|
|
||||||
|
if (!world_entity_valid(e))
|
||||||
|
return 1;
|
||||||
|
|
||||||
Input *i = ecs_get_mut(world_ecs(), e, Input, NULL);
|
Input *i = ecs_get_mut(world_ecs(), e, Input, NULL);
|
||||||
if (i && !i->is_blocked) {
|
if (i && !i->is_blocked) {
|
||||||
|
|
|
@ -261,7 +261,7 @@ static void world_tracker_update(uint8_t ticker, uint32_t freq, uint8_t radius)
|
||||||
librg_entity_radius_set(world_tracker(), p[i].peer, radius);
|
librg_entity_radius_set(world_tracker(), p[i].peer, radius);
|
||||||
}
|
}
|
||||||
// TODO(zaklaus): push radius once librg patch comes in
|
// TODO(zaklaus): push radius once librg patch comes in
|
||||||
int32_t result = librg_world_write(world_tracker(), p[i].peer, buffer, &datalen, NULL);
|
int32_t result = librg_world_write(world_tracker(), it.entities[i], buffer, &datalen, NULL);
|
||||||
|
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
zpl_printf("[info] buffer size was not enough, please increase it by at least: %d\n", result);
|
zpl_printf("[info] buffer size was not enough, please increase it by at least: %d\n", result);
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
#include "world/blocks.h"
|
#include "world/blocks.h"
|
||||||
#include "world/perlin.h"
|
#include "world/perlin.h"
|
||||||
|
|
||||||
|
#include "modules/components.h"
|
||||||
|
#include "vehicle.h"
|
||||||
|
#include "items.h"
|
||||||
|
|
||||||
#define WORLD_BLOCK_OBSERVER(name) uint8_t name(uint8_t id, uint32_t block_idx)
|
#define WORLD_BLOCK_OBSERVER(name) uint8_t name(uint8_t id, uint32_t block_idx)
|
||||||
typedef WORLD_BLOCK_OBSERVER(world_block_observer_proc);
|
typedef WORLD_BLOCK_OBSERVER(world_block_observer_proc);
|
||||||
|
|
||||||
|
@ -173,5 +177,27 @@ int32_t worldgen_test(world_data *wld) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// vehicles
|
||||||
|
#if 1
|
||||||
|
for (int i=0; i<RAND_RANGE(258, 1124); i++) {
|
||||||
|
uint64_t e = vehicle_spawn();
|
||||||
|
|
||||||
|
Position *dest = ecs_get_mut(world_ecs(), e, Position, NULL);
|
||||||
|
dest->x = RAND_RANGE(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
dest->y = RAND_RANGE(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// items
|
||||||
|
#if 1
|
||||||
|
for (int i=0; i<RAND_RANGE(328, 164); i++) {
|
||||||
|
uint64_t e = item_spawn(IKIND_DEMO_ICEMAKER, 32);
|
||||||
|
|
||||||
|
Position *dest = ecs_get_mut(world_ecs(), e, Position, NULL);
|
||||||
|
dest->x = RAND_RANGE(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
dest->y = RAND_RANGE(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return WORLD_ERROR_NONE;
|
return WORLD_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
build\Debug\eco2d.exe -v %*
|
|
@ -0,0 +1,5 @@
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
call package.bat
|
||||||
|
|
||||||
|
pkg\eco2d.exe -v %*
|
Loading…
Reference in New Issue