Refactor Entity
This commit is contained in:
parent
cd25387a4b
commit
2ee9710f93
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -1916,9 +1916,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "pumpkin-entity"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"pumpkin-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pumpkin-inventory"
|
||||
|
||||
@ -4,4 +4,3 @@ version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
pumpkin-core = { path = "../pumpkin-core"}
|
||||
@ -1,63 +1,4 @@
|
||||
use entity_type::EntityType;
|
||||
use pose::EntityPose;
|
||||
use pumpkin_core::math::{
|
||||
get_section_cord, position::WorldPosition, vector2::Vector2, vector3::Vector3,
|
||||
};
|
||||
|
||||
pub mod entity_type;
|
||||
pub mod pose;
|
||||
|
||||
pub type EntityId = i32;
|
||||
|
||||
pub struct Entity {
|
||||
pub entity_id: EntityId,
|
||||
pub entity_type: EntityType,
|
||||
pub pos: Vector3<f64>,
|
||||
pub block_pos: WorldPosition,
|
||||
pub chunk_pos: Vector2<i32>,
|
||||
|
||||
pub yaw: f32,
|
||||
pub head_yaw: f32,
|
||||
pub pitch: f32,
|
||||
// TODO: Change this in diffrent poses
|
||||
pub standing_eye_height: f32,
|
||||
pub pose: EntityPose,
|
||||
}
|
||||
|
||||
impl Entity {
|
||||
pub fn new(entity_id: EntityId, entity_type: EntityType, standing_eye_height: f32) -> Self {
|
||||
Self {
|
||||
entity_id,
|
||||
entity_type,
|
||||
pos: Vector3::new(0.0, 0.0, 0.0),
|
||||
block_pos: WorldPosition(Vector3::new(0, 0, 0)),
|
||||
chunk_pos: Vector2::new(0, 0),
|
||||
yaw: 0.0,
|
||||
head_yaw: 0.0,
|
||||
pitch: 0.0,
|
||||
standing_eye_height,
|
||||
pose: EntityPose::Standing,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_pos(&mut self, x: f64, y: f64, z: f64) {
|
||||
if self.pos.x != x || self.pos.y != y || self.pos.z != z {
|
||||
self.pos = Vector3::new(x, y, z);
|
||||
let i = x.floor() as i32;
|
||||
let j = y.floor() as i32;
|
||||
let k = z.floor() as i32;
|
||||
|
||||
let block_pos = self.block_pos.0;
|
||||
if i != block_pos.x || j != block_pos.y || k != block_pos.z {
|
||||
self.block_pos = WorldPosition(Vector3::new(i, j, k));
|
||||
|
||||
if get_section_cord(i) != self.chunk_pos.x
|
||||
|| get_section_cord(k) != self.chunk_pos.z
|
||||
{
|
||||
self.chunk_pos =
|
||||
Vector2::new(get_section_cord(block_pos.x), get_section_cord(block_pos.z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,11 +5,11 @@ use serde::Serialize;
|
||||
#[derive(Serialize)]
|
||||
#[packet(0x1D)]
|
||||
pub struct CPlayDisconnect<'a> {
|
||||
reason: TextComponent<'a>,
|
||||
reason: &'a TextComponent<'a>,
|
||||
}
|
||||
|
||||
impl<'a> CPlayDisconnect<'a> {
|
||||
pub fn new(reason: TextComponent<'a>) -> Self {
|
||||
pub fn new(reason: &'a TextComponent<'a>) -> Self {
|
||||
Self { reason }
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,7 +323,7 @@ impl Client {
|
||||
}
|
||||
// So we can also kick on errors, but generally should use Player::kick
|
||||
ConnectionState::Play => {
|
||||
self.try_send_packet(&CPlayDisconnect::new(TextComponent::text(reason)))
|
||||
self.try_send_packet(&CPlayDisconnect::new(&TextComponent::text(reason)))
|
||||
.unwrap_or_else(|_| self.close());
|
||||
}
|
||||
_ => {
|
||||
|
||||
@ -82,15 +82,27 @@ impl Player {
|
||||
Self::clamp_vertical(position.feet_y),
|
||||
Self::clamp_horizontal(position.z),
|
||||
);
|
||||
// TODO: teleport when moving > 8 block
|
||||
|
||||
// send new position to all other players
|
||||
let on_ground = self.on_ground;
|
||||
entity.on_ground = position.ground;
|
||||
let on_ground = entity.on_ground;
|
||||
let entity_id = entity.entity_id;
|
||||
let (x, y, z) = entity.pos.into();
|
||||
let (lastx, lasty, lastz) = self.last_position.into();
|
||||
let world = self.world.clone();
|
||||
let world = world.lock().await;
|
||||
|
||||
// let delta = Vector3::new(x - lastx, y - lasty, z - lastz);
|
||||
// let velocity = self.velocity;
|
||||
|
||||
// // Player is falling down fast, we should account for that
|
||||
// let max_speed = if self.fall_flying { 300.0 } else { 100.0 };
|
||||
|
||||
// teleport when more than 8 blocks (i guess 8 blocks)
|
||||
// TODO: REPLACE * 2.0 by movement packets. see vanilla for details
|
||||
// if delta.length_squared() - velocity.length_squared() > max_speed * 2.0 {
|
||||
// self.teleport(x, y, z, self.entity.yaw, self.entity.pitch);
|
||||
// return;
|
||||
// }
|
||||
// send new position to all other players
|
||||
world.broadcast_packet(
|
||||
&[self.client.token],
|
||||
&CUpdateEntityPos::new(
|
||||
@ -128,11 +140,11 @@ impl Player {
|
||||
Self::clamp_vertical(position_rotation.feet_y),
|
||||
Self::clamp_horizontal(position_rotation.z),
|
||||
);
|
||||
entity.on_ground = position_rotation.ground;
|
||||
entity.yaw = wrap_degrees(position_rotation.yaw) % 360.0;
|
||||
entity.pitch = wrap_degrees(position_rotation.pitch).clamp(-90.0, 90.0) % 360.0;
|
||||
|
||||
// send new position to all other players
|
||||
let on_ground = self.on_ground;
|
||||
let on_ground = entity.on_ground;
|
||||
let entity_id = entity.entity_id;
|
||||
let (x, y, z) = entity.pos.into();
|
||||
let (lastx, lasty, lastz) = self.last_position.into();
|
||||
@ -142,6 +154,20 @@ impl Player {
|
||||
let world = self.world.clone();
|
||||
let world = world.lock().await;
|
||||
|
||||
// let delta = Vector3::new(x - lastx, y - lasty, z - lastz);
|
||||
// let velocity = self.velocity;
|
||||
|
||||
// // Player is falling down fast, we should account for that
|
||||
// let max_speed = if self.fall_flying { 300.0 } else { 100.0 };
|
||||
|
||||
// // teleport when more than 8 blocks (i guess 8 blocks)
|
||||
// // TODO: REPLACE * 2.0 by movement packets. see vanilla for details
|
||||
// if delta.length_squared() - velocity.length_squared() > max_speed * 2.0 {
|
||||
// self.teleport(x, y, z, yaw, pitch);
|
||||
// return;
|
||||
// }
|
||||
// send new position to all other players
|
||||
|
||||
world.broadcast_packet(
|
||||
&[self.client.token],
|
||||
&CUpdateEntityPosRot::new(
|
||||
@ -168,10 +194,11 @@ impl Player {
|
||||
return;
|
||||
}
|
||||
let entity = &mut self.entity;
|
||||
entity.on_ground = rotation.ground;
|
||||
entity.yaw = wrap_degrees(rotation.yaw) % 360.0;
|
||||
entity.pitch = wrap_degrees(rotation.pitch).clamp(-90.0, 90.0) % 360.0;
|
||||
// send new position to all other players
|
||||
let on_ground = self.on_ground;
|
||||
let on_ground = entity.on_ground;
|
||||
let entity_id = entity.entity_id;
|
||||
let yaw = modulus(entity.yaw * 256.0 / 360.0, 256.0);
|
||||
let pitch = modulus(entity.pitch * 256.0 / 360.0, 256.0);
|
||||
@ -191,7 +218,7 @@ impl Player {
|
||||
}
|
||||
|
||||
pub fn handle_player_ground(&mut self, _server: &mut Server, ground: SSetPlayerGround) {
|
||||
self.on_ground = ground.on_ground;
|
||||
self.entity.on_ground = ground.on_ground;
|
||||
}
|
||||
|
||||
pub async fn handle_player_command(&mut self, _server: &mut Server, command: SPlayerCommand) {
|
||||
@ -202,30 +229,45 @@ impl Player {
|
||||
if let Some(action) = Action::from_i32(command.action.0) {
|
||||
match action {
|
||||
pumpkin_protocol::server::play::Action::StartSneaking => {
|
||||
if !self.sneaking {
|
||||
self.set_sneaking(true).await
|
||||
if !self.entity.sneaking {
|
||||
self.entity
|
||||
.set_sneaking(&mut self.client, self.world.clone(), true)
|
||||
.await
|
||||
}
|
||||
}
|
||||
pumpkin_protocol::server::play::Action::StopSneaking => {
|
||||
if self.sneaking {
|
||||
self.set_sneaking(false).await
|
||||
if self.entity.sneaking {
|
||||
self.entity
|
||||
.set_sneaking(&mut self.client, self.world.clone(), false)
|
||||
.await
|
||||
}
|
||||
}
|
||||
pumpkin_protocol::server::play::Action::LeaveBed => todo!(),
|
||||
pumpkin_protocol::server::play::Action::StartSprinting => {
|
||||
if !self.sprinting {
|
||||
self.set_sprinting(true).await
|
||||
if !self.entity.sprinting {
|
||||
self.entity
|
||||
.set_sprinting(&mut self.client, self.world.clone(), true)
|
||||
.await
|
||||
}
|
||||
}
|
||||
pumpkin_protocol::server::play::Action::StopSprinting => {
|
||||
if self.sprinting {
|
||||
self.set_sprinting(false).await
|
||||
if self.entity.sprinting {
|
||||
self.entity
|
||||
.set_sprinting(&mut self.client, self.world.clone(), false)
|
||||
.await
|
||||
}
|
||||
}
|
||||
pumpkin_protocol::server::play::Action::StartHorseJump => todo!(),
|
||||
pumpkin_protocol::server::play::Action::StopHorseJump => todo!(),
|
||||
pumpkin_protocol::server::play::Action::OpenVehicleInventory => todo!(),
|
||||
pumpkin_protocol::server::play::Action::StartFlyingElytra => {} // TODO
|
||||
pumpkin_protocol::server::play::Action::StartFlyingElytra => {
|
||||
let fall_flying = self.entity.check_fall_flying();
|
||||
if self.entity.fall_flying != fall_flying {
|
||||
self.entity
|
||||
.set_fall_flying(&mut self.client, self.world.clone(), fall_flying)
|
||||
.await;
|
||||
}
|
||||
} // TODO
|
||||
}
|
||||
} else {
|
||||
self.kick(TextComponent::text("Invalid player command"))
|
||||
@ -320,8 +362,10 @@ impl Player {
|
||||
|
||||
pub async fn handle_interact(&mut self, _: &mut Server, interact: SInteract) {
|
||||
let sneaking = interact.sneaking;
|
||||
if self.sneaking != sneaking {
|
||||
self.set_sneaking(sneaking).await;
|
||||
if self.entity.sneaking != sneaking {
|
||||
self.entity
|
||||
.set_sneaking(&mut self.client, self.world.clone(), sneaking)
|
||||
.await;
|
||||
}
|
||||
match ActionType::from_i32(interact.typ.0) {
|
||||
Some(action) => match action {
|
||||
@ -335,27 +379,27 @@ impl Player {
|
||||
let attacked_player = world.get_by_entityid(self, entity_id.0 as EntityId);
|
||||
if let Some(mut player) = attacked_player {
|
||||
let token = player.client.token;
|
||||
let velo = player.velocity;
|
||||
let velo = player.entity.velocity;
|
||||
if config.protect_creative && player.gamemode == GameMode::Creative {
|
||||
return;
|
||||
}
|
||||
if config.knockback {
|
||||
let yaw = self.entity.yaw;
|
||||
let strength = 1.0;
|
||||
player.knockback(
|
||||
player.entity.knockback(
|
||||
strength * 0.5,
|
||||
(yaw * (PI / 180.0)).sin() as f64,
|
||||
-(yaw * (PI / 180.0)).cos() as f64,
|
||||
);
|
||||
let packet = &CEntityVelocity::new(
|
||||
&entity_id,
|
||||
player.velocity.x as f32,
|
||||
player.velocity.y as f32,
|
||||
player.velocity.z as f32,
|
||||
velo.x as f32,
|
||||
velo.y as f32,
|
||||
velo.z as f32,
|
||||
);
|
||||
self.velocity = self.velocity.multiply(0.6, 1.0, 0.6);
|
||||
self.entity.velocity = self.entity.velocity.multiply(0.6, 1.0, 0.6);
|
||||
|
||||
player.velocity = velo;
|
||||
player.entity.velocity = velo;
|
||||
player.client.send_packet(packet);
|
||||
}
|
||||
if config.hurt_animation {
|
||||
|
||||
@ -1 +1,195 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use pumpkin_core::math::{
|
||||
get_section_cord, position::WorldPosition, vector2::Vector2, vector3::Vector3,
|
||||
};
|
||||
use pumpkin_entity::{entity_type::EntityType, pose::EntityPose, EntityId};
|
||||
use pumpkin_protocol::{
|
||||
client::play::{CSetEntityMetadata, Metadata},
|
||||
VarInt,
|
||||
};
|
||||
|
||||
use crate::{client::Client, world::World};
|
||||
|
||||
pub mod player;
|
||||
|
||||
pub struct Entity {
|
||||
pub entity_id: EntityId,
|
||||
pub entity_type: EntityType,
|
||||
pub pos: Vector3<f64>,
|
||||
pub block_pos: WorldPosition,
|
||||
pub chunk_pos: Vector2<i32>,
|
||||
|
||||
pub sneaking: bool,
|
||||
pub sprinting: bool,
|
||||
pub fall_flying: bool,
|
||||
pub velocity: Vector3<f64>,
|
||||
|
||||
// Should be not trusted
|
||||
pub on_ground: bool,
|
||||
|
||||
pub yaw: f32,
|
||||
pub head_yaw: f32,
|
||||
pub pitch: f32,
|
||||
// TODO: Change this in diffrent poses
|
||||
pub standing_eye_height: f32,
|
||||
pub pose: EntityPose,
|
||||
}
|
||||
|
||||
// TODO: Remove client: &mut Client, world: Arc<tokio::sync::Mutex<World>> bs
|
||||
impl Entity {
|
||||
pub fn new(entity_id: EntityId, entity_type: EntityType, standing_eye_height: f32) -> Self {
|
||||
Self {
|
||||
entity_id,
|
||||
entity_type,
|
||||
on_ground: false,
|
||||
pos: Vector3::new(0.0, 0.0, 0.0),
|
||||
block_pos: WorldPosition(Vector3::new(0, 0, 0)),
|
||||
chunk_pos: Vector2::new(0, 0),
|
||||
sneaking: false,
|
||||
sprinting: false,
|
||||
fall_flying: false,
|
||||
yaw: 0.0,
|
||||
head_yaw: 0.0,
|
||||
pitch: 0.0,
|
||||
velocity: Vector3::new(0.0, 0.0, 0.0),
|
||||
standing_eye_height,
|
||||
pose: EntityPose::Standing,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_pos(&mut self, x: f64, y: f64, z: f64) {
|
||||
if self.pos.x != x || self.pos.y != y || self.pos.z != z {
|
||||
self.pos = Vector3::new(x, y, z);
|
||||
let i = x.floor() as i32;
|
||||
let j = y.floor() as i32;
|
||||
let k = z.floor() as i32;
|
||||
|
||||
let block_pos = self.block_pos.0;
|
||||
if i != block_pos.x || j != block_pos.y || k != block_pos.z {
|
||||
self.block_pos = WorldPosition(Vector3::new(i, j, k));
|
||||
|
||||
if get_section_cord(i) != self.chunk_pos.x
|
||||
|| get_section_cord(k) != self.chunk_pos.z
|
||||
{
|
||||
self.chunk_pos =
|
||||
Vector2::new(get_section_cord(block_pos.x), get_section_cord(block_pos.z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn knockback(&mut self, strength: f64, x: f64, z: f64) {
|
||||
// This has some vanilla magic
|
||||
let mut x = x;
|
||||
let mut z = z;
|
||||
while x * x + z * z < 1.0E-5 {
|
||||
x = (rand::random::<f64>() - rand::random::<f64>()) * 0.01;
|
||||
z = (rand::random::<f64>() - rand::random::<f64>()) * 0.01;
|
||||
}
|
||||
|
||||
let var8 = Vector3::new(x, 0.0, z).normalize() * strength;
|
||||
let var7 = self.velocity;
|
||||
self.velocity = Vector3::new(
|
||||
var7.x / 2.0 - var8.x,
|
||||
if self.on_ground {
|
||||
(var7.y / 2.0 + strength).min(0.4)
|
||||
} else {
|
||||
var7.y
|
||||
},
|
||||
var7.z / 2.0 - var8.z,
|
||||
);
|
||||
}
|
||||
|
||||
pub async fn set_sneaking(
|
||||
&mut self,
|
||||
client: &mut Client,
|
||||
world: Arc<tokio::sync::Mutex<World>>,
|
||||
sneaking: bool,
|
||||
) {
|
||||
assert!(self.sneaking != sneaking);
|
||||
self.sneaking = sneaking;
|
||||
self.set_flag(client, world, Self::SNEAKING_FLAG_INDEX, sneaking)
|
||||
.await;
|
||||
// if sneaking {
|
||||
// self.set_pose(EntityPose::Crouching).await;
|
||||
// } else {
|
||||
// self.set_pose(EntityPose::Standing).await;
|
||||
// }
|
||||
}
|
||||
|
||||
pub async fn set_sprinting(
|
||||
&mut self,
|
||||
client: &mut Client,
|
||||
world: Arc<tokio::sync::Mutex<World>>,
|
||||
sprinting: bool,
|
||||
) {
|
||||
assert!(self.sprinting != sprinting);
|
||||
self.sprinting = sprinting;
|
||||
self.set_flag(client, world, Self::SPRINTING_FLAG_INDEX, sprinting)
|
||||
.await;
|
||||
}
|
||||
|
||||
pub fn check_fall_flying(&self) -> bool {
|
||||
!self.on_ground
|
||||
}
|
||||
|
||||
pub async fn set_fall_flying(
|
||||
&mut self,
|
||||
client: &mut Client,
|
||||
world: Arc<tokio::sync::Mutex<World>>,
|
||||
fall_flying: bool,
|
||||
) {
|
||||
assert!(self.fall_flying != fall_flying);
|
||||
self.fall_flying = fall_flying;
|
||||
self.set_flag(client, world, Self::FALL_FLYING_FLAG_INDEX, fall_flying)
|
||||
.await;
|
||||
}
|
||||
|
||||
pub const ON_FIRE_FLAG_INDEX: u32 = 0;
|
||||
pub const SNEAKING_FLAG_INDEX: u32 = 1;
|
||||
pub const SPRINTING_FLAG_INDEX: u32 = 3;
|
||||
pub const SWIMMING_FLAG_INDEX: u32 = 4;
|
||||
pub const INVISIBLE_FLAG_INDEX: u32 = 5;
|
||||
pub const GLOWING_FLAG_INDEX: u32 = 6;
|
||||
pub const FALL_FLYING_FLAG_INDEX: u32 = 7;
|
||||
async fn set_flag(
|
||||
&mut self,
|
||||
client: &mut Client,
|
||||
world: Arc<tokio::sync::Mutex<World>>,
|
||||
index: u32,
|
||||
value: bool,
|
||||
) {
|
||||
let mut b = 0i8;
|
||||
if value {
|
||||
b |= 1 << index;
|
||||
} else {
|
||||
b &= !(1 << index);
|
||||
}
|
||||
let packet = CSetEntityMetadata::new(self.entity_id.into(), Metadata::new(0, 0.into(), b));
|
||||
client.send_packet(&packet);
|
||||
world
|
||||
.lock()
|
||||
.await
|
||||
.broadcast_packet(&[client.token], &packet);
|
||||
}
|
||||
|
||||
pub async fn set_pose(
|
||||
&mut self,
|
||||
client: &mut Client,
|
||||
world: Arc<tokio::sync::Mutex<World>>,
|
||||
pose: EntityPose,
|
||||
) {
|
||||
self.pose = pose;
|
||||
let pose = self.pose as i32;
|
||||
let packet = CSetEntityMetadata::<VarInt>::new(
|
||||
self.entity_id.into(),
|
||||
Metadata::new(6, 20.into(), (pose).into()),
|
||||
);
|
||||
client.send_packet(&packet);
|
||||
world
|
||||
.lock()
|
||||
.await
|
||||
.broadcast_packet(&[client.token], &packet)
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,13 +7,13 @@ use pumpkin_core::{
|
||||
text::TextComponent,
|
||||
GameMode,
|
||||
};
|
||||
use pumpkin_entity::{entity_type::EntityType, pose::EntityPose, Entity, EntityId};
|
||||
use pumpkin_entity::{entity_type::EntityType, EntityId};
|
||||
use pumpkin_inventory::player::PlayerInventory;
|
||||
use pumpkin_protocol::{
|
||||
bytebuf::{packet_id::Packet, DeserializerError},
|
||||
client::play::{
|
||||
CGameEvent, CPlayDisconnect, CPlayerAbilities, CPlayerInfoUpdate, CSetEntityMetadata,
|
||||
CSyncPlayerPosition, CSystemChatMessage, Metadata, PlayerAction,
|
||||
CGameEvent, CPlayDisconnect, CPlayerAbilities, CPlayerInfoUpdate, CSyncPlayerPosition,
|
||||
CSystemChatMessage, PlayerAction,
|
||||
},
|
||||
server::play::{
|
||||
SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract,
|
||||
@ -30,6 +30,8 @@ use crate::{
|
||||
world::World,
|
||||
};
|
||||
|
||||
use super::Entity;
|
||||
|
||||
pub struct PlayerAbilities {
|
||||
pub invulnerable: bool,
|
||||
pub flying: bool,
|
||||
@ -53,9 +55,10 @@ impl Default for PlayerAbilities {
|
||||
}
|
||||
|
||||
pub struct Player {
|
||||
pub entity: Entity,
|
||||
|
||||
pub gameprofile: GameProfile,
|
||||
pub client: Client,
|
||||
pub entity: Entity,
|
||||
pub config: PlayerConfig,
|
||||
// TODO: Put this into entity
|
||||
pub world: Arc<tokio::sync::Mutex<World>>,
|
||||
@ -68,20 +71,11 @@ pub struct Player {
|
||||
pub inventory: PlayerInventory,
|
||||
/// send `send_abilties_update` when changed
|
||||
pub abilities: PlayerAbilities,
|
||||
|
||||
pub last_position: Vector3<f64>,
|
||||
// Client side value, Should be not trusted
|
||||
pub on_ground: bool,
|
||||
|
||||
pub sneaking: bool,
|
||||
pub sprinting: bool,
|
||||
|
||||
// TODO: This is currently unused, We have to calculate the block breaking speed our own and then break the block our own if its done
|
||||
pub current_block_destroy_stage: u8,
|
||||
|
||||
// TODO: prbly should put this into an Living Entitiy or something
|
||||
pub velocity: Vector3<f64>,
|
||||
|
||||
pub teleport_id_count: i32,
|
||||
// Current awaiting teleport id and location, None if did not teleport
|
||||
pub awaiting_teleport: Option<(VarInt, Vector3<f64>)>,
|
||||
@ -110,21 +104,17 @@ impl Player {
|
||||
};
|
||||
let config = client.config.clone().unwrap_or_default();
|
||||
Self {
|
||||
entity: Entity::new(entity_id, EntityType::Player, 1.62),
|
||||
config,
|
||||
gameprofile,
|
||||
client,
|
||||
entity: Entity::new(entity_id, EntityType::Player, 1.62),
|
||||
world,
|
||||
on_ground: false,
|
||||
awaiting_teleport: None,
|
||||
sneaking: false,
|
||||
sprinting: false,
|
||||
// TODO: Load this from previous instance
|
||||
health: 20.0,
|
||||
food: 20,
|
||||
food_saturation: 20.0,
|
||||
current_block_destroy_stage: 0,
|
||||
velocity: Vector3::new(0.0, 0.0, 0.0),
|
||||
inventory: PlayerInventory::new(),
|
||||
teleport_id_count: 0,
|
||||
abilities: PlayerAbilities::default(),
|
||||
@ -144,28 +134,6 @@ impl Player {
|
||||
self.entity.entity_id
|
||||
}
|
||||
|
||||
pub fn knockback(&mut self, strength: f64, x: f64, z: f64) {
|
||||
// This has some vanilla magic
|
||||
let mut x = x;
|
||||
let mut z = z;
|
||||
while x * x + z * z < 1.0E-5 {
|
||||
x = (rand::random::<f64>() - rand::random::<f64>()) * 0.01;
|
||||
z = (rand::random::<f64>() - rand::random::<f64>()) * 0.01;
|
||||
}
|
||||
|
||||
let var8 = Vector3::new(x, 0.0, z).normalize() * strength;
|
||||
let var7 = self.velocity;
|
||||
self.velocity = Vector3::new(
|
||||
var7.x / 2.0 - var8.x,
|
||||
if self.on_ground {
|
||||
(var7.y / 2.0 + strength).min(0.4)
|
||||
} else {
|
||||
var7.y
|
||||
},
|
||||
var7.z / 2.0 - var8.z,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn send_abilties_update(&mut self) {
|
||||
let mut b = 0i8;
|
||||
let abilities = &self.abilities;
|
||||
@ -189,60 +157,6 @@ impl Player {
|
||||
));
|
||||
}
|
||||
|
||||
pub async fn set_sneaking(&mut self, sneaking: bool) {
|
||||
assert!(self.sneaking != sneaking);
|
||||
self.sneaking = sneaking;
|
||||
self.set_flag(Self::SNEAKING_FLAG_INDEX, sneaking).await;
|
||||
// if sneaking {
|
||||
// self.set_pose(EntityPose::Crouching).await;
|
||||
// } else {
|
||||
// self.set_pose(EntityPose::Standing).await;
|
||||
// }
|
||||
}
|
||||
|
||||
pub async fn set_sprinting(&mut self, sprinting: bool) {
|
||||
assert!(self.sprinting != sprinting);
|
||||
self.sprinting = sprinting;
|
||||
self.set_flag(Self::SPRINTING_FLAG_INDEX, sprinting).await;
|
||||
}
|
||||
|
||||
pub const ON_FIRE_FLAG_INDEX: u32 = 0;
|
||||
pub const SNEAKING_FLAG_INDEX: u32 = 1;
|
||||
pub const SPRINTING_FLAG_INDEX: u32 = 3;
|
||||
pub const SWIMMING_FLAG_INDEX: u32 = 4;
|
||||
pub const INVISIBLE_FLAG_INDEX: u32 = 5;
|
||||
pub const GLOWING_FLAG_INDEX: u32 = 6;
|
||||
pub const FALL_FLYING_FLAG_INDEX: u32 = 7;
|
||||
async fn set_flag(&mut self, index: u32, value: bool) {
|
||||
let mut b = 0i8;
|
||||
if value {
|
||||
b |= 1 << index;
|
||||
} else {
|
||||
b &= !(1 << index);
|
||||
}
|
||||
let packet =
|
||||
CSetEntityMetadata::new(self.entity_id().into(), Metadata::new(0, 0.into(), b));
|
||||
self.client.send_packet(&packet);
|
||||
self.world
|
||||
.lock()
|
||||
.await
|
||||
.broadcast_packet(&[self.client.token], &packet);
|
||||
}
|
||||
|
||||
pub async fn set_pose(&mut self, pose: EntityPose) {
|
||||
self.entity.pose = pose;
|
||||
let pose = self.entity.pose as i32;
|
||||
let packet = CSetEntityMetadata::<VarInt>::new(
|
||||
self.entity_id().into(),
|
||||
Metadata::new(6, 20.into(), (pose).into()),
|
||||
);
|
||||
self.client.send_packet(&packet);
|
||||
self.world
|
||||
.lock()
|
||||
.await
|
||||
.broadcast_packet(&[self.client.token], &packet)
|
||||
}
|
||||
|
||||
pub fn teleport(&mut self, x: f64, y: f64, z: f64, yaw: f32, pitch: f32) {
|
||||
// this is the ultra special magic code used to create the teleport id
|
||||
self.teleport_id_count += 1;
|
||||
@ -251,7 +165,6 @@ impl Player {
|
||||
}
|
||||
let entity = &mut self.entity;
|
||||
entity.set_pos(x, y, z);
|
||||
self.last_position = entity.pos;
|
||||
entity.yaw = yaw;
|
||||
entity.pitch = pitch;
|
||||
self.awaiting_teleport = Some((self.teleport_id_count.into(), Vector3::new(x, y, z)));
|
||||
@ -287,11 +200,16 @@ impl Player {
|
||||
/// Kicks the Client with a reason depending on the connection state
|
||||
pub fn kick(&mut self, reason: TextComponent) {
|
||||
assert!(self.client.connection_state == ConnectionState::Play);
|
||||
dbg!(&reason);
|
||||
self.client
|
||||
.try_send_packet(&CPlayDisconnect::new(reason))
|
||||
.unwrap_or_else(|_| self.client.close());
|
||||
assert!(!self.client.closed);
|
||||
|
||||
self.client
|
||||
.try_send_packet(&CPlayDisconnect::new(&reason))
|
||||
.unwrap_or_else(|_| self.client.close());
|
||||
log::info!(
|
||||
"Kicked {} for {}",
|
||||
self.gameprofile.name,
|
||||
reason.to_pretty_console()
|
||||
);
|
||||
self.client.close()
|
||||
}
|
||||
|
||||
|
||||
@ -158,9 +158,6 @@ impl World {
|
||||
.client
|
||||
.send_packet(&CPlayerInfoUpdate::new(0x01 | 0x08, &entries));
|
||||
|
||||
// Start waiting for level chunks
|
||||
player.client.send_packet(&CGameEvent::new(13, 0.0));
|
||||
|
||||
let gameprofile = &player.gameprofile;
|
||||
|
||||
// spawn player for every client
|
||||
@ -216,6 +213,9 @@ impl World {
|
||||
self.broadcast_packet(&[player.client.token], &packet)
|
||||
}
|
||||
|
||||
// Start waiting for level chunks
|
||||
player.client.send_packet(&CGameEvent::new(13, 0.0));
|
||||
|
||||
// Spawn in inital chunks
|
||||
player_chunker::player_join(self, player).await;
|
||||
}
|
||||
@ -231,8 +231,9 @@ impl World {
|
||||
|
||||
let level = self.level.clone();
|
||||
let closed = client.closed;
|
||||
tokio::spawn(async move {
|
||||
level.lock().unwrap().fetch_chunks(&chunks, sender, closed);
|
||||
let chunks = Arc::new(chunks);
|
||||
tokio::task::spawn_blocking(move || {
|
||||
level.lock().unwrap().fetch_chunks(&chunks, sender, closed)
|
||||
});
|
||||
|
||||
while let Some(chunk_data) = chunk_receiver.recv().await {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user