encode sim id buckets for now

This commit is contained in:
jacob 2025-02-24 14:21:23 -06:00
parent 944be252c5
commit a8246541e9
6 changed files with 430 additions and 53 deletions

View File

@ -57,9 +57,11 @@
</Type> </Type>
<Type Name = "sim_ent"> <Type Name = "sim_ent">
<DisplayString Condition="(valid == 0 || (id.uid.hi == 0 &amp;&amp; id.uid.lo == 0)) &amp;&amp; this != *_g_sim_ent_nil">~~~MISMATCH~~~ {id}</DisplayString> <DisplayString Condition="(valid == 0 || (id.uid.hi == 0 &amp;&amp; id.uid.lo == 0)) &amp;&amp; this != *_g_sim_ent_nil">~~~MISMATCH~~~ {id} &lt;{this - this->ss->ents}&gt;</DisplayString>
<DisplayString Condition="valid == 1 &amp;&amp; (id.uid.hi == 0 || id.uid.lo == 0)">~~~MISMATCH~~~ {id}</DisplayString> <DisplayString Condition="valid == 1 &amp;&amp; (id.uid.hi == 0 || id.uid.lo == 0)">~~~MISMATCH~~~ {id} &lt;{this - this->ss->ents}&gt;</DisplayString>
<DisplayString>{id}</DisplayString> <DisplayString Condition="this == *_g_sim_ent_nil">{id}</DisplayString>
<DisplayString>{id} &lt;{this - this->ss->ents}&gt;</DisplayString>
</Type> </Type>
<Type Name = "String"> <Type Name = "String">

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 100 #define SIM_TICKS_PER_SECOND 50
#define SIM_TIMESCALE 1 #define SIM_TIMESCALE 1
#define SIM_PHYSICS_SUBSTEPS 4 #define SIM_PHYSICS_SUBSTEPS 4

310
src/sim.c
View File

