prediction progress

This commit is contained in:
jacob 2025-02-22 23:20:42 -06:00
parent ba12d5677a
commit 1dc1c42678
12 changed files with 268 additions and 134 deletions

View File

@ -20,9 +20,8 @@ enum dbg_magic {
DBG_MAGIC_IV = 0x981f, DBG_MAGIC_IV = 0x981f,
DBG_MAGIC_F32 = 0x56F9, DBG_MAGIC_F32 = 0x56F9,
DBG_MAGIC_F64 = 0x7053, DBG_MAGIC_F64 = 0x7053,
DBG_MAGIC_U128 = 0xa24e, DBG_MAGIC_U128 = 0xA24E,
DBG_MAGIC_STRING = 0x7866, DBG_MAGIC_STRING = 0x7866,
DBG_MAGIC_BYTES = 0x8B90
}; };
INTERNAL void bw_write_ubits_nomagic(struct bitbuff_writer *bw, u64 value, u8 num_bits); INTERNAL void bw_write_ubits_nomagic(struct bitbuff_writer *bw, u64 value, u8 num_bits);
@ -202,7 +201,11 @@ b32 bw_check_overflow_bits(struct bitbuff_writer *bw, u64 num_bits)
/* Align the pos to the next byte */ /* Align the pos to the next byte */
void bw_align(struct bitbuff_writer *bw) void bw_align(struct bitbuff_writer *bw)
{ {
#if BITBUFF_DEBUG
if ((bw->cur_bit & 7) != 0) {
_dbg_write_magic(bw, DBG_MAGIC_ALIGN, 0); _dbg_write_magic(bw, DBG_MAGIC_ALIGN, 0);
}
#endif
bw->cur_bit += (8 - (bw->cur_bit & 7)) & 7; bw->cur_bit += (8 - (bw->cur_bit & 7)) & 7;
} }
@ -330,8 +333,8 @@ void bw_write_f64(struct bitbuff_writer *bw, f64 value)
void bw_write_u128(struct bitbuff_writer *bw, u128 value) void bw_write_u128(struct bitbuff_writer *bw, u128 value)
{ {
_dbg_write_magic(bw, DBG_MAGIC_U128, 128); _dbg_write_magic(bw, DBG_MAGIC_U128, 128);
bw_write_ubits(bw, U128_LO(value), 64);
bw_write_ubits(bw, U128_HI(value), 64); bw_write_ubits(bw, U128_HI(value), 64);
bw_write_ubits(bw, U128_LO(value), 64);
} }
void bw_write_string(struct bitbuff_writer *bw, struct string s) void bw_write_string(struct bitbuff_writer *bw, struct string s)
@ -343,8 +346,6 @@ void bw_write_string(struct bitbuff_writer *bw, struct string s)
void bw_write_bytes(struct bitbuff_writer *bw, struct string bytes) void bw_write_bytes(struct bitbuff_writer *bw, struct string bytes)
{ {
_dbg_write_magic(bw, DBG_MAGIC_BYTES, 0);
/* Align start of bytes */ /* Align start of bytes */
bw_align(bw); bw_align(bw);
@ -440,7 +441,11 @@ b32 br_check_overflow_bits(struct bitbuff_reader *br, u64 num_bits)
/* Align the pos to the next byte */ /* Align the pos to the next byte */
void br_align(struct bitbuff_reader *br) void br_align(struct bitbuff_reader *br)
{ {
#if BITBUFF_DEBUG
if ((br->cur_bit & 7) != 0) {
_dbg_read_magic(br, DBG_MAGIC_ALIGN, 0); _dbg_read_magic(br, DBG_MAGIC_ALIGN, 0);
}
#endif
br->cur_bit += (8 - (br->cur_bit & 7)) & 7; br->cur_bit += (8 - (br->cur_bit & 7)) & 7;
} }
@ -608,7 +613,6 @@ void br_read_bytes(struct bitbuff_reader *br, struct string out)
/* NULL will return on bitbuff overflow, result should be checked. */ /* NULL will return on bitbuff overflow, result should be checked. */
u8 *br_read_bytes_raw(struct bitbuff_reader *br, u64 num_bytes) u8 *br_read_bytes_raw(struct bitbuff_reader *br, u64 num_bytes)
{ {
_dbg_read_magic(br, DBG_MAGIC_BYTES, 0);
br_align(br); br_align(br);
u64 num_bits = num_bytes << 3; u64 num_bits = num_bytes << 3;

View File

@ -33,7 +33,7 @@
#define SPACE_CELL_BUCKETS_SQRT (256) #define SPACE_CELL_BUCKETS_SQRT (256)
#define SPACE_CELL_SIZE 1.0f #define SPACE_CELL_SIZE 1.0f
#define SIM_TICKS_PER_SECOND 50 #define SIM_TICKS_PER_SECOND 100
#define SIM_TIMESCALE 1 #define SIM_TIMESCALE 1
#define SIM_PHYSICS_SUBSTEPS 4 #define SIM_PHYSICS_SUBSTEPS 4
@ -45,10 +45,8 @@
#define SIM_SPAWN_TESTENT 0 #define SIM_SPAWN_TESTENT 0
#define SIM_PLAYER_AIM 1 #define SIM_PLAYER_AIM 1
//#define SIM_MAX_LINEAR_VELOCITY 500 #define SIM_MAX_LINEAR_VELOCITY 500
//#define SIM_MAX_ANGULAR_VELOCITY (TAU * 20) #define SIM_MAX_ANGULAR_VELOCITY (TAU * 20)
#define SIM_MAX_LINEAR_VELOCITY F32_INFINITY
#define SIM_MAX_ANGULAR_VELOCITY F32_INFINITY
/* How many ticks back in time should the user blend between? /* How many ticks back in time should the user blend between?
* <Delay ms> = <USER_INTERP_RATIO> * <Tick interval> * <Delay ms> = <USER_INTERP_RATIO> * <Tick interval>
@ -62,7 +60,7 @@
#define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 0 #define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 0
/* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */ /* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */
#define BITBUFF_DEBUG RTC #define BITBUFF_DEBUG 0
#define BITBUFF_TEST RTC #define BITBUFF_TEST RTC
/* ========================== * /* ========================== *

View File

@ -128,7 +128,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
if (!sim_ent_is_valid_and_active(constraint_ent)) { if (!sim_ent_is_valid_and_active(constraint_ent)) {
/* Create constraint */ /* Create constraint */
{ {
constraint_ent = sim_ent_alloc_net_src(root); constraint_ent = sim_ent_alloc_local(root);
constraint_ent->contact_constraint_data.e1 = e1->handle; constraint_ent->contact_constraint_data.e1 = e1->handle;
constraint_ent->contact_constraint_data.e0 = e0->handle; constraint_ent->contact_constraint_data.e0 = e0->handle;
constraint_ent->contact_constraint_data.skip_solve = sim_ent_has_prop(e0, SIM_ENT_PROP_SENSOR) || sim_ent_has_prop(e1, SIM_ENT_PROP_SENSOR) constraint_ent->contact_constraint_data.skip_solve = sim_ent_has_prop(e0, SIM_ENT_PROP_SENSOR) || sim_ent_has_prop(e1, SIM_ENT_PROP_SENSOR)
@ -245,7 +245,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
if (!dbg_ent->valid) { if (!dbg_ent->valid) {
/* FIXME: Entity never released */ /* FIXME: Entity never released */
dbg_ent = sim_ent_alloc_net_src(root); dbg_ent = sim_ent_alloc_local(root);
sim_ent_enable_prop(dbg_ent, SIM_ENT_PROP_COLLISION_DEBUG); sim_ent_enable_prop(dbg_ent, SIM_ENT_PROP_COLLISION_DEBUG);
sim_lookup_set(debug_lookup, key, dbg_ent->handle); sim_lookup_set(debug_lookup, key, dbg_ent->handle);
} }

View File

@ -284,8 +284,8 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
arena = ss->arena; arena = ss->arena;
} else { } else {
/* Arenas allocated here will be released with client */ /* Arenas allocated here will be released with client */
arena = arena_alloc(GIGABYTE(8)); arena = arena_alloc(GIGABYTE(1));
ents_arena = arena_alloc(GIGABYTE(8)); ents_arena = arena_alloc(GIGABYTE(1));
} }
} }
arena_reset(&arena); arena_reset(&arena);
@ -311,9 +311,13 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
/* Copy netid lookup buckets */ /* Copy netid lookup buckets */
ss->num_netid_buckets = src->num_netid_buckets > 0 ? src->num_netid_buckets : NETID_LOOKUP_BUCKETS; ss->num_netid_buckets = src->num_netid_buckets > 0 ? src->num_netid_buckets : NETID_LOOKUP_BUCKETS;
ss->netid_buckets = arena_push_array(&ss->arena, struct sim_ent_bucket, ss->num_netid_buckets); ss->netid_buckets = arena_push_array(&ss->arena, struct sim_ent_bucket, ss->num_netid_buckets);
if (src->num_netid_buckets > 0) {
for (u64 i = 0; i < src->num_netid_buckets; ++i) { for (u64 i = 0; i < src->num_netid_buckets; ++i) {
ss->netid_buckets[i] = src->netid_buckets[i]; ss->netid_buckets[i] = src->netid_buckets[i];
} }
} else {
MEMZERO(ss->netid_buckets, sizeof(*ss->netid_buckets) * ss->num_netid_buckets);
}
/* Copy entities */ /* Copy entities */
ss->first_free_ent = src->first_free_ent; ss->first_free_ent = src->first_free_ent;
@ -500,6 +504,23 @@ struct sim_snapshot *sim_snapshot_from_closest_tick_lte(struct sim_client *clien
return ss; return ss;
} }
/* Returns the snapshot at nearest valid tick >= supplied tick */
struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *client, u64 tick)
{
struct sim_snapshot *ss = sim_snapshot_from_tick(client, tick);
if (!ss->valid) {
/* Degenerate to linear search */
ss = sim_snapshot_from_tick(client, client->first_tick);
while (ss->valid) {
if (ss->tick >= tick) {
break;
}
ss = sim_snapshot_from_tick(client, ss->next_tick);
}
}
return ss;
}
/* ========================== * /* ========================== *
* Snapshot lerp * Snapshot lerp
* ========================== */ * ========================== */
@ -555,7 +576,7 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, str
* Snapshot encode * Snapshot encode
* ========================== */ * ========================== */
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_ent *receiver_client, struct sim_snapshot *ss0, struct sim_snapshot *ss1) void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1)
{ {
__prof; __prof;
@ -565,7 +586,7 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_ent *receiver_cli
bw_write_uv(bw, ss1->continuity_gen); bw_write_uv(bw, ss1->continuity_gen);
bw_write_uv(bw, ss1->phys_iteration); bw_write_uv(bw, ss1->phys_iteration);
bw_write_u128(bw, sim_ent_get_netid(receiver_client).v); bw_write_u128(bw, receiver->client_ent_netid.v);
/* Ents */ /* Ents */
if (ss1->num_ents_allocated == ss0->num_ents_allocated) { if (ss1->num_ents_allocated == ss0->num_ents_allocated) {

View File

@ -79,17 +79,20 @@ struct sim_client {
struct sim_client_handle next_in_bucket; struct sim_client_handle next_in_bucket;
struct sim_client_handle prev_in_bucket; struct sim_client_handle prev_in_bucket;
/* The client entity's net id in the master sim (if one is present) */ /* The client entity's net id in the master sim (if relevant) */
struct sim_netid client_ent_netid; struct sim_netid client_ent_netid;
/* This is the last confirmed tick of ours that we know this client has received */ /* This is the highest confirmed tick of ours that we know this client has received */
u64 ack; u64 ack;
/* This is the last confirmed ack of ours that we know this client has received (this /* This is the highest confirmed ack of ours that we know this client has received (this
* can be used to determine which client ticks will no longer be delta encoded from and * can be used to determine which client ticks will no longer be delta encoded from and
* can therefore be released) */ * can therefore be released) */
u64 double_ack; u64 double_ack;
/* This is the highest tick of their's that we have received */
u64 highest_received_tick;
/* Snapshots sorted by tick (low to high) */ /* Snapshots sorted by tick (low to high) */
u64 first_tick; u64 first_tick;
u64 last_tick; u64 last_tick;
@ -199,12 +202,13 @@ void sim_snapshot_release_ticks_in_range(struct sim_client *client, u64 start, u
/* Lookup */ /* Lookup */
struct sim_snapshot *sim_snapshot_from_tick(struct sim_client *client, u64 tick); struct sim_snapshot *sim_snapshot_from_tick(struct sim_client *client, u64 tick);
struct sim_snapshot *sim_snapshot_from_closest_tick_lte(struct sim_client *client, u64 tick); struct sim_snapshot *sim_snapshot_from_closest_tick_lte(struct sim_client *client, u64 tick);
struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *client, u64 tick);
/* Lerp */ /* Lerp */
struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend); struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend);
/* Encode / decode */ /* Encode / decode */
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_ent *receiver_client, struct sim_snapshot *ss0, struct sim_snapshot *ss1); void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1);
void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss); void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss);
/* ========================== * /* ========================== *

View File

@ -108,7 +108,8 @@ void sim_ent_release(struct sim_ent *ent)
INLINE u64 hash_from_netid(struct sim_netid netid) INLINE u64 hash_from_netid(struct sim_netid netid)
{ {
return hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&netid)); /* Just use lower 64 bits of netid since it's already randomnized */
return U128_LO(netid.v);
} }
struct sim_netid sim_ent_get_netid(struct sim_ent *ent) struct sim_netid sim_ent_get_netid(struct sim_ent *ent)
@ -174,7 +175,7 @@ struct sim_ent *sim_ent_from_netid(struct sim_snapshot *ss, struct sim_netid net
{ {
struct sim_ent *res = sim_ent_nil(); struct sim_ent *res = sim_ent_nil();
u64 num_buckets = ss->num_netid_buckets; u64 num_buckets = ss->num_netid_buckets;
if (num_buckets > 0) { if (num_buckets > 0 && !sim_netid_eq(netid, SIM_NETID_NIL)) {
u64 hash = hash_from_netid(netid); u64 hash = hash_from_netid(netid);
struct sim_ent_bucket *bucket = &ss->netid_buckets[hash % num_buckets]; struct sim_ent_bucket *bucket = &ss->netid_buckets[hash % num_buckets];
for (struct sim_ent *e = sim_ent_from_handle(ss, bucket->first); e->valid; e = sim_ent_from_handle(ss, e->next_in_netid_bucket)) { for (struct sim_ent *e = sim_ent_from_handle(ss, bucket->first); e->valid; e = sim_ent_from_handle(ss, e->next_in_netid_bucket)) {
@ -540,7 +541,7 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e)
} }
struct sim_netid new_netid = sim_ent_get_netid(e); struct sim_netid new_netid = sim_ent_get_netid(e);
e->_netid = old_netid;
if (!sim_netid_eq(old_netid, new_netid)) { if (!sim_netid_eq(old_netid, new_netid)) {
sim_ent_set_netid(e, new_netid); sim_ent_set_netid(e, new_netid);
} }

View File

@ -132,6 +132,7 @@ struct sim_ent {
struct sim_ent_handle cmd_client; struct sim_ent_handle cmd_client;
struct sim_control cmd_control; struct sim_control cmd_control;
struct sim_netid cmd_hovered_ent_netid;
/* ====================================================================== */ /* ====================================================================== */
/* Client */ /* Client */
@ -145,6 +146,7 @@ struct sim_ent {
struct sim_control client_control; struct sim_control client_control;
struct v2 client_cursor_pos; struct v2 client_cursor_pos;
struct sim_ent_handle client_hovered_ent;
struct sim_ent_handle client_control_ent; struct sim_ent_handle client_control_ent;
struct sim_ent_handle client_camera_ent; struct sim_ent_handle client_camera_ent;

View File

@ -124,16 +124,6 @@ void sim_lookup_remove(struct sim_lookup *l, struct sim_lookup_entry *entry)
l->first_free_entry = entry; l->first_free_entry = entry;
} }
struct sim_lookup_key sim_lookup_key_from_client_and_ent_handles(struct sim_client_handle client_handle, struct sim_ent_handle ent_handle)
{
struct sim_lookup_key key = ZI;
struct string b0 = STRING_FROM_STRUCT(&client_handle);
struct string b1 = STRING_FROM_STRUCT(&ent_handle);
key.hash = hash_fnv64(HASH_FNV64_BASIS, b0);
key.hash = hash_fnv64(key.hash, b1);
return key;
}
struct sim_lookup_key sim_lookup_key_from_two_handles(struct sim_ent_handle h0, struct sim_ent_handle h1) struct sim_lookup_key sim_lookup_key_from_two_handles(struct sim_ent_handle h0, struct sim_ent_handle h1)
{ {
struct sim_lookup_key key = ZI; struct sim_lookup_key key = ZI;
@ -144,13 +134,6 @@ struct sim_lookup_key sim_lookup_key_from_two_handles(struct sim_ent_handle h0,
return key; return key;
} }
struct sim_lookup_key sim_lookup_key_from_client_handle(struct sim_client_handle handle)
{
struct sim_lookup_key key = ZI;
key.hash = hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&handle));
return key;
}
/* ========================== * /* ========================== *
* Sim accel * Sim accel
* ========================== */ * ========================== */
@ -159,7 +142,6 @@ struct sim_accel sim_accel_alloc(void)
{ {
struct sim_accel accel = ZI; struct sim_accel accel = ZI;
accel.space = space_alloc(1, 256); accel.space = space_alloc(1, 256);
accel.client_lookup = sim_lookup_alloc(4096);
accel.contact_lookup = sim_lookup_alloc(4096); accel.contact_lookup = sim_lookup_alloc(4096);
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
accel.collision_debug_lookup = sim_lookup_alloc(4096); accel.collision_debug_lookup = sim_lookup_alloc(4096);
@ -173,7 +155,6 @@ void sim_accel_release(struct sim_accel *accel)
sim_lookup_release(&accel->collision_debug_lookup); sim_lookup_release(&accel->collision_debug_lookup);
#endif #endif
sim_lookup_release(&accel->contact_lookup); sim_lookup_release(&accel->contact_lookup);
sim_lookup_release(&accel->client_lookup);
space_release(accel->space); space_release(accel->space);
} }
@ -182,7 +163,6 @@ void sim_accel_rebuild(struct sim_snapshot *ss, struct sim_accel *accel)
/* FIXME: Rebuild collision debug lookup */ /* FIXME: Rebuild collision debug lookup */
space_reset(accel->space); space_reset(accel->space);
sim_lookup_reset(&accel->client_lookup);
sim_lookup_reset(&accel->contact_lookup); sim_lookup_reset(&accel->contact_lookup);
/* Reset ent space handles */ /* Reset ent space handles */
@ -198,10 +178,6 @@ void sim_accel_rebuild(struct sim_snapshot *ss, struct sim_accel *accel)
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { 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]; struct sim_ent *ent = &ss->ents[sim_ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_is_valid_and_active(ent)) continue;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CLIENT)) {
struct sim_lookup_key key = sim_lookup_key_from_client_handle(ent->client_handle);
sim_lookup_set(&accel->client_lookup, key, ent->handle);
}
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) { if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) {
struct sim_lookup_key contact_lookup_key = sim_lookup_key_from_two_handles(ent->contact_constraint_data.e0, ent->contact_constraint_data.e1); struct sim_lookup_key contact_lookup_key = sim_lookup_key_from_two_handles(ent->contact_constraint_data.e0, ent->contact_constraint_data.e1);
sim_lookup_set(&accel->contact_lookup, contact_lookup_key, ent->handle); sim_lookup_set(&accel->contact_lookup, contact_lookup_key, ent->handle);
@ -223,7 +199,8 @@ INTERNAL void spawn_test_entities(struct sim_snapshot *world, struct v2 offset)
/* Enemy */ /* Enemy */
{ {
struct sim_ent *e = sim_ent_alloc_net_src(root); //struct sim_ent *e = sim_ent_alloc_net_src(root);
struct sim_ent *e = sim_ent_alloc_local(root);
struct v2 pos = V2(1, -2); struct v2 pos = V2(1, -2);
pos = v2_add(pos, offset); pos = v2_add(pos, offset);
@ -689,6 +666,9 @@ void sim_step(struct sim_step_ctx *ctx)
} }
} }
/* Dereference hovered ent */
client_ent->client_hovered_ent = sim_ent_from_netid(world, cmd_ent->cmd_hovered_ent_netid)->handle;
u32 flags = control->flags; u32 flags = control->flags;
if (flags & SIM_CONTROL_FLAG_DRAG) { if (flags & SIM_CONTROL_FLAG_DRAG) {
if (!(old_control.flags & SIM_CONTROL_FLAG_DRAG)) { if (!(old_control.flags & SIM_CONTROL_FLAG_DRAG)) {
@ -1192,6 +1172,7 @@ void sim_step(struct sim_step_ctx *ctx)
struct sim_ent *target_ent = sim_ent_from_handle(world, joint_ent->mouse_joint_data.target); struct sim_ent *target_ent = sim_ent_from_handle(world, joint_ent->mouse_joint_data.target);
if (start_dragging) { if (start_dragging) {
#if 0
struct xform mouse_xf = xform_from_pos(cursor); struct xform mouse_xf = xform_from_pos(cursor);
struct collider_shape mouse_shape = ZI; struct collider_shape mouse_shape = ZI;
mouse_shape.points[0] = V2(0, 0); mouse_shape.points[0] = V2(0, 0);
@ -1213,7 +1194,11 @@ void sim_step(struct sim_step_ctx *ctx)
} }
} }
} }
#else
target_ent = sim_ent_from_handle(world, client_ent->client_hovered_ent);
#endif
} }
if (stop_dragging) { if (stop_dragging) {
target_ent = sim_ent_nil(); target_ent = sim_ent_nil();
} }

