From ba12d5677a1df5fae9ef2237c13408f05cbf684c Mon Sep 17 00:00:00 2001 From: jacob Date: Sat, 22 Feb 2025 16:07:55 -0600 Subject: [PATCH] prediction progress --- .natvis | 4 + src/bitbuff.c | 18 ++++- src/bitbuff.h | 2 + src/common.h | 4 + src/config.h | 2 +- src/phys.c | 4 +- src/rng.c | 24 ++++-- src/rng.h | 4 +- src/sim.c | 18 +++-- src/sim.h | 25 ++++++- src/sim_ent.c | 140 +++++++++++++++++++++++++++++++++-- src/sim_ent.h | 44 ++++++++--- src/sim_step.c | 114 ++++------------------------- src/sim_step.h | 1 - src/string.c | 1 + src/user.c | 194 +++++++++++++++++++++++++------------------------ 16 files changed, 368 insertions(+), 231 deletions(-) diff --git a/.natvis b/.natvis index da9af172..3fd140af 100644 --- a/.natvis +++ b/.natvis @@ -42,6 +42,10 @@ + + 0x{*((u64 *)this + 1), xb}{*(u64 *)this, xb} + + ({len}) {text, [len] s} text, [len] diff --git a/src/bitbuff.c b/src/bitbuff.c index cf7903fe..0a3d8da5 100644 --- a/src/bitbuff.c +++ b/src/bitbuff.c @@ -20,8 +20,9 @@ enum dbg_magic { DBG_MAGIC_IV = 0x981f, DBG_MAGIC_F32 = 0x56F9, DBG_MAGIC_F64 = 0x7053, + DBG_MAGIC_U128 = 0xa24e, DBG_MAGIC_STRING = 0x7866, - DBG_MAGIC_BYTES = 0x8B90, + DBG_MAGIC_BYTES = 0x8B90 }; INTERNAL void bw_write_ubits_nomagic(struct bitbuff_writer *bw, u64 value, u8 num_bits); @@ -326,6 +327,13 @@ void bw_write_f64(struct bitbuff_writer *bw, f64 value) bw_write_ubits(bw, *(u64 *)&value, 64); } +void bw_write_u128(struct bitbuff_writer *bw, u128 value) +{ + _dbg_write_magic(bw, DBG_MAGIC_U128, 128); + bw_write_ubits(bw, U128_LO(value), 64); + bw_write_ubits(bw, U128_HI(value), 64); +} + void bw_write_string(struct bitbuff_writer *bw, struct string s) { _dbg_write_magic(bw, DBG_MAGIC_STRING, 0); @@ -564,6 +572,14 @@ f64 br_read_f64(struct bitbuff_reader *br) return *(f64 *)&ubits; } +u128 br_read_u128(struct bitbuff_reader *br) +{ + _dbg_read_magic(br, DBG_MAGIC_U128, 128); + u64 hi = br_read_ubits(br, 64); + u64 lo = br_read_ubits(br, 64); + return U128(hi, lo); +} + struct string br_read_string(struct arena *arena, struct bitbuff_reader *br) { _dbg_read_magic(br, DBG_MAGIC_STRING, 0); diff --git a/src/bitbuff.h b/src/bitbuff.h index 72204a56..ea76e0a2 100644 --- a/src/bitbuff.h +++ b/src/bitbuff.h @@ -57,6 +57,7 @@ void bw_write_iv(struct bitbuff_writer *bw, i64 value); void bw_write_f32(struct bitbuff_writer *bw, f32 value); void bw_write_f64(struct bitbuff_writer *bw, f64 value); +void bw_write_u128(struct bitbuff_writer *bw, u128 value); void bw_write_string(struct bitbuff_writer *bw, struct string s); @@ -98,6 +99,7 @@ i64 br_read_iv(struct bitbuff_reader *br); f32 br_read_f32(struct bitbuff_reader *br); f64 br_read_f64(struct bitbuff_reader *br); +u128 br_read_u128(struct bitbuff_reader *br); struct string br_read_string(struct arena *arena, struct bitbuff_reader *br); diff --git a/src/common.h b/src/common.h index e6b15ab1..b66eb0a8 100644 --- a/src/common.h +++ b/src/common.h @@ -501,6 +501,10 @@ struct sim_ent_handle { u64 gen; }; +struct sim_netid { + u128 v; +}; + struct sim_client_handle { u32 idx; u32 gen; diff --git a/src/config.h b/src/config.h index 313d1935..236cb173 100644 --- a/src/config.h +++ b/src/config.h @@ -62,7 +62,7 @@ #define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 0 /* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */ -#define BITBUFF_DEBUG 0 +#define BITBUFF_DEBUG RTC #define BITBUFF_TEST RTC /* ========================== * diff --git a/src/phys.c b/src/phys.c index 7279edd2..8c3e24b6 100644 --- a/src/phys.c +++ b/src/phys.c @@ -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)) { /* Create constraint */ { - constraint_ent = sim_ent_alloc(root); + constraint_ent = sim_ent_alloc_net_src(root); constraint_ent->contact_constraint_data.e1 = e1->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) @@ -245,7 +245,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a if (!dbg_ent->valid) { /* FIXME: Entity never released */ - dbg_ent = sim_ent_alloc(root); + dbg_ent = sim_ent_alloc_net_src(root); sim_ent_enable_prop(dbg_ent, SIM_ENT_PROP_COLLISION_DEBUG); sim_lookup_set(debug_lookup, key, dbg_ent->handle); } diff --git a/src/rng.c b/src/rng.c index daeea3b6..0fcce607 100644 --- a/src/rng.c +++ b/src/rng.c @@ -5,7 +5,7 @@ GLOBAL struct { struct arena arena; - u64 *noise; + u128 *noise; u64 noise_count; } G = ZI, DEBUG_ALIAS(G, G_rng); @@ -25,7 +25,7 @@ INTERNAL void gen_random_file(struct string path, u32 count) } struct sys_file f = sys_file_open_append(path); for (u32 i = 0; i < count; ++i) { - u64 rand = rng_rand_u64(); + u128 rand = rng_rand_u128(); sys_file_write(f, STRING_FROM_STRUCT(&rand)); } sys_file_close(f); @@ -43,8 +43,8 @@ struct rng_startup_receipt rng_startup(struct resource_startup_receipt *resource if (resource_exists(noise_path)) { struct resource r = resource_open(noise_path); G.noise_count = r.data.len / sizeof(*G.noise); - G.arena = arena_alloc(sizeof(u64) * G.noise_count); - G.noise = arena_push_array(&G.arena, u64, G.noise_count); + G.arena = arena_alloc(sizeof(u128) * G.noise_count); + G.noise = arena_push_array(&G.arena, u128, G.noise_count); MEMCPY(G.noise, r.data.text, r.data.len); resource_close(r); } else { @@ -71,6 +71,13 @@ u64 rng_rand_u64(void) return v; } +u128 rng_rand_u128(void) +{ + u128 v = 0; + sys_rand(STRING_FROM_STRUCT(&v)); + return v; +} + f32 rng_rand_f32(f32 range_start, f32 range_end) { return ((f32)rng_rand_u32() / (f32)U32_MAX) * (range_end - range_start) + range_start; @@ -90,12 +97,17 @@ f64 rng_rand_f64(f64 range_start, f64 range_end) /* TODO: Use deterministic prng rather than embedded data */ -u32 rng_noise_u32(u32 seed) +u32 rng_noise_u32(u64 seed) { - return (u32)G.noise[seed % G.noise_count]; + return (u32)U128_LO(G.noise[seed % G.noise_count]); } u64 rng_noise_u64(u64 seed) +{ + return U128_LO(G.noise[seed % G.noise_count]); +} + +u128 rng_noise_u128(u64 seed) { return G.noise[seed % G.noise_count]; } diff --git a/src/rng.h b/src/rng.h index 2177b421..6bfc84f0 100644 --- a/src/rng.h +++ b/src/rng.h @@ -10,12 +10,14 @@ struct rng_startup_receipt rng_startup(struct resource_startup_receipt *resource /* Rand */ u32 rng_rand_u32(void); u64 rng_rand_u64(void); +u128 rng_rand_u128(void); f32 rng_rand_f32(f32 range_start, f32 range_end); f64 rng_rand_f64(f64 range_start, f64 range_end); /* Noise */ -u32 rng_noise_u32(u32 seed); +u32 rng_noise_u32(u64 seed); u64 rng_noise_u64(u64 seed); +u128 rng_noise_u128(u64 seed); f32 rng_noise_f32(u64 seed, f32 range_start, f32 range_end); f32 rng_noise_f64(u64 seed, f64 range_start, f64 range_end); diff --git a/src/sim.c b/src/sim.c index 05e85cf3..6214777c 100644 --- a/src/sim.c +++ b/src/sim.c @@ -25,6 +25,7 @@ #define CLIENT_LOOKUP_BUCKETS 127 #define TICK_LOOKUP_BUCKETS 127 +#define NETID_LOOKUP_BUCKETS 1024 /* ========================== * * Startup @@ -304,9 +305,16 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn ss->sim_dt_ns = src->sim_dt_ns; ss->sim_time_ns = src->sim_time_ns; ss->continuity_gen = src->continuity_gen; - ss->local_client = src->local_client; + ss->local_client_netid = src->local_client_netid; ss->phys_iteration = src->phys_iteration; + /* Copy 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); + for (u64 i = 0; i < src->num_netid_buckets; ++i) { + ss->netid_buckets[i] = src->netid_buckets[i]; + } + /* Copy entities */ ss->first_free_ent = src->first_free_ent; ss->num_ents_allocated = src->num_ents_allocated; @@ -547,7 +555,7 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, str * Snapshot encode * ========================== */ -void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1) +void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_ent *receiver_client, struct sim_snapshot *ss0, struct sim_snapshot *ss1) { __prof; @@ -557,8 +565,7 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, bw_write_uv(bw, ss1->continuity_gen); bw_write_uv(bw, ss1->phys_iteration); - bw_write_uv(bw, receiver->handle.gen); - bw_write_uv(bw, receiver->handle.idx); + bw_write_u128(bw, sim_ent_get_netid(receiver_client).v); /* Ents */ if (ss1->num_ents_allocated == ss0->num_ents_allocated) { @@ -597,8 +604,7 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss) ss->continuity_gen = br_read_uv(br); ss->phys_iteration = br_read_uv(br); - ss->local_client.gen = br_read_uv(br); - ss->local_client.idx = br_read_uv(br); + ss->local_client_netid.v = br_read_u128(br); /* Ents */ if (br_read_bit(br)) { diff --git a/src/sim.h b/src/sim.h index 8e08537f..08e34ce4 100644 --- a/src/sim.h +++ b/src/sim.h @@ -79,6 +79,9 @@ struct sim_client { struct sim_client_handle next_in_bucket; struct sim_client_handle prev_in_bucket; + /* The client entity's net id in the master sim (if one is present) */ + struct sim_netid client_ent_netid; + /* This is the last confirmed tick of ours that we know this client has received */ u64 ack; @@ -137,6 +140,8 @@ struct sim_control { u32 flags; }; +struct sim_ent_bucket; + struct sim_snapshot { b32 valid; u64 tick; @@ -163,8 +168,11 @@ struct sim_snapshot { /* The last physics iteration (used for tracking contact lifetime) */ u64 phys_iteration; - /* TODO: Replace with networked id that resolves to local client ent? */ - struct sim_client_handle local_client; /* The receiver's client handle on the master sim (used for finding local client ent in snapshot) */ + struct sim_netid local_client_netid; /* The netid of the receiver's client ent */ + + /* Net id lookup */ + struct sim_ent_bucket *netid_buckets; + u64 num_netid_buckets; /* Entities */ struct arena ents_arena; @@ -196,7 +204,18 @@ struct sim_snapshot *sim_snapshot_from_closest_tick_lte(struct sim_client *clien struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend); /* Encode / decode */ -void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1); +void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_ent *receiver_client, struct sim_snapshot *ss0, struct sim_snapshot *ss1); void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss); +/* ========================== * + * Net id + * ========================== */ + +#define SIM_NETID_NIL (struct sim_netid) { U128(0, 0) } + +INLINE b32 sim_netid_eq(struct sim_netid a, struct sim_netid b) +{ + return u128_eq(a.v, b.v); +} + #endif diff --git a/src/sim_ent.c b/src/sim_ent.c index 07b021c7..490c6768 100644 --- a/src/sim_ent.c +++ b/src/sim_ent.c @@ -2,12 +2,13 @@ #include "sim.h" #include "math.h" #include "bitbuff.h" +#include "rng.h" /* ========================== * * Ent allocation * ========================== */ -INTERNAL struct sim_ent *sim_ent_alloc_internal(struct sim_snapshot *ss) +struct sim_ent *sim_ent_alloc_raw(struct sim_snapshot *ss) { struct sim_ent *ent = NULL; struct sim_ent_handle handle = ZI; @@ -31,26 +32,60 @@ INTERNAL struct sim_ent *sim_ent_alloc_internal(struct sim_snapshot *ss) return ent; } -struct sim_ent *sim_ent_alloc(struct sim_ent *parent) +/* Allocates a new entity that will not touch the network */ +struct sim_ent *sim_ent_alloc_local(struct sim_ent *parent) { ASSERT(parent->valid); struct sim_snapshot *ss = parent->ss; - struct sim_ent *e = sim_ent_alloc_internal(ss); + struct sim_ent *e = sim_ent_alloc_raw(ss); sim_ent_link_parent(e, parent); return e; } -INTERNAL void sim_ent_release_internal(struct sim_ent *ent) +/* Allocates a new entity with a random netid to be synced to clients */ +struct sim_ent *sim_ent_alloc_net_src(struct sim_ent *parent) +{ + struct sim_snapshot *ss = parent->ss; + struct sim_ent *e = sim_ent_alloc_raw(ss); + sim_ent_link_parent(e, parent); + + sim_ent_enable_prop(e, SIM_ENT_PROP_NET_SRC); + struct sim_netid netid = ZI; + netid.v = rng_rand_u128(); + e->net_src_client = ss->client->handle; + sim_ent_set_netid(e, netid); + + return e; +} + +/* Allocates a new entity that will sync with incoming net src ents containing netid, and coming from the specified client */ +struct sim_ent *sim_ent_alloc_net_dst(struct sim_ent *parent, struct sim_client_handle client_handle, struct sim_netid netid) +{ + struct sim_snapshot *ss = parent->ss; + struct sim_ent *e = sim_ent_alloc_raw(ss); + sim_ent_link_parent(e, parent); + + sim_ent_enable_prop(e, SIM_ENT_PROP_NET_DST); + e->net_src_client = client_handle; + sim_ent_set_netid(e, netid); + + return e; +} + +void sim_ent_release_raw(struct sim_ent *ent) { struct sim_snapshot *ss = ent->ss; /* Release children */ struct sim_ent_handle first_handle = ent->first; if (first_handle.gen) { for (struct sim_ent *child = sim_ent_from_handle(ss, first_handle); child->valid; child = sim_ent_from_handle(ss, child->next)) { - sim_ent_release_internal(child); + sim_ent_release_raw(child); } } + /* Release netid */ + sim_ent_set_netid(ent, SIM_NETID_NIL); + /* Release */ ++ent->handle.gen; ent->valid = false; @@ -64,7 +99,92 @@ void sim_ent_release(struct sim_ent *ent) if (ent->parent.gen) { sim_ent_unlink_from_parent(ent); } - sim_ent_release_internal(ent); + sim_ent_release_raw(ent); +} + +/* ========================== * + * Net id + * ========================== */ + +INLINE u64 hash_from_netid(struct sim_netid netid) +{ + return hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&netid)); +} + +struct sim_netid sim_ent_get_netid(struct sim_ent *ent) +{ + return ent->_netid; +} + +void sim_ent_set_netid(struct sim_ent *ent, struct sim_netid netid) +{ + struct sim_snapshot *ss = ent->ss; + struct sim_ent_bucket *buckets = ss->netid_buckets; + u64 num_netid_buckets = ss->num_netid_buckets; + + struct sim_netid old_netid = ent->_netid; + + /* Release old from lookup */ + if (!sim_netid_eq(old_netid, SIM_NETID_NIL)) { + u64 hash = hash_from_netid(old_netid); + struct sim_ent_bucket *bucket = &buckets[hash % num_netid_buckets]; + struct sim_ent *prev = sim_ent_nil(); + struct sim_ent *next = sim_ent_nil(); + struct sim_ent *e = sim_ent_from_handle(ss, bucket->first); + while (e->valid) { + next = sim_ent_from_handle(ss, e->next_in_netid_bucket); + if (sim_netid_eq(e->_netid, old_netid)) { + break; + } + prev = e; + e = next; + } + if (e->valid) { + if (prev->valid) { + prev->next_in_netid_bucket = next->handle; + } else { + bucket->first = next->handle; + } + if (next->valid) { + next->prev_in_netid_bucket = prev->handle; + } else { + bucket->last = prev->handle; + } + } + } + + /* Insert new netid into lookup */ + if (!sim_netid_eq(netid, SIM_NETID_NIL)) { + u64 hash = hash_from_netid(netid); + struct sim_ent_bucket *bucket = &buckets[hash % num_netid_buckets]; + struct sim_ent *last = sim_ent_from_handle(ss, bucket->last); + if (last->valid) { + last->next_in_netid_bucket = ent->handle; + } else { + bucket->first = ent->handle; + } + ent->prev_in_netid_bucket = last->handle; + bucket->last = ent->handle; + } + + ent->_netid = netid; +} + +struct sim_ent *sim_ent_from_netid(struct sim_snapshot *ss, struct sim_netid netid) +{ + struct sim_ent *res = sim_ent_nil(); + u64 num_buckets = ss->num_netid_buckets; + if (num_buckets > 0) { + u64 hash = hash_from_netid(netid); + 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)) { + if (sim_netid_eq(e->_netid, netid)) { + res = e; + break; + } + } + } + return res; } /* ========================== * @@ -406,6 +526,8 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e) { struct sim_snapshot *ss = e->ss; + struct sim_netid old_netid = sim_ent_get_netid(e); + u64 pos = 0; while (pos < sizeof(*e)) { u8 *chunk = (u8 *)e + pos; @@ -417,5 +539,11 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e) pos += 8; } + struct sim_netid new_netid = sim_ent_get_netid(e); + + if (!sim_netid_eq(old_netid, new_netid)) { + sim_ent_set_netid(e, new_netid); + } + e->ss = ss; } diff --git a/src/sim_ent.h b/src/sim_ent.h index 307ed276..8b408bd8 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -13,13 +13,12 @@ struct bitbuff_writer; struct bitbuff_reader; enum sim_ent_prop { - SIM_ENT_PROP_NONE, - SIM_ENT_PROP_ACTIVE, - SIM_ENT_PROP_RELEASE, - SIM_ENT_PROP_REMOTE, + SIM_ENT_PROP_NET_SRC, /* This entity should be networked to other clients */ + SIM_ENT_PROP_NET_DST, /* This entity is not locally created, and should sync with incoming net src ents */ + SIM_ENT_PROP_CLIENT, SIM_ENT_PROP_LOCAL_CLIENT, @@ -85,20 +84,29 @@ struct sim_ent { struct sim_ent_handle prev; struct sim_ent_handle first; struct sim_ent_handle last; + + struct sim_ent_handle next_in_netid_bucket; + struct sim_ent_handle prev_in_netid_bucket; + struct sim_ent_handle next_free; /* ====================================================================== */ - /* Remote */ + /* Net */ - /* SIM_ENT_PROP_REMOTE */ + /* SIM_ENT_PROP_NET_SRC */ + /* SIM_ENT_PROP_NET_DST */ - struct sim_client_handle remote_client; - struct sim_ent_handle remote_ent; + /* Handle of the client that owns the src ent of this dst ent */ + struct sim_client_handle net_src_client; + + /* The (unique) networked ID of the entity. + * Use net getter to access. */ + struct sim_netid _netid; /* ====================================================================== */ /* Position */ - /* Access with xform get/set */ + /* Use xform getters & setters to access. */ struct xform _local_xform; /* Transform in relation to parent ent (or the world if ent has no parent) */ struct xform _xform; /* Calculated from ent tree */ b32 _is_xform_dirty; @@ -324,6 +332,11 @@ struct sim_ent_prop_array { u64 count; }; +struct sim_ent_bucket { + struct sim_ent_handle first; + struct sim_ent_handle last; +}; + /* ========================== * * Handle helpers * ========================== */ @@ -378,9 +391,20 @@ INLINE b32 sim_ent_is_valid_and_active(struct sim_ent *ent) * ========================== */ /* Alloc */ -struct sim_ent *sim_ent_alloc(struct sim_ent *parent); +struct sim_ent *sim_ent_alloc_raw(struct sim_snapshot *ss); +struct sim_ent *sim_ent_alloc_local(struct sim_ent *parent); +struct sim_ent *sim_ent_alloc_net_src(struct sim_ent *parent); +struct sim_ent *sim_ent_alloc_net_dst(struct sim_ent *parent, struct sim_client_handle client_handle, struct sim_netid netid); + +void sim_ent_release_raw(struct sim_ent *ent); void sim_ent_release(struct sim_ent *ent); +/* Net id */ + +struct sim_netid sim_ent_get_netid(struct sim_ent *ent); +void sim_ent_set_netid(struct sim_ent *ent, struct sim_netid netid); +struct sim_ent *sim_ent_from_netid(struct sim_snapshot *ss, struct sim_netid netid); + /* Query */ struct sim_ent *sim_ent_from_handle(struct sim_snapshot *ss, struct sim_ent_handle handle); struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_ent_prop prop); diff --git a/src/sim_step.c b/src/sim_step.c index 26020b5d..024dfc96 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -159,7 +159,6 @@ struct sim_accel sim_accel_alloc(void) { struct sim_accel accel = ZI; accel.space = space_alloc(1, 256); - accel.remote_lookup = sim_lookup_alloc(4096); accel.client_lookup = sim_lookup_alloc(4096); accel.contact_lookup = sim_lookup_alloc(4096); #if COLLIDER_DEBUG @@ -175,7 +174,6 @@ void sim_accel_release(struct sim_accel *accel) #endif sim_lookup_release(&accel->contact_lookup); sim_lookup_release(&accel->client_lookup); - sim_lookup_release(&accel->remote_lookup); space_release(accel->space); } @@ -184,7 +182,6 @@ void sim_accel_rebuild(struct sim_snapshot *ss, struct sim_accel *accel) /* FIXME: Rebuild collision debug lookup */ space_reset(accel->space); - sim_lookup_reset(&accel->remote_lookup); sim_lookup_reset(&accel->client_lookup); sim_lookup_reset(&accel->contact_lookup); @@ -201,10 +198,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) { struct sim_ent *ent = &ss->ents[sim_ent_index]; if (!sim_ent_is_valid_and_active(ent)) continue; - if (sim_ent_has_prop(ent, SIM_ENT_PROP_REMOTE)) { - struct sim_lookup_key key = sim_lookup_key_from_client_and_ent_handles(ent->remote_client, ent->remote_ent); - sim_lookup_set(&accel->remote_lookup, key, ent->handle); - } 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); @@ -230,7 +223,7 @@ INTERNAL void spawn_test_entities(struct sim_snapshot *world, struct v2 offset) /* Enemy */ { - struct sim_ent *e = sim_ent_alloc(root); + struct sim_ent *e = sim_ent_alloc_net_src(root); struct v2 pos = V2(1, -2); pos = v2_add(pos, offset); @@ -253,7 +246,7 @@ INTERNAL void spawn_test_entities(struct sim_snapshot *world, struct v2 offset) /* Big box */ #if 1 { - struct sim_ent *e = sim_ent_alloc(root); + struct sim_ent *e = sim_ent_alloc_net_src(root); struct v2 pos = V2(1, -0.5); pos = v2_add(pos, offset); @@ -277,7 +270,7 @@ INTERNAL void spawn_test_entities(struct sim_snapshot *world, struct v2 offset) /* Tiny box */ #if 0 { - struct sim_ent *e = sim_ent_alloc(root); + struct sim_ent *e = sim_ent_alloc_net_src(root); struct v2 pos = V2(1, -0.5); pos = v2_add(pos, offset); @@ -307,7 +300,7 @@ INTERNAL struct sim_ent *spawn_test_player(struct sim_snapshot *world) //if (!ctx->extra_spawn) { { - struct sim_ent *e = sim_ent_alloc(root); + struct sim_ent *e = sim_ent_alloc_net_src(root); struct v2 pos = V2(1, -1); @@ -360,7 +353,7 @@ INTERNAL struct sim_ent *spawn_test_player(struct sim_snapshot *world) /* Player weapon */ if (player_ent->valid) { - struct sim_ent *e = sim_ent_alloc(player_ent); + struct sim_ent *e = sim_ent_alloc_net_src(player_ent); e->sprite = sprite_tag_from_path(LIT("res/graphics/gun.ase")); sim_ent_enable_prop(e, SIM_ENT_PROP_ATTACHED); @@ -383,7 +376,7 @@ INTERNAL struct sim_ent *spawn_test_player_camera(struct sim_snapshot *world, st struct sim_ent *camera_ent = sim_ent_nil(); if (player_ent->valid) { - camera_ent = sim_ent_alloc(root); + camera_ent = sim_ent_alloc_net_src(root); sim_ent_set_xform(camera_ent, XFORM_IDENT); sim_ent_enable_prop(camera_ent, SIM_ENT_PROP_CAMERA); @@ -556,7 +549,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, st /* TODO: Remove this */ { struct xform xf = XFORM_TRS(.t = point, .r = rng_rand_f32(0, TAU)); - struct sim_ent *decal = sim_ent_alloc(root); + struct sim_ent *decal = sim_ent_alloc_net_src(root); decal->sprite = sprite_tag_from_path(LIT("res/graphics/blood.ase")); decal->sprite_tint = RGBA_32_F(1, 1, 1, 0.25f); decal->layer = SIM_LAYER_FLOOR_DECALS; @@ -726,85 +719,6 @@ void sim_step(struct sim_step_ctx *ctx) } } -#if 0 - for (struct sim_snapshot_list_node *n = cmd_snapshots->first; n; n = n->next) { - struct sim_snapshot *cmd_snapshot = n->ss; - struct sim_client_handle client_handle = cmd_snapshot->producer_client; - - 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); - struct sim_ent *client_ent = client_entry ? sim_ent_from_handle(world, client_entry->ent) : sim_ent_nil(); - - /* Create client ent if it doesn't exist */ - /* FIXME: Client ent never released upon disconnect */ - if (!client_ent->valid) { - client_ent = sim_ent_alloc(root); - client_ent->client_handle = client_handle; - sim_ent_enable_prop(client_ent, SIM_ENT_PROP_CLIENT); - if (cmd_snapshot->producer_client_is_local) { - sim_ent_enable_prop(client_ent, SIM_ENT_PROP_LOCAL_CLIENT); - } - sim_ent_enable_prop(client_ent, SIM_ENT_PROP_ACTIVE); - /* FIXME: Remove from lookup table when client disconnects */ - sim_lookup_set(&accel->client_lookup, key, client_ent->handle); - } - - /* Process client control */ - /* TODO: Create client cmd ents here and process them separately */ - struct sim_control old_control = client_ent->client_control; - struct sim_control *control = &client_ent->client_control; - *control = cmd_snapshot->control; - { - client_ent->client_dbg_drag_start = false; - client_ent->client_dbg_drag_stop = false; - - if (v2_len_sq(control->move) > 1) { - /* Cap movement vector magnitude at 1 */ - control->move = v2_norm(control->move); - } - - /* Determine cursor pos from focus */ - { - struct sim_ent_handle client_control_ent_handle = client_ent->client_control_ent; - struct sim_ent *client_control_ent = sim_ent_from_handle(world, client_control_ent_handle); - if (client_control_ent->valid || sim_ent_handle_eq(client_control_ent_handle, SIM_ENT_NIL_HANDLE)) { - /* Only update cursor pos if focus ent is valid (or nil) */ - client_ent->client_cursor_pos = v2_add(sim_ent_get_xform(client_control_ent).og, client_ent->client_control.focus); - } - } - - u32 flags = control->flags; - if (flags & SIM_CONTROL_FLAG_DRAG) { - if (!(old_control.flags & SIM_CONTROL_FLAG_DRAG)) { - client_ent->client_dbg_drag_start = true; - } - } else { - if (old_control.flags & SIM_CONTROL_FLAG_DRAG) { - client_ent->client_dbg_drag_stop = true; - } - } - if (flags & SIM_CONTROL_FLAG_CLEAR_ALL) { - if (!(old_control.flags & SIM_CONTROL_FLAG_CLEAR_ALL)) { - test_clear_level(world); - } - } - if (flags & SIM_CONTROL_FLAG_SPAWN_TEST) { - if (!(old_control.flags & SIM_CONTROL_FLAG_SPAWN_TEST)) { - logf_info("Spawning (test)"); - u32 count = 1; - f32 spread = 1; - for (u32 j = 0; j < count; ++j) { - spawn_test_entities(world, V2(0, (((f32)j / (f32)count) - 0.5) * spread)); - } - } - } - } - } -#endif - - - - /* ========================== * * Create client player ents * ========================== */ @@ -1070,7 +984,7 @@ void sim_step(struct sim_step_ctx *ctx) /* Spawn bullet */ struct sim_ent *bullet; { - bullet = sim_ent_alloc(root); + bullet = sim_ent_alloc_net_src(root); bullet->bullet_src = ent->handle; bullet->bullet_src_pos = rel_pos; @@ -1097,7 +1011,7 @@ void sim_step(struct sim_step_ctx *ctx) /* Spawn tracer */ { - struct sim_ent *tracer = sim_ent_alloc(root); + struct sim_ent *tracer = sim_ent_alloc_net_src(root); tracer->tracer_fade_duration = 0.025f; tracer->layer = SIM_LAYER_TRACERS; sim_ent_enable_prop(tracer, SIM_ENT_PROP_TRACER); @@ -1118,7 +1032,7 @@ void sim_step(struct sim_step_ctx *ctx) if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) { struct sim_ent *joint_ent = sim_ent_from_handle(world, ent->move_joint); if (!sim_ent_is_valid_and_active(joint_ent)) { - joint_ent = sim_ent_alloc(root); + joint_ent = sim_ent_alloc_net_src(root); joint_ent->mass_unscaled = F32_INFINITY; joint_ent->inertia_unscaled = F32_INFINITY; sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT); @@ -1155,7 +1069,7 @@ void sim_step(struct sim_step_ctx *ctx) /* Retrieve / create aim joint */ struct sim_ent *joint_ent = sim_ent_from_handle(world, ent->aim_joint); if (!sim_ent_is_valid_and_active(joint_ent)) { - joint_ent = sim_ent_alloc(root); + joint_ent = sim_ent_alloc_net_src(root); joint_ent->mass_unscaled = F32_INFINITY; joint_ent->inertia_unscaled = F32_INFINITY; sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_PHYSICAL_KINEMATIC); /* Since we'll be setting velocity manually */ @@ -1252,7 +1166,7 @@ void sim_step(struct sim_step_ctx *ctx) def.max_torque = ent->angular_ground_friction; if (joint_ent->motor_joint_data.max_force != def.max_force || joint_ent->motor_joint_data.max_torque != def.max_torque) { if (!sim_ent_is_valid_and_active(joint_ent)) { - joint_ent = sim_ent_alloc(root); + joint_ent = sim_ent_alloc_net_src(root); sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT); sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_ACTIVE); joint_ent->motor_joint_data = phys_motor_joint_from_def(def); @@ -1307,7 +1221,7 @@ void sim_step(struct sim_step_ctx *ctx) if (sim_ent_is_valid_and_active(target_ent)) { if (!sim_ent_is_valid_and_active(joint_ent)) { /* FIXME: Joint ent may never release */ - joint_ent = sim_ent_alloc(root); + joint_ent = sim_ent_alloc_net_src(root); joint_ent->mass_unscaled = F32_INFINITY; joint_ent->inertia_unscaled = F32_INFINITY; client_ent->client_dbg_drag_joint_ent = joint_ent->handle; @@ -1413,7 +1327,7 @@ void sim_step(struct sim_step_ctx *ctx) /* Spawn quake */ { - struct sim_ent *quake = sim_ent_alloc(root); + struct sim_ent *quake = sim_ent_alloc_net_src(root); sim_ent_set_xform(quake, XFORM_POS(pos)); quake->quake_intensity = 0.2f; quake->quake_fade = quake->quake_intensity / 0.1f; diff --git a/src/sim_step.h b/src/sim_step.h index 9ed68d01..9ef8cb59 100644 --- a/src/sim_step.h +++ b/src/sim_step.h @@ -58,7 +58,6 @@ struct sim_lookup_key sim_lookup_key_from_client_handle(struct sim_client_handle struct sim_accel { struct space *space; - struct sim_lookup remote_lookup; struct sim_lookup client_lookup; struct sim_lookup contact_lookup; #if COLLIDER_DEBUG diff --git a/src/string.c b/src/string.c index 418ee1f9..cbfc13ab 100644 --- a/src/string.c +++ b/src/string.c @@ -416,6 +416,7 @@ b32 string_ends_with(struct string str, struct string substring) * FMT_FLOAT_P: Format an f64 with specified precision * FMT_HEX: Format a u64 in hexadecimal notation * FMT_PTR: Format a pointer in hexadecimal notation prefixed by "0x" + * FMT_HANDLE: Format a 128 bit handle * * FMT_END (internal): Denote the end of the va_list * diff --git a/src/user.c b/src/user.c index 4c27c2fe..bfb85f8c 100644 --- a/src/user.c +++ b/src/user.c @@ -342,11 +342,12 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e struct temp_arena scratch = scratch_begin(arena); struct sim_snapshot *ss = ent->ss; + const u8 hex[] = "0123456789abcdef"; + struct string res = ZI; res.text = arena_dry_push(arena, u8); { - const u8 hex[] = "0123456789abcdef"; res.len += string_copy(arena, LIT("props: 0x")).len; for (u64 chunk_index = ARRAY_COUNT(ent->props); chunk_index-- > 0;) { u64 chunk = ent->props[chunk_index]; @@ -362,6 +363,18 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e 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)) { res.len += string_format(arena, LIT("parent: <%F>\n"), FMT_HANDLE(ent->parent)).len; } @@ -672,21 +685,7 @@ INTERNAL void user_update(void) * Find local entities * ========================== */ - struct sim_ent *local_client_ent = sim_ent_nil(); - { - struct sim_client_handle local_client_handle = G.ss_blended->local_client; - for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) { - struct sim_ent *ent = &G.ss_blended->ents[ent_index]; - if (!sim_ent_is_valid_and_active(ent)) continue; - if (sim_ent_has_prop(ent, SIM_ENT_PROP_CLIENT)) { - struct sim_client_handle h = ent->client_handle; - if (h.gen != 0 && h.gen == local_client_handle.gen && h.idx == local_client_handle.idx) { - local_client_ent = ent; - break; - } - } - } - } + struct sim_ent *local_client_ent = sim_ent_from_netid(G.ss_blended, G.ss_blended->local_client_netid); struct sim_ent *local_player = sim_ent_from_handle(G.ss_blended, local_client_ent->client_control_ent); struct sim_ent *local_camera = sim_ent_from_handle(G.ss_blended, local_client_ent->client_camera_ent); @@ -1822,44 +1821,43 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_thread_entry_point, arg) - -/* TODO: Move this */ - - -#define translate(fieldname) local->fieldname = _translate(remote_lookup, remote_client_handle, old.fieldname, remote->fieldname) -INTERNAL struct sim_ent_handle _translate(struct sim_lookup *remote_lookup, struct sim_client_handle remote_client_handle, struct sim_ent_handle old_local_handle, struct sim_ent_handle remote_ent_handle) +#define translate(fieldname) local->fieldname = _translate(local_ss, remote_ss, remote->fieldname) +INTERNAL struct sim_ent_handle _translate(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss, struct sim_ent_handle remote_ent_handle) { - if (!sim_ent_handle_eq(remote_ent_handle, SIM_ENT_ROOT_HANDLE)) { - struct sim_lookup_key key = sim_lookup_key_from_client_and_ent_handles(remote_client_handle, remote_ent_handle); - struct sim_lookup_entry *entry = sim_lookup_get(remote_lookup, key); - return entry ? entry->ent : old_local_handle; - } else { - return SIM_ENT_ROOT_HANDLE; + struct sim_ent_handle local_handle = SIM_ENT_NIL_HANDLE; + struct sim_ent *remote_ent = sim_ent_from_handle(remote_ss, remote_ent_handle); + if (remote_ent->valid) { + struct sim_netid netid = sim_ent_get_netid(remote_ent); + struct sim_ent *local_ent = sim_ent_from_netid(local_ss, netid); + local_handle = local_ent->handle; } + return local_handle; } - -INTERNAL void sim_ent_sync_remote(struct sim_accel *accel, struct sim_ent *local, struct sim_ent *remote, struct sim_ent *client_ent) +INTERNAL void sim_ent_sync_remote(struct sim_ent *local, struct sim_ent *remote) { - struct sim_client_handle remote_client_handle = remote->ss->client->handle; - struct sim_lookup *remote_lookup = &accel->remote_lookup; + struct sim_snapshot *local_ss = local->ss; + struct sim_snapshot *remote_ss = remote->ss; + struct sim_client_handle remote_client_handle = remote_ss->client->handle; struct sim_ent old = *local; MEMCPY_STRUCT(local, remote); - sim_ent_enable_prop(local, SIM_ENT_PROP_REMOTE); + sim_ent_disable_prop(local, SIM_ENT_PROP_NET_SRC); + sim_ent_enable_prop(local, SIM_ENT_PROP_NET_DST); /* Keep non-remote handles */ local->ss = old.ss; local->handle = old.handle; - local->remote_client = remote_client_handle; - local->remote_ent = remote->handle; + local->net_src_client = remote_client_handle; local->parent = old.parent; local->prev = old.prev; local->next = old.next; local->first = old.first; local->last = old.last; local->top = old.top; + local->next_in_netid_bucket = old.next_in_netid_bucket; + local->prev_in_netid_bucket = old.prev_in_netid_bucket; local->next_free = old.next_free; /* Translate remote handles */ @@ -1874,44 +1872,30 @@ INTERNAL void sim_ent_sync_remote(struct sim_accel *accel, struct sim_ent *local translate(bullet_src); translate(bullet_tracer); translate(camera_follow); - - if (sim_ent_has_prop(local, SIM_ENT_PROP_CMD_CONTROL)) { - local->cmd_client = client_ent->handle; - } } -INTERNAL void sim_ent_alloc_remote(struct sim_accel *accel, struct sim_ent *local_parent, struct sim_ent *remote) +INTERNAL void sim_ent_alloc_any_missing_net_dst(struct sim_ent *local_parent, struct sim_ent *remote) { - struct sim_snapshot *local_ss = local_parent->ss; - struct sim_snapshot *remote_ss = remote->ss; - struct sim_client_handle remote_client_handle = remote_ss->client->handle; - struct sim_lookup *remote_lookup = &accel->remote_lookup; + __prof; + if (sim_ent_has_prop(remote, SIM_ENT_PROP_NET_SRC)) { + struct sim_snapshot *local_ss = local_parent->ss; + struct sim_snapshot *remote_ss = remote->ss; + struct sim_client_handle remote_client_handle = remote_ss->client->handle; - if (remote->valid) { - struct sim_lookup_key key = sim_lookup_key_from_client_and_ent_handles(remote_client_handle, remote->handle); - struct sim_ent *local_ent = sim_ent_nil(); - { - struct sim_lookup_entry *entry = sim_lookup_get(remote_lookup, key); - if (entry) { - local_ent = sim_ent_from_handle(local_ss, entry->ent); - } - } + struct sim_netid netid = sim_ent_get_netid(remote); + struct sim_ent *local_ent = sim_ent_from_netid(local_ss, netid); if (!local_ent->valid) { - local_ent = sim_ent_alloc(local_parent); - sim_ent_enable_prop(local_ent, SIM_ENT_PROP_REMOTE); - local_ent->remote_client = remote_client_handle; - local_ent->remote_ent = remote->handle; - sim_lookup_set(remote_lookup, key, local_ent->handle); + local_ent = sim_ent_alloc_net_dst(local_parent, remote_client_handle, netid); } for (struct sim_ent *remote_child = sim_ent_from_handle(remote_ss, remote->first); remote_child->valid; remote_child = sim_ent_from_handle(remote_ss, remote_child->next)) { - sim_ent_alloc_remote(accel, local_ent, remote_child); + sim_ent_alloc_any_missing_net_dst(local_ent, remote_child); } } } -INTERNAL void sim_snapshot_sync_remote_ents(struct sim_accel *accel, struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss) +INTERNAL void sim_snapshot_sync_remote_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss) { __prof; @@ -1920,42 +1904,24 @@ INTERNAL void sim_snapshot_sync_remote_ents(struct sim_accel *accel, struct sim_ struct sim_ent *remote_root = sim_ent_from_handle(remote_ss, SIM_ENT_ROOT_HANDLE); struct sim_client_handle remote_client_handle = remote_ss->client->handle; - struct sim_lookup *remote_lookup = &accel->remote_lookup; - struct sim_lookup *client_lookup = &accel->client_lookup; - - struct sim_ent *client_ent; - { - struct sim_lookup_key key = sim_lookup_key_from_client_handle(remote_client_handle); - struct sim_lookup_entry *client_entry = sim_lookup_get(client_lookup, key); - client_ent = client_entry ? sim_ent_from_handle(local_ss, client_entry->ent) : sim_ent_nil(); - } - - /* Build remote lookup table */ - 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_REMOTE) && sim_client_handle_eq(ent->remote_client, remote_client_handle)) { - struct sim_lookup_key key = sim_lookup_key_from_client_and_ent_handles(remote_client_handle, ent->remote_ent); - sim_lookup_set(remote_lookup, key, ent->handle); - } - } - /* Create new ents from remote */ for (struct sim_ent *remote_top = sim_ent_from_handle(remote_ss, remote_root->first); remote_top->valid; remote_top = sim_ent_from_handle(remote_ss, remote_top->next)) { - sim_ent_alloc_remote(accel, local_root, remote_top); + sim_ent_alloc_any_missing_net_dst(local_root, remote_top); } /* Sync ents with remote */ for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) { struct sim_ent *local_ent = &local_ss->ents[i]; - if (local_ent->valid && sim_ent_has_prop(local_ent, SIM_ENT_PROP_REMOTE) && sim_client_handle_eq(local_ent->remote_client, remote_client_handle)) { - struct sim_ent *remote_ent = sim_ent_from_handle(remote_ss, local_ent->remote_ent); + if (local_ent->valid && sim_ent_has_prop(local_ent, SIM_ENT_PROP_NET_DST) && sim_client_handle_eq(local_ent->net_src_client, remote_client_handle)) { + struct sim_netid netid = sim_ent_get_netid(local_ent); + struct sim_ent *remote_ent = sim_ent_from_netid(remote_ss, netid); if (remote_ent->valid) { /* Copy all ent data from remote */ - sim_ent_sync_remote(accel, local_ent, remote_ent, client_ent); + sim_ent_sync_remote(local_ent, remote_ent); } else { /* Remote ent is no longer valid / networked, release it */ sim_ent_enable_prop(local_ent, SIM_ENT_PROP_RELEASE); - sim_ent_disable_prop(local_ent, SIM_ENT_PROP_REMOTE); + sim_ent_disable_prop(local_ent, SIM_ENT_PROP_NET_DST); } } } @@ -2028,8 +1994,8 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) { host_update(host); struct host_event_array host_events = host_pop_events(scratch.arena, host); - for (u64 i = 0; i < host_events.count; ++i) { - struct host_event *event = &host_events.events[i]; + for (u64 event_index = 0; event_index < host_events.count; ++event_index) { + struct host_event *event = &host_events.events[event_index]; struct host_channel_id channel_id = event->channel_id; struct sim_client *client = sim_client_from_channel_id(store, channel_id); switch (event->kind) { @@ -2078,6 +2044,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) /* Alloc & decode snapshot */ struct sim_snapshot *ss = sim_snapshot_alloc(client, base_ss, tick); sim_snapshot_decode(&decoder_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 */ @@ -2103,12 +2076,12 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) /* Create user input */ { struct sim_snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_tick); - struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, step_tick); + struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, step_tick + 50); struct sim_ent *user_input_root = sim_ent_from_handle(user_input_ss, SIM_ENT_ROOT_HANDLE); /* 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); if (!control_cmd_ent->valid) { - control_cmd_ent = sim_ent_alloc(user_input_root); + control_cmd_ent = sim_ent_alloc_net_src(user_input_root); sim_ent_enable_prop(control_cmd_ent, SIM_ENT_PROP_CMD_CONTROL); sim_ent_activate(control_cmd_ent, user_input_ss->tick); } @@ -2141,13 +2114,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) struct sim_ent *client_ent = client_entry ? sim_ent_from_handle(local_ss, client_entry->ent) : sim_ent_nil(); if (!client_ent->valid) { /* FIXME: Client ent never released upon disconnect */ - client_ent = sim_ent_alloc(local_root); + client_ent = sim_ent_alloc_net_src(local_root); 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_ACTIVE); sim_lookup_set(&accel.client_lookup, key, client_ent->handle); if (client == user_input_client) { - local_ss->local_client = user_input_client->handle; + local_ss->local_client_netid = sim_ent_get_netid(client_ent); } } } @@ -2157,9 +2130,9 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) if (client != publish_client && client != local_client) { struct sim_snapshot *client_ss = sim_snapshot_from_tick(client, step_tick); if (client_ss->valid) { - sim_snapshot_sync_remote_ents(&accel, local_ss, client_ss); + sim_snapshot_sync_remote_ents(local_ss, client_ss); if (!is_master && client == master_client) { - local_ss->local_client = client_ss->local_client; + local_ss->local_client_netid = client_ss->local_client_netid; } } } @@ -2167,6 +2140,23 @@ 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) { + 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_NET_DST)) { + struct sim_ent *client_ent = sim_ent_nil(); + { + 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; + } + } + } + /* Release unneeded snapshots */ for (u64 i = 0; i < store->num_clients_reserved; ++i) { struct sim_client *client = &store->clients[i]; @@ -2245,6 +2235,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) /* Construct publishable snapshot */ +#if 0 { if (is_master) { //struct sim_snapshot *prev_pub_ss = sim_snapshot_from_tick(publish_client, publish_client->last_tick); @@ -2252,6 +2243,14 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) (UNUSED)pub_ss; } } +#else + { + struct sim_snapshot *pub_ss = sim_snapshot_alloc(publish_client, sim_snapshot_from_tick(publish_client, publish_client->last_tick), local_ss->tick); + sim_snapshot_sync_remote_ents(pub_ss, local_ss); + } +#endif + + @@ -2274,6 +2273,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) for (u64 i = 0; i < store->num_clients_reserved; ++i) { struct sim_client *client = &store->clients[i]; 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); bw_write_uv(&msg_bw, client->last_tick); /* ack */ @@ -2295,7 +2301,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, publish_ss->tick); - sim_snapshot_encode(&snapshot_bw, client, base_ss, publish_ss); + sim_snapshot_encode(&snapshot_bw, client_ent, base_ss, publish_ss); tmp_snapshot_encoded.len = bw_num_bytes_written(&snapshot_bw); tmp_snapshot_encoded.text = bw_get_written_raw(&snapshot_bw); } @@ -2317,7 +2323,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) /* TODO: Double buffer */ struct sys_lock lock = sys_mutex_lock_e(&G.local_to_user_client_mutex); struct sim_snapshot *copy_ss = sim_snapshot_alloc(G.local_to_user_client, local_ss, local_ss->tick); - copy_ss->local_client = local_ss->local_client; + copy_ss->local_client_netid = local_ss->local_client_netid; i64 publish_ns = sys_time_ns(); copy_ss->publish_dt_ns = publish_ns - last_publish_ns; copy_ss->publish_time_ns = publish_ns;