encode sim id buckets for now
This commit is contained in:
parent
944be252c5
commit
a8246541e9
8
.natvis
8
.natvis
@ -57,9 +57,11 @@
|
|||||||
</Type>
|
</Type>
|
||||||
|
|
||||||
<Type Name = "sim_ent">
|
<Type Name = "sim_ent">
|
||||||
<DisplayString Condition="(valid == 0 || (id.uid.hi == 0 && id.uid.lo == 0)) && this != *_g_sim_ent_nil">~~~MISMATCH~~~ {id}</DisplayString>
|
<DisplayString Condition="(valid == 0 || (id.uid.hi == 0 && id.uid.lo == 0)) && this != *_g_sim_ent_nil">~~~MISMATCH~~~ {id} <{this - this->ss->ents}></DisplayString>
|
||||||
<DisplayString Condition="valid == 1 && (id.uid.hi == 0 || id.uid.lo == 0)">~~~MISMATCH~~~ {id}</DisplayString>
|
<DisplayString Condition="valid == 1 && (id.uid.hi == 0 || id.uid.lo == 0)">~~~MISMATCH~~~ {id} <{this - this->ss->ents}></DisplayString>
|
||||||
<DisplayString>{id}</DisplayString>
|
<DisplayString Condition="this == *_g_sim_ent_nil">{id}</DisplayString>
|
||||||
|
<DisplayString>{id} <{this - this->ss->ents}></DisplayString>
|
||||||
|
|
||||||
</Type>
|
</Type>
|
||||||
|
|
||||||
<Type Name = "String">
|
<Type Name = "String">
|
||||||
|
|||||||
@ -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
310
src/sim.c
@ -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
|
||||||
|
|||||||
107
src/sim_ent.c
107
src/sim_ent.c
@ -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
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
24
src/user.c
24
src/user.c
@ -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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user