Refactor Entity

This commit is contained in:
Snowiiii 2024-09-07 19:33:01 +02:00
parent cd25387a4b
commit 2ee9710f93
9 changed files with 290 additions and 196 deletions

3
Cargo.lock generated
View File

@ -1916,9 +1916,6 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-entity" name = "pumpkin-entity"
version = "0.1.0" version = "0.1.0"
dependencies = [
"pumpkin-core",
]
[[package]] [[package]]
name = "pumpkin-inventory" name = "pumpkin-inventory"

View File

@ -4,4 +4,3 @@ version.workspace = true
edition.workspace = true edition.workspace = true
[dependencies] [dependencies]
pumpkin-core = { path = "../pumpkin-core"}

View File

@ -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 entity_type;
pub mod pose; pub mod pose;
pub type EntityId = i32; 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));
}
}
}
}
}

View File

@ -5,11 +5,11 @@ use serde::Serialize;
#[derive(Serialize)] #[derive(Serialize)]
#[packet(0x1D)] #[packet(0x1D)]
pub struct CPlayDisconnect<'a> { pub struct CPlayDisconnect<'a> {
reason: TextComponent<'a>, reason: &'a TextComponent<'a>,
} }
impl<'a> CPlayDisconnect<'a> { impl<'a> CPlayDisconnect<'a> {
pub fn new(reason: TextComponent<'a>) -> Self { pub fn new(reason: &'a TextComponent<'a>) -> Self {
Self { reason } Self { reason }
} }
} }

View File

