Implement player entities

This commit is contained in:
Thinkofname 2016-04-07 19:30:42 +01:00
parent b037fb1e5c
commit e157daecaf
4 changed files with 242 additions and 0 deletions

View File

@ -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<f64>,
}
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,

View File

@ -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<model::ModelKey>,

View File

@ -118,3 +118,99 @@ impl ecs::System for UpdateLastPosition {
}
}
}
pub struct LerpPosition {
filter: ecs::Filter,
position: ecs::Key<Position>,
target_position: ecs::Key<TargetPosition>,
game_info: ecs::Key<GameInfo>,
}
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<Rotation>,
target_rotation: ecs::Key<TargetRotation>,
game_info: ecs::Key<GameInfo>,
}
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);
}
}
}

View File

@ -59,8 +59,10 @@ pub struct Server {
player_movement: ecs::Key<entity::player::PlayerMovement>,
gravity: ecs::Key<entity::Gravity>,
position: ecs::Key<entity::Position>,
target_position: ecs::Key<entity::TargetPosition>,
gamemode: ecs::Key<Gamemode>,
pub rotation: ecs::Key<entity::Rotation>,
target_rotation: ecs::Key<entity::TargetRotation>,
//
pub player: Option<ecs::Entity>,
@ -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::player::PlayerModel>(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();