View File

@ -45,9 +45,7 @@ void sim_lookup_set(struct sim_lookup *l, struct sim_lookup_key key, struct sim_
void sim_lookup_remove(struct sim_lookup *l, struct sim_lookup_entry *entry); void sim_lookup_remove(struct sim_lookup *l, struct sim_lookup_entry *entry);
struct sim_lookup_key sim_lookup_key_from_client_and_ent_handles(struct sim_client_handle client_handle, struct sim_ent_handle ent_handle);
struct sim_lookup_key sim_lookup_key_from_two_handles(struct sim_ent_handle h0, struct sim_ent_handle h1); struct sim_lookup_key sim_lookup_key_from_two_handles(struct sim_ent_handle h0, struct sim_ent_handle h1);
struct sim_lookup_key sim_lookup_key_from_client_handle(struct sim_client_handle handle);
/* ========================== * /* ========================== *
* Sim accel * Sim accel
@ -58,7 +56,6 @@ struct sim_lookup_key sim_lookup_key_from_client_handle(struct sim_client_handle
struct sim_accel { struct sim_accel {
struct space *space; struct space *space;
struct sim_lookup client_lookup;
struct sim_lookup contact_lookup; struct sim_lookup contact_lookup;
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
struct sim_lookup collision_debug_lookup; struct sim_lookup collision_debug_lookup;

View File

@ -36,7 +36,7 @@ struct string string_from_char(struct arena *arena, char c)
}; };
} }
struct string string_from_uint(struct arena *arena, u64 n, u32 base) struct string string_from_uint(struct arena *arena, u64 n, u64 base, u64 zfill)
{ {
/* Base too large */ /* Base too large */
ASSERT(base <= (ARRAY_COUNT(INT_CHARS) - 1)); ASSERT(base <= (ARRAY_COUNT(INT_CHARS) - 1));
@ -52,6 +52,11 @@ struct string string_from_uint(struct arena *arena, u64 n, u32 base)
n /= base; n /= base;
} while (n > 0); } while (n > 0);
while (len < zfill) {
string_from_char(scratch.arena, '0');
++len;
}
/* Reverse text into final string */ /* Reverse text into final string */
u8 *final_text = arena_push_array(arena, u8, len); u8 *final_text = arena_push_array(arena, u8, len);
for (u64 i = 0; i < len; ++i) { for (u64 i = 0; i < len; ++i) {
@ -66,7 +71,7 @@ struct string string_from_uint(struct arena *arena, u64 n, u32 base)
}; };
} }
struct string string_from_int(struct arena *arena, i64 n, u32 base) struct string string_from_int(struct arena *arena, i64 n, u64 base, u64 zfill)
{ {
u8 *final_text = arena_dry_push(arena, u8); u8 *final_text = arena_dry_push(arena, u8);
u8 len = 0; u8 len = 0;
@ -77,7 +82,7 @@ struct string string_from_int(struct arena *arena, i64 n, u32 base)
n = -n; n = -n;
} }
/* Push unsigned number */ /* Push unsigned number */
struct string uint_str = string_from_uint(arena, n, base); struct string uint_str = string_from_uint(arena, n, base, zfill);
return (struct string) { return (struct string) {
.len = len + uint_str.len, .len = len + uint_str.len,
.text = final_text .text = final_text
@ -87,7 +92,7 @@ struct string string_from_int(struct arena *arena, i64 n, u32 base)
struct string string_from_ptr(struct arena *arena, void *ptr) struct string string_from_ptr(struct arena *arena, void *ptr)
{ {
struct string prepend = string_copy(arena, LIT("0x")); struct string prepend = string_copy(arena, LIT("0x"));
struct string uint_str = string_from_uint(arena, (u64)ptr, 16); struct string uint_str = string_from_uint(arena, (u64)ptr, 16, sizeof(ptr));
return (struct string) { return (struct string) {
.len = prepend.len + uint_str.len, .len = prepend.len + uint_str.len,
.text = prepend.text .text = prepend.text
@ -164,9 +169,9 @@ struct string string_from_handle(struct arena *arena, u64 v0, u64 v1)
struct string res = ZI; struct string res = ZI;
res.text = arena_dry_push(arena, u8); res.text = arena_dry_push(arena, u8);
res.len += string_copy(arena, LIT("h")).len; res.len += string_copy(arena, LIT("h")).len;
res.len += string_from_uint(arena, v0, 16).len; res.len += string_from_uint(arena, v0, 16, 0).len;
res.len += string_copy(arena, LIT("x")).len; res.len += string_copy(arena, LIT("x")).len;
res.len += string_from_uint(arena, v1, 16).len; res.len += string_from_uint(arena, v1, 16, 0).len;
return res; return res;
} }
@ -458,15 +463,15 @@ struct string string_formatv(struct arena *arena, struct string fmt, va_list arg
} break; } break;
case FMT_TYPE_UINT: { case FMT_TYPE_UINT: {
parsed_str = string_from_uint(arena, arg.value.uint, 10); parsed_str = string_from_uint(arena, arg.value.uint, 10, 0);
} break; } break;
case FMT_TYPE_SINT: { case FMT_TYPE_SINT: {
parsed_str = string_from_int(arena, arg.value.sint, 10); parsed_str = string_from_int(arena, arg.value.sint, 10, 0);
} break; } break;
case FMT_TYPE_HEX: { case FMT_TYPE_HEX: {
parsed_str = string_from_uint(arena, arg.value.sint, 16); parsed_str = string_from_uint(arena, arg.value.sint, 16, 0);
} break; } break;
case FMT_TYPE_PTR: { case FMT_TYPE_PTR: {

View File

@ -11,8 +11,8 @@ struct string_array {
* ========================== */ * ========================== */
struct string string_from_char(struct arena *arena, char c); struct string string_from_char(struct arena *arena, char c);
struct string string_from_uint(struct arena *arena, u64 n, u32 base); struct string string_from_uint(struct arena *arena, u64 n, u64 base, u64 zfill);
struct string string_from_int(struct arena *arena, i64 n, u32 base); struct string string_from_int(struct arena *arena, i64 n, u64 base, u64 zfill);
struct string string_from_ptr(struct arena *arena, void *ptr); struct string string_from_ptr(struct arena *arena, void *ptr);
struct string string_from_float(struct arena *arena, f64 f, u32 precision); struct string string_from_float(struct arena *arena, f64 f, u32 precision);
struct string string_from_handle(struct arena *arena, u64 v0, u64 v1); struct string string_from_handle(struct arena *arena, u64 v0, u64 v1);

View File

@ -86,6 +86,7 @@ GLOBAL struct {
/* User -> local sim */ /* User -> local sim */
struct sys_mutex user_sim_cmd_mutex; struct sys_mutex user_sim_cmd_mutex;
struct sim_control user_sim_cmd_control; struct sim_control user_sim_cmd_control;
struct sim_netid user_sim_cmd_hovered_ent_netid;
u64 last_user_sim_cmd_gen; u64 last_user_sim_cmd_gen;
u64 user_sim_cmd_gen; u64 user_sim_cmd_gen;
@ -347,6 +348,31 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
struct string res = ZI; struct string res = ZI;
res.text = arena_dry_push(arena, u8); res.text = arena_dry_push(arena, u8);
{
res.len += string_copy(arena, LIT("net: ")).len;
struct sim_netid netid = sim_ent_get_netid(ent);
if (!sim_netid_eq(netid, SIM_NETID_NIL)) {
res.len += string_copy(arena, LIT(" [")).len;
res.len += string_from_uint(arena, (U128_HI(netid.v) >> 36) & 0xFFFFFFF, 16, 7).len;
res.len += string_copy(arena, LIT("]")).len;
}
b32 transmitting = sim_ent_has_prop(ent, SIM_ENT_PROP_NET_SRC);
b32 receiving = sim_ent_has_prop(ent, SIM_ENT_PROP_NET_DST);
if (transmitting & receiving) {
res.len += string_copy(arena, LIT(" recv & send")).len;
} else if (transmitting) {
res.len += string_copy(arena, LIT(" send")).len;
} else if (receiving) {
res.len += string_copy(arena, LIT(" recv")).len;
} else {
res.len += string_copy(arena, LIT(" local")).len;
}
res.len += string_copy(arena, LIT("\n")).len;
}
{ {
res.len += string_copy(arena, LIT("props: 0x")).len; res.len += string_copy(arena, LIT("props: 0x")).len;
for (u64 chunk_index = ARRAY_COUNT(ent->props); chunk_index-- > 0;) { for (u64 chunk_index = ARRAY_COUNT(ent->props); chunk_index-- > 0;) {
@ -363,18 +389,6 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
res.len += string_copy(arena, LIT("\n")).len; res.len += string_copy(arena, LIT("\n")).len;
} }
{
struct sim_netid netid = sim_ent_get_netid(ent);
if (!sim_netid_eq(netid, SIM_NETID_NIL)) {
res.len += string_copy(arena, LIT("net id: 0x")).len;
u64 hi = U128_HI(netid.v);
u64 lo = U128_LO(netid.v);
res.len += string_from_uint(arena, hi, 16).len;
res.len += string_from_uint(arena, lo, 16).len;
res.len += string_copy(arena, LIT("\n")).len;
}
}
if (!sim_ent_handle_eq(ent->parent, SIM_ENT_ROOT_HANDLE)) { if (!sim_ent_handle_eq(ent->parent, SIM_ENT_ROOT_HANDLE)) {
res.len += string_format(arena, LIT("parent: <%F>\n"), FMT_HANDLE(ent->parent)).len; res.len += string_format(arena, LIT("parent: <%F>\n"), FMT_HANDLE(ent->parent)).len;
} }
@ -608,7 +622,6 @@ INTERNAL void user_update(void)
for (u64 ent_index = 0; ent_index < events.count; ++ent_index) { for (u64 ent_index = 0; ent_index < events.count; ++ent_index) {
struct sys_event *event = &events.events[ent_index]; struct sys_event *event = &events.events[ent_index];
if (event->kind == SYS_EVENT_KIND_QUIT) { if (event->kind == SYS_EVENT_KIND_QUIT) {
app_exit(); app_exit();
} }
@ -1517,6 +1530,7 @@ INTERNAL void user_update(void)
u32 old_flags = G.user_sim_cmd_control.flags; u32 old_flags = G.user_sim_cmd_control.flags;
G.user_sim_cmd_control = control; G.user_sim_cmd_control = control;
G.user_sim_cmd_control.flags |= old_flags; G.user_sim_cmd_control.flags |= old_flags;
G.user_sim_cmd_hovered_ent_netid = sim_ent_get_netid(hovered_ent);
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
} }
} }
@ -1850,6 +1864,7 @@ INTERNAL void sim_ent_sync_remote(struct sim_ent *local, struct sim_ent *remote)
local->ss = old.ss; local->ss = old.ss;
local->handle = old.handle; local->handle = old.handle;
local->net_src_client = remote_client_handle; local->net_src_client = remote_client_handle;
local->_netid = old._netid;
local->parent = old.parent; local->parent = old.parent;
local->prev = old.prev; local->prev = old.prev;
local->next = old.next; local->next = old.next;
@ -1863,6 +1878,7 @@ INTERNAL void sim_ent_sync_remote(struct sim_ent *local, struct sim_ent *remote)
/* Translate remote handles */ /* Translate remote handles */
translate(client_control_ent); translate(client_control_ent);
translate(client_camera_ent); translate(client_camera_ent);
translate(client_hovered_ent);
translate(client_dbg_drag_joint_ent); translate(client_dbg_drag_joint_ent);
translate(controlling_client); translate(controlling_client);
translate(move_joint); translate(move_joint);
@ -1940,7 +1956,18 @@ INTERNAL void sim_snapshot_sync_remote_ents(struct sim_snapshot *local_ss, struc
struct sim_decode_node {
struct sim_client *client;
u64 tick;
u64 base_tick;
struct string tmp_encoded;
struct sim_decode_node *next;
};
struct sim_decode_queue {
struct sim_decode_node *first;
struct sim_decode_node *last;
};
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
@ -1973,7 +2000,9 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
struct sim_client *user_input_client = sim_client_alloc(store); /* Stores snapshots containing commands to be published to both local & master clients */ struct sim_client *user_input_client = sim_client_alloc(store); /* Stores snapshots containing commands to be published to both local & master clients */
struct sim_client *local_client = sim_client_alloc(store); /* Stores snapshots produced locally */ struct sim_client *local_client = sim_client_alloc(store); /* Stores snapshots produced locally */
struct sim_client *publish_client = sim_client_alloc(store); /* Stores versions of local snapshots that will be published to remote sims */ struct sim_client *publish_client = sim_client_alloc(store); /* Stores versions of local snapshots that will be published to remote sims */
struct sim_client *master_client = sim_client_nil(); /* Stores snapshots received from master (if relevant) */ struct sim_client *master_client = sim_client_nil(); /* Stores snapshots received from master (if relevant) */
b32 initialized_from_master = false;
u64 step_tick = 0; u64 step_tick = 0;
i64 last_publish_ns = 0; i64 last_publish_ns = 0;
@ -1991,6 +2020,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
++step_tick; ++step_tick;
/* Read net messages */ /* Read net messages */
struct sim_decode_queue queue = ZI;
{ {
host_update(host); host_update(host);
struct host_event_array host_events = host_pop_events(scratch.arena, host); struct host_event_array host_events = host_pop_events(scratch.arena, host);
@ -2037,18 +2067,46 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
struct bitbuff_reader decoder_br = br_from_bitbuff(&decoder_bb); struct bitbuff_reader decoder_br = br_from_bitbuff(&decoder_bb);
u64 base_tick = br_read_uv(&decoder_br); u64 base_tick = br_read_uv(&decoder_br);
u64 tick = br_read_uv(&decoder_br); u64 tick = br_read_uv(&decoder_br);
if (tick > client->last_tick) {
struct string tmp_encoded = ZI;
tmp_encoded.len = br_num_bytes_left(&decoder_br);
tmp_encoded.text = br_read_bytes_raw(&decoder_br, tmp_encoded.len);
if (!tmp_encoded.text) tmp_encoded.len = 0;
struct sim_snapshot *base_ss = sim_snapshot_from_tick(client, base_tick); struct sim_snapshot *base_ss = sim_snapshot_from_tick(client, base_tick);
if (base_ss->tick == base_tick) { if (base_ss->tick == base_tick) {
if (client == master_client || (tick == client->last_tick + 1 || tick > client->last_tick + 100)) { if (is_master) {
/* Alloc & decode snapshot */ /* Decode incoming slave client snapshots */
struct sim_snapshot *ss = sim_snapshot_alloc(client, base_ss, tick); b32 should_decode = tick == client->highest_received_tick + 1 || client->highest_received_tick == 0;
sim_snapshot_decode(&decoder_br, ss); if (should_decode) {
for (u64 i = 0; i < ss->num_ents_reserved; ++i) { struct sim_decode_node *node = arena_push_zero(scratch.arena, struct sim_decode_node);
struct sim_ent *ent = &ss->ents[i]; node->client = client;
if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_NET_DST)) { node->tick = tick;
sim_ent_disable_prop(ent, SIM_ENT_PROP_NET_DST); node->base_tick = base_tick;
sim_ent_enable_prop(ent, SIM_ENT_PROP_NET_SRC); node->tmp_encoded = tmp_encoded;
if (queue.last) {
queue.last->next = node;
} else {
queue.first = node;
}
queue.last = node;
if (tick > client->highest_received_tick) {
client->highest_received_tick = tick;
}
}
} else {
/* Decode incoming master client snapshots (only the newest one) */
b32 should_decode = tick > client->highest_received_tick;
if (should_decode) {
struct sim_decode_node *node = queue.first ? queue.first : arena_push_zero(scratch.arena, struct sim_decode_node);
node->client = client;
node->tick = tick;
node->base_tick = base_tick;
node->tmp_encoded = tmp_encoded;
queue.first = node;
queue.last = node;
if (tick > client->highest_received_tick) {
client->highest_received_tick = tick;
} }
} }
} }
@ -2056,7 +2114,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* We do not have the tick that the incoming delta is based from */ /* We do not have the tick that the incoming delta is based from */
ASSERT(false); ASSERT(false);
} }
}
tmp_encoded_len = br_read_uv(&msg_br); tmp_encoded_len = br_read_uv(&msg_br);
} }
} }
@ -2067,16 +2125,47 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
} }
} }
if (master_client->valid) { /* Decode incoming snapshots */
if (master_client->last_tick > step_tick && (master_client->last_tick - step_tick) > 50) { for (struct sim_decode_node *n = queue.first; n; n = n->next) {
struct sim_client *client = n->client;
u64 base_tick = n->base_tick;
u64 tick = n->tick;
struct sim_snapshot *base_ss = sim_snapshot_from_tick(client, base_tick);
if (base_ss->tick == base_tick) {
struct bitbuff bb = bitbuff_from_string(n->tmp_encoded);
struct bitbuff_reader br = br_from_bitbuff(&bb);
/* Alloc & decode snapshot */
struct sim_snapshot *ss = sim_snapshot_alloc(client, base_ss, tick);
sim_snapshot_decode(&br, ss);
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_NET_DST)) {
sim_ent_disable_prop(ent, SIM_ENT_PROP_NET_DST);
sim_ent_enable_prop(ent, SIM_ENT_PROP_NET_SRC);
}
}
} else {
/* We do not have the tick that the incoming delta is based from.
* This decode should never have been queued in the first place. */
ASSERT(false);
}
}
if (!is_master && !initialized_from_master) {
if (master_client->valid && master_client->last_tick > 0) {
step_tick = master_client->last_tick; step_tick = master_client->last_tick;
initialized_from_master = true;
} else {
step_tick = 0;
goto skip_step;
} }
} }
/* Create user input */ /* 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 *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, step_tick + 50); struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, step_tick);;
struct sim_ent *user_input_root = sim_ent_from_handle(user_input_ss, SIM_ENT_ROOT_HANDLE); struct sim_ent *user_input_root = sim_ent_from_handle(user_input_ss, SIM_ENT_ROOT_HANDLE);
/* Find / create local control cmd ent */ /* 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); struct sim_ent *control_cmd_ent = sim_ent_find_first_match_one(user_input_ss, SIM_ENT_PROP_CMD_CONTROL);
@ -2089,6 +2178,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
{ {
struct sys_lock lock = sys_mutex_lock_e(&G.user_sim_cmd_mutex); struct sys_lock lock = sys_mutex_lock_e(&G.user_sim_cmd_mutex);
control_cmd_ent->cmd_control = G.user_sim_cmd_control; control_cmd_ent->cmd_control = G.user_sim_cmd_control;
control_cmd_ent->cmd_hovered_ent_netid = G.user_sim_cmd_hovered_ent_netid;
++G.user_sim_cmd_gen; ++G.user_sim_cmd_gen;
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
} }
@ -2109,16 +2199,14 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
if (client->valid) { if (client->valid) {
/* Create client ent if necessary */ /* Create client ent if necessary */
if (is_master && client != publish_client && client != local_client && client != master_client) { if (is_master && client != publish_client && client != local_client && client != master_client) {
struct sim_lookup_key key = sim_lookup_key_from_client_handle(client->handle); struct sim_ent *client_ent = sim_ent_from_netid(local_ss, client->client_ent_netid);
struct sim_lookup_entry *client_entry = sim_lookup_get(&accel.client_lookup, key);
struct sim_ent *client_ent = client_entry ? sim_ent_from_handle(local_ss, client_entry->ent) : sim_ent_nil();
if (!client_ent->valid) { if (!client_ent->valid) {
/* FIXME: Client ent never released upon disconnect */ /* FIXME: Client ent never released upon disconnect */
client_ent = sim_ent_alloc_net_src(local_root); client_ent = sim_ent_alloc_net_src(local_root);
client_ent->client_handle = client->handle; client_ent->client_handle = client->handle;
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_CLIENT); sim_ent_enable_prop(client_ent, SIM_ENT_PROP_CLIENT);
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_ACTIVE); sim_ent_enable_prop(client_ent, SIM_ENT_PROP_ACTIVE);
sim_lookup_set(&accel.client_lookup, key, client_ent->handle); client->client_ent_netid = sim_ent_get_netid(client_ent);
if (client == user_input_client) { if (client == user_input_client) {
local_ss->local_client_netid = sim_ent_get_netid(client_ent); local_ss->local_client_netid = sim_ent_get_netid(client_ent);
} }
@ -2140,36 +2228,65 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
} }
} }
/* Point incoming client cmds to correct client ents */
if (is_master) { if (is_master) {
/* Point incoming client cmds to correct client ents */
for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) { for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) {
struct sim_ent *ent = &local_ss->ents[i]; struct sim_ent *ent = &local_ss->ents[i];
if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_NET_DST)) { if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_NET_DST)) {
struct sim_ent *client_ent = sim_ent_nil(); struct sim_client *src_client = sim_client_from_handle(store, ent->net_src_client);
{ struct sim_ent *client_ent = sim_ent_from_netid(local_ss, src_client->client_ent_netid);
struct sim_client_handle src_client = ent->net_src_client;
struct sim_lookup_key key = sim_lookup_key_from_client_handle(src_client);
struct sim_lookup_entry *client_entry = sim_lookup_get(&accel.client_lookup, key);
client_ent = client_entry ? sim_ent_from_handle(local_ss, client_entry->ent) : sim_ent_nil();
}
ent->cmd_client = client_ent->handle; ent->cmd_client = client_ent->handle;
} }
} }
} else {
/* Mark all local commands as networked */
for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) {
struct sim_ent *ent = &local_ss->ents[i];
if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_CMD_CONTROL) && sim_ent_has_prop(ent, SIM_ENT_PROP_NET_DST)) {
sim_ent_enable_prop(ent, SIM_ENT_PROP_NET_SRC);
}
}
} }
/* Release unneeded snapshots */ /* Release unneeded received snapshots */
u64 oldest_client_ack = 0;
for (u64 i = 0; i < store->num_clients_reserved; ++i) { for (u64 i = 0; i < store->num_clients_reserved; ++i) {
struct sim_client *client = &store->clients[i]; struct sim_client *client = &store->clients[i];
if (client->valid) { if (client->valid && client != local_client && client != publish_client && client != user_input_client) {
u64 keep_count = 100; if (client->double_ack > 0) {
if (client->last_tick > keep_count) { u64 keep_tick = max_u64(min_u64(client->double_ack, step_tick), 1);
u64 keep_tick = client->last_tick - keep_count;
sim_snapshot_release_ticks_in_range(client, 0, keep_tick - 1); sim_snapshot_release_ticks_in_range(client, 0, keep_tick - 1);
} }
if (client->ack < oldest_client_ack || oldest_client_ack == 0) {
oldest_client_ack = client->ack;
}
}
}
/* Release unneeded published snapshots */
{
u64 keep_tick = oldest_client_ack;
if (keep_tick == 0 && publish_client->last_tick > 0) {
keep_tick = publish_client->last_tick - 1;
}
if (keep_tick > 0) {
--keep_tick;
}
sim_snapshot_release_ticks_in_range(publish_client, 0, keep_tick);
}
/* Release unneeded user input snapshots */
sim_snapshot_release_ticks_in_range(user_input_client, 0, step_tick - 1);
/* Release old local snapshots */
{
u64 keep_range = 100;
if (local_client->last_tick > keep_range) {
u64 keep_tick = local_client->last_tick - keep_range;
sim_snapshot_release_ticks_in_range(local_client, 0, keep_tick);
} }
} }
/* Release unneeded snapshots */
#if 0 #if 0
#if 0 #if 0
u64 oldest_client_ack = 0; u64 oldest_client_ack = 0;
@ -2245,7 +2362,12 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
} }
#else #else
{ {
struct sim_snapshot *pub_ss = sim_snapshot_alloc(publish_client, sim_snapshot_from_tick(publish_client, publish_client->last_tick), local_ss->tick); struct sim_snapshot *pub_ss;
if (is_master) {
pub_ss = sim_snapshot_alloc(publish_client, sim_snapshot_from_tick(publish_client, publish_client->last_tick), local_ss->tick);
} else {
pub_ss = sim_snapshot_alloc(publish_client, sim_snapshot_from_tick(publish_client, publish_client->last_tick), local_ss->tick + 5);
}
sim_snapshot_sync_remote_ents(pub_ss, local_ss); sim_snapshot_sync_remote_ents(pub_ss, local_ss);
} }
#endif #endif
@ -2273,23 +2395,16 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
for (u64 i = 0; i < store->num_clients_reserved; ++i) { for (u64 i = 0; i < store->num_clients_reserved; ++i) {
struct sim_client *client = &store->clients[i]; struct sim_client *client = &store->clients[i];
if (client->valid && client != user_input_client && client != local_client && client != publish_client) { if (client->valid && client != user_input_client && client != local_client && client != publish_client) {
struct sim_ent *client_ent = sim_ent_nil();
{
struct sim_lookup_key key = sim_lookup_key_from_client_handle(client->handle);
struct sim_lookup_entry *client_entry = sim_lookup_get(&accel.client_lookup, key);
client_ent = client_entry ? sim_ent_from_handle(local_ss, client_entry->ent) : sim_ent_nil();
}
struct bitbuff_writer msg_bw = bw_from_bitbuff(&msg_writer_bb); struct bitbuff_writer msg_bw = bw_from_bitbuff(&msg_writer_bb);
bw_write_uv(&msg_bw, client->last_tick); /* ack */ 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 *base_ss = sim_snapshot_from_tick(publish_client, client->ack);
struct sim_snapshot *publish_ss; struct sim_snapshot *publish_ss;
if (client == master_client) { if (client == master_client) {
/* If sending to master, start sending all snapshots since last ack */ /* If sending to master, start sending all snapshots since last ack */
publish_ss = sim_snapshot_from_tick(publish_client, base_ss->tick + 1); publish_ss = sim_snapshot_from_closest_tick_gte(publish_client, base_ss->tick + 1);
} else { } else {
/* If sending to slave, only send latest snapshot */ /* If sending to slave, only send latest snapshot */
publish_ss = sim_snapshot_from_tick(publish_client, publish_client->last_tick); publish_ss = sim_snapshot_from_tick(publish_client, publish_client->last_tick);
@ -2301,7 +2416,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
{ {
bw_write_uv(&snapshot_bw, base_ss->tick); bw_write_uv(&snapshot_bw, base_ss->tick);
bw_write_uv(&snapshot_bw, publish_ss->tick); bw_write_uv(&snapshot_bw, publish_ss->tick);
sim_snapshot_encode(&snapshot_bw, client_ent, base_ss, publish_ss); sim_snapshot_encode(&snapshot_bw, client, base_ss, publish_ss);
tmp_snapshot_encoded.len = bw_num_bytes_written(&snapshot_bw); tmp_snapshot_encoded.len = bw_num_bytes_written(&snapshot_bw);
tmp_snapshot_encoded.text = bw_get_written_raw(&snapshot_bw); tmp_snapshot_encoded.text = bw_get_written_raw(&snapshot_bw);
} }
@ -2332,6 +2447,8 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
} }
skip_step:
/* Send host messages */ /* Send host messages */
host_update(host); host_update(host);
__profframe("Local sim"); __profframe("Local sim");