@ -622,6 +622,20 @@ void sim_snapshot_sync(struct sim_snapshot *local_ss, struct sim_snapshot *remot
sim_ent_release_all_with_prop(local_ss, SIM_ENT_PROP_RELEASE); sim_ent_release_all_with_prop(local_ss, SIM_ENT_PROP_RELEASE);
} }
#if 1
/* ========================== * /* ========================== *
* Snapshot encode * Snapshot encode
* ========================== */ * ========================== */
@ -638,6 +652,38 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver,
bw_write_uid(bw, receiver->ent_id.uid); bw_write_uid(bw, receiver->ent_id.uid);
/* Id buckets */
/* TODO: Don't encode these */
for (u64 i = 0; i < ss1->num_id_buckets; ++i) {
u32 old_first = 0;
u32 old_last = 0;
if (i < ss0->num_id_buckets) {
struct sim_ent_bucket *old_bucket = &ss0->id_buckets[i];
old_first = old_bucket->first;
old_last = old_bucket->last;
}
struct sim_ent_bucket *bucket = &ss1->id_buckets[i];
u32 new_first = bucket->first;
u32 new_last = bucket->last;
if (new_first != old_first || new_last != old_last) {
bw_write_bit(bw, 1);
bw_write_uv(bw, i);
if (old_first == bucket->first) {
bw_write_bit(bw, 0);
} else {
bw_write_bit(bw, 1);
bw_write_uv(bw, bucket->first);
}
if (old_last == bucket->last) {
bw_write_bit(bw, 0);
} else {
bw_write_bit(bw, 1);
bw_write_uv(bw, bucket->last);
}
}
}
bw_write_bit(bw, 0);
/* Ents */ /* Ents */
if (ss1->num_ents_allocated == ss0->num_ents_allocated) { if (ss1->num_ents_allocated == ss0->num_ents_allocated) {
bw_write_bit(bw, 0); bw_write_bit(bw, 0);
@ -677,6 +723,29 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
ss->local_client_ent = (struct sim_ent_id) { .uid = br_read_uid(br) }; ss->local_client_ent = (struct sim_ent_id) { .uid = br_read_uid(br) };
/* Id buckets */
/* TODO: Don't decode these, determine them implicitly from decoded ents */
{
b32 bucket_changed = br_read_bit(br);
while (bucket_changed) {
u32 bucket_index = br_read_uv(br);
if (bucket_index < ss->num_id_buckets) {
struct sim_ent_bucket *bucket = &ss->id_buckets[bucket_index];
if (br_read_bit(br)) {
bucket->first = br_read_uv(br);
}
if (br_read_bit(br)) {
bucket->last = br_read_uv(br);
}
} else {
/* Invalid bucket index */
ASSERT(false);
}
bucket_changed = br_read_bit(br);
}
}
/* Ents */ /* Ents */
if (br_read_bit(br)) { if (br_read_bit(br)) {
ss->num_ents_allocated = br_read_uv(br); ss->num_ents_allocated = br_read_uv(br);
@ -700,3 +769,244 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
sim_ent_decode(br, e); sim_ent_decode(br, e);
} }
} }
#else
/* ========================== *
* Snapshot encode
* ========================== */
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1)
{
__prof;
bw_write_iv(bw, ss1->sim_dt_ns);
bw_write_iv(bw, ss1->sim_time_ns);
bw_write_uv(bw, ss1->continuity_gen);
bw_write_uv(bw, ss1->phys_iteration);
bw_write_uid(bw, receiver->ent_id.uid);
/* Ents */
if (ss1->num_ents_allocated == ss0->num_ents_allocated) {
bw_write_bit(bw, 0);
} else {
bw_write_bit(bw, 1);
bw_write_uv(bw, ss1->num_ents_allocated);
}
if (ss1->num_ents_reserved == ss0->num_ents_reserved) {
bw_write_bit(bw, 0);
} else {
bw_write_bit(bw, 1);
bw_write_uv(bw, ss1->num_ents_reserved);
}
bw_align(bw);
for (u64 i = 0; i < ss1->num_ents_reserved; ++i) {
struct sim_ent *e0 = sim_ent_nil();
if (i < ss0->num_ents_reserved) {
e0 = &ss0->ents[i];
}
if (e0->valid != e1->valid) {
bw_write_bit(1);
bw_write_bit(e1->valid);
if (e1->valid) {
bw_write_uid(bw, e1->id.uid);
}
} else {
bw_write_bit(0);
}
if (e1->valid) {
struct sim_ent *e1 = &ss1->ents[i];
sim_ent_encode(bw, e0, e1);
}
}
}
/* ========================== *
* Snapshot decode
* ========================== */
struct sim_ent_decode_node {
struct string tmp_encoded;
};
struct sim_ent_decode_queue {
struct sim_ent_decode_node *first;
struct sim_ent_decode_node *last;
};
void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
{
__prof;
struct temp_arena scratch = scratch_begin_no_conflict();
ss->sim_dt_ns = br_read_iv(br);
ss->sim_time_ns = br_read_iv(br);
ss->continuity_gen = br_read_uv(br);
ss->phys_iteration = br_read_uv(br);
ss->local_client_ent = (struct sim_ent_id) { .uid = br_read_uid(br) };
#if 1
if (br_read_bit(br)) {
ss->num_ents_allocated = br_read_uv(br);
}
if (br_read_bit(br)) {
u64 old_num_ents_reserved = ss->num_ents_reserved;
ss->num_ents_reserved = br_read_uv(br);
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
if (reserve_diff > 0) {
arena_push_array(&ss->ents_arena, struct sim_ent, reserve_diff);
for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) {
struct sim_ent *e = &ss->ents[i];
*e = *sim_ent_nil();
e->ss = ss;
}
}
}
/* Build decode queue */
struct sim_ent_decode_queue queue;
b32 should_read_ent = br_read_bit(br);
while (should_read_ent) {
/* TODO: Delta decode index based on last read index */
u32 index = br_read_uv(br);
b32 allocation_changed = br_read_bit(br);
b32 released = false;
u32 alloc_parent_index = ZI;
struct sim_ent_id alloc_ent_id = ZI;
if (allocation_changed) {
released = br_read_bit(br);
if (released) {
struct sim_ent *e = sim_ent_from_index(ss, e);
ASSERT(e->valid); /* An entity that we don't have allocated should never have been marked for release */
if (e->valid) {
sim_ent_enable_prop(e, SIM_ENT_PROP_RELEASE);
}
} else {
alloc_parent_index = br_read_uv();
alloc_ent_id = sim_ent_id_from_uid(br_read_uid(br));
}
}
if (!released) {
u64 num_ent_bits = br_read_uv(br);
struct bitbuff_reader ent_br = br_from_seek_bits(br, num_ent_bits);
if (br_num_bits_left(&ent_br) > 0) {
struct sim_ent_decode_node *n = arena_push_zero(scratch.arena, struct sim_ent_decode_node);
n->is_new = allocation_changed && !released;
n->index = index;
n->alloc_parent_ndex = alloc_parent_index;
n->alloc_ent_id = alloc_ent_id;
n->br = ent_br;
if (queue.last) {
queue.last->next = n;
} else {
queue.first = n;
}
queue.last = n;
}
}
should_read_ent = br_read_bit(br);
}
/* Allocate new ents from decode queue */
for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) {
if (n->is_new) {
u32 index = n->index;
struct sim_ent *parent = sim_ent_from_index(ss, n->alloc_parent_index);
ASSERT(!sim_ent_from_index(ss, index)->valid && !sim_ent_from_id(ss, alloc_ent_id)->valid); /* An entity that we have allocated already should never be marked for allocation */
ASSERT(parent->valid); /* Parent for new entity allocation should always be valid */
if (parent->valid && index < ss->num_ents_reserved) {
struct sim_ent *ent = &ss->ents[index];
ent->valid = true;
sim_ent_set_id(ent, n->alloc_ent_id);
sim_ent_link_parent(parent, ent);
} else {
/* Received an invalid entity allocation */
ASSERT(false);
}
}
}
/* Decode ent data from decode queue */
for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) {
struct bitbuff_reader ent_br = n->br;
u32 index = n->index;
struct sim_ent *e = sim_ent_from_index(ss, index);
if (e->valid) {
sim_ent_decode(&ent_br, e);
} else {
/* Received delta for unallocated ent */
ASSERT(false);
}
}
#else
/* Ents */
if (br_read_bit(br)) {
ss->num_ents_allocated = br_read_uv(br);
}
if (br_read_bit(br)) {
u64 old_num_ents_reserved = ss->num_ents_reserved;
ss->num_ents_reserved = br_read_uv(br);
i64 reserve_diff = (i64)ss->num_ents_reserved - (i64)old_num_ents_reserved;
if (reserve_diff > 0) {
arena_push_array(&ss->ents_arena, struct sim_ent, reserve_diff);
for (u64 i = old_num_ents_reserved; i < ss->num_ents_reserved; ++i) {
struct sim_ent *e = &ss->ents[i];
*e = *sim_ent_nil();
e->ss = ss;
}
}
}
for (u64 i = 0; i < ss->num_ents_reserved; ++i) {
b32 allocation_changed = br_read_bit(br);
if (allocation_changed) {
if (br_read_bit(br)) {
struct sim_ent_decode_node *n = arena_push_zero(scratch.arena, struct sim_ent_decode_node)
} else {
sim_ent_enable_prop(e, SIM_ENT_PROP_RELEASE);
}
}
}
for (u64 i = 0; i < ss->num_ents_reserved; ++i) {
struct sim_ent *e = &ss->ents[i];
e->ss = ss;
b32 valid_changed = br_read_bit(br);
b32 allocated = true;
if (valid_changed) {
allocated = br_read_bit(br);
}
if (!allocated) {
/* Why is an already released ent being marked as released? */
ASSERT(e->valid);
if (e->valid) {
sim_ent_enable_prop(e, SIM_ENT_PROP_RELEASE);
}
} else {
sim_ent_decode(br, e);
}
}
sim_ent_release_all_with_prop(ss, SIM_ENT_PROP_RELEASE);
#endif
scratch_end(scratch);
}
#endif

