prediction progress
This commit is contained in:
parent
34713e0c03
commit
ba12d5677a
4
.natvis
4
.natvis
@ -42,6 +42,10 @@
|
|||||||
</Expand>
|
</Expand>
|
||||||
</Type>
|
</Type>
|
||||||
|
|
||||||
|
<Type Name = "sim_netid">
|
||||||
|
<DisplayString>0x{*((u64 *)this + 1), xb}{*(u64 *)this, xb}</DisplayString>
|
||||||
|
</Type>
|
||||||
|
|
||||||
<Type Name = "String">
|
<Type Name = "String">
|
||||||
<DisplayString>({len}) {text, [len] s}</DisplayString>
|
<DisplayString>({len}) {text, [len] s}</DisplayString>
|
||||||
<StringView>text, [len]</StringView>
|
<StringView>text, [len]</StringView>
|
||||||
|
|||||||
@ -20,8 +20,9 @@ enum dbg_magic {
|
|||||||
DBG_MAGIC_IV = 0x981f,
|
DBG_MAGIC_IV = 0x981f,
|
||||||
DBG_MAGIC_F32 = 0x56F9,
|
DBG_MAGIC_F32 = 0x56F9,
|
||||||
DBG_MAGIC_F64 = 0x7053,
|
DBG_MAGIC_F64 = 0x7053,
|
||||||
|
DBG_MAGIC_U128 = 0xa24e,
|
||||||
DBG_MAGIC_STRING = 0x7866,
|
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);
|
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);
|
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)
|
void bw_write_string(struct bitbuff_writer *bw, struct string s)
|
||||||
{
|
{
|
||||||
_dbg_write_magic(bw, DBG_MAGIC_STRING, 0);
|
_dbg_write_magic(bw, DBG_MAGIC_STRING, 0);
|
||||||
@ -564,6 +572,14 @@ f64 br_read_f64(struct bitbuff_reader *br)
|
|||||||
return *(f64 *)&ubits;
|
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)
|
struct string br_read_string(struct arena *arena, struct bitbuff_reader *br)
|
||||||
{
|
{
|
||||||
_dbg_read_magic(br, DBG_MAGIC_STRING, 0);
|
_dbg_read_magic(br, DBG_MAGIC_STRING, 0);
|
||||||
|
|||||||
@ -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_f32(struct bitbuff_writer *bw, f32 value);
|
||||||
void bw_write_f64(struct bitbuff_writer *bw, f64 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);
|
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);
|
f32 br_read_f32(struct bitbuff_reader *br);
|
||||||
f64 br_read_f64(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);
|
struct string br_read_string(struct arena *arena, struct bitbuff_reader *br);
|
||||||
|
|
||||||
|
|||||||
@ -501,6 +501,10 @@ struct sim_ent_handle {
|
|||||||
u64 gen;
|
u64 gen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sim_netid {
|
||||||
|
u128 v;
|
||||||
|
};
|
||||||
|
|
||||||
struct sim_client_handle {
|
struct sim_client_handle {
|
||||||
u32 idx;
|
u32 idx;
|
||||||
u32 gen;
|
u32 gen;
|
||||||
|
|||||||
@ -62,7 +62,7 @@
|
|||||||
#define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 0
|
#define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 0
|
||||||
|
|
||||||
/* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */
|
/* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */
|
||||||
#define BITBUFF_DEBUG 0
|
#define BITBUFF_DEBUG RTC
|
||||||
#define BITBUFF_TEST RTC
|
#define BITBUFF_TEST RTC
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
@ -128,7 +128,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
|
|||||||
if (!sim_ent_is_valid_and_active(constraint_ent)) {
|
if (!sim_ent_is_valid_and_active(constraint_ent)) {
|
||||||
/* Create constraint */
|
/* Create constraint */
|
||||||
{
|
{
|
||||||
constraint_ent = sim_ent_alloc(root);
|
constraint_ent = sim_ent_alloc_net_src(root);
|
||||||
constraint_ent->contact_constraint_data.e1 = e1->handle;
|
constraint_ent->contact_constraint_data.e1 = e1->handle;
|
||||||
constraint_ent->contact_constraint_data.e0 = e0->handle;
|
constraint_ent->contact_constraint_data.e0 = e0->handle;
|
||||||
constraint_ent->contact_constraint_data.skip_solve = sim_ent_has_prop(e0, SIM_ENT_PROP_SENSOR) || sim_ent_has_prop(e1, SIM_ENT_PROP_SENSOR)
|
constraint_ent->contact_constraint_data.skip_solve = sim_ent_has_prop(e0, SIM_ENT_PROP_SENSOR) || sim_ent_has_prop(e1, SIM_ENT_PROP_SENSOR)
|
||||||
@ -245,7 +245,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
|
|||||||
|
|
||||||
if (!dbg_ent->valid) {
|
if (!dbg_ent->valid) {
|
||||||
/* FIXME: Entity never released */
|
/* FIXME: Entity never released */
|
||||||
dbg_ent = sim_ent_alloc(root);
|
dbg_ent = sim_ent_alloc_net_src(root);
|
||||||
sim_ent_enable_prop(dbg_ent, SIM_ENT_PROP_COLLISION_DEBUG);
|
sim_ent_enable_prop(dbg_ent, SIM_ENT_PROP_COLLISION_DEBUG);
|
||||||
sim_lookup_set(debug_lookup, key, dbg_ent->handle);
|
sim_lookup_set(debug_lookup, key, dbg_ent->handle);
|
||||||
}
|
}
|
||||||
|
|||||||
24
src/rng.c
24
src/rng.c
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct arena arena;
|
struct arena arena;
|
||||||
u64 *noise;
|
u128 *noise;
|
||||||
u64 noise_count;
|
u64 noise_count;
|
||||||
} G = ZI, DEBUG_ALIAS(G, G_rng);
|
} 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);
|
struct sys_file f = sys_file_open_append(path);
|
||||||
for (u32 i = 0; i < count; ++i) {
|
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_write(f, STRING_FROM_STRUCT(&rand));
|
||||||
}
|
}
|
||||||
sys_file_close(f);
|
sys_file_close(f);
|
||||||
@ -43,8 +43,8 @@ struct rng_startup_receipt rng_startup(struct resource_startup_receipt *resource
|
|||||||
if (resource_exists(noise_path)) {
|
if (resource_exists(noise_path)) {
|
||||||
struct resource r = resource_open(noise_path);
|
struct resource r = resource_open(noise_path);
|
||||||
G.noise_count = r.data.len / sizeof(*G.noise);
|
G.noise_count = r.data.len / sizeof(*G.noise);
|
||||||
G.arena = arena_alloc(sizeof(u64) * G.noise_count);
|
G.arena = arena_alloc(sizeof(u128) * G.noise_count);
|
||||||
G.noise = arena_push_array(&G.arena, u64, G.noise_count);
|
G.noise = arena_push_array(&G.arena, u128, G.noise_count);
|
||||||
MEMCPY(G.noise, r.data.text, r.data.len);
|
MEMCPY(G.noise, r.data.text, r.data.len);
|
||||||
resource_close(r);
|
resource_close(r);
|
||||||
} else {
|
} else {
|
||||||
@ -71,6 +71,13 @@ u64 rng_rand_u64(void)
|
|||||||
return v;
|
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)
|
f32 rng_rand_f32(f32 range_start, f32 range_end)
|
||||||
{
|
{
|
||||||
return ((f32)rng_rand_u32() / (f32)U32_MAX) * (range_end - range_start) + range_start;
|
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 */
|
/* 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)
|
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];
|
return G.noise[seed % G.noise_count];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,12 +10,14 @@ struct rng_startup_receipt rng_startup(struct resource_startup_receipt *resource
|
|||||||
/* Rand */
|
/* Rand */
|
||||||
u32 rng_rand_u32(void);
|
u32 rng_rand_u32(void);
|
||||||
u64 rng_rand_u64(void);
|
u64 rng_rand_u64(void);
|
||||||
|
u128 rng_rand_u128(void);
|
||||||
f32 rng_rand_f32(f32 range_start, f32 range_end);
|
f32 rng_rand_f32(f32 range_start, f32 range_end);
|
||||||
f64 rng_rand_f64(f64 range_start, f64 range_end);
|
f64 rng_rand_f64(f64 range_start, f64 range_end);
|
||||||
|
|
||||||
/* Noise */
|
/* Noise */
|
||||||
u32 rng_noise_u32(u32 seed);
|
u32 rng_noise_u32(u64 seed);
|
||||||
u64 rng_noise_u64(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_f32(u64 seed, f32 range_start, f32 range_end);
|
||||||
f32 rng_noise_f64(u64 seed, f64 range_start, f64 range_end);
|
f32 rng_noise_f64(u64 seed, f64 range_start, f64 range_end);
|
||||||
|
|
||||||
|
|||||||
18
src/sim.c
18
src/sim.c
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#define CLIENT_LOOKUP_BUCKETS 127
|
#define CLIENT_LOOKUP_BUCKETS 127
|
||||||
#define TICK_LOOKUP_BUCKETS 127
|
#define TICK_LOOKUP_BUCKETS 127
|
||||||
|
#define NETID_LOOKUP_BUCKETS 1024
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Startup
|
* 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_dt_ns = src->sim_dt_ns;
|
||||||
ss->sim_time_ns = src->sim_time_ns;
|
ss->sim_time_ns = src->sim_time_ns;
|
||||||
ss->continuity_gen = src->continuity_gen;
|
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;
|
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 */
|
/* Copy entities */
|
||||||
ss->first_free_ent = src->first_free_ent;
|
ss->first_free_ent = src->first_free_ent;
|
||||||
ss->num_ents_allocated = src->num_ents_allocated;
|
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
|
* 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;
|
__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->continuity_gen);
|
||||||
bw_write_uv(bw, ss1->phys_iteration);
|
bw_write_uv(bw, ss1->phys_iteration);
|
||||||
|
|
||||||
bw_write_uv(bw, receiver->handle.gen);
|
bw_write_u128(bw, sim_ent_get_netid(receiver_client).v);
|
||||||
bw_write_uv(bw, receiver->handle.idx);
|
|
||||||
|
|
||||||
/* Ents */
|
/* Ents */
|
||||||
if (ss1->num_ents_allocated == ss0->num_ents_allocated) {
|
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->continuity_gen = br_read_uv(br);
|
||||||
ss->phys_iteration = br_read_uv(br);
|
ss->phys_iteration = br_read_uv(br);
|
||||||
|
|
||||||
ss->local_client.gen = br_read_uv(br);
|
ss->local_client_netid.v = br_read_u128(br);
|
||||||
ss->local_client.idx = br_read_uv(br);
|
|
||||||
|
|
||||||
/* Ents */
|
/* Ents */
|
||||||
if (br_read_bit(br)) {
|
if (br_read_bit(br)) {
|
||||||
|
|||||||
25
src/sim.h
25
src/sim.h
@ -79,6 +79,9 @@ struct sim_client {
|
|||||||
struct sim_client_handle next_in_bucket;
|
struct sim_client_handle next_in_bucket;
|
||||||
struct sim_client_handle prev_in_bucket;
|
struct sim_client_handle prev_in_bucket;
|
||||||
|
|
||||||
|
/* The client entity's net id in the master sim (if one is present) */
|
||||||
|
struct sim_netid client_ent_netid;
|
||||||
|
|
||||||
/* This is the last confirmed tick of ours that we know this client has received */
|
/* This is the last confirmed tick of ours that we know this client has received */
|
||||||
u64 ack;
|
u64 ack;
|
||||||
|
|
||||||
@ -137,6 +140,8 @@ struct sim_control {
|
|||||||
u32 flags;
|
u32 flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sim_ent_bucket;
|
||||||
|
|
||||||
struct sim_snapshot {
|
struct sim_snapshot {
|
||||||
b32 valid;
|
b32 valid;
|
||||||
u64 tick;
|
u64 tick;
|
||||||
@ -163,8 +168,11 @@ struct sim_snapshot {
|
|||||||
/* The last physics iteration (used for tracking contact lifetime) */
|
/* The last physics iteration (used for tracking contact lifetime) */
|
||||||
u64 phys_iteration;
|
u64 phys_iteration;
|
||||||
|
|
||||||
/* TODO: Replace with networked id that resolves to local client ent? */
|
struct sim_netid local_client_netid; /* The netid of the receiver's 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) */
|
|
||||||
|
/* Net id lookup */
|
||||||
|
struct sim_ent_bucket *netid_buckets;
|
||||||
|
u64 num_netid_buckets;
|
||||||
|
|
||||||
/* Entities */
|
/* Entities */
|
||||||
struct arena ents_arena;
|
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);
|
struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend);
|
||||||
|
|
||||||
/* Encode / decode */
|
/* Encode / decode */
|
||||||
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_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);
|
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
|
#endif
|
||||||
|
|||||||
140
src/sim_ent.c
140
src/sim_ent.c
@ -2,12 +2,13 @@
|
|||||||
#include "sim.h"
|
#include "sim.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "bitbuff.h"
|
#include "bitbuff.h"
|
||||||
|
#include "rng.h"
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Ent allocation
|
* 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 *ent = NULL;
|
||||||
struct sim_ent_handle handle = ZI;
|
struct sim_ent_handle handle = ZI;
|
||||||
@ -31,26 +32,60 @@ INTERNAL struct sim_ent *sim_ent_alloc_internal(struct sim_snapshot *ss)
|
|||||||
return ent;
|
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);
|
ASSERT(parent->valid);
|
||||||
struct sim_snapshot *ss = parent->ss;
|
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);
|
sim_ent_link_parent(e, parent);
|
||||||
return e;
|
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;
|
struct sim_snapshot *ss = ent->ss;
|
||||||
/* Release children */
|
/* Release children */
|
||||||
struct sim_ent_handle first_handle = ent->first;
|
struct sim_ent_handle first_handle = ent->first;
|
||||||
if (first_handle.gen) {
|
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)) {
|
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 */
|
/* Release */
|
||||||
++ent->handle.gen;
|
++ent->handle.gen;
|
||||||
ent->valid = false;
|
ent->valid = false;
|
||||||
@ -64,7 +99,92 @@ void sim_ent_release(struct sim_ent *ent)
|
|||||||
if (ent->parent.gen) {
|
if (ent->parent.gen) {
|
||||||
sim_ent_unlink_from_parent(ent);
|
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_snapshot *ss = e->ss;
|
||||||
|
|
||||||
|
struct sim_netid old_netid = sim_ent_get_netid(e);
|
||||||
|
|
||||||
u64 pos = 0;
|
u64 pos = 0;
|
||||||
while (pos < sizeof(*e)) {
|
while (pos < sizeof(*e)) {
|
||||||
u8 *chunk = (u8 *)e + pos;
|
u8 *chunk = (u8 *)e + pos;
|
||||||
@ -417,5 +539,11 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e)
|
|||||||
pos += 8;
|
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;
|
e->ss = ss;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,13 +13,12 @@ struct bitbuff_writer;
|
|||||||
struct bitbuff_reader;
|
struct bitbuff_reader;
|
||||||
|
|
||||||
enum sim_ent_prop {
|
enum sim_ent_prop {
|
||||||
SIM_ENT_PROP_NONE,
|
|
||||||
|
|
||||||
SIM_ENT_PROP_ACTIVE,
|
SIM_ENT_PROP_ACTIVE,
|
||||||
|
|
||||||
SIM_ENT_PROP_RELEASE,
|
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_CLIENT,
|
||||||
SIM_ENT_PROP_LOCAL_CLIENT,
|
SIM_ENT_PROP_LOCAL_CLIENT,
|
||||||
|
|
||||||
@ -85,20 +84,29 @@ struct sim_ent {
|
|||||||
struct sim_ent_handle prev;
|
struct sim_ent_handle prev;
|
||||||
struct sim_ent_handle first;
|
struct sim_ent_handle first;
|
||||||
struct sim_ent_handle last;
|
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;
|
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;
|
/* Handle of the client that owns the src ent of this dst ent */
|
||||||
struct sim_ent_handle remote_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 */
|
/* 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 _local_xform; /* Transform in relation to parent ent (or the world if ent has no parent) */
|
||||||
struct xform _xform; /* Calculated from ent tree */
|
struct xform _xform; /* Calculated from ent tree */
|
||||||
b32 _is_xform_dirty;
|
b32 _is_xform_dirty;
|
||||||
@ -324,6 +332,11 @@ struct sim_ent_prop_array {
|
|||||||
u64 count;
|
u64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sim_ent_bucket {
|
||||||
|
struct sim_ent_handle first;
|
||||||
|
struct sim_ent_handle last;
|
||||||
|
};
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Handle helpers
|
* Handle helpers
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -378,9 +391,20 @@ INLINE b32 sim_ent_is_valid_and_active(struct sim_ent *ent)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Alloc */
|
/* 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);
|
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 */
|
/* Query */
|
||||||
struct sim_ent *sim_ent_from_handle(struct sim_snapshot *ss, struct sim_ent_handle handle);
|
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);
|
struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_ent_prop prop);
|
||||||
|
|||||||
114
src/sim_step.c
114
src/sim_step.c
@ -159,7 +159,6 @@ struct sim_accel sim_accel_alloc(void)
|
|||||||
{
|
{
|
||||||
struct sim_accel accel = ZI;
|
struct sim_accel accel = ZI;
|
||||||
accel.space = space_alloc(1, 256);
|
accel.space = space_alloc(1, 256);
|
||||||
accel.remote_lookup = sim_lookup_alloc(4096);
|
|
||||||
accel.client_lookup = sim_lookup_alloc(4096);
|
accel.client_lookup = sim_lookup_alloc(4096);
|
||||||
accel.contact_lookup = sim_lookup_alloc(4096);
|
accel.contact_lookup = sim_lookup_alloc(4096);
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
@ -175,7 +174,6 @@ void sim_accel_release(struct sim_accel *accel)
|
|||||||
#endif
|
#endif
|
||||||
sim_lookup_release(&accel->contact_lookup);
|
sim_lookup_release(&accel->contact_lookup);
|
||||||
sim_lookup_release(&accel->client_lookup);
|
sim_lookup_release(&accel->client_lookup);
|
||||||
sim_lookup_release(&accel->remote_lookup);
|
|
||||||
space_release(accel->space);
|
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 */
|
/* FIXME: Rebuild collision debug lookup */
|
||||||
|
|
||||||
space_reset(accel->space);
|
space_reset(accel->space);
|
||||||
sim_lookup_reset(&accel->remote_lookup);
|
|
||||||
sim_lookup_reset(&accel->client_lookup);
|
sim_lookup_reset(&accel->client_lookup);
|
||||||
sim_lookup_reset(&accel->contact_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) {
|
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
|
||||||
struct sim_ent *ent = &ss->ents[sim_ent_index];
|
struct sim_ent *ent = &ss->ents[sim_ent_index];
|
||||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||||
if (sim_ent_has_prop(ent, SIM_ENT_PROP_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)) {
|
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CLIENT)) {
|
||||||
struct sim_lookup_key key = sim_lookup_key_from_client_handle(ent->client_handle);
|
struct sim_lookup_key key = sim_lookup_key_from_client_handle(ent->client_handle);
|
||||||
sim_lookup_set(&accel->client_lookup, key, ent->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 */
|
/* 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);
|
struct v2 pos = V2(1, -2);
|
||||||
pos = v2_add(pos, offset);
|
pos = v2_add(pos, offset);
|
||||||
@ -253,7 +246,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(root);
|
struct sim_ent *e = sim_ent_alloc_net_src(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);
|
||||||
@ -277,7 +270,7 @@ INTERNAL void spawn_test_entities(struct sim_snapshot *world, struct v2 offset)
|
|||||||
/* Tiny box */
|
/* Tiny box */
|
||||||
#if 0
|
#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);
|
struct v2 pos = V2(1, -0.5);
|
||||||
pos = v2_add(pos, offset);
|
pos = v2_add(pos, offset);
|
||||||
@ -307,7 +300,7 @@ INTERNAL struct sim_ent *spawn_test_player(struct sim_snapshot *world)
|
|||||||
//if (!ctx->extra_spawn) {
|
//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);
|
struct v2 pos = V2(1, -1);
|
||||||
|
|
||||||
@ -360,7 +353,7 @@ INTERNAL struct sim_ent *spawn_test_player(struct sim_snapshot *world)
|
|||||||
|
|
||||||
/* Player weapon */
|
/* Player weapon */
|
||||||
if (player_ent->valid) {
|
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"));
|
e->sprite = sprite_tag_from_path(LIT("res/graphics/gun.ase"));
|
||||||
|
|
||||||
sim_ent_enable_prop(e, SIM_ENT_PROP_ATTACHED);
|
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();
|
struct sim_ent *camera_ent = sim_ent_nil();
|
||||||
if (player_ent->valid) {
|
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_set_xform(camera_ent, XFORM_IDENT);
|
||||||
|
|
||||||
sim_ent_enable_prop(camera_ent, SIM_ENT_PROP_CAMERA);
|
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 */
|
/* TODO: Remove this */
|
||||||
{
|
{
|
||||||
struct xform xf = XFORM_TRS(.t = point, .r = rng_rand_f32(0, TAU));
|
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 = sprite_tag_from_path(LIT("res/graphics/blood.ase"));
|
||||||
decal->sprite_tint = RGBA_32_F(1, 1, 1, 0.25f);
|
decal->sprite_tint = RGBA_32_F(1, 1, 1, 0.25f);
|
||||||
decal->layer = SIM_LAYER_FLOOR_DECALS;
|
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
|
* Create client player ents
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -1070,7 +984,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
/* Spawn bullet */
|
/* Spawn bullet */
|
||||||
struct sim_ent *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 = ent->handle;
|
||||||
bullet->bullet_src_pos = rel_pos;
|
bullet->bullet_src_pos = rel_pos;
|
||||||
@ -1097,7 +1011,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
|
|
||||||
/* Spawn tracer */
|
/* 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->tracer_fade_duration = 0.025f;
|
||||||
tracer->layer = SIM_LAYER_TRACERS;
|
tracer->layer = SIM_LAYER_TRACERS;
|
||||||
sim_ent_enable_prop(tracer, SIM_ENT_PROP_TRACER);
|
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)) {
|
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) {
|
||||||
struct sim_ent *joint_ent = sim_ent_from_handle(world, ent->move_joint);
|
struct sim_ent *joint_ent = sim_ent_from_handle(world, ent->move_joint);
|
||||||
if (!sim_ent_is_valid_and_active(joint_ent)) {
|
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->mass_unscaled = F32_INFINITY;
|
||||||
joint_ent->inertia_unscaled = F32_INFINITY;
|
joint_ent->inertia_unscaled = F32_INFINITY;
|
||||||
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT);
|
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 */
|
/* Retrieve / create aim joint */
|
||||||
struct sim_ent *joint_ent = sim_ent_from_handle(world, ent->aim_joint);
|
struct sim_ent *joint_ent = sim_ent_from_handle(world, ent->aim_joint);
|
||||||
if (!sim_ent_is_valid_and_active(joint_ent)) {
|
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->mass_unscaled = F32_INFINITY;
|
||||||
joint_ent->inertia_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 */
|
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;
|
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 (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)) {
|
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_MOTOR_JOINT);
|
||||||
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_ACTIVE);
|
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_ACTIVE);
|
||||||
joint_ent->motor_joint_data = phys_motor_joint_from_def(def);
|
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(target_ent)) {
|
||||||
if (!sim_ent_is_valid_and_active(joint_ent)) {
|
if (!sim_ent_is_valid_and_active(joint_ent)) {
|
||||||
/* FIXME: Joint ent may never release */
|
/* 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->mass_unscaled = F32_INFINITY;
|
||||||
joint_ent->inertia_unscaled = F32_INFINITY;
|
joint_ent->inertia_unscaled = F32_INFINITY;
|
||||||
client_ent->client_dbg_drag_joint_ent = joint_ent->handle;
|
client_ent->client_dbg_drag_joint_ent = joint_ent->handle;
|
||||||
@ -1413,7 +1327,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
|
|
||||||
/* Spawn quake */
|
/* 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));
|
sim_ent_set_xform(quake, XFORM_POS(pos));
|
||||||
quake->quake_intensity = 0.2f;
|
quake->quake_intensity = 0.2f;
|
||||||
quake->quake_fade = quake->quake_intensity / 0.1f;
|
quake->quake_fade = quake->quake_intensity / 0.1f;
|
||||||
|
|||||||
@ -58,7 +58,6 @@ struct sim_lookup_key sim_lookup_key_from_client_handle(struct sim_client_handle
|
|||||||
|
|
||||||
struct sim_accel {
|
struct sim_accel {
|
||||||
struct space *space;
|
struct space *space;
|
||||||
struct sim_lookup remote_lookup;
|
|
||||||
struct sim_lookup client_lookup;
|
struct sim_lookup client_lookup;
|
||||||
struct sim_lookup contact_lookup;
|
struct sim_lookup contact_lookup;
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
|
|||||||
@ -416,6 +416,7 @@ b32 string_ends_with(struct string str, struct string substring)
|
|||||||
* FMT_FLOAT_P: Format an f64 with specified precision
|
* FMT_FLOAT_P: Format an f64 with specified precision
|
||||||
* FMT_HEX: Format a u64 in hexadecimal notation
|
* FMT_HEX: Format a u64 in hexadecimal notation
|
||||||
* FMT_PTR: Format a pointer in hexadecimal notation prefixed by "0x"
|
* 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
|
* FMT_END (internal): Denote the end of the va_list
|
||||||
*
|
*
|
||||||
|
|||||||
194
src/user.c
194
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 temp_arena scratch = scratch_begin(arena);
|
||||||
struct sim_snapshot *ss = ent->ss;
|
struct sim_snapshot *ss = ent->ss;
|
||||||
|
|
||||||
|
const u8 hex[] = "0123456789abcdef";
|
||||||
|
|
||||||
struct string res = ZI;
|
struct string res = ZI;
|
||||||
res.text = arena_dry_push(arena, u8);
|
res.text = arena_dry_push(arena, u8);
|
||||||
|
|
||||||
{
|
{
|
||||||
const u8 hex[] = "0123456789abcdef";
|
|
||||||
res.len += string_copy(arena, LIT("props: 0x")).len;
|
res.len += string_copy(arena, LIT("props: 0x")).len;
|
||||||
for (u64 chunk_index = ARRAY_COUNT(ent->props); chunk_index-- > 0;) {
|
for (u64 chunk_index = ARRAY_COUNT(ent->props); chunk_index-- > 0;) {
|
||||||
u64 chunk = ent->props[chunk_index];
|
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;
|
res.len += string_copy(arena, LIT("\n")).len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
struct sim_netid netid = sim_ent_get_netid(ent);
|
||||||
|
if (!sim_netid_eq(netid, SIM_NETID_NIL)) {
|
||||||
|
res.len += string_copy(arena, LIT("net id: 0x")).len;
|
||||||
|
u64 hi = U128_HI(netid.v);
|
||||||
|
u64 lo = U128_LO(netid.v);
|
||||||
|
res.len += string_from_uint(arena, hi, 16).len;
|
||||||
|
res.len += string_from_uint(arena, lo, 16).len;
|
||||||
|
res.len += string_copy(arena, LIT("\n")).len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!sim_ent_handle_eq(ent->parent, SIM_ENT_ROOT_HANDLE)) {
|
if (!sim_ent_handle_eq(ent->parent, SIM_ENT_ROOT_HANDLE)) {
|
||||||
res.len += string_format(arena, LIT("parent: <%F>\n"), FMT_HANDLE(ent->parent)).len;
|
res.len += string_format(arena, LIT("parent: <%F>\n"), FMT_HANDLE(ent->parent)).len;
|
||||||
}
|
}
|
||||||
@ -672,21 +685,7 @@ INTERNAL void user_update(void)
|
|||||||
* Find local entities
|
* Find local entities
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sim_ent *local_client_ent = sim_ent_nil();
|
struct sim_ent *local_client_ent = sim_ent_from_netid(G.ss_blended, G.ss_blended->local_client_netid);
|
||||||
{
|
|
||||||
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_player = sim_ent_from_handle(G.ss_blended, local_client_ent->client_control_ent);
|
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);
|
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)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define translate(fieldname) local->fieldname = _translate(local_ss, remote_ss, remote->fieldname)
|
||||||
/* TODO: Move this */
|
INTERNAL struct sim_ent_handle _translate(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss, struct sim_ent_handle remote_ent_handle)
|
||||||
|
|
||||||
|
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
if (!sim_ent_handle_eq(remote_ent_handle, SIM_ENT_ROOT_HANDLE)) {
|
struct sim_ent_handle local_handle = SIM_ENT_NIL_HANDLE;
|
||||||
struct sim_lookup_key key = sim_lookup_key_from_client_and_ent_handles(remote_client_handle, remote_ent_handle);
|
struct sim_ent *remote_ent = sim_ent_from_handle(remote_ss, remote_ent_handle);
|
||||||
struct sim_lookup_entry *entry = sim_lookup_get(remote_lookup, key);
|
if (remote_ent->valid) {
|
||||||
return entry ? entry->ent : old_local_handle;
|
struct sim_netid netid = sim_ent_get_netid(remote_ent);
|
||||||
} else {
|
struct sim_ent *local_ent = sim_ent_from_netid(local_ss, netid);
|
||||||
return SIM_ENT_ROOT_HANDLE;
|
local_handle = local_ent->handle;
|
||||||
}
|
}
|
||||||
|
return local_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INTERNAL void sim_ent_sync_remote(struct sim_ent *local, struct sim_ent *remote)
|
||||||
INTERNAL void sim_ent_sync_remote(struct sim_accel *accel, struct sim_ent *local, struct sim_ent *remote, struct sim_ent *client_ent)
|
|
||||||
{
|
{
|
||||||
struct sim_client_handle remote_client_handle = remote->ss->client->handle;
|
struct sim_snapshot *local_ss = local->ss;
|
||||||
struct sim_lookup *remote_lookup = &accel->remote_lookup;
|
struct sim_snapshot *remote_ss = remote->ss;
|
||||||
|
struct sim_client_handle remote_client_handle = remote_ss->client->handle;
|
||||||
|
|
||||||
struct sim_ent old = *local;
|
struct sim_ent old = *local;
|
||||||
MEMCPY_STRUCT(local, remote);
|
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 */
|
/* Keep non-remote handles */
|
||||||
local->ss = old.ss;
|
local->ss = old.ss;
|
||||||
local->handle = old.handle;
|
local->handle = old.handle;
|
||||||
local->remote_client = remote_client_handle;
|
local->net_src_client = remote_client_handle;
|
||||||
local->remote_ent = remote->handle;
|
|
||||||
local->parent = old.parent;
|
local->parent = old.parent;
|
||||||
local->prev = old.prev;
|
local->prev = old.prev;
|
||||||
local->next = old.next;
|
local->next = old.next;
|
||||||
local->first = old.first;
|
local->first = old.first;
|
||||||
local->last = old.last;
|
local->last = old.last;
|
||||||
local->top = old.top;
|
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;
|
local->next_free = old.next_free;
|
||||||
|
|
||||||
/* Translate remote handles */
|
/* 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_src);
|
||||||
translate(bullet_tracer);
|
translate(bullet_tracer);
|
||||||
translate(camera_follow);
|
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;
|
__prof;
|
||||||
struct sim_snapshot *remote_ss = remote->ss;
|
if (sim_ent_has_prop(remote, SIM_ENT_PROP_NET_SRC)) {
|
||||||
struct sim_client_handle remote_client_handle = remote_ss->client->handle;
|
struct sim_snapshot *local_ss = local_parent->ss;
|
||||||
struct sim_lookup *remote_lookup = &accel->remote_lookup;
|
struct sim_snapshot *remote_ss = remote->ss;
|
||||||
|
struct sim_client_handle remote_client_handle = remote_ss->client->handle;
|
||||||
|
|
||||||
if (remote->valid) {
|
struct sim_netid netid = sim_ent_get_netid(remote);
|
||||||
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_from_netid(local_ss, netid);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!local_ent->valid) {
|
if (!local_ent->valid) {
|
||||||
local_ent = sim_ent_alloc(local_parent);
|
local_ent = sim_ent_alloc_net_dst(local_parent, remote_client_handle, netid);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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)) {
|
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;
|
__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_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_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 */
|
/* 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)) {
|
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 */
|
/* Sync ents with remote */
|
||||||
for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) {
|
for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) {
|
||||||
struct sim_ent *local_ent = &local_ss->ents[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)) {
|
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_ent *remote_ent = sim_ent_from_handle(remote_ss, local_ent->remote_ent);
|
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) {
|
if (remote_ent->valid) {
|
||||||
/* Copy all ent data from remote */
|
/* 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 {
|
} else {
|
||||||
/* Remote ent is no longer valid / networked, release it */
|
/* Remote ent is no longer valid / networked, release it */
|
||||||
sim_ent_enable_prop(local_ent, SIM_ENT_PROP_RELEASE);
|
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);
|
host_update(host);
|
||||||
struct host_event_array host_events = host_pop_events(scratch.arena, host);
|
struct host_event_array host_events = host_pop_events(scratch.arena, host);
|
||||||
for (u64 i = 0; i < host_events.count; ++i) {
|
for (u64 event_index = 0; event_index < host_events.count; ++event_index) {
|
||||||
struct host_event *event = &host_events.events[i];
|
struct host_event *event = &host_events.events[event_index];
|
||||||
struct host_channel_id channel_id = event->channel_id;
|
struct host_channel_id channel_id = event->channel_id;
|
||||||
struct sim_client *client = sim_client_from_channel_id(store, channel_id);
|
struct sim_client *client = sim_client_from_channel_id(store, channel_id);
|
||||||
switch (event->kind) {
|
switch (event->kind) {
|
||||||
@ -2078,6 +2044,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
/* Alloc & decode snapshot */
|
/* Alloc & decode snapshot */
|
||||||
struct sim_snapshot *ss = sim_snapshot_alloc(client, base_ss, tick);
|
struct sim_snapshot *ss = sim_snapshot_alloc(client, base_ss, tick);
|
||||||
sim_snapshot_decode(&decoder_br, ss);
|
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 {
|
} else {
|
||||||
/* We do not have the tick that the incoming delta is based from */
|
/* We do not have the tick that the incoming delta is based from */
|
||||||
@ -2103,12 +2076,12 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
/* Create user input */
|
/* Create user input */
|
||||||
{
|
{
|
||||||
struct sim_snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_tick);
|
struct sim_snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_tick);
|
||||||
struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, step_tick);
|
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);
|
struct sim_ent *user_input_root = sim_ent_from_handle(user_input_ss, SIM_ENT_ROOT_HANDLE);
|
||||||
/* Find / create local control cmd ent */
|
/* Find / create local control cmd ent */
|
||||||
struct sim_ent *control_cmd_ent = sim_ent_find_first_match_one(user_input_ss, SIM_ENT_PROP_CMD_CONTROL);
|
struct sim_ent *control_cmd_ent = sim_ent_find_first_match_one(user_input_ss, SIM_ENT_PROP_CMD_CONTROL);
|
||||||
if (!control_cmd_ent->valid) {
|
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_enable_prop(control_cmd_ent, SIM_ENT_PROP_CMD_CONTROL);
|
||||||
sim_ent_activate(control_cmd_ent, user_input_ss->tick);
|
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();
|
struct sim_ent *client_ent = client_entry ? sim_ent_from_handle(local_ss, client_entry->ent) : sim_ent_nil();
|
||||||
if (!client_ent->valid) {
|
if (!client_ent->valid) {
|
||||||
/* FIXME: Client ent never released upon disconnect */
|
/* FIXME: Client ent never released upon disconnect */
|
||||||
client_ent = sim_ent_alloc(local_root);
|
client_ent = sim_ent_alloc_net_src(local_root);
|
||||||
client_ent->client_handle = client->handle;
|
client_ent->client_handle = client->handle;
|
||||||
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_CLIENT);
|
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_CLIENT);
|
||||||
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_ACTIVE);
|
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_ACTIVE);
|
||||||
sim_lookup_set(&accel.client_lookup, key, client_ent->handle);
|
sim_lookup_set(&accel.client_lookup, key, client_ent->handle);
|
||||||
if (client == user_input_client) {
|
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) {
|
if (client != publish_client && client != local_client) {
|
||||||
struct sim_snapshot *client_ss = sim_snapshot_from_tick(client, step_tick);
|
struct sim_snapshot *client_ss = sim_snapshot_from_tick(client, step_tick);
|
||||||
if (client_ss->valid) {
|
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) {
|
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 */
|
/* Release unneeded snapshots */
|
||||||
for (u64 i = 0; i < store->num_clients_reserved; ++i) {
|
for (u64 i = 0; i < store->num_clients_reserved; ++i) {
|
||||||
struct sim_client *client = &store->clients[i];
|
struct sim_client *client = &store->clients[i];
|
||||||
@ -2245,6 +2235,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
|
|
||||||
|
|
||||||
/* Construct publishable snapshot */
|
/* Construct publishable snapshot */
|
||||||
|
#if 0
|
||||||
{
|
{
|
||||||
if (is_master) {
|
if (is_master) {
|
||||||
//struct sim_snapshot *prev_pub_ss = sim_snapshot_from_tick(publish_client, publish_client->last_tick);
|
//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;
|
(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) {
|
for (u64 i = 0; i < store->num_clients_reserved; ++i) {
|
||||||
struct sim_client *client = &store->clients[i];
|
struct sim_client *client = &store->clients[i];
|
||||||
if (client->valid && client != user_input_client && client != local_client && client != publish_client) {
|
if (client->valid && client != user_input_client && client != local_client && client != publish_client) {
|
||||||
|
struct sim_ent *client_ent = sim_ent_nil();
|
||||||
|
{
|
||||||
|
struct sim_lookup_key key = sim_lookup_key_from_client_handle(client->handle);
|
||||||
|
struct sim_lookup_entry *client_entry = sim_lookup_get(&accel.client_lookup, key);
|
||||||
|
client_ent = client_entry ? sim_ent_from_handle(local_ss, client_entry->ent) : sim_ent_nil();
|
||||||
|
}
|
||||||
|
|
||||||
struct bitbuff_writer msg_bw = bw_from_bitbuff(&msg_writer_bb);
|
struct bitbuff_writer msg_bw = bw_from_bitbuff(&msg_writer_bb);
|
||||||
|
|
||||||
bw_write_uv(&msg_bw, client->last_tick); /* ack */
|
bw_write_uv(&msg_bw, client->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, base_ss->tick);
|
||||||
bw_write_uv(&snapshot_bw, publish_ss->tick);
|
bw_write_uv(&snapshot_bw, publish_ss->tick);
|
||||||
sim_snapshot_encode(&snapshot_bw, client, 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.len = bw_num_bytes_written(&snapshot_bw);
|
||||||
tmp_snapshot_encoded.text = bw_get_written_raw(&snapshot_bw);
|
tmp_snapshot_encoded.text = bw_get_written_raw(&snapshot_bw);
|
||||||
}
|
}
|
||||||
@ -2317,7 +2323,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
|||||||
/* TODO: Double buffer */
|
/* TODO: Double buffer */
|
||||||
struct sys_lock lock = sys_mutex_lock_e(&G.local_to_user_client_mutex);
|
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);
|
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();
|
i64 publish_ns = sys_time_ns();
|
||||||
copy_ss->publish_dt_ns = publish_ns - last_publish_ns;
|
copy_ss->publish_dt_ns = publish_ns - last_publish_ns;
|
||||||
copy_ss->publish_time_ns = publish_ns;
|
copy_ss->publish_time_ns = publish_ns;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user