mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
fix(redstone): use vanilla pressure plate detection bounds (#2439)
Replace full-block entity queries with vanilla's centered 14x4x14 pressure plate detection box. Share the bounds between normal and weighted pressure plates and cover the geometry with unit tests.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use pumpkin_data::{Block, BlockDirection, BlockState, BlockStateId};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_util::math::{boundingbox::BoundingBox, position::BlockPos};
|
||||
use pumpkin_world::{tick::TickPriority, world::BlockFlags};
|
||||
|
||||
use crate::{
|
||||
@@ -12,6 +12,19 @@ use crate::{
|
||||
pub mod plate;
|
||||
pub mod weighted;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
// Vanilla pressure plates detect entities in a centered 14x4x14-pixel volume.
|
||||
const PRESSURE_PLATE_DETECTION_BOX: BoundingBox = BoundingBox::new_array(
|
||||
[1.0 / 16.0, 0.0, 1.0 / 16.0],
|
||||
[15.0 / 16.0, 4.0 / 16.0, 15.0 / 16.0],
|
||||
);
|
||||
|
||||
fn detection_box_at(pos: &BlockPos) -> BoundingBox {
|
||||
PRESSURE_PLATE_DETECTION_BOX.at_pos(*pos)
|
||||
}
|
||||
|
||||
pub(crate) trait PressurePlate {
|
||||
async fn on_entity_collision_pp(&self, args: OnEntityCollisionArgs<'_>) {
|
||||
let output = self.get_redstone_output(args.block, args.state.id);
|
||||
|
||||
@@ -3,7 +3,7 @@ use pumpkin_data::{
|
||||
block_properties::BlockProperties,
|
||||
tag::{self},
|
||||
};
|
||||
use pumpkin_util::math::{boundingbox::BoundingBox, position::BlockPos};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
|
||||
use crate::{
|
||||
@@ -15,7 +15,7 @@ use crate::{
|
||||
world::World,
|
||||
};
|
||||
|
||||
use super::PressurePlate;
|
||||
use super::{PressurePlate, detection_box_at};
|
||||
|
||||
/// This is for Normal Pressure plates, so not Gold or Iron
|
||||
pub struct PressurePlateBlock;
|
||||
@@ -99,8 +99,7 @@ impl PressurePlate for PressurePlateBlock {
|
||||
}
|
||||
|
||||
async fn calculate_redstone_output(&self, world: &World, _block: &Block, pos: &BlockPos) -> u8 {
|
||||
// TODO: this is bad use real box
|
||||
let aabb = BoundingBox::from_block(pos);
|
||||
let aabb = detection_box_at(pos);
|
||||
if !world.get_entities_at_box(&aabb).is_empty()
|
||||
|| !world.get_players_at_box(&aabb).is_empty()
|
||||
{
|
||||
|
||||
51
pumpkin/src/block/blocks/redstone/pressure_plate/tests.rs
Normal file
51
pumpkin/src/block/blocks/redstone/pressure_plate/tests.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
use pumpkin_util::math::{boundingbox::BoundingBox, position::BlockPos, vector3::Vector3};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn detection_box_is_offset_to_block_position() {
|
||||
let bounding_box = detection_box_at(&BlockPos::new(10, 64, -5));
|
||||
|
||||
assert_eq!(bounding_box.min, Vector3::new(10.0625, 64.0, -4.9375));
|
||||
assert_eq!(bounding_box.max, Vector3::new(10.9375, 64.25, -4.0625));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn entity_at_plate_center_intersects_detection_box() {
|
||||
let detection_box = detection_box_at(&BlockPos::new(0, 0, 0));
|
||||
let entity_box = BoundingBox::new_array([0.4, 0.0, 0.4], [0.6, 1.8, 0.6]);
|
||||
|
||||
assert!(detection_box.intersects(&entity_box));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn entity_outside_horizontal_bounds_does_not_intersect_detection_box() {
|
||||
let detection_box = detection_box_at(&BlockPos::new(0, 0, 0));
|
||||
let entity_box = BoundingBox::new_array([0.95, 0.0, 0.4], [1.0, 0.2, 0.6]);
|
||||
|
||||
assert!(!detection_box.intersects(&entity_box));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn entity_above_detection_height_does_not_intersect_detection_box() {
|
||||
let detection_box = detection_box_at(&BlockPos::new(0, 0, 0));
|
||||
let entity_box = BoundingBox::new_array([0.4, 0.3, 0.4], [0.6, 0.6, 0.6]);
|
||||
|
||||
assert!(!detection_box.intersects(&entity_box));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn entity_partially_overlapping_detection_box_intersects() {
|
||||
let detection_box = detection_box_at(&BlockPos::new(0, 0, 0));
|
||||
let entity_box = BoundingBox::new_array([0.9, 0.2, 0.4], [0.95, 0.3, 0.6]);
|
||||
|
||||
assert!(detection_box.intersects(&entity_box));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn entity_touching_detection_box_boundary_does_not_intersect() {
|
||||
let detection_box = detection_box_at(&BlockPos::new(0, 0, 0));
|
||||
let entity_box = BoundingBox::new_array([0.9375, 0.0, 0.4], [1.0, 0.2, 0.6]);
|
||||
|
||||
assert!(!detection_box.intersects(&entity_box));
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
use pumpkin_data::{
|
||||
Block, BlockDirection, BlockId, BlockState, BlockStateId, block_properties::BlockProperties,
|
||||
};
|
||||
use pumpkin_util::math::{boundingbox::BoundingBox, position::BlockPos};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
|
||||
use crate::{
|
||||
@@ -13,7 +13,7 @@ use crate::{
|
||||
world::World,
|
||||
};
|
||||
|
||||
use super::PressurePlate;
|
||||
use super::{PressurePlate, detection_box_at};
|
||||
|
||||
/// This is for Gold and Iron Pressure Plate
|
||||
pub struct WeightedPressurePlateBlock;
|
||||
@@ -109,8 +109,7 @@ impl PressurePlate for WeightedPressurePlateBlock {
|
||||
// Iron
|
||||
150
|
||||
};
|
||||
// TODO: this is bad use real box
|
||||
let aabb = BoundingBox::from_block(pos);
|
||||
let aabb = detection_box_at(pos);
|
||||
let len = world.get_entities_at_box(&aabb).len() + world.get_players_at_box(&aabb).len();
|
||||
let len = len.min(weight);
|
||||
if len > 0 {
|
||||
|
||||
Reference in New Issue
Block a user