From 48dbcacd453e5db5a79ca94f4ff21dd7953aa3fa Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 25 Feb 2025 16:08:26 -0600 Subject: [PATCH] working prediction prototype --- src/sim.c | 28 ++++++++++++++++------------ src/sim.h | 5 +++-- src/sim_ent.c | 19 +++++++++---------- src/sim_ent.h | 7 ++----- src/sim_step.c | 50 ++++++++++++++++++++++++-------------------------- src/user.c | 19 ++++++++++++++----- 6 files changed, 68 insertions(+), 60 deletions(-) diff --git a/src/sim.c b/src/sim.c index 38a09438..40af86e3 100644 --- a/src/sim.c +++ b/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); + } } } } diff --git a/src/sim.h b/src/sim.h index ea94208f..fea9ac63 100644 --- a/src/sim.h +++ b/src/sim.h @@ -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); diff --git a/src/sim_ent.c b/src/sim_ent.c index c2a76cc1..aa1eaa99 100644 --- a/src/sim_ent.c +++ b/src/sim_ent.c @@ -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; diff --git a/src/sim_ent.h b/src/sim_ent.h index e6249470..94b5bffa 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -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 */ diff --git a/src/sim_step.c b/src/sim_step.c index 30a87ff3..0c0719f0 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -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; diff --git a/src/user.c b/src/user.c index 9d9d0ddf..b824d5a0 100644 --- a/src/user.c +++ b/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);