View File

@ -93,11 +93,11 @@ struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, struct sim_client
struct sim_ent *e = sim_ent_alloc_raw(ss); struct sim_ent *e = sim_ent_alloc_raw(ss);
sim_ent_set_id(e, id); sim_ent_set_id(e, id);
sim_ent_link_parent(e, parent);
sim_ent_enable_prop(e, SIM_ENT_PROP_SYNC_DST); sim_ent_enable_prop(e, SIM_ENT_PROP_SYNC_DST);
e->sync_src_client = client_handle; e->sync_src_client = client_handle;
sim_ent_link_parent(e, parent);
return e; return e;
} }
@ -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) */ * child entities will be released along with parent anyway) */
for (u64 i = 0; i < ents_to_release_count; ++i) { for (u64 i = 0; i < ents_to_release_count; ++i) {
struct sim_ent *ent = ents_to_release[i]; struct sim_ent *ent = ents_to_release[i];
if (ent->is_top && !ent->is_root) { if (ent->is_top && !ent->is_root && ent->valid) {
sim_ent_release(ent); sim_ent_release(ent);
} }
} }
@ -190,36 +190,36 @@ void sim_ent_set_id(struct sim_ent *ent, struct sim_ent_id id)
struct sim_ent_bucket *bucket = bucket_from_id(ss, old_id); struct sim_ent_bucket *bucket = bucket_from_id(ss, old_id);
u32 prev_index = 0; u32 prev_index = 0;
u32 next_index = 0; u32 next_index = 0;
u32 e_index = bucket->first; u32 search_index = bucket->first;
struct sim_ent *prev = sim_ent_nil(); struct sim_ent *prev = sim_ent_nil();
struct sim_ent *next = sim_ent_nil(); struct sim_ent *next = sim_ent_nil();
struct sim_ent *e = ent_from_index(ss, e_index); struct sim_ent *search = ent_from_index(ss, search_index);
while (e->valid) { while (search->valid) {
next_index = e->next_in_id_bucket; next_index = search->next_in_id_bucket;
next = ent_from_index(ss, next_index); next = ent_from_index(ss, next_index);
if (sim_ent_id_eq(e->id, old_id)) { if (sim_ent_id_eq(search->id, old_id)) {
break; break;
} }
prev_index = e_index; prev_index = search_index;
prev = e; prev = search;
e_index = next_index; search_index = next_index;
e = next; search = next;
} }
if (e->valid) {
/* Old id not in bucket, this should be impossible. */
ASSERT(search->valid);
if (prev->valid) { if (prev->valid) {
prev->next_in_id_bucket = next_index; prev->next_in_id_bucket = next_index;
} else { } else {
bucket->first = next_index; bucket->first = next_index;
} }
if (next->valid) { if (next->valid) {
next->prev_in_id_bucket = prev_index; next->prev_in_id_bucket = prev_index;
} else { } else {
bucket->last = prev_index; bucket->last = prev_index;
} }
} else {
/* Old id not in bucket, this should be impossible. */
ASSERT(false);
}
} }
/* Insert new id into lookup */ /* Insert new id into lookup */
@ -599,6 +599,74 @@ void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote)
sim_ent_enable_prop(local, SIM_ENT_PROP_SYNC_DST); sim_ent_enable_prop(local, SIM_ENT_PROP_SYNC_DST);
} }
#if 1
/* ========================== *
* Ent encode
* ========================== */
void sim_ent_encode(struct bitbuff_writer *bw, struct sim_ent *e0, struct sim_ent *e1)
{
struct sim_snapshot *ss = e1->ss;
/* FIXME: Things like xforms need to be retreived manually rather than memcopied.
* This will also be true for things like ent handles once uids are implemented. */
/* TODO: Granular delta encoding */
u64 pos = 0;
e1->ss = e0->ss;
while (pos < sizeof(*e1)) {
u64 chunk_size = min_u64(pos + 8, sizeof(*e1)) - pos;
u8 *chunk0 = (u8 *)e0 + pos;
u8 *chunk1 = (u8 *)e1 + pos;
if (MEMEQ(chunk0, chunk1, chunk_size)) {
bw_write_bit(bw, 0);
} else {
bw_write_bit(bw, 1);
u64 bits = 0;
MEMCPY(&bits, chunk1, chunk_size);
bw_write_ubits(bw, bits, 64);
}
pos += 8;
}
e1->ss = ss;
}
/* ========================== *
* Ent decode
* ========================== */
void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e)
{
struct sim_snapshot *old_ss = e->ss;
{
u64 pos = 0;
while (pos < sizeof(*e)) {
u8 *chunk = (u8 *)e + pos;
if (br_read_bit(br)) {
u64 chunk_size = min_u64(pos + 8, sizeof(*e)) - pos;
u64 bits = br_read_ubits(br, 64);
MEMCPY(chunk, &bits, chunk_size);
}
pos += 8;
}
}
e->ss = old_ss;
}
#else
/* ========================== * /* ========================== *
* Ent encode * Ent encode
* ========================== */ * ========================== */
@ -653,9 +721,6 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e)
} }
decoded.ss = e->ss; decoded.ss = e->ss;
if (e->valid && !decoded.valid) {
sim_ent_release(e);
} else {
struct sim_ent_id old_id = e->id; struct sim_ent_id old_id = e->id;
struct sim_ent_id new_id = decoded.id; struct sim_ent_id new_id = decoded.id;
MEMCPY_STRUCT(e, &decoded); MEMCPY_STRUCT(e, &decoded);
@ -663,5 +728,5 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e)
if (!sim_ent_id_eq(old_id, new_id)) { if (!sim_ent_id_eq(old_id, new_id)) {
sim_ent_set_id(e, new_id); sim_ent_set_id(e, new_id);
} }
}
} }
#endif

