Make an enum for horizontal facing blocks

awkward that the interface is also called HorizontalFacing, so I had to improvise for the naming
This commit is contained in:
Dylan K. Taylor 2025-08-29 23:11:17 +01:00
parent 6f6b23d4e4
commit 6aaf6b336a
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
40 changed files with 305 additions and 250 deletions

View File

@ -27,6 +27,7 @@ use pocketmine\block\inventory\AnvilInventory;
use pocketmine\block\utils\Fallable; use pocketmine\block\utils\Fallable;
use pocketmine\block\utils\FallableTrait; use pocketmine\block\utils\FallableTrait;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
@ -57,7 +58,7 @@ class Anvil extends Transparent implements Fallable, HorizontalFacing{
} }
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
} }
public function getDamage() : int{ return $this->damage; } public function getDamage() : int{ return $this->damage; }
@ -72,7 +73,7 @@ class Anvil extends Transparent implements Fallable, HorizontalFacing{
} }
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->squashedCopy(Facing::axis(Facing::rotateY($this->facing, false)), 1 / 8)]; return [AxisAlignedBB::one()->squashedCopy(Facing::axis(Facing::rotateY($this->facing->toFacing(), false)), 1 / 8)];
} }
public function getSupportType(Facing $facing) : SupportType{ public function getSupportType(Facing $facing) : SupportType{
@ -89,7 +90,7 @@ class Anvil extends Transparent implements Fallable, HorizontalFacing{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){ if($player !== null){
$this->facing = Facing::rotateY($player->getHorizontalFacing(), false); $this->facing = HorizontalFacingOption::fromFacing(Facing::rotateY($player->getHorizontalFacing(), false));
} }
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\event\block\StructureGrowEvent; use pocketmine\event\block\StructureGrowEvent;
@ -63,7 +64,7 @@ abstract class BaseBigDripleaf extends Transparent implements HorizontalFacing{
return false; return false;
} }
if($player !== null){ if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing()); $this->facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
} }
if($block instanceof BaseBigDripleaf){ if($block instanceof BaseBigDripleaf){
$this->facing = $block->facing; $this->facing = $block->facing;

View File

@ -28,6 +28,7 @@ use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait; use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\DyeColor; use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
@ -51,7 +52,7 @@ class Bed extends Transparent implements Colored, HorizontalFacing{
protected bool $head = false; protected bool $head = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->bool($this->occupied); $w->bool($this->occupied);
$w->bool($this->head); $w->bool($this->head);
} }
@ -107,7 +108,7 @@ class Bed extends Transparent implements Colored, HorizontalFacing{
} }
private function getOtherHalfSide() : Facing{ private function getOtherHalfSide() : Facing{
return $this->head ? Facing::opposite($this->facing) : $this->facing; return $this->head ? Facing::opposite($this->facing->toFacing()) : $this->facing->toFacing();
} }
public function getOtherHalf() : ?Bed{ public function getOtherHalf() : ?Bed{
@ -174,7 +175,9 @@ class Bed extends Transparent implements Colored, HorizontalFacing{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedAt($blockReplace)){ if($this->canBeSupportedAt($blockReplace)){
$this->facing = $player !== null ? $player->getHorizontalFacing() : Facing::NORTH; if($player !== null){
$this->facing = HorizontalFacingOption::fromFacing($player->getHorizontalFacing());
}
$next = $this->getSide($this->getOtherHalfSide()); $next = $this->getSide($this->getOtherHalfSide());
if($next->canBeReplaced() && $this->canBeSupportedAt($next)){ if($next->canBeReplaced() && $this->canBeSupportedAt($next)){

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\Bell as TileBell; use pocketmine\block\tile\Bell as TileBell;
use pocketmine\block\utils\BellAttachmentType; use pocketmine\block\utils\BellAttachmentType;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
@ -46,13 +47,14 @@ final class Bell extends Transparent implements HorizontalFacing{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->enum($this->attachmentType); $w->enum($this->attachmentType);
$w->horizontalFacing($this->facing); $w->enum($this->facing);
} }
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
$realFacing = $this->facing->toFacing();
if($this->attachmentType === BellAttachmentType::FLOOR){ if($this->attachmentType === BellAttachmentType::FLOOR){
return [ return [
AxisAlignedBB::one()->squashedCopy(Facing::axis($this->facing), 1 / 4)->trimmedCopy(Facing::UP, 3 / 16) AxisAlignedBB::one()->squashedCopy(Facing::axis($realFacing), 1 / 4)->trimmedCopy(Facing::UP, 3 / 16)
]; ];
} }
if($this->attachmentType === BellAttachmentType::CEILING){ if($this->attachmentType === BellAttachmentType::CEILING){
@ -62,12 +64,12 @@ final class Bell extends Transparent implements HorizontalFacing{
} }
$box = AxisAlignedBB::one() $box = AxisAlignedBB::one()
->squashedCopy(Facing::axis(Facing::rotateY($this->facing, true)), 1 / 4) ->squashedCopy(Facing::axis(Facing::rotateY($realFacing, true)), 1 / 4)
->trimmedCopy(Facing::UP, 1 / 16) ->trimmedCopy(Facing::UP, 1 / 16)
->trimmedCopy(Facing::DOWN, 1 / 4); ->trimmedCopy(Facing::DOWN, 1 / 4);
return [ return [
$this->attachmentType === BellAttachmentType::ONE_WALL ? $box->trimmedCopy($this->facing, 3 / 16) : $box $this->attachmentType === BellAttachmentType::ONE_WALL ? $box->trimmedCopy($realFacing, 3 / 16) : $box
]; ];
} }
@ -93,13 +95,13 @@ final class Bell extends Transparent implements HorizontalFacing{
} }
if($face === Facing::UP){ if($face === Facing::UP){
if($player !== null){ if($player !== null){
$this->setFacing(Facing::opposite($player->getHorizontalFacing())); $this->setFacing(HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing())));
} }
$this->setAttachmentType(BellAttachmentType::FLOOR); $this->setAttachmentType(BellAttachmentType::FLOOR);
}elseif($face === Facing::DOWN){ }elseif($face === Facing::DOWN){
$this->setAttachmentType(BellAttachmentType::CEILING); $this->setAttachmentType(BellAttachmentType::CEILING);
}else{ }else{
$this->setFacing($face); $this->setFacing(HorizontalFacingOption::fromFacing($face));
$this->setAttachmentType( $this->setAttachmentType(
$this->canBeSupportedAt($blockReplace, $face) ? $this->canBeSupportedAt($blockReplace, $face) ?
BellAttachmentType::TWO_WALLS : BellAttachmentType::TWO_WALLS :
@ -113,8 +115,8 @@ final class Bell extends Transparent implements HorizontalFacing{
foreach(match($this->attachmentType){ foreach(match($this->attachmentType){
BellAttachmentType::CEILING => [Facing::UP], BellAttachmentType::CEILING => [Facing::UP],
BellAttachmentType::FLOOR => [Facing::DOWN], BellAttachmentType::FLOOR => [Facing::DOWN],
BellAttachmentType::ONE_WALL => [Facing::opposite($this->facing)], BellAttachmentType::ONE_WALL => [Facing::opposite($this->facing->toFacing())],
BellAttachmentType::TWO_WALLS => [$this->facing, Facing::opposite($this->facing)] BellAttachmentType::TWO_WALLS => [$this->facing->toFacing(), Facing::opposite($this->facing->toFacing())]
} as $supportBlockDirection){ } as $supportBlockDirection){
if(!$this->canBeSupportedAt($this, $supportBlockDirection)){ if(!$this->canBeSupportedAt($this, $supportBlockDirection)){
$this->position->getWorld()->useBreakOn($this->position); $this->position->getWorld()->useBreakOn($this->position);
@ -158,8 +160,8 @@ final class Bell extends Transparent implements HorizontalFacing{
private function isValidFaceToRing(Facing $faceHit) : bool{ private function isValidFaceToRing(Facing $faceHit) : bool{
return match($this->attachmentType){ return match($this->attachmentType){
BellAttachmentType::CEILING => true, BellAttachmentType::CEILING => true,
BellAttachmentType::FLOOR => Facing::axis($faceHit) === Facing::axis($this->facing), BellAttachmentType::FLOOR => Facing::axis($faceHit) === Facing::axis($this->facing->toFacing()),
BellAttachmentType::ONE_WALL, BellAttachmentType::TWO_WALLS => $faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true), BellAttachmentType::ONE_WALL, BellAttachmentType::TWO_WALLS => $faceHit === Facing::rotateY($this->facing->toFacing(), false) || $faceHit === Facing::rotateY($this->facing->toFacing(), true),
}; };
} }
} }

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\block\inventory\CampfireInventory; use pocketmine\block\inventory\CampfireInventory;
use pocketmine\block\tile\Campfire as TileCampfire; use pocketmine\block\tile\Campfire as TileCampfire;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\Lightable; use pocketmine\block\utils\Lightable;
use pocketmine\block\utils\LightableTrait; use pocketmine\block\utils\LightableTrait;
@ -176,7 +177,7 @@ class Campfire extends Transparent implements Lightable, HorizontalFacing{
return false; return false;
} }
if($player !== null){ if($player !== null){
$this->facing = $player->getHorizontalFacing(); $this->facing = HorizontalFacingOption::fromFacing($player->getHorizontalFacing());
} }
$this->lit = true; $this->lit = true;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\item\Item; use pocketmine\item\Item;
@ -44,7 +45,7 @@ final class CeilingEdgesHangingSign extends BaseSign implements HorizontalFacing
return false; return false;
} }
if($player !== null){ if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing()); $this->facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
} }
if(!$this->canBeSupportedAt($blockReplace)){ if(!$this->canBeSupportedAt($blockReplace)){
return false; return false;
@ -63,6 +64,6 @@ final class CeilingEdgesHangingSign extends BaseSign implements HorizontalFacing
$supportBlock = $block->getSide(Facing::UP); $supportBlock = $block->getSide(Facing::UP);
return return
$supportBlock->getSupportType(Facing::DOWN) === SupportType::FULL || $supportBlock->getSupportType(Facing::DOWN) === SupportType::FULL ||
(($supportBlock instanceof WallHangingSign || $supportBlock instanceof CeilingEdgesHangingSign) && Facing::axis($supportBlock->getFacing()) === Facing::axis($this->facing)); (($supportBlock instanceof WallHangingSign || $supportBlock instanceof CeilingEdgesHangingSign) && Facing::axis($supportBlock->getFacing()->toFacing()) === Facing::axis($this->facing->toFacing()));
} }
} }

View File

@ -51,7 +51,7 @@ class Chest extends Transparent implements HorizontalFacing{
$tile = $world->getTile($this->position); $tile = $world->getTile($this->position);
if($tile instanceof TileChest){ if($tile instanceof TileChest){
foreach([false, true] as $clockwise){ foreach([false, true] as $clockwise){
$side = Facing::rotateY($this->facing, $clockwise); $side = Facing::rotateY($this->facing->toFacing(), $clockwise);
$c = $this->getSide($side); $c = $this->getSide($side);
if($c instanceof Chest && $c->hasSameTypeId($this) && $c->facing === $this->facing){ if($c instanceof Chest && $c->hasSameTypeId($this) && $c->facing === $this->facing){
$pair = $world->getTile($c->position); $pair = $world->getTile($c->position);

View File

@ -52,7 +52,7 @@ class ChiseledBookshelf extends Opaque implements HorizontalFacing{
private ?ChiseledBookshelfSlot $lastInteractedSlot = null; private ?ChiseledBookshelfSlot $lastInteractedSlot = null;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->enumSet($this->slots, ChiseledBookshelfSlot::cases()); $w->enumSet($this->slots, ChiseledBookshelfSlot::cases());
} }
@ -144,7 +144,7 @@ class ChiseledBookshelf extends Opaque implements HorizontalFacing{
} }
public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($face !== $this->facing){ if($face !== $this->facing->toFacing()){
return false; return false;
} }

View File

@ -27,6 +27,7 @@ use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait; use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper; use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\WoodType; use pocketmine\block\utils\WoodType;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
@ -48,18 +49,19 @@ class CocoaBlock extends Flowable implements Ageable, HorizontalFacing{
public const MAX_AGE = 2; public const MAX_AGE = 2;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->boundedIntAuto(0, self::MAX_AGE, $this->age); $w->boundedIntAuto(0, self::MAX_AGE, $this->age);
} }
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
$realFacing = $this->facing->toFacing();
return [ return [
AxisAlignedBB::one() AxisAlignedBB::one()
->squashedCopy(Facing::axis(Facing::rotateY($this->facing, true)), (6 - $this->age) / 16) //sides ->squashedCopy(Facing::axis(Facing::rotateY($realFacing, true)), (6 - $this->age) / 16) //sides
->trimmedCopy(Facing::DOWN, (7 - $this->age * 2) / 16) ->trimmedCopy(Facing::DOWN, (7 - $this->age * 2) / 16)
->trimmedCopy(Facing::UP, 0.25) ->trimmedCopy(Facing::UP, 0.25)
->trimmedCopy(Facing::opposite($this->facing), 1 / 16) //gap between log and pod ->trimmedCopy(Facing::opposite($realFacing), 1 / 16) //gap between log and pod
->trimmedCopy($this->facing, (11 - $this->age * 2) / 16) //outward face ->trimmedCopy($realFacing, (11 - $this->age * 2) / 16) //outward face
]; ];
} }
@ -68,8 +70,8 @@ class CocoaBlock extends Flowable implements Ageable, HorizontalFacing{
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(Facing::axis($face) !== Axis::Y && $this->canAttachTo($blockClicked)){ if(($hzFacing = HorizontalFacingOption::tryFromFacing($face)) !== null && $this->canAttachTo($blockClicked)){
$this->facing = $face; $this->facing = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }
@ -87,7 +89,7 @@ class CocoaBlock extends Flowable implements Ageable, HorizontalFacing{
} }
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->canAttachTo($this->getSide(Facing::opposite($this->facing)))){ if(!$this->canAttachTo($this->getSide(Facing::opposite($this->facing->toFacing())))){
$this->position->getWorld()->useBreakOn($this->position); $this->position->getWorld()->useBreakOn($this->position);
} }
} }

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
@ -43,7 +44,7 @@ class Door extends Transparent implements HorizontalFacing{
protected bool $open = false; protected bool $open = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->bool($this->top); $w->bool($this->top);
$w->bool($this->hingeRight); $w->bool($this->hingeRight);
$w->bool($this->open); $w->bool($this->open);
@ -98,7 +99,7 @@ class Door extends Transparent implements HorizontalFacing{
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
//TODO: doors are 0.1825 blocks thick, instead of 0.1875 like JE (https://bugs.mojang.com/browse/MCPE-19214) //TODO: doors are 0.1825 blocks thick, instead of 0.1875 like JE (https://bugs.mojang.com/browse/MCPE-19214)
return [AxisAlignedBB::one()->trimmedCopy($this->open ? Facing::rotateY($this->facing, !$this->hingeRight) : $this->facing, 327 / 400)]; return [AxisAlignedBB::one()->trimmedCopy($this->open ? Facing::rotateY($this->facing->toFacing(), !$this->hingeRight) : $this->facing->toFacing(), 327 / 400)];
} }
public function getSupportType(Facing $facing) : SupportType{ public function getSupportType(Facing $facing) : SupportType{
@ -119,11 +120,13 @@ class Door extends Transparent implements HorizontalFacing{
} }
if($player !== null){ if($player !== null){
$this->facing = $player->getHorizontalFacing(); //TODO: not sure if entities should use HorizontalFacingOption too
$this->facing = HorizontalFacingOption::fromFacing($player->getHorizontalFacing());
} }
$next = $this->getSide(Facing::rotateY($this->facing, false)); $realFacing = $this->facing->toFacing();
$next2 = $this->getSide(Facing::rotateY($this->facing, true)); $next = $this->getSide(Facing::rotateY($realFacing, false));
$next2 = $this->getSide(Facing::rotateY($realFacing, true));
if($next->hasSameTypeId($this) || (!$next2->isTransparent() && $next->isTransparent())){ //Door hinge if($next->hasSameTypeId($this) || (!$next2->isTransparent() && $next->isTransparent())){ //Door hinge
$this->hingeRight = true; $this->hingeRight = true;

View File

@ -35,7 +35,7 @@ class EndPortalFrame extends Opaque implements HorizontalFacing{
protected bool $eye = false; protected bool $eye = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->bool($this->eye); $w->bool($this->eye);
} }

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\block\utils\WoodMaterial; use pocketmine\block\utils\WoodMaterial;
@ -45,7 +46,7 @@ class FenceGate extends Transparent implements HorizontalFacing, WoodMaterial{
protected bool $inWall = false; protected bool $inWall = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->bool($this->open); $w->bool($this->open);
$w->bool($this->inWall); $w->bool($this->inWall);
} }
@ -67,7 +68,7 @@ class FenceGate extends Transparent implements HorizontalFacing, WoodMaterial{
} }
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return $this->open ? [] : [AxisAlignedBB::one()->extendedCopy(Facing::UP, 0.5)->squashedCopy(Facing::axis($this->facing), 6 / 16)]; return $this->open ? [] : [AxisAlignedBB::one()->extendedCopy(Facing::UP, 0.5)->squashedCopy(Facing::axis($this->facing->toFacing()), 6 / 16)];
} }
public function getSupportType(Facing $facing) : SupportType{ public function getSupportType(Facing $facing) : SupportType{
@ -75,15 +76,16 @@ class FenceGate extends Transparent implements HorizontalFacing, WoodMaterial{
} }
private function checkInWall() : bool{ private function checkInWall() : bool{
$realFacing = $this->facing->toFacing();
return ( return (
$this->getSide(Facing::rotateY($this->facing, false)) instanceof Wall || $this->getSide(Facing::rotateY($realFacing, false)) instanceof Wall ||
$this->getSide(Facing::rotateY($this->facing, true)) instanceof Wall $this->getSide(Facing::rotateY($realFacing, true)) instanceof Wall
); );
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){ if($player !== null){
$this->facing = $player->getHorizontalFacing(); $this->facing = HorizontalFacingOption::fromFacing($player->getHorizontalFacing());
} }
$this->inWall = $this->checkInWall(); $this->inWall = $this->checkInWall();
@ -103,8 +105,8 @@ class FenceGate extends Transparent implements HorizontalFacing, WoodMaterial{
$this->open = !$this->open; $this->open = !$this->open;
if($this->open && $player !== null){ if($this->open && $player !== null){
$playerFacing = $player->getHorizontalFacing(); $playerFacing = $player->getHorizontalFacing();
if($playerFacing === Facing::opposite($this->facing)){ if($playerFacing === Facing::opposite($this->facing->toFacing())){
$this->facing = $playerFacing; $this->facing = HorizontalFacingOption::fromFacing($playerFacing);
} }
} }

View File

@ -48,7 +48,7 @@ class Furnace extends Opaque implements Lightable, HorizontalFacing{
} }
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->bool($this->lit); $w->bool($this->lit);
} }

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
@ -60,7 +61,7 @@ class Ladder extends Transparent implements HorizontalFacing{
} }
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trimmedCopy($this->facing, 13 / 16)]; return [AxisAlignedBB::one()->trimmedCopy($this->facing->toFacing(), 13 / 16)];
} }
public function getSupportType(Facing $facing) : SupportType{ public function getSupportType(Facing $facing) : SupportType{
@ -68,8 +69,8 @@ class Ladder extends Transparent implements HorizontalFacing{
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedAt($blockReplace, Facing::opposite($face)) && Facing::axis($face) !== Axis::Y){ if(($hzFacing = HorizontalFacingOption::tryFromFacing($face)) !== null && $this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
$this->facing = $face; $this->facing = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }
@ -77,7 +78,7 @@ class Ladder extends Transparent implements HorizontalFacing{
} }
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){ //Replace with common break method if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing->toFacing()))){ //Replace with common break method
$this->position->getWorld()->useBreakOn($this->position); $this->position->getWorld()->useBreakOn($this->position);
} }
} }

