Improve hashtable entry removal performance
parent
a589845065
commit
296857df71
|
@ -90,7 +90,6 @@ static debug_item items[] = {
|
|||
{ .kind = DITEM_TEXT, .name = "delta time", .proc = DrawDeltaTime },
|
||||
{ .kind = DITEM_TEXT, .name = "pos", .proc = DrawCameraPos },
|
||||
{ .kind = DITEM_TEXT, .name = "zoom", .proc = DrawZoom },
|
||||
{ .kind = DITEM_SLIDER, .name = "slider", .slider = { .min = 0.0f, .max = 1.0f, .val = 0.5f } },
|
||||
{ .kind = DITEM_END },
|
||||
}
|
||||
}
|
||||
|
@ -180,6 +179,7 @@ static debug_item items[] = {
|
|||
{ .kind = DITEM_END },
|
||||
},
|
||||
.is_sp_only = true,
|
||||
.is_collapsed = true,
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -226,9 +226,7 @@ void
|
|||
ActDespawnDemoNPCs(void) {
|
||||
if (!demo_npcs) return;
|
||||
|
||||
for (uint32_t i = 0; i < zpl_array_count(demo_npcs); i++) {
|
||||
entity_despawn(demo_npcs[i]);
|
||||
}
|
||||
entity_batch_despawn(demo_npcs, zpl_array_count(demo_npcs));
|
||||
|
||||
zpl_array_free(demo_npcs);
|
||||
demo_npcs = 0;
|
||||
|
|
|
@ -12,19 +12,20 @@
|
|||
uint64_t entity_spawn(uint16_t class_id) {
|
||||
ecs_entity_t e = ecs_new(world_ecs(), 0);
|
||||
|
||||
ecs_set(world_ecs(), e, Velocity, {0});
|
||||
ecs_set(world_ecs(), e, Classify, { .id = class_id });
|
||||
ecs_add(world_ecs(), e, Walking);
|
||||
Position *pos = ecs_get_mut(world_ecs(), e, Position, NULL);
|
||||
#if 1
|
||||
pos->x=rand() % world_dim();
|
||||
pos->y=rand() % world_dim();
|
||||
#else
|
||||
pos->x=350;
|
||||
pos->y=88;
|
||||
#endif
|
||||
|
||||
if (class_id != EKIND_SERVER) {
|
||||
ecs_set(world_ecs(), e, Velocity, {0});
|
||||
ecs_add(world_ecs(), e, Walking);
|
||||
Position *pos = ecs_get_mut(world_ecs(), e, Position, NULL);
|
||||
#if 1
|
||||
pos->x=(float)(rand() % world_dim());
|
||||
pos->y=(float)(rand() % world_dim());
|
||||
#else
|
||||
pos->x=350.0f;
|
||||
pos->y=88.0f;
|
||||
#endif
|
||||
|
||||
librg_entity_track(world_tracker(), e);
|
||||
librg_entity_chunk_set(world_tracker(), e, librg_chunk_from_realpos(world_tracker(), pos->x, pos->y, 0));
|
||||
librg_entity_owner_set(world_tracker(), e, (int64_t)e);
|
||||
|
@ -33,6 +34,13 @@ uint64_t entity_spawn(uint16_t class_id) {
|
|||
return (uint64_t)e;
|
||||
}
|
||||
|
||||
void entity_batch_despawn(uint64_t *ids, size_t num_ids) {
|
||||
for (size_t i = 0; i < num_ids; i++ ) {
|
||||
librg_entity_untrack(world_tracker(), ids[i]);
|
||||
ecs_delete(world_ecs(), ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void entity_despawn(uint64_t ent_id) {
|
||||
librg_entity_untrack(world_tracker(), ent_id);
|
||||
ecs_delete(world_ecs(), ent_id);
|
||||
|
|
|
@ -1,188 +1,188 @@
|
|||
#include "zpl.h"
|
||||
|
||||
#define ENET_IMPLEMENTATION
|
||||
#include "enet.h"
|
||||
|
||||
#define LIBRG_IMPL
|
||||
#define LIBRG_CUSTOM_ZPL
|
||||
#define LIBRG_ENTITY_MAXCHUNKS 1
|
||||
#include "librg.h"
|
||||
|
||||
#include "network.h"
|
||||
#include "packet.h"
|
||||
#include "world/world.h"
|
||||
#include "game.h"
|
||||
#include "player.h"
|
||||
|
||||
#define NETWORK_UPDATE_DELAY 0.100
|
||||
|
||||
static ENetHost *host = NULL;
|
||||
static ENetHost *server = NULL;
|
||||
static ENetPeer *peer = NULL;
|
||||
static librg_world *world = NULL;
|
||||
|
||||
int32_t network_init() {
|
||||
return enet_initialize() != 0;
|
||||
}
|
||||
|
||||
int32_t network_destroy() {
|
||||
enet_deinitialize();
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
//~ NOTE(zaklaus): client
|
||||
|
||||
int32_t network_client_connect(const char *hostname, uint16_t port) {
|
||||
ENetAddress address = {0}; address.port = port;
|
||||
enet_address_set_host(&address, hostname);
|
||||
|
||||
host = enet_host_create(NULL, 1, 2, 0, 0);
|
||||
peer = enet_host_connect(host, &address, 2, 0);
|
||||
|
||||
if (peer == NULL) {
|
||||
zpl_printf("[ERROR] Cannot connect to specicied server: %s:%d\n", hostname, port);
|
||||
return 1;
|
||||
}
|
||||
|
||||
world = librg_world_create();
|
||||
librg_world_userdata_set(world, peer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t network_client_disconnect() {
|
||||
enet_peer_disconnect_now(peer, 0);
|
||||
enet_host_destroy(host);
|
||||
|
||||
librg_world_destroy(world);
|
||||
|
||||
peer = NULL;
|
||||
host = NULL;
|
||||
world = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t network_client_tick() {
|
||||
ENetEvent event = {0};
|
||||
|
||||
while (enet_host_service(host, &event, 1) > 0) {
|
||||
switch (event.type) {
|
||||
case ENET_EVENT_TYPE_CONNECT: {
|
||||
zpl_printf("[INFO] We connected to the server.\n");
|
||||
pkt_00_init_send(0);
|
||||
} break;
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: {
|
||||
zpl_printf("[INFO] We disconnected from server.\n");
|
||||
} break;
|
||||
|
||||
case ENET_EVENT_TYPE_RECEIVE: {
|
||||
if (!world_read(event.packet->data, event.packet->dataLength, event.peer)) {
|
||||
zpl_printf("[INFO] Server sent us an unsupported packet.\n");
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
bool network_client_is_connected() {
|
||||
return peer ? enet_peer_get_state(peer) == ENET_PEER_STATE_CONNECTED : false;
|
||||
}
|
||||
|
||||
//~ 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, 8, 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, uint16_t channel_id) {
|
||||
if (peer_id == 0) peer_id = peer;
|
||||
ENetPacket *packet = enet_packet_create(data, datalen, flags);
|
||||
return enet_peer_send(peer_id, channel_id, packet);
|
||||
}
|
||||
|
||||
int32_t network_msg_send(void *peer_id, void *data, size_t datalen, uint16_t channel_id) {
|
||||
return network_msg_send_raw(peer_id, data, datalen, ENET_PACKET_FLAG_RELIABLE, channel_id);
|
||||
}
|
||||
|
||||
int32_t network_msg_send_unreliable(void *peer_id, void *data, size_t datalen, uint16_t channel_id) {
|
||||
return network_msg_send_raw(peer_id, data, datalen, 0, channel_id);
|
||||
}
|
||||
#include "zpl.h"
|
||||
|
||||
#define ENET_IMPLEMENTATION
|
||||
#include "enet.h"
|
||||
|
||||
#define LIBRG_IMPL
|
||||
#define LIBRG_CUSTOM_ZPL
|
||||
#define LIBRG_ENTITY_MAXCHUNKS 1
|
||||
#include "librg.h"
|
||||
|
||||
#include "network.h"
|
||||
#include "packet.h"
|
||||
#include "world/world.h"
|
||||
#include "game.h"
|
||||
#include "player.h"
|
||||
|
||||
#define NETWORK_UPDATE_DELAY 0.100
|
||||
|
||||
static ENetHost *host = NULL;
|
||||
static ENetHost *server = NULL;
|
||||
static ENetPeer *peer = NULL;
|
||||
static librg_world *world = NULL;
|
||||
|
||||
int32_t network_init() {
|
||||
return enet_initialize() != 0;
|
||||
}
|
||||
|
||||
int32_t network_destroy() {
|
||||
enet_deinitialize();
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
//~ NOTE(zaklaus): client
|
||||
|
||||
int32_t network_client_connect(const char *hostname, uint16_t port) {
|
||||
ENetAddress address = {0}; address.port = port;
|
||||
enet_address_set_host(&address, hostname);
|
||||
|
||||
host = enet_host_create(NULL, 1, 2, 0, 0);
|
||||
peer = enet_host_connect(host, &address, 2, 0);
|
||||
|
||||
if (peer == NULL) {
|
||||
zpl_printf("[ERROR] Cannot connect to specicied server: %s:%d\n", hostname, port);
|
||||
return 1;
|
||||
}
|
||||
|
||||
world = librg_world_create();
|
||||
librg_world_userdata_set(world, peer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t network_client_disconnect() {
|
||||
enet_peer_disconnect_now(peer, 0);
|
||||
enet_host_destroy(host);
|
||||
|
||||
librg_world_destroy(world);
|
||||
|
||||
peer = NULL;
|
||||
host = NULL;
|
||||
world = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t network_client_tick() {
|
||||
ENetEvent event = {0};
|
||||
|
||||
while (enet_host_service(host, &event, 1) > 0) {
|
||||
switch (event.type) {
|
||||
case ENET_EVENT_TYPE_CONNECT: {
|
||||
zpl_printf("[INFO] We connected to the server.\n");
|
||||
pkt_00_init_send(0);
|
||||
} break;
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: {
|
||||
zpl_printf("[INFO] We disconnected from server.\n");
|
||||
} break;
|
||||
|
||||
case ENET_EVENT_TYPE_RECEIVE: {
|
||||
if (!world_read(event.packet->data, event.packet->dataLength, event.peer)) {
|
||||
zpl_printf("[INFO] Server sent us an unsupported packet.\n");
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
bool network_client_is_connected() {
|
||||
return peer ? enet_peer_get_state(peer) == ENET_PEER_STATE_CONNECTED : false;
|
||||
}
|
||||
|
||||
//~ 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, 8, 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, uint16_t channel_id) {
|
||||
if (peer_id == 0) peer_id = peer;
|
||||
ENetPacket *packet = enet_packet_create(data, datalen, flags);
|
||||
return enet_peer_send(peer_id, channel_id, packet);
|
||||
}
|
||||
|
||||
int32_t network_msg_send(void *peer_id, void *data, size_t datalen, uint16_t channel_id) {
|
||||
return network_msg_send_raw(peer_id, data, datalen, ENET_PACKET_FLAG_RELIABLE, channel_id);
|
||||
}
|
||||
|
||||
int32_t network_msg_send_unreliable(void *peer_id, void *data, size_t datalen, uint16_t channel_id) {
|
||||
return network_msg_send_raw(peer_id, data, datalen, 0, channel_id);
|
||||
}
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
#include "player.h"
|
||||
#include "entity.h"
|
||||
#include "entity_view.h"
|
||||
#include "flecs/flecs.h"
|
||||
#include "flecs/flecs_meta.h"
|
||||
#include "librg.h"
|
||||
#include "world/world.h"
|
||||
|
||||
#include "modules/components.h"
|
||||
#include "modules/systems.h"
|
||||
#include "zpl.h"
|
||||
|
||||
#define PLAYER_MAX_HP 100.0f
|
||||
|
||||
uint64_t player_spawn(char *name) {
|
||||
ecs_entity_t e = entity_spawn(EKIND_PLAYER);
|
||||
|
||||
if (!name) {
|
||||
name = zpl_bprintf("player_%d", e);
|
||||
}
|
||||
|
||||
ecs_set_name(world_ecs(), e, name);
|
||||
ecs_set(world_ecs(), e, ClientInfo, {0});
|
||||
ecs_set(world_ecs(), e, Input, {0});
|
||||
ecs_set(world_ecs(), e, Inventory, {0});
|
||||
ecs_set(world_ecs(), e, Health, {.hp = PLAYER_MAX_HP, .max_hp = PLAYER_MAX_HP});
|
||||
ecs_add(world_ecs(), e, Player);
|
||||
|
||||
librg_entity_owner_set(world_tracker(), e, (int64_t)e);
|
||||
|
||||
return (uint64_t)e;
|
||||
}
|
||||
|
||||
void player_despawn(uint64_t ent_id) {
|
||||
entity_despawn(ent_id);
|
||||
}
|
||||
#include "player.h"
|
||||
#include "entity.h"
|
||||
#include "entity_view.h"
|
||||
#include "flecs/flecs.h"
|
||||
#include "flecs/flecs_meta.h"
|
||||
#include "librg.h"
|
||||
#include "world/world.h"
|
||||
|
||||
#include "modules/components.h"
|
||||
#include "modules/systems.h"
|
||||
#include "zpl.h"
|
||||
|
||||
#define PLAYER_MAX_HP 100.0f
|
||||
|
||||
uint64_t player_spawn(char *name) {
|
||||
ecs_entity_t e = entity_spawn(EKIND_PLAYER);
|
||||
|
||||
if (!name) {
|
||||
name = zpl_bprintf("player_%d", e);
|
||||
}
|
||||
|
||||
ecs_set_name(world_ecs(), e, name);
|
||||
ecs_set(world_ecs(), e, ClientInfo, {0});
|
||||
ecs_set(world_ecs(), e, Input, {0});
|
||||
ecs_set(world_ecs(), e, Inventory, {0});
|
||||
ecs_set(world_ecs(), e, Health, {.hp = PLAYER_MAX_HP, .max_hp = PLAYER_MAX_HP});
|
||||
ecs_add(world_ecs(), e, Player);
|
||||
|
||||
librg_entity_owner_set(world_tracker(), e, (int64_t)e);
|
||||
|
||||
return (uint64_t)e;
|
||||
}
|
||||
|
||||
void player_despawn(uint64_t ent_id) {
|
||||
entity_despawn(ent_id);
|
||||
}
|
||||
|
|
|
@ -1,171 +1,171 @@
|
|||
#pragma once
|
||||
#include "flecs/flecs.h"
|
||||
#include "flecs/flecs_meta.h"
|
||||
|
||||
//NOTE(zaklaus): custom macro to define meta components outside the current scope
|
||||
|
||||
#ifndef ECS_META_DEFINE
|
||||
#define ECS_META_DEFINE(world, T)\
|
||||
ECS_COMPONENT_DEFINE(world, T);\
|
||||
ecs_new_meta(world, ecs_entity(T), &__##T##__);
|
||||
#endif
|
||||
|
||||
#ifndef ecs_get_mut_if
|
||||
#define ecs_get_mut_if(world, entity, component)\
|
||||
(ecs_get(world, entity, component) ? ecs_get_mut(world, entity, component, NULL) : NULL)
|
||||
#endif
|
||||
|
||||
#define ITEMS_INVENTORY_SIZE 9
|
||||
|
||||
ECS_STRUCT(Vector2D, {
|
||||
float x;
|
||||
float y;
|
||||
});
|
||||
|
||||
ECS_STRUCT(Chunk, {
|
||||
uint32_t id;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
uint8_t is_dirty;
|
||||
});
|
||||
|
||||
ECS_STRUCT(Drawable, {
|
||||
uint16_t id;
|
||||
});
|
||||
|
||||
ECS_ALIAS(Vector2D, Position);
|
||||
ECS_ALIAS(Vector2D, Velocity);
|
||||
|
||||
ECS_STRUCT(Input, {
|
||||
float x;
|
||||
float y;
|
||||
float mx;
|
||||
float my;
|
||||
uint8_t use;
|
||||
uint8_t sprint;
|
||||
uint8_t ctrl;
|
||||
uint8_t is_blocked;
|
||||
|
||||
// NOTE(zaklaus): inventory
|
||||
uint8_t selected_item;
|
||||
uint8_t drop;
|
||||
uint8_t swap;
|
||||
uint8_t swap_from;
|
||||
uint8_t swap_to;
|
||||
});
|
||||
|
||||
ECS_STRUCT(ClientInfo, {
|
||||
uintptr_t peer;
|
||||
uint16_t view_id;
|
||||
});
|
||||
|
||||
ECS_STRUCT(Health, {
|
||||
float hp;
|
||||
float max_hp;
|
||||
|
||||
//NOTE(zaklaus): Intentionally global, to allow for creative use of damage combos
|
||||
float pain_time;
|
||||
float heal_time;
|
||||
});
|
||||
|
||||
ECS_STRUCT(Classify, {
|
||||
uint16_t id;
|
||||
});
|
||||
|
||||
ECS_STRUCT(Vehicle, {
|
||||
uint64_t seats[4];
|
||||
|
||||
float force;
|
||||
float heading;
|
||||
float steer;
|
||||
float wheel_base;
|
||||
|
||||
float speed;
|
||||
float reverse_speed;
|
||||
});
|
||||
|
||||
typedef struct {
|
||||
ecs_entity_t veh;
|
||||
} IsInVehicle;
|
||||
|
||||
typedef struct {
|
||||
uint16_t kind;
|
||||
uint32_t quantity;
|
||||
float merger_time;
|
||||
} ItemDrop;
|
||||
|
||||
typedef struct {
|
||||
ItemDrop items[ITEMS_INVENTORY_SIZE];
|
||||
float pickup_time;
|
||||
} Inventory;
|
||||
|
||||
ECS_COMPONENT_EXTERN(Chunk);
|
||||
ECS_COMPONENT_EXTERN(Position);
|
||||
ECS_COMPONENT_EXTERN(Vector2D);
|
||||
ECS_COMPONENT_EXTERN(Drawable);
|
||||
ECS_COMPONENT_EXTERN(Input);
|
||||
ECS_COMPONENT_EXTERN(Velocity);
|
||||
ECS_COMPONENT_EXTERN(ClientInfo);
|
||||
ECS_COMPONENT_EXTERN(Health);
|
||||
ECS_COMPONENT_EXTERN(Classify);
|
||||
ECS_COMPONENT_EXTERN(Vehicle);
|
||||
ECS_COMPONENT_EXTERN(IsInVehicle);
|
||||
ECS_COMPONENT_EXTERN(ItemDrop);
|
||||
ECS_COMPONENT_EXTERN(Inventory);
|
||||
ECS_TAG_EXTERN(EcsActor);
|
||||
ECS_TAG_EXTERN(EcsDemoNPC);
|
||||
ECS_TYPE_EXTERN(Player);
|
||||
ECS_TYPE_EXTERN(Movement);
|
||||
ECS_TYPE_EXTERN(Walking);
|
||||
ECS_TYPE_EXTERN(Flying);
|
||||
ECS_TYPE_EXTERN(EcsClient);
|
||||
// NOTE(zaklaus): @1 EXTERN
|
||||
|
||||
typedef struct {
|
||||
ECS_DECLARE_COMPONENT(Chunk);
|
||||
ECS_DECLARE_COMPONENT(Position);
|
||||
ECS_DECLARE_COMPONENT(Vector2D);
|
||||
ECS_DECLARE_COMPONENT(Drawable);
|
||||
ECS_DECLARE_COMPONENT(Input);
|
||||
ECS_DECLARE_COMPONENT(Velocity);
|
||||
ECS_DECLARE_COMPONENT(ClientInfo);
|
||||
ECS_DECLARE_COMPONENT(Health);
|
||||
ECS_DECLARE_COMPONENT(Classify);
|
||||
ECS_DECLARE_COMPONENT(Vehicle);
|
||||
ECS_DECLARE_COMPONENT(IsInVehicle);
|
||||
ECS_DECLARE_COMPONENT(ItemDrop);
|
||||
ECS_DECLARE_COMPONENT(Inventory);
|
||||
ECS_DECLARE_ENTITY(EcsActor);
|
||||
ECS_DECLARE_ENTITY(EcsDemoNPC);
|
||||
ECS_DECLARE_TYPE(Player);
|
||||
ECS_DECLARE_TYPE(Builder);
|
||||
ECS_DECLARE_TYPE(Movement);
|
||||
ECS_DECLARE_ENTITY(Walking);
|
||||
ECS_DECLARE_ENTITY(Flying);
|
||||
// NOTE(zaklaus): @2 DECLARE
|
||||
} Components;
|
||||
|
||||
#define ComponentsImportHandles(handles)\
|
||||
ECS_IMPORT_COMPONENT(handles, Chunk);\
|
||||
ECS_IMPORT_COMPONENT(handles, Vector2D);\
|
||||
ECS_IMPORT_COMPONENT(handles, Position);\
|
||||
ECS_IMPORT_COMPONENT(handles, Drawable);\
|
||||
ECS_IMPORT_COMPONENT(handles, Input);\
|
||||
ECS_IMPORT_COMPONENT(handles, Velocity);\
|
||||
ECS_IMPORT_COMPONENT(handles, ClientInfo);\
|
||||
ECS_IMPORT_COMPONENT(handles, Health);\
|
||||
ECS_IMPORT_COMPONENT(handles, Classify);\
|
||||
ECS_IMPORT_COMPONENT(handles, Vehicle);\
|
||||
ECS_IMPORT_COMPONENT(handles, IsInVehicle);\
|
||||
ECS_IMPORT_COMPONENT(handles, ItemDrop);\
|
||||
ECS_IMPORT_COMPONENT(handles, Inventory);\
|
||||
ECS_IMPORT_TYPE(handles, Player);\
|
||||
ECS_IMPORT_TYPE(handles, Builder);\
|
||||
ECS_IMPORT_TYPE(handles, Movement);\
|
||||
ECS_IMPORT_ENTITY(handles, EcsActor);\
|
||||
ECS_IMPORT_ENTITY(handles, EcsDemoNPC);\
|
||||
ECS_IMPORT_ENTITY(handles, Walking);\
|
||||
ECS_IMPORT_ENTITY(handles, Flying);\
|
||||
// NOTE(zaklaus): @3 IMPORT
|
||||
|
||||
void ComponentsImport(ecs_world_t *ecs);
|
||||
#pragma once
|
||||
#include "flecs/flecs.h"
|
||||
#include "flecs/flecs_meta.h"
|
||||
|
||||
//NOTE(zaklaus): custom macro to define meta components outside the current scope
|
||||
|
||||
#ifndef ECS_META_DEFINE
|
||||
#define ECS_META_DEFINE(world, T)\
|
||||
ECS_COMPONENT_DEFINE(world, T);\
|
||||
ecs_new_meta(world, ecs_entity(T), &__##T##__);
|
||||
#endif
|
||||
|
||||
#ifndef ecs_get_mut_if
|
||||
#define ecs_get_mut_if(world, entity, component)\
|
||||
(ecs_get(world, entity, component) ? ecs_get_mut(world, entity, component, NULL) : NULL)
|
||||
#endif
|
||||
|
||||
#define ITEMS_INVENTORY_SIZE 9
|
||||
|
||||
ECS_STRUCT(Vector2D, {
|
||||
float x;
|
||||
float y;
|
||||
});
|
||||
|
||||
ECS_STRUCT(Chunk, {
|
||||
uint32_t id;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
uint8_t is_dirty;
|
||||
});
|
||||
|
||||
ECS_STRUCT(Drawable, {
|
||||
uint16_t id;
|
||||
});
|
||||
|
||||
ECS_ALIAS(Vector2D, Position);
|
||||
ECS_ALIAS(Vector2D, Velocity);
|
||||
|
||||
ECS_STRUCT(Input, {
|
||||
float x;
|
||||
float y;
|
||||
float mx;
|
||||
float my;
|
||||
uint8_t use;
|
||||
uint8_t sprint;
|
||||
uint8_t ctrl;
|
||||
uint8_t is_blocked;
|
||||
|
||||
// NOTE(zaklaus): inventory
|
||||
uint8_t selected_item;
|
||||
uint8_t drop;
|
||||
uint8_t swap;
|
||||
uint8_t swap_from;
|
||||
uint8_t swap_to;
|
||||
});
|
||||
|
||||
ECS_STRUCT(ClientInfo, {
|
||||
uintptr_t peer;
|
||||
uint16_t view_id;
|
||||
});
|
||||
|
||||
ECS_STRUCT(Health, {
|
||||
float hp;
|
||||
float max_hp;
|
||||
|
||||
//NOTE(zaklaus): Intentionally global, to allow for creative use of damage combos
|
||||
float pain_time;
|
||||
float heal_time;
|
||||
});
|
||||
|
||||
ECS_STRUCT(Classify, {
|
||||
uint16_t id;
|
||||
});
|
||||
|
||||
ECS_STRUCT(Vehicle, {
|
||||
uint64_t seats[4];
|
||||
|
||||
float force;
|
||||
float heading;
|
||||
float steer;
|
||||
float wheel_base;
|
||||
|
||||
float speed;
|
||||
float reverse_speed;
|
||||
});
|
||||
|
||||
typedef struct {
|
||||
ecs_entity_t veh;
|
||||
} IsInVehicle;
|
||||
|
||||
typedef struct {
|
||||
uint16_t kind;
|
||||
uint32_t quantity;
|
||||
float merger_time;
|
||||
} ItemDrop;
|
||||
|
||||
typedef struct {
|
||||
ItemDrop items[ITEMS_INVENTORY_SIZE];
|
||||
float pickup_time;
|
||||
} Inventory;
|
||||
|
||||
ECS_COMPONENT_EXTERN(Chunk);
|
||||
ECS_COMPONENT_EXTERN(Position);
|
||||
ECS_COMPONENT_EXTERN(Vector2D);
|
||||
ECS_COMPONENT_EXTERN(Drawable);
|
||||
ECS_COMPONENT_EXTERN(Input);
|
||||
ECS_COMPONENT_EXTERN(Velocity);
|
||||
ECS_COMPONENT_EXTERN(ClientInfo);
|
||||
ECS_COMPONENT_EXTERN(Health);
|
||||
ECS_COMPONENT_EXTERN(Classify);
|
||||
ECS_COMPONENT_EXTERN(Vehicle);
|
||||
ECS_COMPONENT_EXTERN(IsInVehicle);
|
||||
ECS_COMPONENT_EXTERN(ItemDrop);
|
||||
ECS_COMPONENT_EXTERN(Inventory);
|
||||
ECS_TAG_EXTERN(EcsActor);
|
||||
ECS_TAG_EXTERN(EcsDemoNPC);
|
||||
ECS_TYPE_EXTERN(Player);
|
||||
ECS_TYPE_EXTERN(Movement);
|
||||
ECS_TYPE_EXTERN(Walking);
|
||||
ECS_TYPE_EXTERN(Flying);
|
||||
ECS_TYPE_EXTERN(EcsClient);
|
||||
// NOTE(zaklaus): @1 EXTERN
|
||||
|
||||
typedef struct {
|
||||
ECS_DECLARE_COMPONENT(Chunk);
|
||||
ECS_DECLARE_COMPONENT(Position);
|
||||
ECS_DECLARE_COMPONENT(Vector2D);
|
||||
ECS_DECLARE_COMPONENT(Drawable);
|
||||
ECS_DECLARE_COMPONENT(Input);
|
||||
ECS_DECLARE_COMPONENT(Velocity);
|
||||
ECS_DECLARE_COMPONENT(ClientInfo);
|
||||
ECS_DECLARE_COMPONENT(Health);
|
||||
ECS_DECLARE_COMPONENT(Classify);
|
||||
ECS_DECLARE_COMPONENT(Vehicle);
|
||||
ECS_DECLARE_COMPONENT(IsInVehicle);
|
||||
ECS_DECLARE_COMPONENT(ItemDrop);
|
||||
ECS_DECLARE_COMPONENT(Inventory);
|
||||
ECS_DECLARE_ENTITY(EcsActor);
|
||||
ECS_DECLARE_ENTITY(EcsDemoNPC);
|
||||
ECS_DECLARE_TYPE(Player);
|
||||
ECS_DECLARE_TYPE(Builder);
|
||||
ECS_DECLARE_TYPE(Movement);
|
||||
ECS_DECLARE_ENTITY(Walking);
|
||||
ECS_DECLARE_ENTITY(Flying);
|
||||
// NOTE(zaklaus): @2 DECLARE
|
||||
} Components;
|
||||
|
||||
#define ComponentsImportHandles(handles)\
|
||||
ECS_IMPORT_COMPONENT(handles, Chunk);\
|
||||
ECS_IMPORT_COMPONENT(handles, Vector2D);\
|
||||
ECS_IMPORT_COMPONENT(handles, Position);\
|
||||
ECS_IMPORT_COMPONENT(handles, Drawable);\
|
||||
ECS_IMPORT_COMPONENT(handles, Input);\
|
||||
ECS_IMPORT_COMPONENT(handles, Velocity);\
|
||||
ECS_IMPORT_COMPONENT(handles, ClientInfo);\
|
||||
ECS_IMPORT_COMPONENT(handles, Health);\
|
||||
ECS_IMPORT_COMPONENT(handles, Classify);\
|
||||
ECS_IMPORT_COMPONENT(handles, Vehicle);\
|
||||
ECS_IMPORT_COMPONENT(handles, IsInVehicle);\
|
||||
ECS_IMPORT_COMPONENT(handles, ItemDrop);\
|
||||
ECS_IMPORT_COMPONENT(handles, Inventory);\
|
||||
ECS_IMPORT_TYPE(handles, Player);\
|
||||
ECS_IMPORT_TYPE(handles, Builder);\
|
||||
ECS_IMPORT_TYPE(handles, Movement);\
|
||||
ECS_IMPORT_ENTITY(handles, EcsActor);\
|
||||
ECS_IMPORT_ENTITY(handles, EcsDemoNPC);\
|
||||
ECS_IMPORT_ENTITY(handles, Walking);\
|
||||
ECS_IMPORT_ENTITY(handles, Flying);\
|
||||
// NOTE(zaklaus): @3 IMPORT
|
||||
|
||||
void ComponentsImport(ecs_world_t *ecs);
|
||||
|
|
|
@ -92,8 +92,8 @@ void HurtOnHazardBlock(ecs_iter_t *it) {
|
|||
for (int i = 0; i < it->count; i++) {
|
||||
world_block_lookup l = world_block_from_realpos(p[i].x, p[i].y);
|
||||
if (blocks_get_flags(l.block_id) & BLOCK_FLAG_HAZARD) {
|
||||
if (h->pain_time < game_time()) {
|
||||
h->pain_time = game_time() + HAZARD_BLOCK_TIME;
|
||||
if (h->pain_time < 0.0f) {
|
||||
h->pain_time = HAZARD_BLOCK_TIME;
|
||||
h->hp -= HAZARD_BLOCK_DMG;
|
||||
h->hp = zpl_max(0.0f, h->hp);
|
||||
}
|
||||
|
@ -109,12 +109,16 @@ void RegenerateHP(ecs_iter_t *it) {
|
|||
Health *h = ecs_column(it, Health, 1);
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
if (h->pain_time < game_time() - HP_REGEN_PAIN_COOLDOWN) {
|
||||
if (h->heal_time < game_time() && h->hp < h->max_hp) {
|
||||
h->heal_time = game_time() + HP_REGEN_TIME;
|
||||
h->hp += HP_REGEN_RECOVERY;
|
||||
h->hp = zpl_min(h->max_hp, h->hp);
|
||||
if (h[i].pain_time < 0.0f) {
|
||||
if (h[i].heal_time < 0.0f && h[i].hp < h[i].max_hp) {
|
||||
h[i].heal_time = HP_REGEN_TIME;
|
||||
h[i].hp += HP_REGEN_RECOVERY;
|
||||
h[i].hp = zpl_min(h[i].max_hp, h[i].hp);
|
||||
} else {
|
||||
h[i].heal_time -= safe_dt(it);
|
||||
}
|
||||
} else {
|
||||
h[i].pain_time -= safe_dt(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ void DemoNPCMoveAround(ecs_iter_t *it) {
|
|||
Velocity *v = ecs_column(it, Velocity, 1);
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
float d = zpl_quake_rsqrt(v[i].x*v[i].x + v[i].y*v[i].y);
|
||||
v[i].x += (v[i].x*d*DEMO_NPC_MOVE_SPEED*it->delta_time + zpl_cos(zpl_to_radians(rand()%360))*DEMO_NPC_STEER_SPEED*it->delta_time);
|
||||
v[i].y += (v[i].y*d*DEMO_NPC_MOVE_SPEED*it->delta_time + zpl_sin(zpl_to_radians(rand()%360))*DEMO_NPC_STEER_SPEED*it->delta_time);
|
||||
v[i].x += (v[i].x*d*DEMO_NPC_MOVE_SPEED*safe_dt(it) + zpl_cos(zpl_to_radians(rand()%360))*DEMO_NPC_STEER_SPEED*safe_dt(it));
|
||||
v[i].y += (v[i].y*d*DEMO_NPC_MOVE_SPEED*safe_dt(it) + zpl_sin(zpl_to_radians(rand()%360))*DEMO_NPC_STEER_SPEED*safe_dt(it));
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue