deactivationDelayTicks = $deactivationDelayTicks; } public function isSolid() : bool{ return false; } protected function recalculateCollisionBoxes() : array{ return []; } public function getSupportType(Facing $facing) : SupportType{ return SupportType::NONE; } private function canBeSupportedAt(Block $block) : bool{ return $block->getAdjacentSupportType(Facing::DOWN) !== SupportType::NONE; } public function hasEntityCollision() : bool{ return true; } public function onEntityInside(Entity $entity) : bool{ if(!$this->hasOutputSignal()){ $this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 0); } return true; } /** * Returns the AABB that entities must intersect to activate the pressure plate. * Note that this is not the same as the collision box (pressure plate doesn't have one), nor the visual bounding * box. The activation area has a height of 0.25 blocks. */ protected function getActivationBox() : AxisAlignedBB{ return AxisAlignedBB::one() ->squashedCopy(Axis::X, 1 / 8) ->squashedCopy(Axis::Z, 1 / 8) ->trimmedCopy(Facing::UP, 3 / 4) ->offsetCopy($this->position->x, $this->position->y, $this->position->z); } /** * TODO: make this abstract in PM6 */ protected function hasOutputSignal() : bool{ return false; } /** * TODO: make this abstract in PM6 * * @param Entity[] $entities * * @return mixed[] * @phpstan-return array{Block, ?bool} */ protected function calculatePlateState(array $entities) : array{ return [$this, null]; } /** * Filters entities which don't affect the pressure plate state from the given list. * * @param Entity[] $entities * @return Entity[] */ protected function filterIrrelevantEntities(array $entities) : array{ return $entities; } public function onScheduledUpdate() : void{ $world = $this->position->getWorld(); $intersectionAABB = $this->getActivationBox(); $activatingEntities = $this->filterIrrelevantEntities($world->getNearbyEntities($intersectionAABB)); //if an irrelevant entity is inside the full cube space of the pressure plate but not activating the plate, //it will cause scheduled updates on the plate every tick. We don't want to fire events in this case if the //plate is already deactivated. if(count($activatingEntities) > 0 || $this->hasOutputSignal()){ [$newState, $pressedChange] = $this->calculatePlateState($activatingEntities); //always call this, in case there are new entities on the plate if(PressurePlateUpdateEvent::hasHandlers()){ $ev = new PressurePlateUpdateEvent($this, $newState, $activatingEntities); $ev->call(); $newState = $ev->isCancelled() ? null : $ev->getNewState(); } if($newState !== null){ $world->setBlock($this->position, $newState); if($pressedChange !== null){ $world->addSound($this->position, $pressedChange ? new PressurePlateActivateSound($this) : new PressurePlateDeactivateSound($this) ); } } if($pressedChange ?? $this->hasOutputSignal()){ $world->scheduleDelayedBlockUpdate($this->position, $this->deactivationDelayTicks); } } } }