Fixed admin physics check exemption

This commit is contained in:
Joshua Barretto 2021-04-30 14:06:07 +01:00
parent bc4d827650
commit b29e2b0017

View File

@ -14,6 +14,7 @@ use common_net::msg::{ClientGeneral, PresenceKind, ServerGeneral};
use common_state::{BlockChange, BuildAreas}; use common_state::{BlockChange, BuildAreas};
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write, WriteStorage}; use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write, WriteStorage};
use tracing::{debug, trace, warn}; use tracing::{debug, trace, warn};
use vek::*;
impl Sys { impl Sys {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
@ -108,56 +109,80 @@ impl Sys {
}); });
if matches!(presence.kind, PresenceKind::Character(_)) if matches!(presence.kind, PresenceKind::Character(_))
&& maybe_admin.is_none() // Admins are exempt from physics restrictions
&& force_updates.get(entity).is_none() && force_updates.get(entity).is_none()
&& healths.get(entity).map_or(true, |h| !h.is_dead) && healths.get(entity).map_or(true, |h| !h.is_dead)
&& player_physics_setting && player_physics_setting
.as_ref() .as_ref()
.map_or(true, |s| s.client_authoritative()) .map_or(true, |s| s.client_authoritative())
{ {
let mut reject_update = false; enum Rejection {
if let Some(mut setting) = player_physics_setting { TooFar { old: Vec3<f32>, new: Vec3<f32> },
TooFast { vel: Vec3<f32> },
}
let rejection = if maybe_admin.is_some() {
None
} else if let Some(mut setting) = player_physics_setting {
// If we detect any thresholds being exceeded, force server-authoritative // If we detect any thresholds being exceeded, force server-authoritative
// physics for that player. This doesn't detect subtle hacks, but it // physics for that player. This doesn't detect subtle hacks, but it
// prevents blatant ones and forces people to not debug physics hacks on the // prevents blatant ones and forces people to not debug physics hacks on the
// live server (and also mitigates some floating-point overflow crashes) // live server (and also mitigates some floating-point overflow crashes)
if let Some(prev_pos) = positions.get(entity) { let rejection = None
let value_squared = prev_pos.0.distance_squared(pos.0); // Check position
if value_squared > (500.0f32).powf(2.0) { .or_else(|| {
// for position, this gets triggered too often by legitimate if let Some(prev_pos) = positions.get(entity) {
// teleports (since the client has the old location for a few if prev_pos.0.distance_squared(pos.0) > (500.0f32).powf(2.0) {
// frames) so only reject the individual updates, don't force Some(Rejection::TooFar { old: prev_pos.0, new: pos.0 })
// server-authoritative physics for them } else {
reject_update = true; None
warn!( }
"PlayerPhysics position exceeded {:?} {:?} {:?}", } else {
prev_pos, None
pos, }
value_squared.sqrt() })
); // Check velocity
} .or_else(|| {
if vel.0.magnitude_squared() > (500.0f32).powf(2.0) {
Some(Rejection::TooFast { vel: vel.0 })
} else {
None
}
});
// Force a client-side physics update if rejectable physics data is
// received.
if rejection.is_some() {
// We skip this for `TooFar` because false positives can occur when
// using server-side teleportation commands
// that the client doesn't know about (leading to the client sending
// physics state that disagree with the server). In the future,
// client-authoritative physics will be gone
// and this will no longer be necessary.
setting.server_force =
!matches!(rejection, Some(Rejection::TooFar { .. })); // true;
} }
if vel.0.magnitude_squared() > (500.0f32).powf(2.0) { rejection
setting.server_force = true;
reject_update = true;
warn!(
"PlayerPhysics velocity exceeded {:?} {:?}",
pos,
vel.0.magnitude()
);
}
}
if reject_update {
warn!(
"Rejected PlayerPhysics update {:?} {:?} {:?} {:?}",
pos, vel, ori, maybe_player
);
} else { } else {
let _ = positions.insert(entity, pos); None
let _ = velocities.insert(entity, vel); };
let _ = orientations.insert(entity, ori);
match rejection {
Some(Rejection::TooFar { old, new }) => warn!(
"Rejected player physics update (new position {:?} is too far from \
old position {:?})",
new, old
),
Some(Rejection::TooFast { vel }) => warn!(
"Rejected player physics update (new velocity {:?} is too fast)",
vel
),
None => {
// Don't insert unless the component already exists
let _ = positions.get_mut(entity).map(|p| *p = pos);
let _ = velocities.get_mut(entity).map(|v| *v = vel);
let _ = orientations.get_mut(entity).map(|o| *o = ori);
},
} }
} }
}, },