Rework movement to improve compatibility with servers using NoCheatPlus (Fixes #35)

This commit is contained in:
Thinkofname 2016-04-09 00:40:35 +01:00
parent 1df78ad1c9
commit e35a122305
2 changed files with 45 additions and 38 deletions

View File

@ -25,10 +25,8 @@ use shared::Position as BPosition;
use format;
pub fn add_systems(m: &mut ecs::Manager) {
// Not actually rendering related but the faster
// we can handle input the better.
let sys = MovementHandler::new(m);
m.add_render_system(sys);
m.add_system(sys);
let sys = PlayerRenderer::new(m);
m.add_render_system(sys);
}
@ -36,6 +34,7 @@ pub fn add_systems(m: &mut ecs::Manager) {
pub fn create_local(m: &mut ecs::Manager) -> ecs::Entity {
let entity = m.create_entity();
m.add_component_direct(entity, Position::new(0.0, 0.0, 0.0));
m.add_component_direct(entity, TargetPosition::new(0.0, 0.0, 0.0));
m.add_component_direct(entity, Rotation::new(0.0, 0.0));
m.add_component_direct(entity, Velocity::new(0.0, 0.0, 0.0));
m.add_component_direct(entity, Gamemode::Survival);
@ -491,7 +490,7 @@ struct MovementHandler {
movement: ecs::Key<PlayerMovement>,
gravity: ecs::Key<Gravity>,
gamemode: ecs::Key<Gamemode>,
position: ecs::Key<Position>,
position: ecs::Key<TargetPosition>,
velocity: ecs::Key<Velocity>,
game_info: ecs::Key<GameInfo>,
bounds: ecs::Key<Bounds>,
@ -531,8 +530,6 @@ impl ecs::System for MovementHandler {
}
fn update(&mut self, m: &mut ecs::Manager, world: &mut world::World, _: &mut render::Renderer) {
let world_entity = m.get_world();
let delta = m.get_component(world_entity, self.game_info).unwrap().delta;
for e in m.find(&self.filter) {
let movement = m.get_component_mut(e, self.movement).unwrap();
if movement.flying && m.get_component(e, self.gravity).is_some() {
@ -550,55 +547,54 @@ impl ecs::System for MovementHandler {
let player_bounds = m.get_component(e, self.bounds).unwrap().bounds;
let prev_position = position.last_position;
let mut last_position = position.position;
if world.is_chunk_loaded((position.position.x as i32) >> 4, (position.position.z as i32) >> 4) {
let (forward, yaw) = movement.calculate_movement(rotation.yaw);
let mut speed = 4.317 / 60.0;
let mut speed = 0.21585;
if movement.is_key_pressed(Keycode::LShift) {
speed = 5.612 / 60.0;
speed = 0.2806;
}
if movement.flying {
speed *= 2.5;
if movement.is_key_pressed(Keycode::Space) {
position.position.y += speed * delta;
position.position.y += speed;
}
if movement.is_key_pressed(Keycode::LCtrl) {
position.position.y -= speed * delta;
position.position.y -= speed;
}
} else if gravity.as_ref().map_or(false, |v| v.on_ground) {
if movement.is_key_pressed(Keycode::Space) {
velocity.velocity.y = 0.15;
} else {
velocity.velocity.y = 0.0;
if movement.is_key_pressed(Keycode::Space) && velocity.velocity.y.abs() < 0.001 {
velocity.velocity.y = 0.42;
}
} else {
velocity.velocity.y -= 0.01 * delta;
if velocity.velocity.y < -0.3 {
velocity.velocity.y = -0.3;
velocity.velocity.y -= 0.08;
if velocity.velocity.y < -3.92 {
velocity.velocity.y = -3.92;
}
}
position.position.x += forward * yaw.cos() * delta * speed;
position.position.z -= forward * yaw.sin() * delta * speed;
position.position.y += velocity.velocity.y * delta;
velocity.velocity.y *= 0.98;
position.position.x += forward * yaw.cos() * speed;
position.position.z -= forward * yaw.sin() * speed;
position.position.y += velocity.velocity.y;
if !gamemode.noclip() {
let mut target = position.position;
position.position.y = position.last_position.y;
position.position.z = position.last_position.z;
position.position.y = last_position.y;
position.position.z = last_position.z;
// We handle each axis separately to allow for a sliding
// effect when pushing up against walls.
let (bounds, xhit) = check_collisions(world, position, player_bounds);
let (bounds, xhit) = check_collisions(world, position, &last_position, player_bounds);
position.position.x = bounds.min.x + 0.3;
position.last_position.x = position.position.x;
last_position.x = position.position.x;
position.position.z = target.z;
let (bounds, zhit) = check_collisions(world, position, player_bounds);
let (bounds, zhit) = check_collisions(world, position, &last_position, player_bounds);
position.position.z = bounds.min.z + 0.3;
position.last_position.z = position.position.z;
last_position.z = position.position.z;
// Half block jumps
// Minecraft lets you 'jump' up 0.5 blocks
@ -613,7 +609,7 @@ impl ecs::System for MovementHandler {
position.position.z = target.z;
for offset in 1 .. 9 {
let mini = player_bounds.add_v(cgmath::Vector3::new(0.0, offset as f64 / 16.0, 0.0));
let (_, hit) = check_collisions(world, position, mini);
let (_, hit) = check_collisions(world, position, &last_position, mini);
if !hit {
target.y += offset as f64 / 16.0;
ox = target.x;
@ -626,20 +622,20 @@ impl ecs::System for MovementHandler {
}
position.position.y = target.y;
let (bounds, yhit) = check_collisions(world, position, player_bounds);
let (bounds, yhit) = check_collisions(world, position, &last_position, player_bounds);
position.position.y = bounds.min.y;
position.last_position.y = position.position.y;
last_position.y = position.position.y;
if yhit {
velocity.velocity.y = 0.0;
}
if let Some(gravity) = gravity {
let ground = Aabb3::new(
Point3::new(-0.3, -0.05, -0.3),
Point3::new(-0.3, -0.005, -0.3),
Point3::new(0.3, 0.0, 0.3)
);
let prev = gravity.on_ground;
let (_, hit) = check_collisions(world, position, ground);
let (_, hit) = check_collisions(world, position, &last_position, ground);
gravity.on_ground = hit;
if !prev && gravity.on_ground {
movement.did_touch_ground = true;
@ -647,17 +643,15 @@ impl ecs::System for MovementHandler {
}
}
}
position.moved = position.position != prev_position;
}
}
}
fn check_collisions(world: &world::World, position: &mut Position, bounds: Aabb3<f64>) -> (Aabb3<f64>, bool) {
fn check_collisions(world: &world::World, position: &mut TargetPosition, last_position: &Vector3<f64>, bounds: Aabb3<f64>) -> (Aabb3<f64>, bool) {
let mut bounds = bounds.add_v(position.position);
let dir = position.position - position.last_position;
let dir = position.position - last_position;
let min_x = (bounds.min.x - 1.0) as i32;
let min_y = (bounds.min.y - 1.0) as i32;

View File

@ -62,6 +62,7 @@ pub struct Server {
gravity: ecs::Key<entity::Gravity>,
position: ecs::Key<entity::Position>,
target_position: ecs::Key<entity::TargetPosition>,
velocity: ecs::Key<entity::Velocity>,
gamemode: ecs::Key<Gamemode>,
pub rotation: ecs::Key<entity::Rotation>,
target_rotation: ecs::Key<entity::TargetRotation>,
@ -292,6 +293,7 @@ impl Server {
gravity: entities.get_key(),
position: entities.get_key(),
target_position: entities.get_key(),
velocity: entities.get_key(),
gamemode: entities.get_key(),
rotation: entities.get_key(),
target_rotation: entities.get_key(),
@ -458,7 +460,7 @@ impl Server {
if let Some(player) = self.player {
let movement = self.entities.get_component_mut(player, self.player_movement).unwrap();
let on_ground = self.entities.get_component(player, self.gravity).map_or(false, |v| v.on_ground);
let position = self.entities.get_component(player, self.position).unwrap();
let position = self.entities.get_component(player, self.target_position).unwrap();
let rotation = self.entities.get_component(player, self.rotation).unwrap();
// Force the server to know when touched the ground
@ -651,8 +653,9 @@ impl Server {
fn on_teleport(&mut self, teleport: packet::play::clientbound::TeleportPlayer) {
use std::f64::consts::PI;
if let Some(player) = self.player {
let position = self.entities.get_component_mut(player, self.position).unwrap();
let position = self.entities.get_component_mut(player, self.target_position).unwrap();
let rotation = self.entities.get_component_mut(player, self.rotation).unwrap();
let velocity = self.entities.get_component_mut(player, self.velocity).unwrap();
position.position.x = calculate_relative_teleport(TeleportFlag::RelX, teleport.flags, position.position.x, teleport.x);
position.position.y = calculate_relative_teleport(TeleportFlag::RelY, teleport.flags, position.position.y, teleport.y);
@ -666,6 +669,16 @@ impl Server {
teleport.pitch as f64
) - 180.0) * (PI / 180.0));
if (teleport.flags & (TeleportFlag::RelX as u8)) == 0 {
velocity.velocity.x = 0.0;
}
if (teleport.flags & (TeleportFlag::RelY as u8)) == 0 {
velocity.velocity.y = 0.0;
}
if (teleport.flags & (TeleportFlag::RelZ as u8)) == 0 {
velocity.velocity.z = 0.0;
}
self.write_packet(packet::play::serverbound::TeleportConfirm {
teleport_id: teleport.teleport_id,
});