networking progress

This commit is contained in:
jacob 2025-02-08 07:06:56 -06:00
parent 78ace4b38a
commit a78c5e1a47
14 changed files with 191 additions and 192 deletions

View File

@ -113,7 +113,7 @@ INTERNAL struct buddy_block *buddy_block_get_unused(struct buddy_ctx *ctx, struc
block = left;
ASSERT(block->memory);
} else {
#if 0
#if 1
/* Create left block from arena */
struct buddy_block *left = buddy_block_alloc_internal(ctx);
left->used = true;

View File

@ -91,9 +91,9 @@ void bw_seek_to(struct byte_writer *bw, u64 pos)
bw->at = bw->buff.text + pos;
}
void bw_write_buffer(struct byte_writer *bw, struct string buff)
void br_write_bytes(struct byte_writer *bw, struct string bytes)
{
write(bw, buff.text, buff.len);
write(bw, bytes.text, bytes.len);
}
void bw_write_u8(struct byte_writer *bw, u8 v)
@ -167,7 +167,7 @@ void bw_write_v2(struct byte_writer *bw, struct v2 v)
void bw_write_string(struct byte_writer *bw, struct string str)
{
bw_write_var_uint(bw, str.len);
bw_write_buffer(bw, str);
br_write_bytes(bw, str);
}
/* ========================== *

View File

@ -25,7 +25,7 @@ struct byte_writer bw_branch(struct byte_writer *bw, u64 size);
void bw_seek(struct byte_writer *bw, u64 amount);
void bw_seek_to(struct byte_writer *bw, u64 pos);
void bw_write_buffer(struct byte_writer *bw, struct string buff);
void br_write_bytes(struct byte_writer *bw, struct string bytes);
void bw_write_u8(struct byte_writer *bw, u8 v);
void bw_write_u16(struct byte_writer *bw, u16 v);
void bw_write_u32(struct byte_writer *bw, u32 v);

View File

@ -58,7 +58,7 @@
#define USER_INTERP_OFFSET_TICK_RATIO 1.1
#define USER_INTERP_ENABLED 1
#define COLLIDER_DEBUG RTC
#define COLLIDER_DEBUG 0
#define COLLIDER_DEBUG_DETAILED 0
#define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 1

View File

@ -81,13 +81,13 @@ INTERNAL struct entity *entity_alloc_internal(struct entity_store *store)
} else {
/* Make new */
entity = arena_push(&store->arena, struct entity);
handle = (struct entity_handle) { .gen = 1, .idx = store->reserved++ };
handle = (struct entity_handle) { .gen = 1, .idx = store->num_reserved++ };
}
*entity = _g_entity_nil;
entity->valid = true;
entity->handle = handle;
entity->cached_global_xform_dirty = true;
++store->allocated;
++store->num_allocated;
return entity;
}
@ -115,7 +115,7 @@ INTERNAL void entity_release_internal(struct entity_store *store, struct entity
ent->valid = false;
ent->next_free = store->first_free;
store->first_free = ent->handle;
--store->allocated;
--store->num_allocated;
}
void entity_release(struct entity_store *store, struct entity *ent)
@ -145,7 +145,7 @@ struct entity_store *entity_store_from_entity(struct entity *ent)
/* Returns a valid entity or read-only nil entity. Always safe to read result, need to check `valid` to write. */
struct entity *entity_from_handle(struct entity_store *store, struct entity_handle handle)
{
if (handle.gen != 0 && handle.idx < store->reserved) {
if (handle.gen != 0 && handle.idx < store->num_reserved) {
struct entity *entity = &store->entities[handle.idx];
if (entity->handle.gen == handle.gen) {
return entity;
@ -156,7 +156,7 @@ struct entity *entity_from_handle(struct entity_store *store, struct entity_hand
struct entity *entity_find_first_match_one(struct entity_store *store, enum entity_prop prop)
{
u64 count = store->reserved;
u64 count = store->num_reserved;
struct entity *entities = store->entities;
for (u64 entity_index = 0; entity_index < count; ++entity_index) {
struct entity *ent = &entities[entity_index];
@ -169,7 +169,7 @@ struct entity *entity_find_first_match_one(struct entity_store *store, enum enti
struct entity *entity_find_first_match_all(struct entity_store *store, struct entity_prop_array props)
{
u64 count = store->reserved;
u64 count = store->num_reserved;
struct entity *entities = store->entities;
for (u64 entity_index = 0; entity_index < count; ++entity_index) {
struct entity *ent = &entities[entity_index];

View File

@ -50,8 +50,8 @@ enum entity_prop {
struct entity_store {
b32 valid;
struct arena arena;
u64 allocated;
u64 reserved;
u64 num_allocated;
u64 num_reserved;
struct entity_handle first_free;
struct entity_handle root;
struct entity *entities;

View File

@ -72,7 +72,6 @@ struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
G.client_store = client_store_alloc();
/* Intialize host */
//struct sock_address bind_address = sock_address_from_port(12345);
G.host = host_alloc(12345);
/* Initialize empty world */
@ -307,7 +306,7 @@ INTERNAL void release_entities_with_prop(enum entity_prop prop)
struct entity **ents_to_release = arena_dry_push(scratch.arena, struct entity *);
u64 ents_to_release_count = 0;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index];
if (!ent->valid) continue;
@ -496,7 +495,7 @@ INTERNAL void game_update(void)
* Activate entities
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!ent->valid) continue;
@ -512,7 +511,7 @@ INTERNAL void game_update(void)
* Reset triggered entities
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
@ -594,7 +593,7 @@ INTERNAL void game_update(void)
* Update entities from sprite
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (sprite_tag_is_nil(ent->sprite)) continue;
@ -689,7 +688,7 @@ INTERNAL void game_update(void)
* Update attachments
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_ATTACHED)) continue;
@ -714,7 +713,7 @@ INTERNAL void game_update(void)
* Update control from player cmds
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
@ -773,7 +772,7 @@ INTERNAL void game_update(void)
* ========================== */
#if 0
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_TEST)) continue;
@ -823,7 +822,7 @@ INTERNAL void game_update(void)
* Trigger equipped
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
@ -839,7 +838,7 @@ INTERNAL void game_update(void)
* Process triggered entities
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_TRIGGERED_THIS_TICK)) continue;
@ -903,7 +902,7 @@ INTERNAL void game_update(void)
* ========================== */
#if 0
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
@ -914,7 +913,7 @@ INTERNAL void game_update(void)
}
}
#else
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
@ -948,7 +947,7 @@ INTERNAL void game_update(void)
* ========================== */
#if GAME_PLAYER_AIM
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
@ -1041,7 +1040,7 @@ INTERNAL void game_update(void)
* Create ground friction force (gravity)
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC)) continue;
@ -1100,7 +1099,7 @@ INTERNAL void game_update(void)
* Update tracers
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_TRACER)) continue;
@ -1124,7 +1123,7 @@ INTERNAL void game_update(void)
* Initialize bullet kinematics from sources
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_BULLET)) continue;
@ -1179,7 +1178,7 @@ INTERNAL void game_update(void)
* Update cameras
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_CAMERA)) continue;
@ -1220,7 +1219,7 @@ INTERNAL void game_update(void)
{
/* TODO: Update based on distance to quake */
ent->shake = 0;
for (u64 quake_ent_index = 0; quake_ent_index < entity_store->reserved; ++quake_ent_index) {
for (u64 quake_ent_index = 0; quake_ent_index < entity_store->num_reserved; ++quake_ent_index) {
struct entity *quake = &entity_store->entities[quake_ent_index];
if (!entity_is_valid_and_active(quake)) continue;
if (!entity_has_prop(quake, ENTITY_PROP_QUAKE)) continue;
@ -1235,7 +1234,7 @@ INTERNAL void game_update(void)
* Update quakes
* ========================== */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_QUAKE)) continue;
@ -1283,7 +1282,7 @@ INTERNAL void game_update(void)
* user thread. This is so sounds play at the correct time on the user
* thread regardless of interp delay. */
for (u64 entity_index = 0; entity_index < entity_store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
struct entity *ent = &entity_store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
@ -1360,7 +1359,7 @@ struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cm
bw_write_i8(&bw, cmd->kind);
bw_write_i8(&bw, cmd->state);
#if RTC
#if COLLIDER_DEBUG
bw_write_u32(&bw, cmd->collider_gjk_steps);
#endif
@ -1428,7 +1427,7 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
u64 cmd_pos_end = br_pos(&br) + cmd_size;
cmd->kind = br_read_i8(&br);
cmd->state = br_read_i8(&br);
#if RTC
#if COLLIDER_DEBUG
cmd->collider_gjk_steps = br_read_u32(&br);
#endif
@ -1563,13 +1562,13 @@ struct string game_string_from_tick(struct arena *arena, struct world *tick)
bw_write_var_sint(&bw, tick->dt_ns);
bw_write_var_sint(&bw, tick->time_ns);
u64 num_entities = tick->entity_store->reserved;
u64 num_entities = tick->entity_store->num_reserved;
bw_write_var_uint(&bw, num_entities);
struct string entities_src = ZI;
entities_src.text = (u8 *)tick->entity_store->entities;
entities_src.len = sizeof(struct entity) * num_entities;
bw_write_buffer(&bw, entities_src);
br_write_bytes(&bw, entities_src);
return bw_get_written(&bw);
}
@ -1588,14 +1587,18 @@ void game_tick_from_string(struct string str, struct world *tick_out)
tick_out->time_ns = br_read_var_sint(&br);
u64 num_entities = br_read_var_uint(&br);
arena_push_array(&tick_out->entity_store->arena, struct entity, num_entities - tick_out->entity_store->reserved);
tick_out->entity_store->reserved = num_entities;
arena_push_array(&tick_out->entity_store->arena, struct entity, num_entities - tick_out->entity_store->num_reserved);
tick_out->entity_store->num_reserved = num_entities;
tick_out->entity_store->num_allocated = 0;
struct entity *entities_src = br_seek(&br, num_entities * sizeof(struct entity));
if (entities_src) {
for (u64 i = 0; i < num_entities; ++i) {
struct entity *src = &entities_src[i];
struct entity *dst = &tick_out->entity_store->entities[i];
if (dst->valid) {
++tick_out->entity_store->num_allocated;
}
*dst = *src;
}
}

View File

@ -31,12 +31,11 @@ enum host_packet_flag {
HOST_PACKET_FLAG_RELIABLE = (1 << 0)
};
struct host_packet {
struct host_snd_packet {
struct host_snd_packet *next;
u64 seq;
u8 flags;
u64 data_len;
struct host_packet *next;
u64 data_len;
u8 data[PACKET_DATA_MAX_LEN];
};
@ -54,10 +53,10 @@ struct host_channel {
struct host_channel *prev_address_hash;
/* NOTE: Packets are allocated in host's `arena` */
struct host_packet *first_reliable_packet;
struct host_packet *last_reliable_packet;
struct host_packet *first_unreliable_packet;
struct host_packet *last_unreliable_packet;
struct host_snd_packet *first_reliable_packet;
struct host_snd_packet *last_reliable_packet;
struct host_snd_packet *first_unreliable_packet;
struct host_snd_packet *last_unreliable_packet;
u64 num_reliable_packets;
u64 num_unreliable_packets;
@ -91,17 +90,17 @@ struct host_queued_event {
struct host_queued_event *next;
};
struct host_recv_packet {
struct host_rcv_packet {
struct sock *sock;
struct sock_address address;
struct string data;
struct host_recv_packet *next;
struct host_rcv_packet *next;
};
struct host_recv_buffer {
struct host_rcv_buffer {
struct arena arena;
struct host_recv_packet *first_packet;
struct host_recv_packet *last_packet;
struct host_rcv_packet *first_packet;
struct host_rcv_packet *last_packet;
};
struct host_msg_assembler {
@ -171,10 +170,10 @@ struct host *host_alloc(u16 listen_port)
host->cmd_arena = arena_alloc(GIGABYTE(64));
host->queued_event_arena = arena_alloc(GIGABYTE(64));
host->channel_arena = arena_alloc(GIGABYTE(64));
host->recv_buffer_read = arena_push_zero(&host->arena, struct host_recv_buffer);
host->recv_buffer_write = arena_push_zero(&host->arena, struct host_recv_buffer);
host->recv_buffer_read->arena = arena_alloc(GIGABYTE(64));
host->recv_buffer_write->arena = arena_alloc(GIGABYTE(64));
host->rcv_buffer_read = arena_push_zero(&host->arena, struct host_rcv_buffer);
host->rcv_buffer_write = arena_push_zero(&host->arena, struct host_rcv_buffer);
host->rcv_buffer_read->arena = arena_alloc(GIGABYTE(64));
host->rcv_buffer_write->arena = arena_alloc(GIGABYTE(64));
host->buddy = buddy_ctx_alloc(GIGABYTE(64));
host->channels = arena_dry_push(&host->channel_arena, struct host_channel);
@ -185,9 +184,9 @@ struct host *host_alloc(u16 listen_port)
host->num_msg_assembler_lookup_buckets = NUM_MSG_ASSEMBLER_LOOKUP_BUCKETS;
host->msg_assembler_lookup_buckets = arena_push_array_zero(&host->arena, struct host_msg_assembler_lookup_bucket, host->num_msg_assembler_lookup_buckets);
host->sock = sock_alloc(listen_port);
host->sock = sock_alloc(listen_port, MEGABYTE(2), MEGABYTE(2));
host->recv_buffer_write_mutex = sys_mutex_alloc();
host->rcv_buffer_write_mutex = sys_mutex_alloc();
host->receiver_thread = sys_thread_alloc(&host_receiver_thread_entry_point, host, LIT("[P6] Host receiver"));
return host;
@ -198,13 +197,13 @@ void host_release(struct host *host)
/* FIXME: Signal thread shutdown */
sys_thread_wait_release(&host->receiver_thread);
sys_mutex_release(&host->recv_buffer_write_mutex);
sys_mutex_release(&host->rcv_buffer_write_mutex);
sock_release(host->sock);
buddy_ctx_release(host->buddy);
arena_release(&host->recv_buffer_write->arena);
arena_release(&host->recv_buffer_read->arena);
arena_release(&host->rcv_buffer_write->arena);
arena_release(&host->rcv_buffer_read->arena);
arena_release(&host->channel_arena);
arena_release(&host->queued_event_arena);
arena_release(&host->cmd_arena);
@ -532,15 +531,15 @@ INTERNAL void host_msg_assembler_set_chunk_received(struct host_msg_assembler *m
* Packet
* ========================== */
INTERNAL struct host_packet *host_channel_packet_alloc(struct host_channel *channel, b32 is_reliable)
INTERNAL struct host_snd_packet *host_channel_snd_packet_alloc(struct host_channel *channel, b32 is_reliable)
{
struct host *host = channel->host;
struct host_packet *packet = NULL;
struct host_snd_packet *packet = NULL;
if (host->first_free_packet) {
packet = host->first_free_packet;
host->first_free_packet = packet->next;
} else {
packet = arena_push(&host->arena, struct host_packet);
packet = arena_push(&host->arena, struct host_snd_packet);
}
MEMZERO_STRUCT(packet);
@ -635,17 +634,17 @@ void host_update(struct host *host)
read_buff.len = PACKET_DATA_MAX_LEN;
read_buff.text = arena_push_array(scratch.arena, u8, read_buff.len);
/* Swap read & write recv buffers */
/* Swap read & write rcv buffers */
{
struct sys_lock lock = sys_mutex_lock_e(&host->recv_buffer_write_mutex);
struct host_recv_buffer *swp = host->recv_buffer_read;
host->recv_buffer_read = host->recv_buffer_write;
host->recv_buffer_write = swp;
struct sys_lock lock = sys_mutex_lock_e(&host->rcv_buffer_write_mutex);
struct host_rcv_buffer *swp = host->rcv_buffer_read;
host->rcv_buffer_read = host->rcv_buffer_write;
host->rcv_buffer_write = swp;
sys_mutex_unlock(&lock);
}
/* Read incoming packets */
struct host_recv_buffer *recv_buffer = host->recv_buffer_read;
for (struct host_recv_packet *packet = recv_buffer->first_packet; packet; packet = packet->next) {
struct host_rcv_buffer *rcv_buffer = host->rcv_buffer_read;
for (struct host_rcv_packet *packet = rcv_buffer->first_packet; packet; packet = packet->next) {
//struct sock *sock = packet->sock;
struct sock_address address = packet->address;
struct byte_reader br = br_from_buffer(packet->data);
@ -772,9 +771,9 @@ void host_update(struct host *host)
}
}
/* Reset read buffer */
recv_buffer->first_packet = NULL;
recv_buffer->last_packet = NULL;
arena_reset(&recv_buffer->arena);
rcv_buffer->first_packet = NULL;
rcv_buffer->last_packet = NULL;
arena_reset(&rcv_buffer->arena);
}
/* Update channels */
@ -792,9 +791,9 @@ void host_update(struct host *host)
/* Release acked reliable packets */
{
u64 acked_seq = channel->their_acked_seq;
struct host_packet *host_packet = channel->first_reliable_packet;
struct host_snd_packet *host_packet = channel->first_reliable_packet;
while (host_packet) {
struct host_packet *next = host_packet->next;
struct host_snd_packet *next = host_packet->next;
u64 seq = host_packet->seq;
if (seq < acked_seq) {
host_packet->next = host->first_free_packet;
@ -810,10 +809,10 @@ void host_update(struct host *host)
channel->last_reliable_packet = NULL;
}
}
/* TODO: Release timed out unreliable msg buffers */
/* Release timed out unreliable msg buffers */
{
/* TODO: Configurable timeout */
i64 timeout_ns = NS_FROM_SECONDS(4);
i64 timeout_ns = NS_FROM_SECONDS(1);
struct host_msg_assembler *ma = channel->least_recent_msg_assembler;
while (ma) {
struct host_msg_assembler *next = ma->more_recent;
@ -845,7 +844,7 @@ void host_update(struct host *host)
case HOST_CMD_KIND_TRY_CONNECT:
{
u8 packet_flags = 0;
struct host_packet *host_packet = host_channel_packet_alloc(channel, false);
struct host_snd_packet *host_packet = host_channel_snd_packet_alloc(channel, false);
struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data));
bw_write_u32(&bw, PACKET_MAGIC);
bw_write_i8(&bw, HOST_PACKET_KIND_TRY_CONNECT);
@ -857,7 +856,7 @@ void host_update(struct host *host)
case HOST_CMD_KIND_CONNECT_SUCCESS:
{
u8 packet_flags = 0;
struct host_packet *host_packet = host_channel_packet_alloc(channel, false);
struct host_snd_packet *host_packet = host_channel_snd_packet_alloc(channel, false);
struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data));
bw_write_u32(&bw, PACKET_MAGIC);
bw_write_i8(&bw, HOST_PACKET_KIND_CONNECT_SUCCESS);
@ -869,7 +868,7 @@ void host_update(struct host *host)
case HOST_CMD_KIND_DISCONNECT:
{
u8 packet_flags = 0;
struct host_packet *host_packet = host_channel_packet_alloc(channel, false);
struct host_snd_packet *host_packet = host_channel_snd_packet_alloc(channel, false);
struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data));
bw_write_u32(&bw, PACKET_MAGIC);
bw_write_i8(&bw, HOST_PACKET_KIND_DISCONNECT);
@ -898,7 +897,7 @@ void host_update(struct host *host)
data_len = msg.len % PACKET_MSG_CHUNK_MAX_LEN;
}
u8 *data = msg.text + (i * PACKET_MSG_CHUNK_MAX_LEN);
struct host_packet *host_packet = host_channel_packet_alloc(channel, is_reliable);
struct host_snd_packet *host_packet = host_channel_snd_packet_alloc(channel, is_reliable);
struct byte_writer bw = bw_from_buffer(STRING_FROM_ARRAY(host_packet->data));
bw_write_u32(&bw, PACKET_MAGIC);
bw_write_i8(&bw, HOST_PACKET_KIND_MSG_CHUNK);
@ -914,7 +913,7 @@ void host_update(struct host *host)
/* FIXME: Ensure data_len can never be 0 */
bw_write_var_uint(&bw, data_len - 1);
}
bw_write_buffer(&bw, STRING(data_len, data));
br_write_bytes(&bw, STRING(data_len, data));
host_packet->data_len = bw_pos(&bw);
}
} break;
@ -935,11 +934,11 @@ void host_update(struct host *host)
if (channel->valid) {
struct sock_address address = channel->address;
/* Send reliable packets to channel */
for (struct host_packet *host_packet = channel->first_reliable_packet; host_packet; host_packet = host_packet->next) {
for (struct host_snd_packet *host_packet = channel->first_reliable_packet; host_packet; host_packet = host_packet->next) {
sock_write(sock, address, STRING(host_packet->data_len, host_packet->data));
}
/* Send unreliable packets to channel */
for (struct host_packet *host_packet = channel->first_unreliable_packet; host_packet; host_packet = host_packet->next) {
for (struct host_snd_packet *host_packet = channel->first_unreliable_packet; host_packet; host_packet = host_packet->next) {
sock_write(sock, address, STRING(host_packet->data_len, host_packet->data));
}
/* Release unreliable packets */
@ -1008,30 +1007,28 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(host_receiver_thread_entry_point, arg)
read_buff.text = arena_push_array(&read_buff_arena, u8, KILOBYTE(64));
struct host *host = (struct host *)arg;
struct sock *sock = host->sock;
struct sock_array socks = ZI;
socks.socks = &sock;
socks.socks = &host->sock;
socks.count = 1;
struct sock_read_result res;
volatile b32 run = true;
while (run) {
res = sock_read_poll(socks, NULL, read_buff, F32_INFINITY);
if (res.valid) {
struct sys_lock lock = sys_mutex_lock_e(&host->recv_buffer_write_mutex);
struct sock *sock = sock_wait_for_available_read(socks, NULL, F32_INFINITY);
struct sock_read_result res;
while (sock && (res = sock_read(sock, read_buff)).valid) {
struct sys_lock lock = sys_mutex_lock_e(&host->rcv_buffer_write_mutex);
{
struct host_recv_buffer *recv_buffer = host->recv_buffer_write;
struct host_recv_packet *packet = arena_push_zero(&recv_buffer->arena, struct host_recv_packet);
packet->sock = res.sock;
struct host_rcv_buffer *rcv_buffer = host->rcv_buffer_write;
struct host_rcv_packet *packet = arena_push_zero(&rcv_buffer->arena, struct host_rcv_packet);
packet->address = res.address;
packet->data = string_copy(&recv_buffer->arena, res.data);
if (recv_buffer->last_packet) {
recv_buffer->last_packet->next = packet;
packet->data = string_copy(&rcv_buffer->arena, res.data);
if (rcv_buffer->last_packet) {
rcv_buffer->last_packet->next = packet;
} else {
recv_buffer->first_packet = packet;
rcv_buffer->first_packet = packet;
}
recv_buffer->last_packet = packet;
rcv_buffer->last_packet = packet;
}
sys_mutex_unlock(&lock);
}

View File

@ -8,9 +8,9 @@
#define HOST_CHANNEL_ID_ALL (struct host_channel_id) { .gen = U32_MAX, .idx = U32_MAX }
struct buddy_ctx;
struct host_packet;
struct host_snd_packet;
struct host_channel_lookup_bucket;
struct host_recv_buffer;
struct host_rcv_buffer;
enum host_cmd_kind {
HOST_CMD_KIND_NONE,
@ -77,7 +77,7 @@ struct host {
struct host_channel *first_free_channel;
u64 num_channels_reserved;
struct host_packet *first_free_packet; /* Allocated in `arena` */
struct host_snd_packet *first_free_packet; /* Allocated in `arena` */
struct host_msg_assembler *first_free_msg_assembler; /* Allocated in `arena` */
struct host_channel_lookup_bucket *channel_lookup_buckets; /* Allocated in `arena` */
@ -87,9 +87,9 @@ struct host {
u64 num_msg_assembler_lookup_buckets;
/* Double buffer for incoming data */
struct sys_mutex recv_buffer_write_mutex;
struct host_recv_buffer *recv_buffer_read;
struct host_recv_buffer *recv_buffer_write;
struct sys_mutex rcv_buffer_write_mutex;
struct host_rcv_buffer *rcv_buffer_read;
struct host_rcv_buffer *rcv_buffer_write;
struct sys_thread receiver_thread;
};

View File

@ -52,7 +52,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
struct entity_store *store = ctx->store;
struct entity *root = entity_from_handle(store, store->root);
for (u64 check0_index = 0; check0_index < store->reserved; ++check0_index) {
for (u64 check0_index = 0; check0_index < store->num_reserved; ++check0_index) {
struct entity *check0 = &store->entities[check0_index];
if (!entity_is_valid_and_active(check0)) continue;
if (!(entity_has_prop(check0, ENTITY_PROP_PHYSICAL_DYNAMIC) || entity_has_prop(check0, ENTITY_PROP_PHYSICAL_KINEMATIC))) continue;
@ -224,7 +224,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
contact->point_local_e1 = xform_invert_mul_v2(e1_xf, point);
contact->starting_separation = sep;
#if COLLIDER_DEBUG
#if DEVELOPER
contact->dbg_pt = point;
#endif
}
@ -286,7 +286,7 @@ void phys_prepare_contacts(struct phys_ctx *ctx, u64 phys_iteration)
struct entity_lookup *contact_lookup = ctx->contact_lookup;
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *constraint_ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(constraint_ent)) continue;
if (!entity_has_prop(constraint_ent, ENTITY_PROP_CONTACT_CONSTRAINT)) continue;
@ -377,7 +377,7 @@ void phys_prepare_contacts(struct phys_ctx *ctx, u64 phys_iteration)
#if COLLIDER_DEBUG
struct entity_lookup *debug_lookup = ctx->debug_lookup;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *dbg_ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(dbg_ent)) continue;
if (!entity_has_prop(dbg_ent, ENTITY_PROP_COLLISION_DEBUG)) continue;
@ -412,7 +412,7 @@ void phys_warm_start_contacts(struct phys_ctx *ctx)
{
__prof;
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *constraint_ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(constraint_ent)) continue;
if (!entity_has_prop(constraint_ent, ENTITY_PROP_CONTACT_CONSTRAINT)) continue;
@ -467,7 +467,7 @@ void phys_solve_contacts(struct phys_ctx *ctx, f32 dt, b32 apply_bias)
{
__prof;
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *constraint_ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(constraint_ent)) continue;
if (!entity_has_prop(constraint_ent, ENTITY_PROP_CONTACT_CONSTRAINT)) continue;
@ -598,7 +598,7 @@ void phys_prepare_motor_joints(struct phys_ctx *ctx)
{
__prof;
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *joint_ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(joint_ent)) continue;
if (!entity_has_prop(joint_ent, ENTITY_PROP_MOTOR_JOINT)) continue;
@ -662,7 +662,7 @@ void phys_warm_start_motor_joints(struct phys_ctx *ctx)
{
__prof;
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *joint_ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(joint_ent)) continue;
if (!entity_has_prop(joint_ent, ENTITY_PROP_MOTOR_JOINT)) continue;
@ -694,7 +694,7 @@ void phys_solve_motor_joints(struct phys_ctx *ctx, f32 dt)
{
__prof;
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *joint_ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(joint_ent)) continue;
if (!entity_has_prop(joint_ent, ENTITY_PROP_MOTOR_JOINT)) continue;
@ -789,7 +789,7 @@ void phys_create_mouse_joints(struct phys_ctx *ctx)
mouse_shape.points[0] = V2(0, 0);
mouse_shape.count = 1;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC)) continue;
@ -843,7 +843,7 @@ void phys_prepare_mouse_joints(struct phys_ctx *ctx)
{
__prof;
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *joint_ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(joint_ent)) continue;
if (!entity_has_prop(joint_ent, ENTITY_PROP_MOUSE_JOINT)) continue;
@ -890,7 +890,7 @@ void phys_warm_start_mouse_joints(struct phys_ctx *ctx)
{
__prof;
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *joint_ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(joint_ent)) continue;
if (!entity_has_prop(joint_ent, ENTITY_PROP_MOUSE_JOINT)) continue;
@ -912,7 +912,7 @@ void phys_solve_mouse_joints(struct phys_ctx *ctx, f32 dt)
{
__prof;
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *joint_ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(joint_ent)) continue;
if (!entity_has_prop(joint_ent, ENTITY_PROP_MOUSE_JOINT)) continue;
@ -999,7 +999,7 @@ void phys_integrate_forces(struct phys_ctx *ctx, f32 dt)
{
__prof;
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
@ -1041,7 +1041,7 @@ void phys_integrate_velocities(struct phys_ctx *ctx, f32 dt)
{
__prof;
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC) && !entity_has_prop(ent, ENTITY_PROP_PHYSICAL_KINEMATIC)) continue;
@ -1067,7 +1067,7 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_ctx *ctx, f32 step_dt, f
struct space *space = ctx->space;
f32 smallest_t = 1;
for (u64 e0_index = 0; e0_index < store->reserved; ++e0_index) {
for (u64 e0_index = 0; e0_index < store->num_reserved; ++e0_index) {
struct entity *e0 = &store->entities[e0_index];
if (!entity_is_valid_and_active(e0)) continue;
if (!(entity_has_prop(e0, ENTITY_PROP_PHYSICAL_DYNAMIC) || entity_has_prop(e0, ENTITY_PROP_PHYSICAL_KINEMATIC))) continue;
@ -1114,7 +1114,7 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_ctx *ctx, f32 step_dt, f
void phys_update_aabbs(struct phys_ctx *ctx)
{
struct entity_store *store = ctx->store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
if (ent->local_collider.count <= 0) continue;

View File

@ -70,7 +70,9 @@ struct phys_contact_point {
f32 inv_tangent_mass;
/* Debugging */
#if DEVELOPER
struct v2 dbg_pt;
#endif
};
struct phys_contact_constraint {

View File

@ -31,7 +31,6 @@ struct sock_address {
struct sock_read_result {
b32 valid;
struct sock *sock; /* In case of read from multiple sockets */
struct sock_address address;
struct string data;
};
@ -47,11 +46,11 @@ INLINE b32 sock_address_eq(struct sock_address a, struct sock_address b)
return MEMEQ_STRUCT(&a, &b);
}
struct sock *sock_alloc(u16 listen_port);
struct sock *sock_alloc(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size);
void sock_release(struct sock *sock);
struct sock *sock_wait_for_available_read(struct sock_array socks, struct sock_signal *signal, f32 timeout);
struct sock_read_result sock_read(struct sock *sock, struct string read_buff);
struct sock_read_result sock_read_poll(struct sock_array socks, struct sock_signal *signal, struct string read_buff, f32 timeout);
void sock_write(struct sock *sock, struct sock_address address, struct string data);
#endif

View File

@ -16,6 +16,8 @@
//#define MAX_IP_STR_LEN 46
#define MAX_POLL_FDS 64
struct winsock_address {
i32 size;
i32 family;
@ -241,13 +243,20 @@ INTERNAL struct sock_address sock_address_from_winsock_address(struct winsock_ad
* Alloc
* ========================== */
struct sock *sock_alloc(u16 listen_port)
struct sock *sock_alloc(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size)
{
struct sock_address addr = sock_address_from_port(listen_port);
struct winsock_address ws_addr = winsock_address_from_sock_address(addr);
SOCKET ws = socket(ws_addr.family, SOCK_DGRAM, IPPROTO_UDP);
{
i32 sb = sndbuf_size;
i32 rb = rcvbuf_size;
setsockopt(ws, SOL_SOCKET, SO_SNDBUF, (char *)&sb, sizeof(sb));
setsockopt(ws, SOL_SOCKET, SO_RCVBUF, (char *)&rb, sizeof(rb));
}
#if 0
if (listen_port != 0) {
bind(ws, &ws_addr.sa, ws_addr.size);
@ -269,51 +278,29 @@ void sock_release(struct sock *sock)
* Read
* ========================== */
struct sock_read_result sock_read(struct sock *sock, struct string read_buff)
{
SOCKET ws = (SOCKET)sock;
struct sock_read_result res = ZI;
res.sock = sock;
struct winsock_address ws_addr = ZI;
ws_addr.size = sizeof(ws_addr.sas);
i32 size = recvfrom(ws, (char *)read_buff.text, read_buff.len, 0, &ws_addr.sa, &ws_addr.size);
ws_addr.family = ws_addr.sin.sin_family;
res.address = sock_address_from_winsock_address(ws_addr);
if (size > 0) {
res.data.text = read_buff.text;
res.data.len = size;
res.valid = true;
} else {
#if RTC
i32 err = WSAGetLastError();
if (err != WSAEWOULDBLOCK && err != WSAETIMEDOUT) {
ASSERT(false);
}
#endif
}
return res;
}
struct sock_read_result sock_read_poll(struct sock_array socks, struct sock_signal *signal, struct string read_buff, f32 timeout)
struct sock *sock_wait_for_available_read(struct sock_array socks, struct sock_signal *signal, f32 timeout)
{
struct temp_arena scratch = scratch_begin_no_conflict();
struct sock_read_result res = ZI;
struct sock *res = NULL;
u64 num_fds = socks.count + (signal != NULL);
WSAPOLLFD *fds = arena_push_array(scratch.arena, WSAPOLLFD, num_fds);
for (u64 i = 0; i < num_fds; ++i) {
if (i + 1 == num_fds && signal != NULL) {
fds[i].fd = (SOCKET)signal;
} else {
SOCKET ws = (SOCKET)socks.socks[i];
fds[i].fd = ws;
WSAPOLLFD fds[MAX_POLL_FDS] = ZI;
{
u32 fd_i = 0;
if (signal != NULL) {
fds[fd_i].fd = (SOCKET)signal;
fds[fd_i].events = POLLRDNORM;
++fd_i;
}
for (u32 i = 0; i < socks.count; ++i) {
if (fd_i >= ARRAY_COUNT(fds)) {
ASSERT(false);
break;
}
fds[fd_i].fd = (SOCKET)socks.socks[i];
fds[fd_i].events = POLLRDNORM;
++fd_i;
}
fds[i].events = POLLRDNORM;
}
i32 timeout_ms;
@ -327,8 +314,25 @@ struct sock_read_result sock_read_poll(struct sock_array socks, struct sock_sign
for (u64 i = 0; i < num_fds; ++i) {
if (fds[i].revents & POLLRDNORM) {
if (i < socks.count) {
SOCKET ws = fds[i].fd;
res.sock = socks.socks[i];
res = socks.socks[i];
break;
} else {
/* FIXME: Return signal */
ASSERT(false);
break;
}
}
}
scratch_end(scratch);
return res;
}
struct sock_read_result sock_read(struct sock *sock, struct string read_buff)
{
SOCKET ws = (SOCKET)sock;
struct sock_read_result res = ZI;
struct winsock_address ws_addr = ZI;
ws_addr.size = sizeof(ws_addr.sas);
@ -340,7 +344,6 @@ struct sock_read_result sock_read_poll(struct sock_array socks, struct sock_sign
res.data.text = read_buff.text;
res.data.len = size;
res.valid = true;
break;
} else {
#if RTC
i32 err = WSAGetLastError();
@ -348,13 +351,8 @@ struct sock_read_result sock_read_poll(struct sock_array socks, struct sock_sign
ASSERT(false);
}
#endif
break;
}
}
}
}
scratch_end(scratch);
return res;
}

View File

@ -547,7 +547,7 @@ INTERNAL void user_update(void)
G.world.dt_ns = math_lerp_i64(t0->dt_ns, t1->dt_ns, (f64)tick_blend);
/* Blend entities */
u64 num_entities = min_u64(t0->entity_store->reserved, t1->entity_store->reserved);
u64 num_entities = min_u64(t0->entity_store->num_reserved, t1->entity_store->num_reserved);
{
__profscope(tick_blending);
for (u64 i = 0; i < num_entities; ++i) {
@ -796,7 +796,7 @@ INTERNAL void user_update(void)
* Apply shake
* ========================== */
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index];
if (!entity_is_valid_and_active(ent)) continue;
@ -964,7 +964,7 @@ INTERNAL void user_update(void)
/* Copy valid entities */
{
__profscope(copy_sprites_for_sorting);
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
for (u64 entity_index = 0; entity_index < store->num_reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index];
if (entity_is_valid_and_active(ent)) {
*arena_push(scratch.arena, struct entity *) = ent;
@ -1605,7 +1605,7 @@ INTERNAL void user_update(void)
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("world time: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.world.time_ns))));
pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("entities: %F/%F"), FMT_UINT(G.world.entity_store->allocated), FMT_UINT(G.world.entity_store->reserved)));
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("entities: %F/%F"), FMT_UINT(G.world.entity_store->num_allocated), FMT_UINT(G.world.entity_store->num_reserved)));
pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("screen_size: (%F, %F)"), FMT_FLOAT((f64)G.screen_size.x), FMT_FLOAT((f64)G.screen_size.y)));