View File

@ -46,7 +46,7 @@ class Lectern extends Transparent implements HorizontalFacing{
protected bool $producingSignal = false; protected bool $producingSignal = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->bool($this->producingSignal); $w->bool($this->producingSignal);
} }

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\math\Axis; use pocketmine\math\Axis;
@ -36,14 +37,15 @@ final class OminousWallBanner extends BaseOminousBanner implements HorizontalFac
use HorizontalFacingTrait; use HorizontalFacingTrait;
protected function getSupportingFace() : Facing{ protected function getSupportingFace() : Facing{
return Facing::opposite($this->facing); return Facing::opposite($this->facing->toFacing());
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(Facing::axis($face) === Axis::Y){ $hzFacing = HorizontalFacingOption::tryFromFacing($face);
if($hzFacing === null){
return false; return false;
} }
$this->facing = $face; $this->facing = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }
} }

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper; use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\StaticSupportTrait; use pocketmine\block\utils\StaticSupportTrait;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
@ -47,7 +48,7 @@ class PinkPetals extends Flowable implements HorizontalFacing{
protected int $count = self::MIN_COUNT; protected int $count = self::MIN_COUNT;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->boundedIntAuto(self::MIN_COUNT, self::MAX_COUNT, $this->count); $w->boundedIntAuto(self::MIN_COUNT, self::MAX_COUNT, $this->count);
} }
@ -79,7 +80,7 @@ class PinkPetals extends Flowable implements HorizontalFacing{
$this->count = $blockReplace->count + 1; $this->count = $blockReplace->count + 1;
$this->facing = $blockReplace->facing; $this->facing = $blockReplace->facing;
}elseif($player !== null){ }elseif($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing()); $this->facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
} }
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\item\Shears; use pocketmine\item\Shears;
use pocketmine\item\VanillaItems; use pocketmine\item\VanillaItems;
@ -34,10 +35,10 @@ use function in_array;
class Pumpkin extends Opaque{ class Pumpkin extends Opaque{
public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Shears && in_array($face, Facing::HORIZONTAL, true)){ if($item instanceof Shears && ($hzFacing = HorizontalFacingOption::tryFromFacing($face)) !== null){
$item->applyDamage(1); $item->applyDamage(1);
$world = $this->position->getWorld(); $world = $this->position->getWorld();
$world->setBlock($this->position, VanillaBlocks::CARVED_PUMPKIN()->setFacing($face)); $world->setBlock($this->position, VanillaBlocks::CARVED_PUMPKIN()->setFacing($hzFacing));
$world->dropItem($this->position->add(0.5, 0.5, 0.5), VanillaItems::PUMPKIN_SEEDS()->setCount(1)); $world->dropItem($this->position->add(0.5, 0.5, 0.5), VanillaItems::PUMPKIN_SEEDS()->setCount(1));
return true; return true;
} }

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\Comparator; use pocketmine\block\tile\Comparator;
use pocketmine\block\utils\AnalogRedstoneSignalEmitter; use pocketmine\block\utils\AnalogRedstoneSignalEmitter;
use pocketmine\block\utils\AnalogRedstoneSignalEmitterTrait; use pocketmine\block\utils\AnalogRedstoneSignalEmitterTrait;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\PoweredByRedstone; use pocketmine\block\utils\PoweredByRedstone;
@ -42,7 +43,7 @@ use pocketmine\world\BlockTransaction;
use function assert; use function assert;
class RedstoneComparator extends Flowable implements AnalogRedstoneSignalEmitter, PoweredByRedstone, HorizontalFacing{ class RedstoneComparator extends Flowable implements AnalogRedstoneSignalEmitter, PoweredByRedstone, HorizontalFacing{
use HorizontalFacingTrait; use FacesOppositePlacingPlayerTrait;
use AnalogRedstoneSignalEmitterTrait; use AnalogRedstoneSignalEmitterTrait;
use PoweredByRedstoneTrait; use PoweredByRedstoneTrait;
use StaticSupportTrait; use StaticSupportTrait;
@ -50,7 +51,7 @@ class RedstoneComparator extends Flowable implements AnalogRedstoneSignalEmitter
protected bool $isSubtractMode = false; protected bool $isSubtractMode = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->bool($this->isSubtractMode); $w->bool($this->isSubtractMode);
$w->bool($this->powered); $w->bool($this->powered);
} }
@ -86,13 +87,6 @@ class RedstoneComparator extends Flowable implements AnalogRedstoneSignalEmitter
return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 7 / 8)]; return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 7 / 8)];
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$this->isSubtractMode = !$this->isSubtractMode; $this->isSubtractMode = !$this->isSubtractMode;
$this->position->getWorld()->setBlock($this->position, $this); $this->position->getWorld()->setBlock($this->position, $this);

