diff --git a/src/buddy.c b/src/buddy.c index 84c2fb4f..98bf0e37 100644 --- a/src/buddy.c +++ b/src/buddy.c @@ -173,6 +173,8 @@ struct buddy_block *buddy_alloc(struct buddy_ctx *ctx, u64 size) /* TODO: Minimum block size */ + /* TODO: Faster MSB calculation */ + u64 desired_block_size = 1; u64 desired_level_tier = 0; while (desired_block_size < size && desired_level_tier < 64) { diff --git a/src/buddy.h b/src/buddy.h index 6294435f..0b79771e 100644 --- a/src/buddy.h +++ b/src/buddy.h @@ -16,7 +16,7 @@ struct buddy_block { struct buddy_level { struct buddy_ctx *ctx; - b32 backed; /* Is this level backed by memory in the ctx arena */ + b32 backed; /* Signals whether this level is backed by memory in the ctx arena */ u32 tier; u64 size; struct buddy_block *first_unused_block; diff --git a/src/host.c b/src/host.c index 24715db7..e9895256 100644 --- a/src/host.c +++ b/src/host.c @@ -661,7 +661,7 @@ void host_update(struct host *host) struct sock_address address = packet->address; struct bitbuff bb = bitbuff_from_string(packet->data); struct bitbuff_reader br = br_from_bitbuff(&bb); - u32 magic = br_read_ubits(&br, 32); + u32 magic = br_read_ubits(&br, 32); /* TODO: implicitly encode magic into crc32 */ if (magic == PACKET_MAGIC) { /* TODO: Combine kind byte with flags byte */ struct host_channel *channel = host_channel_from_address(host, address); @@ -864,7 +864,7 @@ void host_update(struct host *host) struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, false); struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data)); struct bitbuff_writer bw = bw_from_bitbuff(&bb); - bw_write_ubits(&bw, PACKET_MAGIC, 32); + bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */ bw_write_ibits(&bw, HOST_PACKET_KIND_TRY_CONNECT, 8); bw_write_ubits(&bw, packet_flags, 8); bw_write_uv(&bw, channel->our_acked_seq); @@ -877,7 +877,7 @@ void host_update(struct host *host) struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, false); struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data)); struct bitbuff_writer bw = bw_from_bitbuff(&bb); - bw_write_ubits(&bw, PACKET_MAGIC, 32); + bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */ bw_write_ibits(&bw, HOST_PACKET_KIND_CONNECT_SUCCESS, 8); bw_write_ubits(&bw, packet_flags, 8); bw_write_uv(&bw, channel->our_acked_seq); @@ -890,7 +890,7 @@ void host_update(struct host *host) struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, false); struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data)); struct bitbuff_writer bw = bw_from_bitbuff(&bb); - bw_write_ubits(&bw, PACKET_MAGIC, 32); + bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */ bw_write_ibits(&bw, HOST_PACKET_KIND_DISCONNECT, 8); bw_write_ubits(&bw, packet_flags, 8); bw_write_uv(&bw, channel->our_acked_seq); @@ -922,7 +922,7 @@ void host_update(struct host *host) struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, is_reliable); struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data)); struct bitbuff_writer bw = bw_from_bitbuff(&bb); - bw_write_ubits(&bw, PACKET_MAGIC, 32); + bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */ bw_write_ibits(&bw, HOST_PACKET_KIND_MSG_CHUNK, 8); bw_write_ubits(&bw, packet_flags, 8); bw_write_uv(&bw, channel->our_acked_seq); diff --git a/src/phys.c b/src/phys.c index db19d9ef..38f9af9a 100644 --- a/src/phys.c +++ b/src/phys.c @@ -53,7 +53,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a for (u64 check0_index = 0; check0_index < ss->num_ents_reserved; ++check0_index) { struct sim_ent *check0 = &ss->ents[check0_index]; - if (!sim_ent_is_valid_and_active(check0)) continue; + if (!sim_ent_should_simulate(check0)) continue; if (!(sim_ent_has_prop(check0, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check0, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; if (check0->local_collider.count <= 0) continue; @@ -66,7 +66,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a while ((space_entry = space_iter_next(&iter))) { struct sim_ent *check1 = sim_ent_from_id(ss, space_entry->ent); if (check1 == check0) continue; - if (!sim_ent_is_valid_and_active(check1)) continue; + if (!sim_ent_should_simulate(check1)) continue; if (!(sim_ent_has_prop(check1, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check1, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; if (check1->local_collider.count <= 0) continue; @@ -274,7 +274,7 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration) for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *constraint_ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(constraint_ent)) continue; + if (!sim_ent_should_simulate(constraint_ent)) continue; if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue; struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data; @@ -282,7 +282,7 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration) u32 num_points = constraint->num_points; struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0); struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1); - if (constraint->last_phys_iteration >= phys_iteration && num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) { + if (constraint->last_phys_iteration >= phys_iteration && num_points > 0 && sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) { struct v2 normal = constraint->normal; struct v2 tangent = v2_perp(normal); @@ -392,7 +392,7 @@ void phys_warm_start_contacts(struct phys_step_ctx *ctx) struct sim_snapshot *ss = ctx->sim_step_ctx->world; for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *constraint_ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(constraint_ent)) continue; + if (!sim_ent_should_simulate(constraint_ent)) continue; if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue; struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data; @@ -401,7 +401,7 @@ void phys_warm_start_contacts(struct phys_step_ctx *ctx) struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0); struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1); - if (num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1) && !constraint->skip_solve) { + if (num_points > 0 && sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1) && !constraint->skip_solve) { struct xform e0_xf = sim_ent_get_xform(e0); struct xform e1_xf = sim_ent_get_xform(e1); @@ -447,7 +447,7 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias) struct sim_snapshot *ss = ctx->sim_step_ctx->world; for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *constraint_ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(constraint_ent)) continue; + if (!sim_ent_should_simulate(constraint_ent)) continue; if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue; struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data; @@ -461,7 +461,7 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias) f32 w1 = e1->angular_velocity; u32 num_points = constraint->num_points; - if (num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1) && !constraint->skip_solve) { + if (num_points > 0 && sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1) && !constraint->skip_solve) { struct xform e0_xf = sim_ent_get_xform(e0); struct xform e1_xf = sim_ent_get_xform(e1); @@ -578,7 +578,7 @@ void phys_prepare_motor_joints(struct phys_step_ctx *ctx) struct sim_snapshot *ss = ctx->sim_step_ctx->world; for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(joint_ent)) continue; + if (!sim_ent_should_simulate(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue; struct phys_motor_joint *joint = &joint_ent->motor_joint_data; @@ -586,7 +586,7 @@ void phys_prepare_motor_joints(struct phys_step_ctx *ctx) struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0); struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1); - if (sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) { + if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) { struct xform e0_xf = sim_ent_get_xform(e0); struct xform e1_xf = sim_ent_get_xform(e1); @@ -642,7 +642,7 @@ void phys_warm_start_motor_joints(struct phys_step_ctx *ctx) struct sim_snapshot *ss = ctx->sim_step_ctx->world; for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(joint_ent)) continue; + if (!sim_ent_should_simulate(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue; struct phys_motor_joint *joint = &joint_ent->motor_joint_data; @@ -674,7 +674,7 @@ void phys_solve_motor_joints(struct phys_step_ctx *ctx, f32 dt) struct sim_snapshot *ss = ctx->sim_step_ctx->world; for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(joint_ent)) continue; + if (!sim_ent_should_simulate(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue; struct phys_motor_joint *joint = &joint_ent->motor_joint_data; @@ -767,12 +767,12 @@ void phys_prepare_mouse_joints(struct phys_step_ctx *ctx) struct sim_snapshot *ss = ctx->sim_step_ctx->world; for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(joint_ent)) continue; + if (!sim_ent_should_simulate(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue; struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data; struct sim_ent *ent = sim_ent_from_id(ss, joint->target); - if (sim_ent_is_valid_and_active(ent)) { + if (sim_ent_should_simulate(ent)) { struct xform xf = sim_ent_get_xform(ent); /* TODO: Cache this */ @@ -814,12 +814,12 @@ void phys_warm_start_mouse_joints(struct phys_step_ctx *ctx) struct sim_snapshot *ss = ctx->sim_step_ctx->world; for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(joint_ent)) continue; + if (!sim_ent_should_simulate(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue; struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data; struct sim_ent *ent = sim_ent_from_id(ss, joint->target); - if (sim_ent_is_valid_and_active(ent)) { + if (sim_ent_should_simulate(ent)) { f32 inv_m = joint->inv_m; f32 inv_i = joint->inv_i; struct xform xf = sim_ent_get_xform(ent); @@ -836,12 +836,12 @@ void phys_solve_mouse_joints(struct phys_step_ctx *ctx, f32 dt) struct sim_snapshot *ss = ctx->sim_step_ctx->world; for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(joint_ent)) continue; + if (!sim_ent_should_simulate(joint_ent)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue; struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data; struct sim_ent *ent = sim_ent_from_id(ss, joint->target); - if (sim_ent_is_valid_and_active(ent)) { + if (sim_ent_should_simulate(ent)) { struct v2 v = ent->linear_velocity; f32 w = ent->angular_velocity; @@ -923,7 +923,7 @@ void phys_integrate_forces(struct phys_step_ctx *ctx, f32 dt) struct sim_snapshot *ss = ctx->sim_step_ctx->world; for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(ent)) continue; + if (!sim_ent_should_simulate(ent)) continue; b32 is_dynamic = sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC); b32 is_kinematic = sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_KINEMATIC); @@ -965,7 +965,7 @@ void phys_integrate_velocities(struct phys_step_ctx *ctx, f32 dt) struct sim_snapshot *ss = ctx->sim_step_ctx->world; for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(ent)) continue; + if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC) && !sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_KINEMATIC)) continue; struct xform xf = get_derived_xform(ent, dt); @@ -986,7 +986,7 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_step_ctx *ctx, f32 step_ for (u64 e0_index = 0; e0_index < ss->num_ents_reserved; ++e0_index) { struct sim_ent *e0 = &ss->ents[e0_index]; - if (!sim_ent_is_valid_and_active(e0)) continue; + if (!sim_ent_should_simulate(e0)) continue; if (!(sim_ent_has_prop(e0, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e0, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; if (!sim_ent_has_prop(e0, SIM_ENT_PROP_BULLET)) continue; if (e0->local_collider.count <= 0) continue; @@ -1005,7 +1005,7 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_step_ctx *ctx, f32 step_ while ((entry = space_iter_next(&iter))) { struct sim_ent *e1 = sim_ent_from_id(ss, entry->ent); if (e1 == e0) continue; - if (!sim_ent_is_valid_and_active(e1)) continue; + if (!sim_ent_should_simulate(e1)) continue; if (!(sim_ent_has_prop(e1, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; if (e1->local_collider.count <= 0) continue; diff --git a/src/sim.c b/src/sim.c index 269131d1..38a09438 100644 --- a/src/sim.c +++ b/src/sim.c @@ -10,17 +10,26 @@ * * Client store -> clients -> snapshots -> ents * - * A client store holds clients, which can be retrieved by client handle or by a host channel id (if one is set). + * A client store holds clients, which can be retrieved by client handle or by a host channel id (if one is assigned). * - * A client holds snapshots, which can be retrieved by tick (64 bit unsigned int). + * A client holds snapshots, which can be retrieved by tick number. * - The snapshots stored in clients & the contents of those snapshots are determined from data transmitted by the client. - * - Different kinds of clients will transmit different subsets of snapshot data (e.g. a master client will transmit most/all ent state, while slave clients may just transmit 1 or more cmds) + * - Different kinds of clients will transmit different subsets of snapshot data (e.g. a master client will transmit most ent state, while slave clients may just transmit 1 or more command ents) * - A client will never hold more than one snapshot for the same tick (e.g. a client will never have 2 snapshots at tick 5) * - * A snapshot holds the ent tree for a particular tick, in which ents can be retrieved by ent handle. + * A snapshot holds the ent tree for a particular tick, in which ents can be retrieved by ent id. * - A tick is the quantized time step that all clients implicitly conform to. * * An ent is the smallest unit of simulation state. + * - It is assigned a 128 bit unique identifer generated at allocation time. + * - This id is used to refer to other ents in the tree and to sync ents accross clients. + * - This id is usually random, but can be deterministic under certain conditions. + * - For example, instead of storing a contact constraint lookup table, contact constraints are + * retrieved by searching for the ent with the id resulting from combining the ent ids of the + * two contacting entities (plus a unique 'basis' ent id used for all contact constraints). + * - The ent also implicitly has a 32 bit index, which is just its offset from the start of the entity array in the local snapshot. + * - Since index is based on offset which remains stable regardless of snapshot memory location, it + * is used when working in contexts where id is irrelevant. */ #define CLIENT_LOOKUP_BINS 127 @@ -590,7 +599,7 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, str * ========================== */ /* Syncs entity data between snapshots */ -void sim_snapshot_sync(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss) +void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss) { __prof; diff --git a/src/sim.h b/src/sim.h index a48d1c58..ea94208f 100644 --- a/src/sim.h +++ b/src/sim.h @@ -208,7 +208,7 @@ struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *clien struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend); /* Sync */ -void sim_snapshot_sync(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss); +void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss); /* Encode / decode */ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1); diff --git a/src/sim_ent.c b/src/sim_ent.c index 883166a6..17698b98 100644 --- a/src/sim_ent.c +++ b/src/sim_ent.c @@ -151,7 +151,7 @@ void sim_ent_release_all_with_prop(struct sim_snapshot *ss, enum sim_ent_prop pr * child entities will be released along with parent anyway) */ for (u64 i = 0; i < ents_to_release_count; ++i) { struct sim_ent *ent = ents_to_release[i]; - if (ent->is_top && !ent->is_root && ent->valid) { + if (ent->valid && !ent->is_root && !sim_ent_has_prop(ent, SIM_ENT_PROP_CMD_CONTROL) && !sim_ent_has_prop(ent, SIM_ENT_PROP_CLIENT)) { sim_ent_release(ent); } } diff --git a/src/sim_step.c b/src/sim_step.c index e29ec174..a73ac9cd 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -342,6 +342,7 @@ void sim_step(struct sim_step_ctx *ctx) struct sim_client *user_input_client = ctx->user_input_client; struct sim_client *publish_client = ctx->publish_client; struct sim_client *master_client = ctx->master_client; + (UNUSED)master_client; i64 sim_dt_ns = ctx->sim_dt_ns; @@ -361,6 +362,10 @@ void sim_step(struct sim_step_ctx *ctx) * Sync remote ents * ========================== */ + if (user_input_client->valid) { + user_input_client->ent_id = world->local_client_ent; + } + { for (u64 client_index = 0; client_index < client_store->num_clients_reserved; ++client_index) { struct sim_client *client = &client_store->clients[client_index]; @@ -385,15 +390,9 @@ void sim_step(struct sim_step_ctx *ctx) } /* Sync ents from client */ - { - struct sim_snapshot *src_ss = sim_snapshot_from_tick(client, world->tick); - if (src_ss->valid) { - sim_snapshot_sync(world, src_ss); - if (client == master_client) { - world_client->ent_id = src_ss->local_client_ent; - world->local_client_ent = src_ss->local_client_ent; - } - } + struct sim_snapshot *src_ss = sim_snapshot_from_tick(client, world->tick); + if (src_ss->valid) { + sim_snapshot_sync_ents(world, src_ss); } } } @@ -1264,8 +1263,13 @@ void sim_step(struct sim_step_ctx *ctx) if (!pub_world->valid) { struct sim_snapshot *prev_pub_world = sim_snapshot_from_tick(publish_client, publish_client->last_tick); pub_world = sim_snapshot_alloc(publish_client, prev_pub_world, world->tick); + /* Sync */ + sim_snapshot_sync_ents(pub_world, world); + pub_world->sim_dt_ns = world->sim_dt_ns; + pub_world->sim_time_ns = world->sim_time_ns; + pub_world->continuity_gen = world->continuity_gen; + pub_world->phys_iteration = world->phys_iteration; pub_world->local_client_ent = world->local_client_ent; - sim_snapshot_sync(pub_world, world); } } diff --git a/src/user.c b/src/user.c index 4410da04..a43749ca 100644 --- a/src/user.c +++ b/src/user.c @@ -1982,7 +1982,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) struct sim_snapshot *base_ss = sim_snapshot_from_tick(client, base_tick); if (base_ss->tick == base_tick) { if (is_master) { - /* Decode incoming slave client snapshots */ + /* Queue incoming slave client snapshot for decoding */ b32 should_decode = tick == client->highest_received_tick + 1 || client->highest_received_tick == 0; if (should_decode) { struct sim_ss_decode_node *node = arena_push_zero(scratch.arena, struct sim_ss_decode_node); @@ -2000,8 +2000,8 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) client->highest_received_tick = tick; } } - } else { - /* Decode incoming master client snapshots (only the newest one) */ + } else if (client == master_client) { + /* Decode incoming master client snapshots for decoding (only the newest one) */ b32 should_decode = tick > client->highest_received_tick; if (should_decode) { struct sim_ss_decode_node *node = queue.first ? queue.first : arena_push_zero(scratch.arena, struct sim_ss_decode_node); @@ -2044,9 +2044,12 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) /* Alloc & decode snapshot */ struct sim_snapshot *ss = sim_snapshot_alloc(client, base_ss, tick); sim_snapshot_decode(&br, ss); + + /* Assume all incoming ents want to be sync srcs */ for (u64 i = 0; i < ss->num_ents_reserved; ++i) { struct sim_ent *ent = &ss->ents[i]; if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST)) { + sim_ent_disable_prop(ent, SIM_ENT_PROP_SYNC_DST); sim_ent_enable_prop(ent, SIM_ENT_PROP_SYNC_SRC); } @@ -2070,7 +2073,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) /* Create user input */ { struct sim_snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_tick); - struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, local_client->last_tick + ahead + 1); + struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, local_client->last_tick + 1); struct sim_ent *user_input_root = sim_ent_from_id(user_input_ss, SIM_ENT_ROOT_ID); /* Find / create local control cmd ent */ struct sim_ent *control_cmd_ent = sim_ent_find_first_match_one(user_input_ss, SIM_ENT_PROP_CMD_CONTROL); @@ -2138,7 +2141,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) } /* Release unneeded user input snapshots */ - sim_snapshot_release_ticks_in_range(user_input_client, 0, local_client->last_tick - 1); + sim_snapshot_release_ticks_in_range(user_input_client, 0, local_client->first_tick - 1); @@ -2237,7 +2240,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) struct bitbuff_writer msg_bw = bw_from_bitbuff(&msg_writer_bb); bw_write_uv(&msg_bw, client->highest_received_tick); /* ack */ - bw_write_uv(&msg_bw, client->ack); /* double ack */ + bw_write_uv(&msg_bw, client->ack); /* double ack */ struct sim_snapshot *base_ss = sim_snapshot_from_tick(publish_client, client->ack); struct sim_snapshot *publish_ss;