@ -323,7 +323,7 @@ impl Client {
} }
// So we can also kick on errors, but generally should use Player::kick // So we can also kick on errors, but generally should use Player::kick
ConnectionState::Play => { 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()); .unwrap_or_else(|_| self.close());
} }
_ => { _ => {

View File

@ -82,15 +82,27 @@ impl Player {
Self::clamp_vertical(position.feet_y), Self::clamp_vertical(position.feet_y),
Self::clamp_horizontal(position.z), Self::clamp_horizontal(position.z),
); );
// TODO: teleport when moving > 8 block entity.on_ground = position.ground;
let on_ground = entity.on_ground;
// send new position to all other players
let on_ground = self.on_ground;
let entity_id = entity.entity_id; let entity_id = entity.entity_id;
let (x, y, z) = entity.pos.into(); let (x, y, z) = entity.pos.into();
let (lastx, lasty, lastz) = self.last_position.into(); let (lastx, lasty, lastz) = self.last_position.into();
let world = self.world.clone(); let world = self.world.clone();
let world = world.lock().await; 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( world.broadcast_packet(
&[self.client.token], &[self.client.token],
&CUpdateEntityPos::new( &CUpdateEntityPos::new(
@ -128,11 +140,11 @@ impl Player {
Self::clamp_vertical(position_rotation.feet_y), Self::clamp_vertical(position_rotation.feet_y),
Self::clamp_horizontal(position_rotation.z), Self::clamp_horizontal(position_rotation.z),
); );
entity.on_ground = position_rotation.ground;
entity.yaw = wrap_degrees(position_rotation.yaw) % 360.0; entity.yaw = wrap_degrees(position_rotation.yaw) % 360.0;
entity.pitch = wrap_degrees(position_rotation.pitch).clamp(-90.0, 90.0) % 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 = entity.on_ground;
let on_ground = self.on_ground;
let entity_id = entity.entity_id; let entity_id = entity.entity_id;
let (x, y, z) = entity.pos.into(); let (x, y, z) = entity.pos.into();
let (lastx, lasty, lastz) = self.last_position.into(); let (lastx, lasty, lastz) = self.last_position.into();
@ -142,6 +154,20 @@ impl Player {
let world = self.world.clone(); let world = self.world.clone();
let world = world.lock().await; 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( world.broadcast_packet(
&[self.client.token], &[self.client.token],
&CUpdateEntityPosRot::new( &CUpdateEntityPosRot::new(
@ -168,10 +194,11 @@ impl Player {
return; return;
} }
let entity = &mut self.entity; let entity = &mut self.entity;
entity.on_ground = rotation.ground;
entity.yaw = wrap_degrees(rotation.yaw) % 360.0; entity.yaw = wrap_degrees(rotation.yaw) % 360.0;
entity.pitch = wrap_degrees(rotation.pitch).clamp(-90.0, 90.0) % 360.0; entity.pitch = wrap_degrees(rotation.pitch).clamp(-90.0, 90.0) % 360.0;
// send new position to all other players // 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 entity_id = entity.entity_id;
let yaw = modulus(entity.yaw * 256.0 / 360.0, 256.0); let yaw = modulus(entity.yaw * 256.0 / 360.0, 256.0);
let pitch = modulus(entity.pitch * 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) { 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) { 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) { if let Some(action) = Action::from_i32(command.action.0) {
match action { match action {
pumpkin_protocol::server::play::Action::StartSneaking => { pumpkin_protocol::server::play::Action::StartSneaking => {
if !self.sneaking { if !self.entity.sneaking {
self.set_sneaking(true).await self.entity
.set_sneaking(&mut self.client, self.world.clone(), true)
.await
} }
} }
pumpkin_protocol::server::play::Action::StopSneaking => { pumpkin_protocol::server::play::Action::StopSneaking => {
if self.sneaking { if self.entity.sneaking {
self.set_sneaking(false).await self.entity
.set_sneaking(&mut self.client, self.world.clone(), false)
.await
} }
} }
pumpkin_protocol::server::play::Action::LeaveBed => todo!(), pumpkin_protocol::server::play::Action::LeaveBed => todo!(),
pumpkin_protocol::server::play::Action::StartSprinting => { pumpkin_protocol::server::play::Action::StartSprinting => {
if !self.sprinting { if !self.entity.sprinting {
self.set_sprinting(true).await self.entity
.set_sprinting(&mut self.client, self.world.clone(), true)
.await
} }
} }
pumpkin_protocol::server::play::Action::StopSprinting => { pumpkin_protocol::server::play::Action::StopSprinting => {
if self.sprinting { if self.entity.sprinting {
self.set_sprinting(false).await self.entity
.set_sprinting(&mut self.client, self.world.clone(), false)
.await
} }
} }
pumpkin_protocol::server::play::Action::StartHorseJump => todo!(), pumpkin_protocol::server::play::Action::StartHorseJump => todo!(),
pumpkin_protocol::server::play::Action::StopHorseJump => todo!(), pumpkin_protocol::server::play::Action::StopHorseJump => todo!(),
pumpkin_protocol::server::play::Action::OpenVehicleInventory => 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 { } else {
self.kick(TextComponent::text("Invalid player command")) self.kick(TextComponent::text("Invalid player command"))
@ -320,8 +362,10 @@ impl Player {
pub async fn handle_interact(&mut self, _: &mut Server, interact: SInteract) { pub async fn handle_interact(&mut self, _: &mut Server, interact: SInteract) {
let sneaking = interact.sneaking; let sneaking = interact.sneaking;
if self.sneaking != sneaking { if self.entity.sneaking != sneaking {
self.set_sneaking(sneaking).await; self.entity
.set_sneaking(&mut self.client, self.world.clone(), sneaking)
.await;
} }
match ActionType::from_i32(interact.typ.0) { match ActionType::from_i32(interact.typ.0) {
Some(action) => match action { Some(action) => match action {
@ -335,27 +379,27 @@ impl Player {
let attacked_player = world.get_by_entityid(self, entity_id.0 as EntityId); let attacked_player = world.get_by_entityid(self, entity_id.0 as EntityId);
if let Some(mut player) = attacked_player { if let Some(mut player) = attacked_player {
let token = player.client.token; let token = player.client.token;
let velo = player.velocity; let velo = player.entity.velocity;
if config.protect_creative && player.gamemode == GameMode::Creative { if config.protect_creative && player.gamemode == GameMode::Creative {
return; return;
} }
if config.knockback { if config.knockback {
let yaw = self.entity.yaw; let yaw = self.entity.yaw;
let strength = 1.0; let strength = 1.0;
player.knockback( player.entity.knockback(
strength * 0.5, strength * 0.5,
(yaw * (PI / 180.0)).sin() as f64, (yaw * (PI / 180.0)).sin() as f64,
-(yaw * (PI / 180.0)).cos() as f64, -(yaw * (PI / 180.0)).cos() as f64,
); );
let packet = &CEntityVelocity::new( let packet = &CEntityVelocity::new(
&entity_id, &entity_id,
player.velocity.x as f32, velo.x as f32,
player.velocity.y as f32, velo.y as f32,
player.velocity.z 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); player.client.send_packet(packet);
} }
if config.hurt_animation { if config.hurt_animation {

View File

@ -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 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)
}
}

View File

@ -7,13 +7,13 @@ use pumpkin_core::{
text::TextComponent, text::TextComponent,
GameMode, 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_inventory::player::PlayerInventory;
use pumpkin_protocol::{ use pumpkin_protocol::{
bytebuf::{packet_id::Packet, DeserializerError}, bytebuf::{packet_id::Packet, DeserializerError},
client::play::{ client::play::{
CGameEvent, CPlayDisconnect, CPlayerAbilities, CPlayerInfoUpdate, CSetEntityMetadata, CGameEvent, CPlayDisconnect, CPlayerAbilities, CPlayerInfoUpdate, CSyncPlayerPosition,
CSyncPlayerPosition, CSystemChatMessage, Metadata, PlayerAction, CSystemChatMessage, PlayerAction,
}, },
server::play::{ server::play::{
SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract, SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract,
@ -30,6 +30,8 @@ use crate::{
world::World, world::World,
}; };
use super::Entity;
pub struct PlayerAbilities { pub struct PlayerAbilities {
pub invulnerable: bool, pub invulnerable: bool,
pub flying: bool, pub flying: bool,
@ -53,9 +55,10 @@ impl Default for PlayerAbilities {
} }
pub struct Player { pub struct Player {
pub entity: Entity,
pub gameprofile: GameProfile, pub gameprofile: GameProfile,
pub client: Client, pub client: Client,
pub entity: Entity,
pub config: PlayerConfig, pub config: PlayerConfig,
// TODO: Put this into entity // TODO: Put this into entity
pub world: Arc<tokio::sync::Mutex<World>>, pub world: Arc<tokio::sync::Mutex<World>>,
@ -68,20 +71,11 @@ pub struct Player {
pub inventory: PlayerInventory, pub inventory: PlayerInventory,
/// send `send_abilties_update` when changed /// send `send_abilties_update` when changed
pub abilities: PlayerAbilities, pub abilities: PlayerAbilities,
pub last_position: Vector3<f64>, 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 // 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, 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, pub teleport_id_count: i32,
// Current awaiting teleport id and location, None if did not teleport // Current awaiting teleport id and location, None if did not teleport
pub awaiting_teleport: Option<(VarInt, Vector3<f64>)>, pub awaiting_teleport: Option<(VarInt, Vector3<f64>)>,
@ -110,21 +104,17 @@ impl Player {
}; };
let config = client.config.clone().unwrap_or_default(); let config = client.config.clone().unwrap_or_default();
Self { Self {
entity: Entity::new(entity_id, EntityType::Player, 1.62),
config, config,
gameprofile, gameprofile,
client, client,
entity: Entity::new(entity_id, EntityType::Player, 1.62),
world, world,
on_ground: false,
awaiting_teleport: None, awaiting_teleport: None,
sneaking: false,
sprinting: false,
// TODO: Load this from previous instance // TODO: Load this from previous instance
health: 20.0, health: 20.0,
food: 20, food: 20,
food_saturation: 20.0, food_saturation: 20.0,
current_block_destroy_stage: 0, current_block_destroy_stage: 0,
velocity: Vector3::new(0.0, 0.0, 0.0),
inventory: PlayerInventory::new(), inventory: PlayerInventory::new(),
teleport_id_count: 0, teleport_id_count: 0,
abilities: PlayerAbilities::default(), abilities: PlayerAbilities::default(),
@ -144,28 +134,6 @@ impl Player {
self.entity.entity_id 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) { pub fn send_abilties_update(&mut self) {
let mut b = 0i8; let mut b = 0i8;
let abilities = &self.abilities; 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) { 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 // this is the ultra special magic code used to create the teleport id
self.teleport_id_count += 1; self.teleport_id_count += 1;
@ -251,7 +165,6 @@ impl Player {
} }
let entity = &mut self.entity; let entity = &mut self.entity;
entity.set_pos(x, y, z); entity.set_pos(x, y, z);
self.last_position = entity.pos;
entity.yaw = yaw; entity.yaw = yaw;
entity.pitch = pitch; entity.pitch = pitch;
self.awaiting_teleport = Some((self.teleport_id_count.into(), Vector3::new(x, y, z))); 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 /// Kicks the Client with a reason depending on the connection state
pub fn kick(&mut self, reason: TextComponent) { pub fn kick(&mut self, reason: TextComponent) {
assert!(self.client.connection_state == ConnectionState::Play); assert!(self.client.connection_state == ConnectionState::Play);
dbg!(&reason); assert!(!self.client.closed);
self.client
.try_send_packet(&CPlayDisconnect::new(reason))
.unwrap_or_else(|_| self.client.close());
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() self.client.close()
} }

View File

@ -158,9 +158,6 @@ impl World {
.client .client
.send_packet(&CPlayerInfoUpdate::new(0x01 | 0x08, &entries)); .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; let gameprofile = &player.gameprofile;
// spawn player for every client // spawn player for every client
@ -216,6 +213,9 @@ impl World {
self.broadcast_packet(&[player.client.token], &packet) 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 // Spawn in inital chunks
player_chunker::player_join(self, player).await; player_chunker::player_join(self, player).await;
} }
@ -231,8 +231,9 @@ impl World {
let level = self.level.clone(); let level = self.level.clone();
let closed = client.closed; let closed = client.closed;
tokio::spawn(async move { let chunks = Arc::new(chunks);
level.lock().unwrap().fetch_chunks(&chunks, sender, closed); tokio::task::spawn_blocking(move || {
level.lock().unwrap().fetch_chunks(&chunks, sender, closed)
}); });
while let Some(chunk_data) = chunk_receiver.recv().await { while let Some(chunk_data) = chunk_receiver.recv().await {