Check block distance

This commit is contained in:
Snowiiii 2024-08-25 19:16:38 +02:00
parent 268fc19b7b
commit 9d6c8dc524
7 changed files with 107 additions and 14 deletions

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

@ -1 +1,2 @@
pub mod boundingbox;
pub mod math;