diff --git a/src/buddy.c b/src/buddy.c index 85d0ce2a..f8142617 100644 --- a/src/buddy.c +++ b/src/buddy.c @@ -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; diff --git a/src/byteio.c b/src/byteio.c index 2a3d968e..673d112c 100644 --- a/src/byteio.c +++ b/src/byteio.c @@ -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); } /* ========================== * diff --git a/src/byteio.h b/src/byteio.h index c35f67db..7cc45f5c 100644 --- a/src/byteio.h +++ b/src/byteio.h @@ -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); diff --git a/src/config.h b/src/config.h index 8580c2b6..e8a11909 100644 --- a/src/config.h +++ b/src/config.h @@ -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 diff --git a/src/entity.c b/src/entity.c index cd0a0683..8e494d26 100644 --- a/src/entity.c +++ b/src/entity.c @@ -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]; diff --git a/src/entity.h b/src/entity.h index 51d5f2a0..94744d8b 100644 --- a/src/entity.h +++ b/src/entity.h @@ -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; diff --git a/src/game.c b/src/game.c index 1757e110..73791784 100644 --- a/src/game.c +++ b/src/game.c @@ -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; } } diff --git a/src/host.c b/src/host.c index 1d7a059d..6fc9e820 100644 --- a/src/host.c +++ b/src/host.c @@ -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); } diff --git a/src/host.h b/src/host.h index 995fd942..e0248ccd 100644 --- a/src/host.h +++ b/src/host.h @@ -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; }; diff --git a/src/phys.c b/src/phys.c index 0c16849c..914dc05c 100644 --- a/src/phys.c +++ b/src/phys.c @@ -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; diff --git a/src/phys.h b/src/phys.h index 46f8f21c..8c677ec4 100644 --- a/src/phys.h +++ b/src/phys.h @@ -70,7 +70,9 @@ struct phys_contact_point { f32 inv_tangent_mass; /* Debugging */ +#if DEVELOPER struct v2 dbg_pt; +#endif }; struct phys_contact_constraint { diff --git a/src/sock.h b/src/sock.h index ac7861f2..9ecc5a6c 100644 --- a/src/sock.h +++ b/src/sock.h @@ -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 diff --git a/src/sock_win32.c b/src/sock_win32.c index faac0880..e7254dcd 100644 --- a/src/sock_win32.c +++ b/src/sock_win32.c @@ -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,11 +278,60 @@ void sock_release(struct sock *sock) * Read * ========================== */ +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 *res = NULL; + + u64 num_fds = socks.count + (signal != NULL); + 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; + } + } + + i32 timeout_ms; + if (timeout == F32_INFINITY) { + timeout_ms = -1; + } else { + timeout_ms = (i32)(timeout * 1000); + } + WSAPoll(fds, num_fds, timeout_ms); + + for (u64 i = 0; i < num_fds; ++i) { + if (fds[i].revents & POLLRDNORM) { + if (i < socks.count) { + 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; - res.sock = sock; struct winsock_address ws_addr = ZI; ws_addr.size = sizeof(ws_addr.sas); @@ -298,66 +356,6 @@ struct sock_read_result sock_read(struct sock *sock, struct string read_buff) return res; } -struct sock_read_result sock_read_poll(struct sock_array socks, struct sock_signal *signal, struct string read_buff, f32 timeout) -{ - struct temp_arena scratch = scratch_begin_no_conflict(); - struct sock_read_result res = ZI; - - 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; - } - fds[i].events = POLLRDNORM; - } - - i32 timeout_ms; - if (timeout == F32_INFINITY) { - timeout_ms = -1; - } else { - timeout_ms = (i32)(timeout * 1000); - } - WSAPoll(fds, num_fds, timeout_ms); - - 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]; - 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; - break; - } else { -#if RTC - i32 err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK && err != WSAETIMEDOUT) { - ASSERT(false); - } -#endif - break; - } - } - } - } - - scratch_end(scratch); - return res; -} - /* ========================== * * Write * ========================== */ diff --git a/src/user.c b/src/user.c index 61999cf3..53d6ebca 100644 --- a/src/user.c +++ b/src/user.c @@ -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)));