PocketMine-MP 5.15.1 git-fb9a74e8799c71ed8292cfa53abe7a4c9204629d
PressurePlate.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\block;
25
26use pocketmine\block\utils\StaticSupportTrait;
27use pocketmine\block\utils\SupportType;
35use function count;
36
37abstract class PressurePlate extends Transparent{
38 use StaticSupportTrait;
39
40 private readonly int $deactivationDelayTicks;
41
42 public function __construct(
43 BlockIdentifier $idInfo,
44 string $name,
45 BlockTypeInfo $typeInfo,
46 int $deactivationDelayTicks = 20 //TODO: make this mandatory in PM6
47 ){
48 parent::__construct($idInfo, $name, $typeInfo);
49 $this->deactivationDelayTicks = $deactivationDelayTicks;
50 }
51
52 public function isSolid() : bool{
53 return false;
54 }
55
56 protected function recalculateCollisionBoxes() : array{
57 return [];
58 }
59
60 public function getSupportType(int $facing) : SupportType{
61 return SupportType::NONE;
62 }
63
64 private function canBeSupportedAt(Block $block) : bool{
65 return $block->getAdjacentSupportType(Facing::DOWN) !== SupportType::NONE;
66 }
67
68 public function hasEntityCollision() : bool{
69 return true;
70 }
71
72 public function onEntityInside(Entity $entity) : bool{
73 if(!$this->hasOutputSignal()){
74 $this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 0);
75 }
76 return true;
77 }
78
84 protected function getActivationBox() : AxisAlignedBB{
85 return AxisAlignedBB::one()
86 ->squash(Axis::X, 1 / 8)
87 ->squash(Axis::Z, 1 / 8)
88 ->trim(Facing::UP, 3 / 4)
89 ->offset($this->position->x, $this->position->y, $this->position->z);
90 }
91
95 protected function hasOutputSignal() : bool{
96 return false;
97 }
98
107 protected function calculatePlateState(array $entities) : array{
108 return [$this, null];
109 }
110
117 protected function filterIrrelevantEntities(array $entities) : array{
118 return $entities;
119 }
120
121 public function onScheduledUpdate() : void{
122 $world = $this->position->getWorld();
123
124 $intersectionAABB = $this->getActivationBox();
125 $activatingEntities = $this->filterIrrelevantEntities($world->getNearbyEntities($intersectionAABB));
126
127 //if an irrelevant entity is inside the full cube space of the pressure plate but not activating the plate,
128 //it will cause scheduled updates on the plate every tick. We don't want to fire events in this case if the
129 //plate is already deactivated.
130 if(count($activatingEntities) > 0 || $this->hasOutputSignal()){
131 [$newState, $pressedChange] = $this->calculatePlateState($activatingEntities);
132
133 //always call this, in case there are new entities on the plate
134 if(PressurePlateUpdateEvent::hasHandlers()){
135 $ev = new PressurePlateUpdateEvent($this, $newState, $activatingEntities);
136 $ev->call();
137 $newState = $ev->isCancelled() ? null : $ev->getNewState();
138 }
139 if($newState !== null){
140 $world->setBlock($this->position, $newState);
141 if($pressedChange !== null){
142 $world->addSound($this->position, $pressedChange ?
143 new PressurePlateActivateSound($this) :
145 );
146 }
147 }
148 if($pressedChange ?? $this->hasOutputSignal()){
149 $world->scheduleDelayedBlockUpdate($this->position, $this->deactivationDelayTicks);
150 }
151 }
152 }
153}
filterIrrelevantEntities(array $entities)
calculatePlateState(array $entities)