diff --git a/src/entity/mod.rs b/src/entity/mod.rs index db2821b..c36613a 100644 --- a/src/entity/mod.rs +++ b/src/entity/mod.rs @@ -18,6 +18,10 @@ pub fn add_systems(m: &mut ecs::Manager) { m.add_system(sys); let sys = systems::ApplyGravity::new(m); m.add_system(sys); + let sys = systems::LerpPosition::new(m); + m.add_render_system(sys); + let sys = systems::LerpRotation::new(m); + m.add_render_system(sys); block_entity::add_systems(m); } @@ -44,6 +48,23 @@ impl Position { } } +#[derive(Debug)] +pub struct TargetPosition { + pub position: Vector3, +} + +impl TargetPosition { + pub fn new(x: f64, y: f64, z: f64) -> TargetPosition { + TargetPosition { + position: Vector3::new(x, y, z), + } + } + + pub fn zero() -> TargetPosition { + TargetPosition::new(0.0, 0.0, 0.0) + } +} + /// Velocity of an entity in the world. #[derive(Debug)] pub struct Velocity { @@ -81,6 +102,24 @@ impl Rotation { Rotation::new(0.0, 0.0) } } +#[derive(Debug)] +pub struct TargetRotation { + pub yaw: f64, + pub pitch: f64, +} + +impl TargetRotation { + pub fn new(yaw: f64, pitch: f64) -> TargetRotation { + TargetRotation { + yaw: yaw, + pitch: pitch, + } + } + + pub fn zero() -> TargetRotation { + TargetRotation::new(0.0, 0.0) + } +} pub struct Gravity { pub on_ground: bool, diff --git a/src/entity/player.rs b/src/entity/player.rs index 6dce1d7..3280bc2 100644 --- a/src/entity/player.rs +++ b/src/entity/player.rs @@ -2,8 +2,10 @@ use ecs; use super::{ Position, + TargetPosition, Velocity, Rotation, + TargetRotation, Gravity, Bounds, GameInfo, @@ -45,6 +47,21 @@ pub fn create_local(m: &mut ecs::Manager) -> ecs::Entity { entity } +pub fn create_remote(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, TargetRotation::new(0.0, 0.0)); + m.add_component_direct(entity, Velocity::new(0.0, 0.0, 0.0)); + m.add_component_direct(entity, Bounds::new(Aabb3::new( + Point3::new(-0.3, 0.0, -0.3), + Point3::new(0.3, 1.8, 0.3) + ))); + m.add_component_direct(entity, PlayerModel::new(true, true, false)); + entity +} + pub struct PlayerModel { model: Option, diff --git a/src/entity/systems.rs b/src/entity/systems.rs index e4cf832..0bbe7dc 100644 --- a/src/entity/systems.rs +++ b/src/entity/systems.rs @@ -118,3 +118,99 @@ impl ecs::System for UpdateLastPosition { } } } + +pub struct LerpPosition { + filter: ecs::Filter, + position: ecs::Key, + target_position: ecs::Key, + game_info: ecs::Key, +} + +impl LerpPosition { + pub fn new(m: &mut ecs::Manager) -> LerpPosition { + let position = m.get_key(); + let target_position = m.get_key(); + LerpPosition { + filter: ecs::Filter::new() + .with(position) + .with(target_position), + position: position, + target_position: target_position, + game_info: m.get_key(), + } + } +} + +impl ecs::System for LerpPosition { + + fn filter(&self) -> &ecs::Filter { + &self.filter + } + + fn update(&mut self, m: &mut ecs::Manager, _: &mut world::World, _: &mut render::Renderer) { + let world_entity = m.get_world(); + let delta = m.get_component_mut(world_entity, self.game_info).unwrap().delta.min(5.0); + for e in m.find(&self.filter) { + let pos = m.get_component_mut(e, self.position).unwrap(); + let target_pos = m.get_component(e, self.target_position).unwrap(); + + pos.position = pos.position + (target_pos.position - pos.position) * delta * 0.2; + } + } +} + +pub struct LerpRotation { + filter: ecs::Filter, + rotation: ecs::Key, + target_rotation: ecs::Key, + game_info: ecs::Key, +} + +impl LerpRotation { + pub fn new(m: &mut ecs::Manager) -> LerpRotation { + let rotation = m.get_key(); + let target_rotation = m.get_key(); + LerpRotation { + filter: ecs::Filter::new() + .with(rotation) + .with(target_rotation), + rotation: rotation, + target_rotation: target_rotation, + game_info: m.get_key(), + } + } +} + +impl ecs::System for LerpRotation { + + fn filter(&self) -> &ecs::Filter { + &self.filter + } + + fn update(&mut self, m: &mut ecs::Manager, _: &mut world::World, _: &mut render::Renderer) { + use std::f64::consts::PI; + let world_entity = m.get_world(); + let delta = m.get_component_mut(world_entity, self.game_info).unwrap().delta.min(5.0); + for e in m.find(&self.filter) { + let rot = m.get_component_mut(e, self.rotation).unwrap(); + let target_rot = m.get_component_mut(e, self.target_rotation).unwrap(); + target_rot.yaw = (PI*2.0 + target_rot.yaw) % (PI*2.0); + target_rot.pitch = (PI*2.0 + target_rot.pitch) % (PI*2.0); + + let mut delta_yaw = target_rot.yaw - rot.yaw; + let mut delta_pitch = target_rot.pitch - rot.pitch; + + if delta_yaw.abs() > PI { + delta_yaw = (PI - delta_yaw.abs()) * delta_yaw.signum(); + } + if delta_pitch.abs() > PI { + delta_pitch = (PI - delta_pitch.abs()) * delta_pitch.signum(); + } + + rot.yaw += delta_yaw * 0.2 * delta; + rot.pitch += delta_pitch * 0.2 * delta; + rot.yaw = (PI*2.0 + rot.yaw) % (PI*2.0); + rot.pitch = (PI*2.0 + rot.pitch) % (PI*2.0); + } + } +} diff --git a/src/server/mod.rs b/src/server/mod.rs index fc10be3..f38da72 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -59,8 +59,10 @@ pub struct Server { player_movement: ecs::Key, gravity: ecs::Key, position: ecs::Key, + target_position: ecs::Key, gamemode: ecs::Key, pub rotation: ecs::Key, + target_rotation: ecs::Key, // pub player: Option, @@ -286,8 +288,10 @@ impl Server { player_movement: entities.get_key(), gravity: entities.get_key(), position: entities.get_key(), + target_position: entities.get_key(), gamemode: entities.get_key(), rotation: entities.get_key(), + target_rotation: entities.get_key(), // entities: entities, @@ -366,6 +370,13 @@ impl Server { ChangeGameState => on_game_state_change, UpdateSign => on_sign_update, PlayerInfo => on_player_info, + // Entities + EntityDestroy => on_entity_destroy, + SpawnPlayer => on_player_spawn, + EntityTeleport => on_entity_teleport, + EntityMove => on_entity_move, + EntityLook => on_entity_look, + EntityLookAndMove => on_entity_look_and_move, } }, Err(err) => panic!("Err: {:?}", err), @@ -533,6 +544,85 @@ impl Server { } } + fn on_entity_destroy(&mut self, entity_destroy: packet::play::clientbound::EntityDestroy) { + for id in entity_destroy.entity_ids.data { + if let Some(entity) = self.entity_map.remove(&id.0) { + self.entities.remove_entity(entity); + } + } + } + + fn on_entity_teleport(&mut self, entity_telport: packet::play::clientbound::EntityTeleport) { + use std::f64::consts::PI; + if let Some(entity) = self.entity_map.get(&entity_telport.entity_id.0) { + let target_position = self.entities.get_component_mut(*entity, self.target_position).unwrap(); + let target_rotation = self.entities.get_component_mut(*entity, self.target_rotation).unwrap(); + target_position.position.x = entity_telport.x; + target_position.position.y = entity_telport.y; + target_position.position.z = entity_telport.z; + target_rotation.yaw = -((entity_telport.yaw as f64) / 256.0) * PI * 2.0; + target_rotation.pitch = -((entity_telport.pitch as f64) / 256.0) * PI * 2.0; + } + } + + fn on_entity_move(&mut self, m: packet::play::clientbound::EntityMove) { + if let Some(entity) = self.entity_map.get(&m.entity_id.0) { + let position = self.entities.get_component_mut(*entity, self.target_position).unwrap(); + position.position.x += m.delta_x as f64 / (32.0 * 128.0); + position.position.y += m.delta_y as f64 / (32.0 * 128.0); + position.position.z += m.delta_z as f64 / (32.0 * 128.0); + } + } + + fn on_entity_look(&mut self, look: packet::play::clientbound::EntityLook) { + use std::f64::consts::PI; + if let Some(entity) = self.entity_map.get(&look.entity_id.0) { + let rotation = self.entities.get_component_mut(*entity, self.target_rotation).unwrap(); + rotation.yaw = -((look.yaw as f64) / 256.0) * PI * 2.0; + rotation.pitch = -((look.pitch as f64) / 256.0) * PI * 2.0; + } + } + + fn on_entity_look_and_move(&mut self, lookmove: packet::play::clientbound::EntityLookAndMove) { + use std::f64::consts::PI; + if let Some(entity) = self.entity_map.get(&lookmove.entity_id.0) { + let position = self.entities.get_component_mut(*entity, self.target_position).unwrap(); + let rotation = self.entities.get_component_mut(*entity, self.target_rotation).unwrap(); + position.position.x += lookmove.delta_x as f64 / (32.0 * 128.0); + position.position.y += lookmove.delta_y as f64 / (32.0 * 128.0); + position.position.z += lookmove.delta_z as f64 / (32.0 * 128.0); + rotation.yaw = -((lookmove.yaw as f64) / 256.0) * PI * 2.0; + rotation.pitch = -((lookmove.pitch as f64) / 256.0) * PI * 2.0; + } + } + + fn on_player_spawn(&mut self, spawn: packet::play::clientbound::SpawnPlayer) { + use std::f64::consts::PI; + if let Some(entity) = self.entity_map.remove(&spawn.entity_id.0) { + self.entities.remove_entity(entity); + } + let entity = entity::player::create_remote(&mut self.entities); + let position = self.entities.get_component_mut(entity, self.position).unwrap(); + let target_position = self.entities.get_component_mut(entity, self.target_position).unwrap(); + let rotation = self.entities.get_component_mut(entity, self.rotation).unwrap(); + let target_rotation = self.entities.get_component_mut(entity, self.target_rotation).unwrap(); + position.position.x = spawn.x; + position.position.y = spawn.y; + position.position.z = spawn.z; + target_position.position.x = spawn.x; + target_position.position.y = spawn.y; + target_position.position.z = spawn.z; + rotation.yaw = -((spawn.yaw as f64) / 256.0) * PI * 2.0; + rotation.pitch = -((spawn.pitch as f64) / 256.0) * PI * 2.0; + target_rotation.yaw = rotation.yaw; + target_rotation.pitch = rotation.pitch; + if let Some(info) = self.players.get(&spawn.uuid) { + let model = self.entities.get_component_mut_direct::(entity).unwrap(); + model.set_skin(info.skin_url.clone()); + } + self.entity_map.insert(spawn.entity_id.0, entity); + } + fn on_teleport(&mut self, teleport: packet::play::clientbound::TeleportPlayer) { if let Some(player) = self.player { let position = self.entities.get_component_mut(player, self.position).unwrap();