View File

@ -23,7 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\PoweredByRedstone; use pocketmine\block\utils\PoweredByRedstone;
use pocketmine\block\utils\PoweredByRedstoneTrait; use pocketmine\block\utils\PoweredByRedstoneTrait;
@ -38,7 +40,7 @@ use pocketmine\player\Player;
use pocketmine\world\BlockTransaction; use pocketmine\world\BlockTransaction;
class RedstoneRepeater extends Flowable implements PoweredByRedstone, HorizontalFacing{ class RedstoneRepeater extends Flowable implements PoweredByRedstone, HorizontalFacing{
use HorizontalFacingTrait; use FacesOppositePlacingPlayerTrait;
use PoweredByRedstoneTrait; use PoweredByRedstoneTrait;
use StaticSupportTrait; use StaticSupportTrait;
@ -48,7 +50,7 @@ class RedstoneRepeater extends Flowable implements PoweredByRedstone, Horizontal
protected int $delay = self::MIN_DELAY; protected int $delay = self::MIN_DELAY;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->boundedIntAuto(self::MIN_DELAY, self::MAX_DELAY, $this->delay); $w->boundedIntAuto(self::MIN_DELAY, self::MAX_DELAY, $this->delay);
$w->bool($this->powered); $w->bool($this->powered);
} }
@ -68,14 +70,6 @@ class RedstoneRepeater extends Flowable implements PoweredByRedstone, Horizontal
return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 7 / 8)]; return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 7 / 8)];
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if(++$this->delay > self::MAX_DELAY){ if(++$this->delay > self::MAX_DELAY){
$this->delay = self::MIN_DELAY; $this->delay = self::MIN_DELAY;

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
@ -43,7 +44,7 @@ class SmallDripleaf extends Transparent implements HorizontalFacing{
protected bool $top = false; protected bool $top = false;
public function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ public function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->bool($this->top); $w->bool($this->top);
} }
@ -81,7 +82,7 @@ class SmallDripleaf extends Transparent implements HorizontalFacing{
return false; return false;
} }
if($player !== null){ if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing()); $this->facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
} }
$tx->addBlock($block->position, VanillaBlocks::SMALL_DRIPLEAF() $tx->addBlock($block->position, VanillaBlocks::SMALL_DRIPLEAF()

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\StairShape; use pocketmine\block\utils\StairShape;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
@ -43,7 +44,7 @@ class Stair extends Transparent implements HorizontalFacing{
protected StairShape $shape = StairShape::STRAIGHT; protected StairShape $shape = StairShape::STRAIGHT;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->bool($this->upsideDown); $w->bool($this->upsideDown);
} }
@ -52,7 +53,7 @@ class Stair extends Transparent implements HorizontalFacing{
$this->collisionBoxes = null; $this->collisionBoxes = null;
$clockwise = Facing::rotateY($this->facing, true); $clockwise = HorizontalFacingOption::fromFacing(Facing::rotateY($this->facing->toFacing(), true));
if(($backFacing = $this->getPossibleCornerFacing(false)) !== null){ if(($backFacing = $this->getPossibleCornerFacing(false)) !== null){
$this->shape = $backFacing === $clockwise ? StairShape::OUTER_RIGHT : StairShape::OUTER_LEFT; $this->shape = $backFacing === $clockwise ? StairShape::OUTER_RIGHT : StairShape::OUTER_LEFT;
}elseif(($frontFacing = $this->getPossibleCornerFacing(true)) !== null){ }elseif(($frontFacing = $this->getPossibleCornerFacing(true)) !== null){
@ -86,18 +87,19 @@ class Stair extends Transparent implements HorizontalFacing{
AxisAlignedBB::one()->trimmedCopy($topStepFace, 0.5) AxisAlignedBB::one()->trimmedCopy($topStepFace, 0.5)
]; ];
$realFacing = $this->facing->toFacing();
$topStep = AxisAlignedBB::one() $topStep = AxisAlignedBB::one()
->trimmedCopy(Facing::opposite($topStepFace), 0.5) ->trimmedCopy(Facing::opposite($topStepFace), 0.5)
->trimmedCopy(Facing::opposite($this->facing), 0.5); ->trimmedCopy(Facing::opposite($realFacing), 0.5);
if($this->shape === StairShape::OUTER_LEFT || $this->shape === StairShape::OUTER_RIGHT){ if($this->shape === StairShape::OUTER_LEFT || $this->shape === StairShape::OUTER_RIGHT){
$topStep = $topStep->trimmedCopy(Facing::rotateY($this->facing, $this->shape === StairShape::OUTER_LEFT), 0.5); $topStep = $topStep->trimmedCopy(Facing::rotateY($realFacing, $this->shape === StairShape::OUTER_LEFT), 0.5);
}elseif($this->shape === StairShape::INNER_LEFT || $this->shape === StairShape::INNER_RIGHT){ }elseif($this->shape === StairShape::INNER_LEFT || $this->shape === StairShape::INNER_RIGHT){
//add an extra cube //add an extra cube
$bbs[] = AxisAlignedBB::one() $bbs[] = AxisAlignedBB::one()
->trimmedCopy(Facing::opposite($topStepFace), 0.5) ->trimmedCopy(Facing::opposite($topStepFace), 0.5)
->trimmedCopy($this->facing, 0.5) //avoid overlapping with main step ->trimmedCopy($realFacing, 0.5) //avoid overlapping with main step
->trimmedCopy(Facing::rotateY($this->facing, $this->shape === StairShape::INNER_LEFT), 0.5); ->trimmedCopy(Facing::rotateY($realFacing, $this->shape === StairShape::INNER_LEFT), 0.5);
} }
$bbs[] = $topStep; $bbs[] = $topStep;
@ -106,30 +108,32 @@ class Stair extends Transparent implements HorizontalFacing{
} }
public function getSupportType(Facing $facing) : SupportType{ public function getSupportType(Facing $facing) : SupportType{
$realFacing = $this->facing->toFacing();
if( if(
$facing === Facing::UP && $this->upsideDown || $facing === Facing::UP && $this->upsideDown ||
$facing === Facing::DOWN && !$this->upsideDown || $facing === Facing::DOWN && !$this->upsideDown ||
($facing === $this->facing && $this->shape !== StairShape::OUTER_LEFT && $this->shape !== StairShape::OUTER_RIGHT) || ($facing === $realFacing && $this->shape !== StairShape::OUTER_LEFT && $this->shape !== StairShape::OUTER_RIGHT) ||
($facing === Facing::rotate($this->facing, Axis::Y, false) && $this->shape === StairShape::INNER_LEFT) || ($facing === Facing::rotate($realFacing, Axis::Y, false) && $this->shape === StairShape::INNER_LEFT) ||
($facing === Facing::rotate($this->facing, Axis::Y, true) && $this->shape === StairShape::INNER_RIGHT) ($facing === Facing::rotate($realFacing, Axis::Y, true) && $this->shape === StairShape::INNER_RIGHT)
){ ){
return SupportType::FULL; return SupportType::FULL;
} }
return SupportType::NONE; return SupportType::NONE;
} }
private function getPossibleCornerFacing(bool $oppositeFacing) : ?Facing{ private function getPossibleCornerFacing(bool $oppositeFacing) : ?HorizontalFacingOption{
$side = $this->getSide($oppositeFacing ? Facing::opposite($this->facing) : $this->facing); $realFacing = $this->facing->toFacing();
$side = $this->getSide($oppositeFacing ? Facing::opposite($realFacing) : $realFacing);
return ( return (
$side instanceof Stair && $side instanceof Stair &&
$side->upsideDown === $this->upsideDown && $side->upsideDown === $this->upsideDown &&
Facing::axis($side->facing) !== Facing::axis($this->facing) //perpendicular Facing::axis($side->facing->toFacing()) !== Facing::axis($realFacing) //perpendicular
) ? $side->facing : null; ) ? $side->facing : null;
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){ if($player !== null){
$this->facing = $player->getHorizontalFacing(); $this->facing = HorizontalFacingOption::fromFacing($player->getHorizontalFacing());
} }
$this->upsideDown = (($clickVector->y > 0.5 && $face !== Facing::UP) || $face === Facing::DOWN); $this->upsideDown = (($clickVector->y > 0.5 && $face !== Facing::UP) || $face === Facing::DOWN);

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
@ -42,7 +43,7 @@ class Trapdoor extends Transparent implements HorizontalFacing{
protected bool $top = false; protected bool $top = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->bool($this->top); $w->bool($this->top);
$w->bool($this->open); $w->bool($this->open);
} }
@ -64,7 +65,7 @@ class Trapdoor extends Transparent implements HorizontalFacing{
} }
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trimmedCopy($this->open ? $this->facing : ($this->top ? Facing::DOWN : Facing::UP), 13 / 16)]; return [AxisAlignedBB::one()->trimmedCopy($this->open ? $this->facing->toFacing() : ($this->top ? Facing::DOWN : Facing::UP), 13 / 16)];
} }
public function getSupportType(Facing $facing) : SupportType{ public function getSupportType(Facing $facing) : SupportType{
@ -73,7 +74,7 @@ class Trapdoor extends Transparent implements HorizontalFacing{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){ if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing()); $this->facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
} }
if(($clickVector->y > 0.5 && $face !== Facing::UP) || $face === Facing::DOWN){ if(($clickVector->y > 0.5 && $face !== Facing::UP) || $face === Facing::DOWN){
$this->top = true; $this->top = true;

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item; use pocketmine\item\Item;
@ -40,7 +41,7 @@ class TripwireHook extends Flowable implements HorizontalFacing{
protected bool $powered = false; protected bool $powered = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
$w->bool($this->connected); $w->bool($this->connected);
$w->bool($this->powered); $w->bool($this->powered);
} }
@ -62,9 +63,9 @@ class TripwireHook extends Flowable implements HorizontalFacing{
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(Facing::axis($face) !== Axis::Y){ $hzFacing = HorizontalFacingOption::tryFromFacing($face);
//TODO: check face is valid if($hzFacing !== null){
$this->facing = $face; $this->facing = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }
return false; return false;

View File

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
use pocketmine\item\Item; use pocketmine\item\Item;
@ -36,30 +38,29 @@ use function count;
class Vine extends Flowable{ class Vine extends Flowable{
/** @var Facing[] */ /** @var HorizontalFacingOption[] */
protected array $faces = []; protected array $faces = [];
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacingFlags($this->faces); $w->horizontalFacingFlags($this->faces);
} }
/** @return Facing[] */ /** @return HorizontalFacingOption[] */
public function getFaces() : array{ return $this->faces; } public function getFaces() : array{ return $this->faces; }
public function hasFace(Facing $face) : bool{ public function hasFace(HorizontalFacingOption $face) : bool{
return isset($this->faces[$face->value]); return isset($this->faces[$face->value]);
} }
/** /**
* @param Facing[] $faces * @param HorizontalFacingOption[] $faces
* @phpstan-param list<Facing::NORTH|Facing::EAST|Facing::SOUTH|Facing::WEST> $faces
* @return $this * @return $this
*/ */
public function setFaces(array $faces) : self{ public function setFaces(array $faces) : self{
$uniqueFaces = []; $uniqueFaces = [];
foreach($faces as $face){ foreach($faces as $face){
if($face !== Facing::NORTH && $face !== Facing::SOUTH && $face !== Facing::WEST && $face !== Facing::EAST){ if(!$face instanceof HorizontalFacingOption){
throw new \InvalidArgumentException("Facing can only be north, east, south or west"); throw new \InvalidArgumentException("Expected array of HorizontalFacingOption");
} }
$uniqueFaces[$face->value] = $face; $uniqueFaces[$face->value] = $face;
} }
@ -68,10 +69,7 @@ class Vine extends Flowable{
} }
/** @return $this */ /** @return $this */
public function setFace(Facing $face, bool $value) : self{ public function setFace(HorizontalFacingOption $face, bool $value) : self{
if($face !== Facing::NORTH && $face !== Facing::SOUTH && $face !== Facing::WEST && $face !== Facing::EAST){
throw new \InvalidArgumentException("Facing can only be north, east, south or west");
}
if($value){ if($value){
$this->faces[$face->value] = $face; $this->faces[$face->value] = $face;
}else{ }else{
@ -102,13 +100,14 @@ class Vine extends Flowable{
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$opposite = Facing::opposite($face); $oppositeFace = Facing::opposite($face);
if(!$blockReplace->getSide($opposite)->isFullCube() || Facing::axis($face) === Axis::Y){ $hzFacing = HorizontalFacingOption::tryFromFacing($oppositeFace);
if($hzFacing === null || !$blockReplace->getSide($oppositeFace)->isFullCube()){
return false; return false;
} }
$this->faces = $blockReplace instanceof Vine ? $blockReplace->faces : []; $this->faces = $blockReplace instanceof Vine ? $blockReplace->faces : [];
$this->faces[$opposite->value] = $opposite; $this->faces[$hzFacing->value] = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }
@ -121,7 +120,7 @@ class Vine extends Flowable{
$supportedFaces = $up instanceof Vine ? array_intersect_key($this->faces, $up->faces) : []; $supportedFaces = $up instanceof Vine ? array_intersect_key($this->faces, $up->faces) : [];
foreach($this->faces as $face){ foreach($this->faces as $face){
if(!isset($supportedFaces[$face->value]) && !$this->getSide($face)->isSolid()){ if(!isset($supportedFaces[$face->value]) && !$this->getSide($face->toFacing())->isSolid()){
unset($this->faces[$face->value]); unset($this->faces[$face->value]);
$changed = true; $changed = true;
} }

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\math\Axis; use pocketmine\math\Axis;
@ -40,14 +41,15 @@ final class WallBanner extends BaseBanner implements HorizontalFacing{
} }
protected function getSupportingFace() : Facing{ protected function getSupportingFace() : Facing{
return Facing::opposite($this->facing); return Facing::opposite($this->facing->toFacing());
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(Facing::axis($face) === Axis::Y){ $hzFacing = HorizontalFacingOption::tryFromFacing($face);
if($hzFacing === null){
return false; return false;
} }
$this->facing = $face; $this->facing = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }
} }

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item; use pocketmine\item\Item;
@ -38,15 +39,15 @@ final class WallCoralFan extends BaseCoral implements HorizontalFacing{
use HorizontalFacingTrait; use HorizontalFacingTrait;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$axis = Facing::axis($face); $hzFacing = HorizontalFacingOption::tryFromFacing($face);
if(($axis !== Axis::X && $axis !== Axis::Z) || !$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){ if($hzFacing === null || !$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false; return false;
} }
$this->facing = $face; $this->facing = $hzFacing;
$this->dead = !$this->isCoveredWithWater(); $this->dead = !$this->isCoveredWithWater();
@ -55,7 +56,7 @@ final class WallCoralFan extends BaseCoral implements HorizontalFacing{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
$world = $this->position->getWorld(); $world = $this->position->getWorld();
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){ if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing->toFacing()))){
$world->useBreakOn($this->position); $world->useBreakOn($this->position);
}else{ }else{
parent::onNearbyBlockChange(); parent::onNearbyBlockChange();

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType; use pocketmine\block\utils\SupportType;
use pocketmine\item\Item; use pocketmine\item\Item;
@ -38,7 +39,7 @@ final class WallHangingSign extends BaseSign implements HorizontalFacing{
use HorizontalFacingTrait; use HorizontalFacingTrait;
protected function getSupportingFace() : Facing{ protected function getSupportingFace() : Facing{
return Facing::rotateY($this->facing, clockwise: true); return Facing::rotateY($this->facing->toFacing(), clockwise: true);
} }
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
@ -47,7 +48,7 @@ final class WallHangingSign extends BaseSign implements HorizontalFacing{
protected function recalculateCollisionBoxes() : array{ protected function recalculateCollisionBoxes() : array{
//only the cross bar is collidable //only the cross bar is collidable
return [AxisAlignedBB::one()->trimmedCopy(Facing::DOWN, 7 / 8)->squashedCopy(Facing::axis($this->facing), 3 / 4)]; return [AxisAlignedBB::one()->trimmedCopy(Facing::DOWN, 7 / 8)->squashedCopy(Facing::axis($this->facing->toFacing()), 3 / 4)];
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
@ -64,18 +65,19 @@ final class WallHangingSign extends BaseSign implements HorizontalFacing{
return false; return false;
} }
$this->facing = Facing::rotateY(Facing::opposite($direction), clockwise: true); $facing = Facing::rotateY(Facing::opposite($direction), clockwise: true);
//the front should always face the player if possible //the front should always face the player if possible
if($this->facing === $player->getHorizontalFacing()){ if($facing === $player->getHorizontalFacing()){
$this->facing = Facing::opposite($this->facing); $facing = Facing::opposite($facing);
} }
$this->facing = HorizontalFacingOption::fromFacing($facing);
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }
private function canBeSupportedAt(Block $block, Facing $face) : bool{ private function canBeSupportedAt(Block $block, Facing $face) : bool{
return return
($block instanceof WallHangingSign && Facing::axis(Facing::rotateY($block->getFacing(), clockwise: true)) === Facing::axis($face)) || ($block instanceof WallHangingSign && Facing::axis(Facing::rotateY($block->getFacing()->toFacing(), clockwise: true)) === Facing::axis($face)) ||
$block->getSupportType(Facing::opposite($face)) === SupportType::FULL; $block->getSupportType(Facing::opposite($face)) === SupportType::FULL;
} }
} }

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block; namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait; use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\math\Axis; use pocketmine\math\Axis;
@ -36,14 +37,15 @@ final class WallSign extends BaseSign implements HorizontalFacing{
use HorizontalFacingTrait; use HorizontalFacingTrait;
protected function getSupportingFace() : Facing{ protected function getSupportingFace() : Facing{
return Facing::opposite($this->facing); return Facing::opposite($this->facing->toFacing());
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(Facing::axis($face) === Axis::Y){ $hzFacing = HorizontalFacingOption::tryFromFacing($face);
if($hzFacing === null){
return false; return false;
} }
$this->facing = $face; $this->facing = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }
} }

View File

@ -38,7 +38,7 @@ trait FacesOppositePlacingPlayerTrait{
*/ */
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){ if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing()); $this->facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
} }
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }

View File

@ -23,11 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block\utils; namespace pocketmine\block\utils;
use pocketmine\math\Facing;
interface HorizontalFacing{ interface HorizontalFacing{
public function getFacing() : Facing; public function getFacing() : HorizontalFacingOption;
/** @return $this */ /** @return $this */
public function setFacing(Facing $facing) : self; public function setFacing(HorizontalFacingOption $facing) : self;
} }

View File

@ -0,0 +1,56 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\math\Facing;
enum HorizontalFacingOption : int{
case NORTH = Facing::NORTH->value;
case SOUTH = Facing::SOUTH->value;
case WEST = Facing::WEST->value;
case EAST = Facing::EAST->value;
public static function tryFromFacing(Facing $facing) : ?self{
return match($facing){
Facing::NORTH => self::NORTH,
Facing::SOUTH => self::SOUTH,
Facing::WEST => self::WEST,
Facing::EAST => self::EAST,
default => null,
};
}
public static function fromFacing(Facing $facing) : self{
return self::tryFromFacing($facing) ?? throw new \InvalidArgumentException("Facing $facing->name cannot be converted to a horizontal facing");
}
public function toFacing() : Facing{
return match($this){
self::NORTH => Facing::NORTH,
self::SOUTH => Facing::SOUTH,
self::WEST => Facing::WEST,
self::EAST => Facing::EAST,
};
}
}

View File

@ -28,21 +28,16 @@ use pocketmine\math\Axis;
use pocketmine\math\Facing; use pocketmine\math\Facing;
trait HorizontalFacingTrait{ trait HorizontalFacingTrait{
//TODO: this really needs a proper HorizontalFacing enum protected HorizontalFacingOption $facing = HorizontalFacingOption::NORTH;
protected Facing $facing = Facing::NORTH;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing); $w->enum($this->facing);
} }
public function getFacing() : Facing{ return $this->facing; } public function getFacing() : HorizontalFacingOption{ return $this->facing; }
/** @return $this */ /** @return $this */
public function setFacing(Facing $facing) : self{ public function setFacing(HorizontalFacingOption $facing) : self{
$axis = Facing::axis($facing);
if($axis !== Axis::X && $axis !== Axis::Z){
throw new \InvalidArgumentException("Facing must be horizontal");
}
$this->facing = $facing; $this->facing = $facing;
return $this; return $this;
} }

View File

@ -97,6 +97,7 @@ use pocketmine\block\utils\DripleafState;
use pocketmine\block\utils\DyeColor; use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\FroglightType; use pocketmine\block\utils\FroglightType;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\LeverFacing; use pocketmine\block\utils\LeverFacing;
use pocketmine\block\utils\MobHeadType; use pocketmine\block\utils\MobHeadType;
use pocketmine\block\utils\MushroomBlockType; use pocketmine\block\utils\MushroomBlockType;
@ -584,15 +585,15 @@ final class VanillaBlockMappings{
$reg->mapModel(Model::create(Blocks::VINES(), Ids::VINE)->properties([ $reg->mapModel(Model::create(Blocks::VINES(), Ids::VINE)->properties([
new ValueSetFromIntProperty( new ValueSetFromIntProperty(
StateNames::VINE_DIRECTION_BITS, StateNames::VINE_DIRECTION_BITS,
IntFromRawStateMap::int([ EnumFromRawStateMap::int(HorizontalFacingOption::class, fn(HorizontalFacingOption $case) => match($case) {
Facing::NORTH->value => BlockLegacyMetadata::VINE_FLAG_NORTH, HorizontalFacingOption::NORTH => BlockLegacyMetadata::VINE_FLAG_NORTH,
Facing::SOUTH->value => BlockLegacyMetadata::VINE_FLAG_SOUTH, HorizontalFacingOption::SOUTH => BlockLegacyMetadata::VINE_FLAG_SOUTH,
Facing::WEST->value => BlockLegacyMetadata::VINE_FLAG_WEST, HorizontalFacingOption::WEST => BlockLegacyMetadata::VINE_FLAG_WEST,
Facing::EAST->value => BlockLegacyMetadata::VINE_FLAG_EAST, HorizontalFacingOption::EAST => BlockLegacyMetadata::VINE_FLAG_EAST,
]), }),
//TODO: hack for lack of HorizontalFacing enum :( //TODO: hack for lack of HorizontalFacing enum :(
fn(Vine $b) => array_map(fn(Facing $facing) => $facing->value, $b->getFaces()), fn(Vine $b) => $b->getFaces(),
fn(Vine $b, array $v) => $b->setFaces(array_map(Facing::from(...), $v)) fn(Vine $b, array $v) => $b->setFaces($v)
) )
])); ]));
@ -619,8 +620,7 @@ final class VanillaBlockMappings{
$reg->mapFlattenedId(FlattenedIdModel::create(Blocks::WALL_CORAL_FAN()) $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::WALL_CORAL_FAN())
->idComponents([...$commonProperties->coralIdPrefixes, "_coral_wall_fan"]) ->idComponents([...$commonProperties->coralIdPrefixes, "_coral_wall_fan"])
->properties([ ->properties([
//TODO: hack for lack of horizontal facing enum :( new ValueFromIntProperty(StateNames::CORAL_DIRECTION, ValueMappings::getInstance()->horizontalFacingCoral, fn(HorizontalFacing $b) => $b->getFacing(), fn(HorizontalFacing $b, HorizontalFacingOption $v) => $b->setFacing($v)),
new ValueFromIntProperty(StateNames::CORAL_DIRECTION, ValueMappings::getInstance()->horizontalFacingCoral, fn(HorizontalFacing $b) => $b->getFacing()->value, fn(HorizontalFacing $b, int $v) => $b->setFacing(Facing::from($v))),
]) ])
); );
} }

View File

@ -45,6 +45,7 @@ use pocketmine\block\utils\CoralMaterial;
use pocketmine\block\utils\CoralType; use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\DyeColor; use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\HorizontalFacing; use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\Lightable; use pocketmine\block\utils\Lightable;
use pocketmine\block\utils\MultiAnyFacing; use pocketmine\block\utils\MultiAnyFacing;
use pocketmine\block\utils\PillarRotation; use pocketmine\block\utils\PillarRotation;
@ -69,13 +70,13 @@ final class CommonProperties{
/** @phpstan-var ValueFromStringProperty<Torch, int> */ /** @phpstan-var ValueFromStringProperty<Torch, int> */
public readonly ValueFromStringProperty $torchFacing; public readonly ValueFromStringProperty $torchFacing;
/** @phpstan-var ValueFromStringProperty<HorizontalFacing, int> */ /** @phpstan-var ValueFromStringProperty<HorizontalFacing, HorizontalFacingOption> */
public readonly ValueFromStringProperty $horizontalFacingCardinal; public readonly ValueFromStringProperty $horizontalFacingCardinal;
/** @phpstan-var ValueFromIntProperty<HorizontalFacing, int> */ /** @phpstan-var ValueFromIntProperty<HorizontalFacing, HorizontalFacingOption> */
public readonly ValueFromIntProperty $horizontalFacingSWNE; public readonly ValueFromIntProperty $horizontalFacingSWNE;
/** @phpstan-var ValueFromIntProperty<HorizontalFacing, int> */ /** @phpstan-var ValueFromIntProperty<HorizontalFacing, HorizontalFacingOption> */
public readonly ValueFromIntProperty $horizontalFacingSWNEInverted; public readonly ValueFromIntProperty $horizontalFacingSWNEInverted;
/** @phpstan-var ValueFromIntProperty<HorizontalFacing, int> */ /** @phpstan-var ValueFromIntProperty<HorizontalFacing, HorizontalFacingOption> */
public readonly ValueFromIntProperty $horizontalFacingClassic; public readonly ValueFromIntProperty $horizontalFacingClassic;
/** @phpstan-var ValueFromIntProperty<AnyFacing, Facing> */ /** @phpstan-var ValueFromIntProperty<AnyFacing, Facing> */
@ -208,8 +209,8 @@ final class CommonProperties{
$vm = ValueMappings::getInstance(); $vm = ValueMappings::getInstance();
//TODO: crude hack here - since we have no HorizontalFacing enum we need to use ints and convert to enum in the accessors //TODO: crude hack here - since we have no HorizontalFacing enum we need to use ints and convert to enum in the accessors
$hfGet = fn(HorizontalFacing $v) => $v->getFacing()->value; $hfGet = fn(HorizontalFacing $v) => $v->getFacing();
$hfSet = fn(HorizontalFacing $v, int $facing) => $v->setFacing(Facing::from($facing)); $hfSet = fn(HorizontalFacing $v, HorizontalFacingOption $facing) => $v->setFacing($facing);
$this->horizontalFacingCardinal = new ValueFromStringProperty(StateNames::MC_CARDINAL_DIRECTION, $vm->cardinalDirection, $hfGet, $hfSet); $this->horizontalFacingCardinal = new ValueFromStringProperty(StateNames::MC_CARDINAL_DIRECTION, $vm->cardinalDirection, $hfGet, $hfSet);
$this->blockFace = new ValueFromStringProperty( $this->blockFace = new ValueFromStringProperty(
@ -355,15 +356,15 @@ final class CommonProperties{
new BoolProperty(StateNames::OPEN_BIT, fn(Door $b) => $b->isOpen(), fn(Door $b, bool $v) => $b->setOpen($v)), new BoolProperty(StateNames::OPEN_BIT, fn(Door $b) => $b->isOpen(), fn(Door $b, bool $v) => $b->setOpen($v)),
new ValueFromStringProperty( new ValueFromStringProperty(
StateNames::MC_CARDINAL_DIRECTION, StateNames::MC_CARDINAL_DIRECTION,
IntFromRawStateMap::string([ EnumFromRawStateMap::string(HorizontalFacingOption::class, fn(HorizontalFacingOption $case) => match ($case) {
//a door facing "east" is actually facing north - thanks mojang //a door facing "east" is actually facing north - thanks mojang
Facing::NORTH->value => BlockStateStringValues::MC_CARDINAL_DIRECTION_EAST, HorizontalFacingOption::NORTH => BlockStateStringValues::MC_CARDINAL_DIRECTION_EAST,
Facing::EAST->value => BlockStateStringValues::MC_CARDINAL_DIRECTION_SOUTH, HorizontalFacingOption::EAST => BlockStateStringValues::MC_CARDINAL_DIRECTION_SOUTH,
Facing::SOUTH->value => BlockStateStringValues::MC_CARDINAL_DIRECTION_WEST, HorizontalFacingOption::SOUTH => BlockStateStringValues::MC_CARDINAL_DIRECTION_WEST,
Facing::WEST->value => BlockStateStringValues::MC_CARDINAL_DIRECTION_NORTH HorizontalFacingOption::WEST => BlockStateStringValues::MC_CARDINAL_DIRECTION_NORTH
]), }),
fn(HorizontalFacing $b) => $b->getFacing()->value, fn(HorizontalFacing $b) => $b->getFacing(),
fn(HorizontalFacing $b, int $v) => $b->setFacing(Facing::from($v)) fn(HorizontalFacing $b, HorizontalFacingOption $v) => $b->setFacing($v)
) )
]; ];

View File

@ -29,6 +29,7 @@ use pocketmine\block\utils\DirtType;
use pocketmine\block\utils\DripleafState; use pocketmine\block\utils\DripleafState;
use pocketmine\block\utils\DyeColor; use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\FroglightType; use pocketmine\block\utils\FroglightType;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\LeverFacing; use pocketmine\block\utils\LeverFacing;
use pocketmine\block\utils\MobHeadType; use pocketmine\block\utils\MobHeadType;
use pocketmine\block\utils\MushroomBlockType; use pocketmine\block\utils\MushroomBlockType;
@ -63,8 +64,8 @@ final class ValueMappings{
/** @phpstan-var EnumFromRawStateMap<MushroomBlockType, int> */ /** @phpstan-var EnumFromRawStateMap<MushroomBlockType, int> */
public readonly EnumFromRawStateMap $mushroomBlockType; public readonly EnumFromRawStateMap $mushroomBlockType;
/** @phpstan-var IntFromRawStateMap<string> */ /** @phpstan-var EnumFromRawStateMap<HorizontalFacingOption, string> */
public readonly IntFromRawStateMap $cardinalDirection; public readonly EnumFromRawStateMap $cardinalDirection;
/** @phpstan-var EnumFromRawStateMap<Facing, string> */ /** @phpstan-var EnumFromRawStateMap<Facing, string> */
public readonly EnumFromRawStateMap $blockFace; public readonly EnumFromRawStateMap $blockFace;
/** @phpstan-var EnumFromRawStateMap<Axis, string> */ /** @phpstan-var EnumFromRawStateMap<Axis, string> */
@ -76,16 +77,16 @@ final class ValueMappings{
/** @phpstan-var IntFromRawStateMap<string> */ /** @phpstan-var IntFromRawStateMap<string> */
public readonly IntFromRawStateMap $bambooLeafSize; public readonly IntFromRawStateMap $bambooLeafSize;
/** @phpstan-var IntFromRawStateMap<int> */ /** @phpstan-var EnumFromRawStateMap<HorizontalFacingOption, int> */
public readonly IntFromRawStateMap $horizontalFacing5Minus; public readonly EnumFromRawStateMap $horizontalFacing5Minus;
/** @phpstan-var IntFromRawStateMap<int> */ /** @phpstan-var EnumFromRawStateMap<HorizontalFacingOption, int> */
public readonly IntFromRawStateMap $horizontalFacingSWNE; public readonly EnumFromRawStateMap $horizontalFacingSWNE;
/** @phpstan-var IntFromRawStateMap<int> */ /** @phpstan-var EnumFromRawStateMap<HorizontalFacingOption, int> */
public readonly IntFromRawStateMap $horizontalFacingSWNEInverted; public readonly EnumFromRawStateMap $horizontalFacingSWNEInverted;
/** @phpstan-var IntFromRawStateMap<int> */ /** @phpstan-var EnumFromRawStateMap<HorizontalFacingOption, int> */
public readonly IntFromRawStateMap $horizontalFacingCoral; public readonly EnumFromRawStateMap $horizontalFacingCoral;
/** @phpstan-var IntFromRawStateMap<int> */ /** @phpstan-var EnumFromRawStateMap<HorizontalFacingOption, int> */
public readonly IntFromRawStateMap $horizontalFacingClassic; public readonly EnumFromRawStateMap $horizontalFacingClassic;
/** @phpstan-var EnumFromRawStateMap<Facing, int> */ /** @phpstan-var EnumFromRawStateMap<Facing, int> */
public readonly EnumFromRawStateMap $facing; public readonly EnumFromRawStateMap $facing;
/** @phpstan-var EnumFromRawStateMap<Facing, int> */ /** @phpstan-var EnumFromRawStateMap<Facing, int> */
@ -191,12 +192,12 @@ final class ValueMappings{
); );
//TODO: this can't use EnumFromRawStateMap until we have a dedicated HorizontalFacing enum //TODO: this can't use EnumFromRawStateMap until we have a dedicated HorizontalFacing enum
$this->cardinalDirection = IntFromRawStateMap::string([ $this->cardinalDirection = EnumFromRawStateMap::string(HorizontalFacingOption::class, fn(HorizontalFacingOption $case) => match ($case) {
Facing::NORTH->value => StringValues::MC_CARDINAL_DIRECTION_NORTH, HorizontalFacingOption::NORTH => StringValues::MC_CARDINAL_DIRECTION_NORTH,
Facing::SOUTH->value => StringValues::MC_CARDINAL_DIRECTION_SOUTH, HorizontalFacingOption::SOUTH => StringValues::MC_CARDINAL_DIRECTION_SOUTH,
Facing::WEST->value => StringValues::MC_CARDINAL_DIRECTION_WEST, HorizontalFacingOption::WEST => StringValues::MC_CARDINAL_DIRECTION_WEST,
Facing::EAST->value => StringValues::MC_CARDINAL_DIRECTION_EAST, HorizontalFacingOption::EAST => StringValues::MC_CARDINAL_DIRECTION_EAST,
]); });
$this->blockFace = EnumFromRawStateMap::string(Facing::class, fn(Facing $case) => match ($case) { $this->blockFace = EnumFromRawStateMap::string(Facing::class, fn(Facing $case) => match ($case) {
Facing::DOWN => StringValues::MC_BLOCK_FACE_DOWN, Facing::DOWN => StringValues::MC_BLOCK_FACE_DOWN,
Facing::UP => StringValues::MC_BLOCK_FACE_UP, Facing::UP => StringValues::MC_BLOCK_FACE_UP,
@ -232,39 +233,36 @@ final class ValueMappings{
Bamboo::LARGE_LEAVES => StringValues::BAMBOO_LEAF_SIZE_LARGE_LEAVES, Bamboo::LARGE_LEAVES => StringValues::BAMBOO_LEAF_SIZE_LARGE_LEAVES,
]); ]);
$this->horizontalFacing5Minus = IntFromRawStateMap::int([ $this->horizontalFacing5Minus = EnumFromRawStateMap::int(HorizontalFacingOption::class, fn(HorizontalFacingOption $case) => match ($case) {
Facing::EAST->value => 0, HorizontalFacingOption::EAST => 0,
Facing::WEST->value => 1, HorizontalFacingOption::WEST => 1,
Facing::SOUTH->value => 2, HorizontalFacingOption::SOUTH => 2,
Facing::NORTH->value => 3 HorizontalFacingOption::NORTH => 3
]); });
$this->horizontalFacingSWNE = IntFromRawStateMap::int([ $this->horizontalFacingSWNE = EnumFromRawStateMap::int(HorizontalFacingOption::class, fn(HorizontalFacingOption $case) => match ($case) {
Facing::SOUTH->value => 0, HorizontalFacingOption::SOUTH => 0,
Facing::WEST->value => 1, HorizontalFacingOption::WEST => 1,
Facing::NORTH->value => 2, HorizontalFacingOption::NORTH => 2,
Facing::EAST->value => 3 HorizontalFacingOption::EAST => 3
]); });
$this->horizontalFacingSWNEInverted = IntFromRawStateMap::int([ $this->horizontalFacingSWNEInverted = EnumFromRawStateMap::int(HorizontalFacingOption::class, fn(HorizontalFacingOption $case) => match ($case) {
Facing::NORTH->value => 0, HorizontalFacingOption::NORTH => 0,
Facing::EAST->value => 1, HorizontalFacingOption::EAST => 1,
Facing::SOUTH->value => 2, HorizontalFacingOption::SOUTH => 2,
Facing::WEST->value => 3, HorizontalFacingOption::WEST => 3,
]); });
$this->horizontalFacingCoral = IntFromRawStateMap::int([ $this->horizontalFacingCoral = EnumFromRawStateMap::int(HorizontalFacingOption::class, fn(HorizontalFacingOption $case) => match ($case) {
Facing::WEST->value => 0, HorizontalFacingOption::WEST => 0,
Facing::EAST->value => 1, HorizontalFacingOption::EAST => 1,
Facing::NORTH->value => 2, HorizontalFacingOption::NORTH => 2,
Facing::SOUTH->value => 3 HorizontalFacingOption::SOUTH => 3
]); });
$horizontalFacingClassicTable = [ $this->horizontalFacingClassic = EnumFromRawStateMap::int(HorizontalFacingOption::class, fn(HorizontalFacingOption $case) => match ($case) {
Facing::NORTH->value => 2, HorizontalFacingOption::NORTH => 2,
Facing::SOUTH->value => 3, HorizontalFacingOption::SOUTH => 3,
Facing::WEST->value => 4, HorizontalFacingOption::WEST => 4,
Facing::EAST->value => 5 HorizontalFacingOption::EAST => 5
]; }, aliasMapper: fn(HorizontalFacingOption $case) => $case === HorizontalFacingOption::NORTH ? [0, 1] : []); //should be illegal but still technically possible
$this->horizontalFacingClassic = IntFromRawStateMap::int($horizontalFacingClassicTable, deserializeAliases: [
Facing::NORTH->value => [0, 1] //should be illegal but still technically possible
]);
$this->facing = EnumFromRawStateMap::int(Facing::class, fn(Facing $case) => match ($case) { $this->facing = EnumFromRawStateMap::int(Facing::class, fn(Facing $case) => match ($case) {
Facing::DOWN => 0, Facing::DOWN => 0,
@ -285,6 +283,13 @@ final class ValueMappings{
Facing::WEST => 5, Facing::WEST => 5,
}); });
//these can't be migrated to enums yet
$horizontalFacingClassicTable = [
Facing::NORTH->value => 2,
Facing::SOUTH->value => 3,
Facing::WEST->value => 4,
Facing::EAST->value => 5
];
$this->coralAxis = IntFromRawStateMap::int([ $this->coralAxis = IntFromRawStateMap::int([
Axis::X->value => 0, Axis::X->value => 0,
Axis::Z->value => 1, Axis::Z->value => 1,

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\data\runtime; namespace pocketmine\data\runtime;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\WallConnectionType; use pocketmine\block\utils\WallConnectionType;
use pocketmine\math\Axis; use pocketmine\math\Axis;
use pocketmine\math\Facing; use pocketmine\math\Facing;
@ -46,15 +47,13 @@ interface RuntimeDataDescriber{
public function bool(bool &$value) : void; public function bool(bool &$value) : void;
public function horizontalFacing(Facing &$facing) : void;
/** /**
* @param Facing[] $faces * @param Facing[] $faces
*/ */
public function facingFlags(array &$faces) : void; public function facingFlags(array &$faces) : void;
/** /**
* @param Facing[] $faces * @param HorizontalFacingOption[] $faces
*/ */
public function horizontalFacingFlags(array &$faces) : void; public function horizontalFacingFlags(array &$faces) : void;

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\data\runtime; namespace pocketmine\data\runtime;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\RailConnectionInfo; use pocketmine\block\utils\RailConnectionInfo;
use pocketmine\block\utils\WallConnectionType; use pocketmine\block\utils\WallConnectionType;
use pocketmine\math\Axis; use pocketmine\math\Axis;
@ -77,16 +78,6 @@ final class RuntimeDataReader implements RuntimeDataDescriber{
$value = $this->readBool(); $value = $this->readBool();
} }
public function horizontalFacing(Facing &$facing) : void{
$facing = match($this->readInt(2)){
0 => Facing::NORTH,
1 => Facing::EAST,
2 => Facing::SOUTH,
3 => Facing::WEST,
default => throw new AssumptionFailedError("Unreachable")
};
}
/** /**
* @param Facing[] $faces * @param Facing[] $faces
*/ */
@ -102,11 +93,11 @@ final class RuntimeDataReader implements RuntimeDataDescriber{
} }
/** /**
* @param Facing[] $faces * @param HorizontalFacingOption[] $faces
*/ */
public function horizontalFacingFlags(array &$faces) : void{ public function horizontalFacingFlags(array &$faces) : void{
$result = []; $result = [];
foreach(Facing::HORIZONTAL as $facing){ foreach(HorizontalFacingOption::cases() as $facing){
if($this->readBool()){ if($this->readBool()){
$result[$facing->value] = $facing; $result[$facing->value] = $facing;
} }

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\data\runtime; namespace pocketmine\data\runtime;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\math\Axis; use pocketmine\math\Axis;
use pocketmine\math\Facing; use pocketmine\math\Facing;
use function count; use function count;
@ -51,16 +52,12 @@ final class RuntimeDataSizeCalculator implements RuntimeDataDescriber{
$this->addBits(1); $this->addBits(1);
} }
public function horizontalFacing(Facing &$facing) : void{
$this->addBits(2);
}
public function facingFlags(array &$faces) : void{ public function facingFlags(array &$faces) : void{
$this->addBits(count(Facing::cases())); $this->addBits(count(Facing::cases()));
} }
public function horizontalFacingFlags(array &$faces) : void{ public function horizontalFacingFlags(array &$faces) : void{
$this->addBits(count(Facing::HORIZONTAL)); $this->addBits(count(HorizontalFacingOption::cases()));
} }
public function facingExcept(Facing &$facing, Facing $except) : void{ public function facingExcept(Facing &$facing, Facing $except) : void{

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\data\runtime; namespace pocketmine\data\runtime;
use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\WallConnectionType; use pocketmine\block\utils\WallConnectionType;
use pocketmine\math\Axis; use pocketmine\math\Axis;
use pocketmine\math\Facing; use pocketmine\math\Facing;
@ -73,16 +74,6 @@ final class RuntimeDataWriter implements RuntimeDataDescriber{
$this->writeBool($value); $this->writeBool($value);
} }
public function horizontalFacing(Facing &$facing) : void{
$this->writeInt(2, match($facing){
Facing::NORTH => 0,
Facing::EAST => 1,
Facing::SOUTH => 2,
Facing::WEST => 3,
default => throw new \InvalidArgumentException("Invalid horizontal facing $facing->name")
});
}
/** /**
* @param Facing[] $faces * @param Facing[] $faces
*/ */
@ -97,14 +88,14 @@ final class RuntimeDataWriter implements RuntimeDataDescriber{
} }
/** /**
* @param Facing[] $faces * @param HorizontalFacingOption[] $faces
*/ */
public function horizontalFacingFlags(array &$faces) : void{ public function horizontalFacingFlags(array &$faces) : void{
$uniqueFaces = []; $uniqueFaces = [];
foreach($faces as $face){ foreach($faces as $face){
$uniqueFaces[$face->value] = true; $uniqueFaces[$face->value] = true;
} }
foreach(Facing::HORIZONTAL as $facing){ foreach(HorizontalFacingOption::cases() as $facing){
$this->writeBool(isset($uniqueFaces[$facing->value])); $this->writeBool(isset($uniqueFaces[$facing->value]));
} }
} }