working prediction prototype
This commit is contained in:
parent
a16a60dd5d
commit
48dbcacd45
28
src/sim.c
28
src/sim.c
@ -599,32 +599,36 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, str
|
||||
* ========================== */
|
||||
|
||||
/* Syncs entity data between snapshots */
|
||||
void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss)
|
||||
void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss, struct sim_ent_id remote_client_ent)
|
||||
{
|
||||
__prof;
|
||||
|
||||
/* FIXME: Only sync cmds from non-master remote */
|
||||
/* FIXME: Only sync ents from correct owner */
|
||||
|
||||
struct sim_ent *local_root = sim_ent_from_id(local_ss, SIM_ENT_ROOT_ID);
|
||||
struct sim_ent *remote_root = sim_ent_from_id(remote_ss, SIM_ENT_ROOT_ID);
|
||||
struct sim_client_handle remote_client_handle = remote_ss->client->handle;
|
||||
|
||||
/* Create new ents from remote */
|
||||
for (struct sim_ent *remote_top = sim_ent_from_id(remote_ss, remote_root->first); remote_top->valid; remote_top = sim_ent_from_id(remote_ss, remote_top->next)) {
|
||||
sim_ent_sync_alloc_tree(local_root, remote_top);
|
||||
sim_ent_sync_alloc_tree(local_root, remote_top, remote_client_ent);
|
||||
}
|
||||
|
||||
/* 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_SYNC_DST) && sim_client_handle_eq(local_ent->sync_src_client, remote_client_handle)) {
|
||||
struct sim_ent *remote_ent = sim_ent_from_id(remote_ss, local_ent->id);
|
||||
if (remote_ent->valid) {
|
||||
/* Copy all ent data from remote */
|
||||
sim_ent_sync(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_SYNC_DST);
|
||||
if (local_ent->valid && sim_ent_has_prop(local_ent, SIM_ENT_PROP_SYNC_DST)) {
|
||||
b32 should_sync = sim_ent_id_eq(local_ent->owner, remote_client_ent) || sim_ent_id_eq(remote_client_ent, SIM_ENT_NIL_ID);
|
||||
if (should_sync) {
|
||||
struct sim_ent *remote_ent = sim_ent_from_id(remote_ss, local_ent->id);
|
||||
if (remote_ent->valid) {
|
||||
/* Copy all ent data from remote */
|
||||
sim_ent_sync(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_SYNC_DST);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,7 +171,8 @@ struct sim_snapshot {
|
||||
/* The last physics iteration (used for tracking contact lifetime) */
|
||||
u64 phys_iteration;
|
||||
|
||||
struct sim_ent_id local_client_ent; /* The id of the receiver's client ent */
|
||||
/* The id of the receiver's client ent in the snapshot */
|
||||
struct sim_ent_id local_client_ent;
|
||||
|
||||
/* Id lookup */
|
||||
struct sim_ent_bin *id_bins;
|
||||
@ -208,7 +209,7 @@ struct sim_snapshot *sim_snapshot_from_closest_tick_gte(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);
|
||||
|
||||
/* Sync */
|
||||
void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss);
|
||||
void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss, struct sim_ent_id remote_client_ent);
|
||||
|
||||
/* Encode / decode */
|
||||
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1);
|
||||
|
||||
@ -80,24 +80,24 @@ struct sim_ent *sim_ent_alloc_sync_src(struct sim_ent *parent)
|
||||
sim_ent_set_id(e, sim_ent_random_id());
|
||||
|
||||
sim_ent_enable_prop(e, SIM_ENT_PROP_SYNC_SRC);
|
||||
e->sync_src_client = ss->client->handle;
|
||||
e->owner = ss->local_client_ent;
|
||||
|
||||
sim_ent_link_parent(e, parent);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Allocates a new entity that will sync with incoming net src ents containing uid, and coming from the specified client */
|
||||
struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, struct sim_client_handle client_handle, struct sim_ent_id id)
|
||||
/* Allocates a new entity that will sync with incoming net src ents containing id, and coming from the specified owner */
|
||||
struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, struct sim_ent_id ent_id, struct sim_ent_id owner_client_ent_id)
|
||||
{
|
||||
struct sim_snapshot *ss = parent->ss;
|
||||
struct sim_ent *e = sim_ent_alloc_raw(ss);
|
||||
sim_ent_set_id(e, id);
|
||||
sim_ent_set_id(e, ent_id);
|
||||
|
||||
sim_ent_link_parent(e, parent);
|
||||
|
||||
sim_ent_enable_prop(e, SIM_ENT_PROP_SYNC_DST);
|
||||
e->sync_src_client = client_handle;
|
||||
e->owner = owner_client_ent_id;
|
||||
|
||||
return e;
|
||||
}
|
||||
@ -552,21 +552,20 @@ void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64
|
||||
* ========================== */
|
||||
|
||||
/* Walks a local & remote ent tree and allocates any missing net dst ents from remote src ents */
|
||||
void sim_ent_sync_alloc_tree(struct sim_ent *local_parent, struct sim_ent *remote)
|
||||
void sim_ent_sync_alloc_tree(struct sim_ent *local_parent, struct sim_ent *remote, struct sim_ent_id remote_client_ent)
|
||||
{
|
||||
__prof;
|
||||
if (sim_ent_has_prop(remote, SIM_ENT_PROP_SYNC_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;
|
||||
|
||||
struct sim_ent_id id = remote->id;
|
||||
struct sim_ent *local_ent = sim_ent_from_id(local_ss, id);
|
||||
if (!local_ent->valid) {
|
||||
local_ent = sim_ent_alloc_sync_dst(local_parent, remote_client_handle, id);
|
||||
local_ent = sim_ent_alloc_sync_dst(local_parent, id, remote_client_ent);
|
||||
}
|
||||
for (struct sim_ent *remote_child = sim_ent_from_id(remote_ss, remote->first); remote_child->valid; remote_child = sim_ent_from_id(remote_ss, remote_child->next)) {
|
||||
sim_ent_sync_alloc_tree(local_ent, remote_child);
|
||||
sim_ent_sync_alloc_tree(local_ent, remote_child, remote_client_ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -581,7 +580,6 @@ void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote)
|
||||
ASSERT(sim_ent_id_eq(local->id, old.id));
|
||||
|
||||
local->ss = old.ss;
|
||||
local->sync_src_client = remote->ss->client->handle;
|
||||
|
||||
/* Keep local tree */
|
||||
local->parent = old.parent;
|
||||
@ -590,6 +588,7 @@ void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote)
|
||||
local->first = old.first;
|
||||
local->last = old.last;
|
||||
local->top = old.top;
|
||||
local->owner = old.owner;
|
||||
|
||||
/* Keep indices */
|
||||
local->next_in_id_bin = old.next_in_id_bin;
|
||||
|
||||
@ -97,9 +97,6 @@ struct sim_ent {
|
||||
/* SIM_ENT_PROP_SYNC_DST */
|
||||
/* SIM_ENT_PROP_SYNC_PREDICT */
|
||||
|
||||
/* Handle of the client that this ent was synced from (if any) */
|
||||
struct sim_client_handle sync_src_client;
|
||||
|
||||
/* Id of the client ent that owns simulation for this entity */
|
||||
struct sim_ent_id owner;
|
||||
|
||||
@ -425,7 +422,7 @@ 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_local_with_id(struct sim_ent *parent, struct sim_ent_id id);
|
||||
struct sim_ent *sim_ent_alloc_sync_src(struct sim_ent *parent);
|
||||
struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, struct sim_client_handle client_handle, struct sim_ent_id id);
|
||||
struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, struct sim_ent_id ent_id, struct sim_ent_id owner_client_ent_id);
|
||||
|
||||
void sim_ent_release_raw(struct sim_ent *ent);
|
||||
void sim_ent_release(struct sim_ent *ent);
|
||||
@ -467,7 +464,7 @@ void sim_ent_apply_torque(struct sim_ent *ent, f32 torque);
|
||||
void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64 blend);
|
||||
|
||||
/* Sync */
|
||||
void sim_ent_sync_alloc_tree(struct sim_ent *local_parent, struct sim_ent *remote);
|
||||
void sim_ent_sync_alloc_tree(struct sim_ent *local_parent, struct sim_ent *remote, struct sim_ent_id remote_client_ent);
|
||||
void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote);
|
||||
|
||||
/* Encode / decode */
|
||||
|
||||
@ -198,6 +198,8 @@ INTERNAL struct sim_ent *spawn_test_player(struct sim_snapshot *world)
|
||||
sim_ent_enable_prop(e, SIM_ENT_PROP_WEAPON);
|
||||
e->trigger_delay = 1.0f / 10.0f;
|
||||
//e->trigger_delay = 1.0f / 100.0f;
|
||||
|
||||
player_ent->equipped = e->id;
|
||||
}
|
||||
|
||||
return player_ent;
|
||||
@ -358,37 +360,34 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
* Sync remote ents
|
||||
* ========================== */
|
||||
|
||||
if (user_input_client->valid) {
|
||||
user_input_client->ent_id = world->local_client_ent;
|
||||
}
|
||||
|
||||
{
|
||||
for (u64 client_index = 0; client_index < client_store->num_clients_reserved; ++client_index) {
|
||||
struct sim_client *client = &client_store->clients[client_index];
|
||||
if (client->valid && client != world_client && client != publish_client) {
|
||||
struct sim_ent *client_ent = sim_ent_from_id(world, client->ent_id);
|
||||
|
||||
/* Create client ent if necessary */
|
||||
if (is_master) {
|
||||
struct sim_ent *client_ent = sim_ent_from_id(world, client->ent_id);
|
||||
if (!client_ent->valid) {
|
||||
/* FIXME: Client ent never released upon disconnect */
|
||||
client_ent = sim_ent_alloc_sync_src(root);
|
||||
client_ent->client_handle = client->handle;
|
||||
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_CLIENT);
|
||||
client_ent->predictor = client_ent->id;
|
||||
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_ACTIVE);
|
||||
client->ent_id = client_ent->id;
|
||||
if (client == user_input_client) {
|
||||
user_input_client->ent_id = client_ent->id;
|
||||
world_client->ent_id = client_ent->id;
|
||||
world->local_client_ent = client_ent->id;
|
||||
}
|
||||
if (is_master && !client_ent->valid) {
|
||||
/* FIXME: Client ent never released upon disconnect */
|
||||
client_ent = sim_ent_alloc_sync_src(root);
|
||||
client_ent->client_handle = client->handle;
|
||||
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_CLIENT);
|
||||
client_ent->predictor = client_ent->id;
|
||||
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_ACTIVE);
|
||||
client->ent_id = client_ent->id;
|
||||
if (client == user_input_client) {
|
||||
user_input_client->ent_id = client_ent->id;
|
||||
world_client->ent_id = client_ent->id;
|
||||
world->local_client_ent = client_ent->id;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sync ents from client */
|
||||
struct sim_snapshot *src_ss = sim_snapshot_from_tick(client, world->tick);
|
||||
if (src_ss->valid) {
|
||||
sim_snapshot_sync_ents(world, src_ss);
|
||||
if (client_ent->valid) {
|
||||
struct sim_snapshot *src_ss = sim_snapshot_from_tick(client, world->tick);
|
||||
if (src_ss->valid) {
|
||||
sim_snapshot_sync_ents(world, src_ss, client_ent->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -406,8 +405,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
for (u64 i = 0; i < world->num_ents_reserved; ++i) {
|
||||
struct sim_ent *ent = &world->ents[i];
|
||||
if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_CMD_CONTROL) && sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST)) {
|
||||
struct sim_client *src_client = sim_client_from_handle(client_store, ent->sync_src_client);
|
||||
ent->cmd_client = src_client->ent_id;
|
||||
ent->cmd_client = ent->owner;
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,7 +468,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *cmd_ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(cmd_ent)) continue;
|
||||
if (!is_master && !sim_ent_should_simulate(cmd_ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(cmd_ent, SIM_ENT_PROP_CMD_CONTROL)) {
|
||||
struct sim_ent *client_ent = sim_ent_from_id(world, cmd_ent->cmd_client);
|
||||
@ -1262,7 +1260,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
struct sim_snapshot *prev_pub_world = sim_snapshot_from_tick(publish_client, publish_client->last_tick);
|
||||
pub_world = sim_snapshot_alloc(publish_client, prev_pub_world, world->tick);
|
||||
/* Sync */
|
||||
sim_snapshot_sync_ents(pub_world, world);
|
||||
sim_snapshot_sync_ents(pub_world, world, world_client->ent_id);
|
||||
pub_world->sim_dt_ns = world->sim_dt_ns;
|
||||
pub_world->sim_time_ns = world->sim_time_ns;
|
||||
pub_world->continuity_gen = world->continuity_gen;
|
||||
|
||||
19
src/user.c
19
src/user.c
@ -349,7 +349,6 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
|
||||
res.text = arena_dry_push(arena, u8);
|
||||
|
||||
res.len += string_format(arena, LIT("[%F]"), FMT_UID(ent->id.uid)).len;
|
||||
|
||||
{
|
||||
b32 transmitting = sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_SRC);
|
||||
b32 receiving = sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST);
|
||||
@ -362,9 +361,12 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
|
||||
} else {
|
||||
res.len += string_copy(arena, LIT(" local")).len;
|
||||
}
|
||||
|
||||
res.len += string_copy(arena, LIT("\n\n")).len;
|
||||
}
|
||||
res.len += string_copy(arena, LIT("\n")).len;
|
||||
|
||||
res.len += string_format(arena, LIT("owner: [%F]\n"), FMT_UID(ent->owner.uid)).len;
|
||||
|
||||
res.len += string_copy(arena, LIT("\n")).len;
|
||||
|
||||
{
|
||||
res.len += string_copy(arena, LIT("props: 0x")).len;
|
||||
@ -1632,6 +1634,10 @@ INTERNAL void user_update(void)
|
||||
pos.y += spacing;
|
||||
pos.y += spacing;
|
||||
|
||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("local client ent: [%F]"), FMT_UID(local_client_ent->id.uid)));
|
||||
pos.y += spacing;
|
||||
pos.y += spacing;
|
||||
|
||||
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Network read: %F mbit/s"), FMT_FLOAT_P((f64)G.net_bytes_read.last_second * 8 / 1000 / 1000, 3)));
|
||||
pos.y += spacing;
|
||||
|
||||
@ -1904,7 +1910,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
||||
|
||||
u64 ahead = 0;
|
||||
if (!is_master) {
|
||||
ahead = 5;
|
||||
ahead = 50;
|
||||
}
|
||||
|
||||
|
||||
@ -2049,7 +2055,6 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
||||
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_SYNC_DST)) {
|
||||
|
||||
sim_ent_disable_prop(ent, SIM_ENT_PROP_SYNC_DST);
|
||||
sim_ent_enable_prop(ent, SIM_ENT_PROP_SYNC_SRC);
|
||||
}
|
||||
@ -2200,6 +2205,10 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
||||
} else {
|
||||
struct sim_snapshot *master_ss = sim_snapshot_from_tick(master_client, master_client->last_tick);
|
||||
if (master_ss->valid) {
|
||||
local_client->ent_id = master_ss->local_client_ent;
|
||||
user_input_client->ent_id = master_ss->local_client_ent;
|
||||
|
||||
|
||||
struct sim_snapshot *prev_world = sim_snapshot_alloc(local_client, master_ss, master_ss->tick);
|
||||
for (u64 i = 0; i < ahead; ++i) {
|
||||
ctx.world = sim_snapshot_alloc(local_client, prev_world, prev_world->tick + 1);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user