Check block distance
This commit is contained in:
parent
268fc19b7b
commit
9d6c8dc524
@ -16,10 +16,12 @@ pub struct Entity {
|
||||
pub yaw: f32,
|
||||
pub head_yaw: f32,
|
||||
pub pitch: f32,
|
||||
// TODO: Change this in diffrent poses
|
||||
pub standing_eye_height: f32,
|
||||
}
|
||||
|
||||
impl Entity {
|
||||
pub fn new(entity_id: EntityId, entity_type: EntityType) -> Self {
|
||||
pub fn new(entity_id: EntityId, entity_type: EntityType, standing_eye_height: f32) -> Self {
|
||||
Self {
|
||||
entity_id,
|
||||
entity_type,
|
||||
@ -32,6 +34,7 @@ impl Entity {
|
||||
yaw: 0.0,
|
||||
head_yaw: 0.0,
|
||||
pitch: 0.0,
|
||||
standing_eye_height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,13 +5,13 @@ use crate::{position::WorldPosition, VarInt};
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[packet(0x09)]
|
||||
pub struct CBlockUpdate {
|
||||
location: WorldPosition,
|
||||
pub struct CBlockUpdate<'a> {
|
||||
location: &'a WorldPosition,
|
||||
block_id: VarInt,
|
||||
}
|
||||
|
||||
impl CBlockUpdate {
|
||||
pub fn new(location: WorldPosition, block_id: VarInt) -> Self {
|
||||
impl<'a> CBlockUpdate<'a> {
|
||||
pub fn new(location: &'a WorldPosition, block_id: VarInt) -> Self {
|
||||
Self { location, block_id }
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,6 +329,10 @@ impl Player {
|
||||
pub fn handle_player_action(&mut self, server: &mut Server, player_action: SPlayerAction) {
|
||||
match Status::from_i32(player_action.status.0).unwrap() {
|
||||
Status::StartedDigging => {
|
||||
if !self.can_interact_with_block_at(&player_action.location, 1.0) {
|
||||
// TODO: maybe log?
|
||||
return;
|
||||
}
|
||||
// TODO: do validation
|
||||
// TODO: Config
|
||||
if self.gamemode == GameMode::Creative {
|
||||
@ -337,20 +341,28 @@ impl Player {
|
||||
// TODO: currently this is always dirt replace it
|
||||
server.broadcast_packet(self, &CWorldEvent::new(2001, &location, 11, false));
|
||||
// AIR
|
||||
server.broadcast_packet(self, &CBlockUpdate::new(location, 0.into()));
|
||||
server.broadcast_packet(self, &CBlockUpdate::new(&location, 0.into()));
|
||||
}
|
||||
}
|
||||
Status::CancelledDigging => {
|
||||
if !self.can_interact_with_block_at(&player_action.location, 1.0) {
|
||||
// TODO: maybe log?
|
||||
return;
|
||||
}
|
||||
self.current_block_destroy_stage = 0;
|
||||
}
|
||||
Status::FinishedDigging => {
|
||||
// TODO: do validation
|
||||
let location = player_action.location;
|
||||
if !self.can_interact_with_block_at(&location, 1.0) {
|
||||
// TODO: maybe log?
|
||||
return;
|
||||
}
|
||||
// Block break & block break sound
|
||||
// TODO: currently this is always dirt replace it
|
||||
server.broadcast_packet(self, &CWorldEvent::new(2001, &location, 11, false));
|
||||
// AIR
|
||||
server.broadcast_packet(self, &CBlockUpdate::new(location, 0.into()));
|
||||
server.broadcast_packet(self, &CBlockUpdate::new(&location, 0.into()));
|
||||
// TODO: Send this every tick
|
||||
self.client
|
||||
.send_packet(&CAcknowledgeBlockChange::new(player_action.sequence));
|
||||
@ -376,12 +388,14 @@ impl Player {
|
||||
}
|
||||
|
||||
pub fn handle_use_item_on(&mut self, server: &mut Server, use_item_on: SUseItemOn) {
|
||||
self.client
|
||||
.send_packet(&CAcknowledgeBlockChange::new(use_item_on.sequence));
|
||||
|
||||
let location = use_item_on.location;
|
||||
|
||||
if !self.can_interact_with_block_at(&location, 1.0) {
|
||||
// TODO: maybe log?
|
||||
return;
|
||||
}
|
||||
|
||||
let face = BlockFace::from_i32(use_item_on.face.0).unwrap();
|
||||
let location = WorldPosition(location.0 + face.to_offset());
|
||||
if let Some(item) = self.inventory.held_item() {
|
||||
let minecraft_id =
|
||||
global_registry::find_minecraft_id(global_registry::ITEM_REGISTRY, item.item_id)
|
||||
@ -394,10 +408,19 @@ impl Player {
|
||||
{
|
||||
server.broadcast_packet(
|
||||
self,
|
||||
&CBlockUpdate::new(location, (block_state_id as i32).into()),
|
||||
&CBlockUpdate::new(&location, (block_state_id as i32).into()),
|
||||
);
|
||||
server.broadcast_packet(
|
||||
self,
|
||||
&CBlockUpdate::new(
|
||||
&WorldPosition(location.0 + face.to_offset()),
|
||||
(block_state_id as i32).into(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
self.client
|
||||
.send_packet(&CAcknowledgeBlockChange::new(use_item_on.sequence));
|
||||
}
|
||||
|
||||
pub fn handle_set_held_item(&mut self, _server: &mut Server, held: SSetHeldItem) {
|
||||
|
||||
@ -11,6 +11,7 @@ use pumpkin_protocol::{
|
||||
CGameEvent, CPlayDisconnect, CPlayerInfoUpdate, CSyncPlayerPosition, CSystemChatMessage,
|
||||
PlayerAction,
|
||||
},
|
||||
position::WorldPosition,
|
||||
server::play::{
|
||||
SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract,
|
||||
SPlayPingRequest, SPlayerAction, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation,
|
||||
@ -21,7 +22,7 @@ use pumpkin_protocol::{
|
||||
use pumpkin_world::vector3::Vector3;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{client::Client, server::Server};
|
||||
use crate::{client::Client, server::Server, util::boundingbox::BoundingBox};
|
||||
|
||||
pub struct Player {
|
||||
pub client: Client,
|
||||
@ -55,7 +56,7 @@ impl Player {
|
||||
pub fn new(client: Client, entity_id: EntityId, gamemode: GameMode) -> Self {
|
||||
Self {
|
||||
client,
|
||||
entity: Entity::new(entity_id, EntityType::Player),
|
||||
entity: Entity::new(entity_id, EntityType::Player, 1.62),
|
||||
on_ground: false,
|
||||
awaiting_teleport: None,
|
||||
sneaking: false,
|
||||
@ -125,6 +126,24 @@ impl Player {
|
||||
));
|
||||
}
|
||||
|
||||
pub fn block_interaction_range(&self) -> f64 {
|
||||
if self.gamemode == GameMode::Creative {
|
||||
5.0
|
||||
} else {
|
||||
4.5
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_interact_with_block_at(&self, pos: &WorldPosition, additional_range: f64) -> bool {
|
||||
let d = self.block_interaction_range() + additional_range;
|
||||
let box_pos = BoundingBox::from_block(pos);
|
||||
box_pos.squared_magnitude(Vector3 {
|
||||
x: self.entity.x,
|
||||
y: self.entity.y + self.entity.standing_eye_height as f64,
|
||||
z: self.entity.z,
|
||||
}) < d * d
|
||||
}
|
||||
|
||||
/// 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);
|
||||
|
||||
43
pumpkin/src/util/boundingbox.rs
Normal file
43
pumpkin/src/util/boundingbox.rs
Normal file
@ -0,0 +1,43 @@
|
||||
use pumpkin_protocol::position::WorldPosition;
|
||||
use pumpkin_world::vector3::Vector3;
|
||||
|
||||
pub struct BoundingBox {
|
||||
pub min_x: f64,
|
||||
pub min_y: f64,
|
||||
pub min_z: f64,
|
||||
pub max_x: f64,
|
||||
pub max_y: f64,
|
||||
pub max_z: f64,
|
||||
}
|
||||
|
||||
impl BoundingBox {
|
||||
pub fn new(min_x: f64, min_y: f64, min_z: f64, max_x: f64, max_y: f64, max_z: f64) -> Self {
|
||||
Self {
|
||||
min_x,
|
||||
min_y,
|
||||
min_z,
|
||||
max_x,
|
||||
max_y,
|
||||
max_z,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_block(position: &WorldPosition) -> Self {
|
||||
let position = position.0;
|
||||
Self {
|
||||
min_x: position.x as f64,
|
||||
min_y: position.y as f64,
|
||||
min_z: position.z as f64,
|
||||
max_x: (position.x as f64) + 1.0,
|
||||
max_y: (position.y as f64) + 1.0,
|
||||
max_z: (position.z as f64) + 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn squared_magnitude(&self, pos: Vector3<f64>) -> f64 {
|
||||
let d = f64::max(f64::max(self.min_x - pos.x, pos.x - self.max_x), 0.0);
|
||||
let e = f64::max(f64::max(self.min_y - pos.y, pos.y - self.max_y), 0.0);
|
||||
let f = f64::max(f64::max(self.min_z - pos.z, pos.z - self.max_z), 0.0);
|
||||
super::math::squared_magnitude(d, e, f)
|
||||
}
|
||||
}
|
||||
@ -10,3 +10,7 @@ pub fn wrap_degrees(var: f32) -> f32 {
|
||||
|
||||
var1
|
||||
}
|
||||
|
||||
pub fn squared_magnitude(a: f64, b: f64, c: f64) -> f64 {
|
||||
a * a + b * b + c * c
|
||||
}
|
||||
|
||||
@ -1 +1,2 @@
|
||||
pub mod boundingbox;
|
||||
pub mod math;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user