View File

@ -59,7 +59,7 @@ INTERNAL void spawn_test_entities(struct sim_snapshot *world, struct v2 offset)
/* Enemy */ /* Enemy */
{ {
struct sim_ent *e = sim_ent_alloc_local(root); struct sim_ent *e = sim_ent_alloc_sync_src(root);
struct v2 pos = V2(1, -2); struct v2 pos = V2(1, -2);
pos = v2_add(pos, offset); pos = v2_add(pos, offset);
@ -82,7 +82,7 @@ INTERNAL void spawn_test_entities(struct sim_snapshot *world, struct v2 offset)
/* Big box */ /* Big box */
#if 1 #if 1
{ {
struct sim_ent *e = sim_ent_alloc_sync_src(root); struct sim_ent *e = sim_ent_alloc_local(root);
struct v2 pos = V2(1, -0.5); struct v2 pos = V2(1, -0.5);
pos = v2_add(pos, offset); pos = v2_add(pos, offset);

View File

@ -383,19 +383,19 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
} }
if (!sim_ent_id_eq(ent->parent, SIM_ENT_ROOT_ID)) { if (!sim_ent_id_eq(ent->parent, SIM_ENT_ROOT_ID)) {
res.len += string_format(arena, LIT("parent: <%F>\n"), FMT_UID(ent->parent.uid)).len; res.len += string_format(arena, LIT("parent: [%F]\n"), FMT_UID(ent->parent.uid)).len;
} }
if (!sim_ent_id_eq(ent->next, SIM_ENT_NIL_ID) || !sim_ent_id_eq(ent->prev, SIM_ENT_NIL_ID)) { if (!sim_ent_id_eq(ent->next, SIM_ENT_NIL_ID) || !sim_ent_id_eq(ent->prev, SIM_ENT_NIL_ID)) {
res.len += string_format(arena, LIT("prev: <%F>\n"), FMT_UID(ent->prev.uid)).len; res.len += string_format(arena, LIT("prev: [%F]\n"), FMT_UID(ent->prev.uid)).len;
res.len += string_format(arena, LIT("next: <%F>\n"), FMT_UID(ent->next.uid)).len; res.len += string_format(arena, LIT("next: [%F]\n"), FMT_UID(ent->next.uid)).len;
} }
if (!sim_ent_id_eq(ent->first, SIM_ENT_NIL_ID) || !sim_ent_id_eq(ent->last, SIM_ENT_NIL_ID)) { if (!sim_ent_id_eq(ent->first, SIM_ENT_NIL_ID) || !sim_ent_id_eq(ent->last, SIM_ENT_NIL_ID)) {
struct sim_ent *child = sim_ent_from_id(ss, ent->first); struct sim_ent *child = sim_ent_from_id(ss, ent->first);
if (!sim_ent_id_eq(ent->first, ent->last) || !child->valid) { if (!sim_ent_id_eq(ent->first, ent->last) || !child->valid) {
res.len += string_format(arena, LIT("first child: <%F>\n"), FMT_UID(ent->first.uid)).len; res.len += string_format(arena, LIT("first child: [%F]\n"), FMT_UID(ent->first.uid)).len;
res.len += string_format(arena, LIT("last child: <%F>\n"), FMT_UID(ent->last.uid)).len; res.len += string_format(arena, LIT("last child: [%F]\n"), FMT_UID(ent->last.uid)).len;
} }
while (child->valid) { while (child->valid) {
res.len += string_copy(arena, LIT("\nCHILD\n")).len; res.len += string_copy(arena, LIT("\nCHILD\n")).len;
@ -1836,17 +1836,17 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_thread_entry_point, arg)
struct sim_decode_node { struct sim_ss_decode_node {
struct sim_client *client; struct sim_client *client;
u64 tick; u64 tick;
u64 base_tick; u64 base_tick;
struct string tmp_encoded; struct string tmp_encoded;
struct sim_decode_node *next; struct sim_ss_decode_node *next;
}; };
struct sim_decode_queue { struct sim_decode_queue {
struct sim_decode_node *first; struct sim_ss_decode_node *first;
struct sim_decode_node *last; struct sim_ss_decode_node *last;
}; };
@ -1959,7 +1959,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* Decode incoming slave client snapshots */ /* Decode incoming slave client snapshots */
b32 should_decode = tick == client->highest_received_tick + 1 || client->highest_received_tick == 0; b32 should_decode = tick == client->highest_received_tick + 1 || client->highest_received_tick == 0;
if (should_decode) { if (should_decode) {
struct sim_decode_node *node = arena_push_zero(scratch.arena, struct sim_decode_node); struct sim_ss_decode_node *node = arena_push_zero(scratch.arena, struct sim_ss_decode_node);
node->client = client; node->client = client;
node->tick = tick; node->tick = tick;
node->base_tick = base_tick; node->base_tick = base_tick;
@ -1978,7 +1978,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* Decode incoming master client snapshots (only the newest one) */ /* Decode incoming master client snapshots (only the newest one) */
b32 should_decode = tick > client->highest_received_tick; b32 should_decode = tick > client->highest_received_tick;
if (should_decode) { if (should_decode) {
struct sim_decode_node *node = queue.first ? queue.first : arena_push_zero(scratch.arena, struct sim_decode_node); struct sim_ss_decode_node *node = queue.first ? queue.first : arena_push_zero(scratch.arena, struct sim_ss_decode_node);
node->client = client; node->client = client;
node->tick = tick; node->tick = tick;
node->base_tick = base_tick; node->base_tick = base_tick;
@ -2006,7 +2006,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
} }
/* Decode incoming snapshots */ /* Decode incoming snapshots */
for (struct sim_decode_node *n = queue.first; n; n = n->next) { for (struct sim_ss_decode_node *n = queue.first; n; n = n->next) {
struct sim_client *client = n->client; struct sim_client *client = n->client;
u64 base_tick = n->base_tick; u64 base_tick = n->base_tick;
u64 tick = n->tick; u64 tick = n->tick;