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; use format;
pub fn add_systems(m: &mut ecs::Manager) { 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); let sys = MovementHandler::new(m);
m.add_render_system(sys); m.add_system(sys);
let sys = PlayerRenderer::new(m); let sys = PlayerRenderer::new(m);
m.add_render_system(sys); 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 { pub fn create_local(m: &mut ecs::Manager) -> ecs::Entity {
let entity = m.create_entity(); let entity = m.create_entity();
m.add_component_direct(entity, Position::new(0.0, 0.0, 0.0)); 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, Rotation::new(0.0, 0.0));
m.add_component_direct(entity, Velocity::new(0.0, 0.0, 0.0)); m.add_component_direct(entity, Velocity::new(0.0, 0.0, 0.0));
m.add_component_direct(entity, Gamemode::Survival); m.add_component_direct(entity, Gamemode::Survival);
@ -491,7 +490,7 @@ struct MovementHandler {
movement: ecs::Key<PlayerMovement>, movement: ecs::Key<PlayerMovement>,
gravity: ecs::Key<Gravity>, gravity: ecs::Key<Gravity>,
gamemode: ecs::Key<Gamemode>, gamemode: ecs::Key<Gamemode>,
position: ecs::Key<Position>, position: ecs::Key<TargetPosition>,
velocity: ecs::Key<Velocity>, velocity: ecs::Key<Velocity>,
game_info: ecs::Key<GameInfo>, game_info: ecs::Key<GameInfo>,
bounds: ecs::Key<Bounds>, 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) { 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) { for e in m.find(&self.filter) {
let movement = m.get_component_mut(e, self.movement).unwrap(); let movement = m.get_component_mut(e, self.movement).unwrap();
if movement.flying && m.get_component(e, self.gravity).is_some() { 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 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) { 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 (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) { if movement.is_key_pressed(Keycode::LShift) {
speed = 5.612 / 60.0; speed = 0.2806;
} }
if movement.flying { if movement.flying {
speed *= 2.5; speed *= 2.5;
if movement.is_key_pressed(Keycode::Space) { if movement.is_key_pressed(Keycode::Space) {
position.position.y += speed * delta; position.position.y += speed;
} }
if movement.is_key_pressed(Keycode::LCtrl) { 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) { } else if gravity.as_ref().map_or(false, |v| v.on_ground) {
if movement.is_key_pressed(Keycode::Space) { if movement.is_key_pressed(Keycode::Space) && velocity.velocity.y.abs() < 0.001 {
velocity.velocity.y = 0.15; velocity.velocity.y = 0.42;
} else {
velocity.velocity.y = 0.0;
} }
} else { } else {
velocity.velocity.y -= 0.01 * delta; velocity.velocity.y -= 0.08;
if velocity.velocity.y < -0.3 { if velocity.velocity.y < -3.92 {
velocity.velocity.y = -0.3; velocity.velocity.y = -3.92;
} }
} }
position.position.x += forward * yaw.cos() * delta * speed; velocity.velocity.y *= 0.98;
position.position.z -= forward * yaw.sin() * delta * speed; position.position.x += forward * yaw.cos() * speed;
position.position.y += velocity.velocity.y * delta; position.position.z -= forward * yaw.sin() * speed;
position.position.y += velocity.velocity.y;
if !gamemode.noclip() { if !gamemode.noclip() {
let mut target = position.position; let mut target = position.position;
position.position.y = position.last_position.y; position.position.y = last_position.y;
position.position.z = position.last_position.z; position.position.z = last_position.z;
// We handle each axis separately to allow for a sliding // We handle each axis separately to allow for a sliding
// effect when pushing up against walls. // 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.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; 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.position.z = bounds.min.z + 0.3;
position.last_position.z = position.position.z; last_position.z = position.position.z;
// Half block jumps // Half block jumps
// Minecraft lets you 'jump' up 0.5 blocks // Minecraft lets you 'jump' up 0.5 blocks
@ -613,7 +609,7 @@ impl ecs::System for MovementHandler {
position.position.z = target.z; position.position.z = target.z;
for offset in 1 .. 9 { for offset in 1 .. 9 {
let mini = player_bounds.add_v(cgmath::Vector3::new(0.0, offset as f64 / 16.0, 0.0)); 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 { if !hit {
target.y += offset as f64 / 16.0; target.y += offset as f64 / 16.0;
ox = target.x; ox = target.x;
@ -626,20 +622,20 @@ impl ecs::System for MovementHandler {
} }
position.position.y = target.y; 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.position.y = bounds.min.y;
position.last_position.y = position.position.y; last_position.y = position.position.y;
if yhit { if yhit {
velocity.velocity.y = 0.0; velocity.velocity.y = 0.0;
} }
if let Some(gravity) = gravity { if let Some(gravity) = gravity {
let ground = Aabb3::new( 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) Point3::new(0.3, 0.0, 0.3)
); );
let prev = gravity.on_ground; 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; gravity.on_ground = hit;
if !prev && gravity.on_ground { if !prev && gravity.on_ground {
movement.did_touch_ground = true; 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 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_x = (bounds.min.x - 1.0) as i32;
let min_y = (bounds.min.y - 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>, gravity: ecs::Key<entity::Gravity>,
position: ecs::Key<entity::Position>, position: ecs::Key<entity::Position>,
target_position: ecs::Key<entity::TargetPosition>, target_position: ecs::Key<entity::TargetPosition>,
velocity: ecs::Key<entity::Velocity>,
gamemode: ecs::Key<Gamemode>, gamemode: ecs::Key<Gamemode>,
pub rotation: ecs::Key<entity::Rotation>, pub rotation: ecs::Key<entity::Rotation>,
target_rotation: ecs::Key<entity::TargetRotation>, target_rotation: ecs::Key<entity::TargetRotation>,
@ -292,6 +293,7 @@ impl Server {
gravity: entities.get_key(), gravity: entities.get_key(),
position: entities.get_key(), position: entities.get_key(),
target_position: entities.get_key(), target_position: entities.get_key(),
velocity: entities.get_key(),
gamemode: entities.get_key(), gamemode: entities.get_key(),
rotation: entities.get_key(), rotation: entities.get_key(),
target_rotation: entities.get_key(), target_rotation: entities.get_key(),
@ -458,7 +460,7 @@ impl Server {
if let Some(player) = self.player { if let Some(player) = self.player {
let movement = self.entities.get_component_mut(player, self.player_movement).unwrap(); 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 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(); let rotation = self.entities.get_component(player, self.rotation).unwrap();
// Force the server to know when touched the ground // 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) { fn on_teleport(&mut self, teleport: packet::play::clientbound::TeleportPlayer) {
use std::f64::consts::PI; use std::f64::consts::PI;
if let Some(player) = self.player { 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 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.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); 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 teleport.pitch as f64
) - 180.0) * (PI / 180.0)); ) - 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 { self.write_packet(packet::play::serverbound::TeleportConfirm {
teleport_id: teleport.teleport_id, teleport_id: teleport.teleport_id,
}); });