diff --git a/src/common.h b/src/common.h index e8d31664..e166163a 100644 --- a/src/common.h +++ b/src/common.h @@ -450,6 +450,7 @@ struct sim_client_handle { struct sim_ent_id { struct uid uid; }; +INLINE b32 sim_ent_id_eq(struct sim_ent_id a, struct sim_ent_id b) { return uid_eq(a.uid, b.uid); } struct space_entry_handle { u64 idx; diff --git a/src/sim_ent.c b/src/sim_ent.c index 17698b98..c2a76cc1 100644 --- a/src/sim_ent.c +++ b/src/sim_ent.c @@ -41,6 +41,7 @@ struct sim_ent *sim_ent_alloc_raw(struct sim_snapshot *ss) *ent = *sim_ent_nil(); ent->ss = ss; ent->valid = true; + ent->owner = ss->client->ent_id; ent->_is_xform_dirty = true; ++ss->num_ents_allocated; return ent; diff --git a/src/sim_ent.h b/src/sim_ent.h index 308e9df4..e6249470 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -18,7 +18,6 @@ enum sim_ent_prop { SIM_ENT_PROP_SYNC_SRC, /* This entity should be networked to other clients */ SIM_ENT_PROP_SYNC_DST, /* This entity is not locally created, and should sync with incoming net src ents */ - SIM_ENT_PROP_SYNC_PREDICT, SIM_ENT_PROP_CLIENT, SIM_ENT_PROP_LOCAL_CLIENT, @@ -96,10 +95,16 @@ struct sim_ent { /* SIM_ENT_PROP_SYNC_SRC */ /* 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; + + struct sim_ent_id predictor; + /* ====================================================================== */ /* Position */ @@ -376,6 +381,7 @@ INLINE b32 sim_ent_is_valid_and_active(struct sim_ent *ent) return ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_ACTIVE); } +#if 0 INLINE b32 sim_ent_should_simulate(struct sim_ent *ent) { b32 res = false; @@ -387,7 +393,29 @@ INLINE b32 sim_ent_should_simulate(struct sim_ent *ent) } return res; } +#else +INLINE b32 sim_ent_should_predict(struct sim_ent *ent) +{ + return sim_ent_id_eq(ent->predictor, ent->ss->local_client_ent); +} + +INLINE b32 sim_ent_should_simulate(struct sim_ent *ent) +{ + b32 res = false; + if (sim_ent_is_valid_and_active(ent)) { + res = true; + if (sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST)) { + res = false; + if (sim_ent_should_predict(ent)) { + res = true; + } + } + } + return res; +} + +#endif /* ========================== * * Ent functions * ========================== */ @@ -407,7 +435,6 @@ void sim_ent_release_all_with_prop(struct sim_snapshot *ss, enum sim_ent_prop pr void sim_ent_activate(struct sim_ent *ent, u64 current_tick); /* Id */ -INLINE b32 sim_ent_id_eq(struct sim_ent_id a, struct sim_ent_id b) { return uid_eq(a.uid, b.uid); } void sim_ent_set_id(struct sim_ent *ent, struct sim_ent_id id); struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id); struct sim_ent_id sim_ent_random_id(void); diff --git a/src/sim_step.c b/src/sim_step.c index a73ac9cd..30a87ff3 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -183,8 +183,6 @@ INTERNAL struct sim_ent *spawn_test_player(struct sim_snapshot *world) sim_ent_enable_prop(e, SIM_ENT_PROP_PHYSICAL_DYNAMIC); - sim_ent_enable_prop(e, SIM_ENT_PROP_SYNC_PREDICT); - player_ent = e; } @@ -200,8 +198,6 @@ 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; @@ -378,7 +374,7 @@ void sim_step(struct sim_step_ctx *ctx) client_ent = sim_ent_alloc_sync_src(root); client_ent->client_handle = client->handle; sim_ent_enable_prop(client_ent, SIM_ENT_PROP_CLIENT); - sim_ent_enable_prop(client_ent, SIM_ENT_PROP_SYNC_PREDICT); + 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) { @@ -397,6 +393,15 @@ void sim_step(struct sim_step_ctx *ctx) } } + /* Mark all incoming ents as sync dsts */ + 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_SYNC_SRC) && !sim_ent_id_eq(ent->owner, world_client->ent_id)) { + sim_ent_disable_prop(ent, SIM_ENT_PROP_SYNC_SRC); + sim_ent_enable_prop(ent, SIM_ENT_PROP_SYNC_DST); + } + } + /* Mark incoming cmds with correct client */ for (u64 i = 0; i < world->num_ents_reserved; ++i) { struct sim_ent *ent = &world->ents[i]; @@ -433,7 +438,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 *ent = &world->ents[ent_index]; if (!ent->valid) continue; - if (sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST) && !sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_PREDICT)) continue; + if (sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST) && !sim_ent_should_predict(ent)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_ACTIVE)) { u64 atick = ent->activation_tick; @@ -544,6 +549,7 @@ void sim_step(struct sim_step_ctx *ctx) struct sim_ent *control_ent = sim_ent_from_id(world, ent->client_control_ent); if (!control_ent->valid) { control_ent = spawn_test_player(world); + control_ent->predictor = ent->id; sim_ent_enable_prop(control_ent, SIM_ENT_PROP_CONTROLLED); ent->client_control_ent = control_ent->id; control_ent->controlling_client = ent->id; @@ -551,6 +557,7 @@ void sim_step(struct sim_step_ctx *ctx) struct sim_ent *camera_ent = sim_ent_from_id(world, ent->client_camera_ent); if (!camera_ent->valid) { camera_ent = spawn_test_player_camera(world, control_ent); + camera_ent->predictor = ent->id; ent->client_camera_ent = camera_ent->id; } } @@ -847,6 +854,7 @@ void sim_step(struct sim_step_ctx *ctx) struct sim_ent *joint_ent = sim_ent_from_id(world, ent->move_joint); if (is_master && !sim_ent_is_valid_and_active(joint_ent)) { joint_ent = sim_ent_alloc_sync_src(root); + joint_ent->predictor = ent->predictor; joint_ent->mass_unscaled = F32_INFINITY; joint_ent->inertia_unscaled = F32_INFINITY; sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT); @@ -860,10 +868,6 @@ void sim_step(struct sim_step_ctx *ctx) def.max_force = ent->control_force; def.max_torque = 0; joint_ent->motor_joint_data = phys_motor_joint_from_def(def); - - if (sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_PREDICT)) { - sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_SYNC_PREDICT); - } } if (sim_ent_should_simulate(joint_ent)) { @@ -890,6 +894,7 @@ void sim_step(struct sim_step_ctx *ctx) struct sim_ent *joint_ent = sim_ent_from_id(world, ent->aim_joint); if (is_master && !sim_ent_is_valid_and_active(joint_ent)) { joint_ent = sim_ent_alloc_sync_src(root); + joint_ent->predictor = ent->predictor; joint_ent->mass_unscaled = F32_INFINITY; joint_ent->inertia_unscaled = F32_INFINITY; sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_PHYSICAL_KINEMATIC); /* Since we'll be setting velocity manually */ @@ -903,10 +908,6 @@ void sim_step(struct sim_step_ctx *ctx) def.max_force = 0; def.max_torque = ent->control_torque; joint_ent->motor_joint_data = phys_motor_joint_from_def(def); - - if (sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_PREDICT)) { - sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_SYNC_PREDICT); - } } if (sim_ent_should_simulate(joint_ent)) { @@ -994,14 +995,11 @@ void sim_step(struct sim_step_ctx *ctx) if (joint_ent->motor_joint_data.max_force != def.max_force || joint_ent->motor_joint_data.max_torque != def.max_torque) { if (is_master && !sim_ent_is_valid_and_active(joint_ent)) { joint_ent = sim_ent_alloc_sync_src(root); + joint_ent->predictor = ent->predictor; sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT); sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_ACTIVE); joint_ent->motor_joint_data = phys_motor_joint_from_def(def); ent->ground_friction_joint = joint_ent->id; - - if (sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_PREDICT)) { - sim_ent_enable_prop(ent, SIM_ENT_PROP_SYNC_PREDICT); - } } } } diff --git a/src/user.c b/src/user.c index a43749ca..9d9d0ddf 100644 --- a/src/user.c +++ b/src/user.c @@ -1904,7 +1904,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) u64 ahead = 0; if (!is_master) { - ahead = 50; + ahead = 5; } @@ -2079,8 +2079,9 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) struct sim_ent *control_cmd_ent = sim_ent_find_first_match_one(user_input_ss, SIM_ENT_PROP_CMD_CONTROL); if (!control_cmd_ent->valid) { control_cmd_ent = sim_ent_alloc_sync_src(user_input_root); + control_cmd_ent->predictor = user_input_ss->local_client_ent; sim_ent_enable_prop(control_cmd_ent, SIM_ENT_PROP_CMD_CONTROL); - sim_ent_enable_prop(control_cmd_ent, SIM_ENT_PROP_SYNC_PREDICT); + control_cmd_ent->predictor = user_input_client->ent_id; sim_ent_activate(control_cmd_ent, user_input_ss->tick); } /* Update local control cmd ent */