From 8dc4371385558421aeb2ae4b89931ef985df7259 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 29 Aug 2025 23:33:52 +0100 Subject: [PATCH] Enums for rail shapes, sort of this makes the API more sane, although the internals will need to be rewritten at some point in the future. --- src/block/Rail.php | 19 ++++----- src/block/StraightOnlyRail.php | 19 ++++----- src/block/utils/RailShape.php | 41 +++++++++++++++++++ src/block/utils/StraightOnlyRailShape.php | 33 +++++++++++++++ .../block/convert/VanillaBlockMappings.php | 21 +++++++--- .../convert/property/CommonProperties.php | 13 ++++++ src/data/runtime/RuntimeDataDescriber.php | 4 -- src/data/runtime/RuntimeDataReader.php | 19 --------- .../runtime/RuntimeDataSizeCalculator.php | 8 ---- src/data/runtime/RuntimeDataWriter.php | 8 ---- 10 files changed, 117 insertions(+), 68 deletions(-) create mode 100644 src/block/utils/RailShape.php create mode 100644 src/block/utils/StraightOnlyRailShape.php diff --git a/src/block/Rail.php b/src/block/Rail.php index faed53c9b..f904c238d 100644 --- a/src/block/Rail.php +++ b/src/block/Rail.php @@ -24,18 +24,16 @@ declare(strict_types=1); namespace pocketmine\block; use pocketmine\block\utils\RailConnectionInfo; -use pocketmine\data\bedrock\block\BlockLegacyMetadata; +use pocketmine\block\utils\RailShape; use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\math\Facing; -use function array_keys; -use function implode; class Rail extends BaseRail{ - private int $railShape = BlockLegacyMetadata::RAIL_STRAIGHT_NORTH_SOUTH; + private RailShape $railShape = RailShape::FLAT_AXIS_Z; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->railShape($this->railShape); + $w->enum($this->railShape); } protected function setShapeFromConnections(array $connections) : void{ @@ -43,11 +41,11 @@ class Rail extends BaseRail{ if($railShape === null){ throw new \InvalidArgumentException("No rail shape matches these connections"); } - $this->railShape = $railShape; + $this->railShape = RailShape::from($railShape); } protected function getCurrentShapeConnections() : array{ - return RailConnectionInfo::CURVE_CONNECTIONS[$this->railShape] ?? RailConnectionInfo::CONNECTIONS[$this->railShape]; + return RailConnectionInfo::CURVE_CONNECTIONS[$this->railShape->value] ?? RailConnectionInfo::CONNECTIONS[$this->railShape->value]; } protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{ @@ -69,13 +67,10 @@ class Rail extends BaseRail{ return $possible; } - public function getShape() : int{ return $this->railShape; } + public function getShape() : RailShape{ return $this->railShape; } /** @return $this */ - public function setShape(int $shape) : self{ - if(!isset(RailConnectionInfo::CONNECTIONS[$shape]) && !isset(RailConnectionInfo::CURVE_CONNECTIONS[$shape])){ - throw new \InvalidArgumentException("Invalid shape, must be one of " . implode(", ", [...array_keys(RailConnectionInfo::CONNECTIONS), ...array_keys(RailConnectionInfo::CURVE_CONNECTIONS)])); - } + public function setShape(RailShape $shape) : self{ $this->railShape = $shape; return $this; } diff --git a/src/block/StraightOnlyRail.php b/src/block/StraightOnlyRail.php index 054983dbc..5a09474a5 100644 --- a/src/block/StraightOnlyRail.php +++ b/src/block/StraightOnlyRail.php @@ -24,20 +24,18 @@ declare(strict_types=1); namespace pocketmine\block; use pocketmine\block\utils\RailConnectionInfo; -use pocketmine\data\bedrock\block\BlockLegacyMetadata; +use pocketmine\block\utils\StraightOnlyRailShape; use pocketmine\data\runtime\RuntimeDataDescriber; -use function array_keys; -use function implode; /** * Simple non-curvable rail. */ class StraightOnlyRail extends BaseRail{ - private int $railShape = BlockLegacyMetadata::RAIL_STRAIGHT_NORTH_SOUTH; + private StraightOnlyRailShape $railShape = StraightOnlyRailShape::FLAT_AXIS_Z; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->straightOnlyRailShape($this->railShape); + $w->enum($this->railShape); } protected function setShapeFromConnections(array $connections) : void{ @@ -45,20 +43,17 @@ class StraightOnlyRail extends BaseRail{ if($railShape === null){ throw new \InvalidArgumentException("No rail shape matches these connections"); } - $this->railShape = $railShape; + $this->railShape = StraightOnlyRailShape::from($railShape); } protected function getCurrentShapeConnections() : array{ - return RailConnectionInfo::CONNECTIONS[$this->railShape]; + return RailConnectionInfo::CONNECTIONS[$this->railShape->value]; } - public function getShape() : int{ return $this->railShape; } + public function getShape() : StraightOnlyRailShape{ return $this->railShape; } /** @return $this */ - public function setShape(int $shape) : self{ - if(!isset(RailConnectionInfo::CONNECTIONS[$shape])){ - throw new \InvalidArgumentException("Invalid rail shape, must be one of " . implode(", ", array_keys(RailConnectionInfo::CONNECTIONS))); - } + public function setShape(StraightOnlyRailShape $shape) : self{ $this->railShape = $shape; return $this; diff --git a/src/block/utils/RailShape.php b/src/block/utils/RailShape.php new file mode 100644 index 000000000..dfd0d09a1 --- /dev/null +++ b/src/block/utils/RailShape.php @@ -0,0 +1,41 @@ +value; + case FLAT_AXIS_X = RailShape::FLAT_AXIS_X->value; + case ASCENDING_EAST = RailShape::ASCENDING_EAST->value; + case ASCENDING_WEST = RailShape::ASCENDING_WEST->value; + case ASCENDING_NORTH = RailShape::ASCENDING_NORTH->value; + case ASCENDING_SOUTH = RailShape::ASCENDING_SOUTH->value; +} diff --git a/src/data/bedrock/block/convert/VanillaBlockMappings.php b/src/data/bedrock/block/convert/VanillaBlockMappings.php index 8bcee6e0b..15fd07659 100644 --- a/src/data/bedrock/block/convert/VanillaBlockMappings.php +++ b/src/data/bedrock/block/convert/VanillaBlockMappings.php @@ -81,7 +81,6 @@ use pocketmine\block\SeaPickle; use pocketmine\block\SmallDripleaf; use pocketmine\block\SnowLayer; use pocketmine\block\Sponge; -use pocketmine\block\StraightOnlyRail; use pocketmine\block\Sugarcane; use pocketmine\block\SweetBerryBush; use pocketmine\block\TNT; @@ -102,6 +101,7 @@ use pocketmine\block\utils\LeverFacing; use pocketmine\block\utils\MobHeadType; use pocketmine\block\utils\MushroomBlockType; use pocketmine\block\utils\PoweredByRedstone; +use pocketmine\block\utils\RailShape; use pocketmine\block\VanillaBlocks as Blocks; use pocketmine\block\Vine; use pocketmine\data\bedrock\block\BlockLegacyMetadata; @@ -1215,7 +1215,7 @@ final class VanillaBlockMappings{ //A $reg->mapModel(Model::create(Blocks::ACTIVATOR_RAIL(), Ids::ACTIVATOR_RAIL)->properties([ new BoolProperty(StateNames::RAIL_DATA_BIT, fn(ActivatorRail $b) => $b->isPowered(), fn(ActivatorRail $b, bool $v) => $b->setPowered($v)), - new IntProperty(StateNames::RAIL_DIRECTION, 0, 5, fn(ActivatorRail $b) => $b->getShape(), fn(ActivatorRail $b, int $v) => $b->setShape($v)) + $commonProperties->straightOnlyRailShape ])); //B @@ -1300,7 +1300,7 @@ final class VanillaBlockMappings{ $reg->mapModel(Model::create(Blocks::DEEPSLATE(), Ids::DEEPSLATE)->properties([$commonProperties->pillarAxis])); $reg->mapModel(Model::create(Blocks::DETECTOR_RAIL(), Ids::DETECTOR_RAIL)->properties([ new BoolProperty(StateNames::RAIL_DATA_BIT, fn(DetectorRail $b) => $b->isActivated(), fn(DetectorRail $b, bool $v) => $b->setActivated($v)), - new IntProperty(StateNames::RAIL_DIRECTION, 0, 5, fn(StraightOnlyRail $b) => $b->getShape(), fn(StraightOnlyRail $b, int $v) => $b->setShape($v)) //TODO: shared with ActivatorRail + $commonProperties->straightOnlyRailShape ])); //E @@ -1381,7 +1381,7 @@ final class VanillaBlockMappings{ ])); $reg->mapModel(Model::create(Blocks::POWERED_RAIL(), Ids::GOLDEN_RAIL)->properties([ new BoolProperty(StateNames::RAIL_DATA_BIT, fn(PoweredRail $b) => $b->isPowered(), fn(PoweredRail $b, bool $v) => $b->setPowered($v)), //TODO: shared with ActivatorRail - new IntProperty(StateNames::RAIL_DIRECTION, 0, 5, fn(StraightOnlyRail $b) => $b->getShape(), fn(StraightOnlyRail $b, int $v) => $b->setShape($v)) //TODO: shared with ActivatorRail + $commonProperties->straightOnlyRailShape ])); $reg->mapModel(Model::create(Blocks::PITCHER_PLANT(), Ids::PITCHER_PLANT)->properties([ new BoolProperty(StateNames::UPPER_BLOCK_BIT, fn(DoublePlant $b) => $b->isTop(), fn(DoublePlant $b, bool $v) => $b->setTop($v)), //TODO: don't we have helpers for this? @@ -1406,7 +1406,18 @@ final class VanillaBlockMappings{ //R $reg->mapModel(Model::create(Blocks::RAIL(), Ids::RAIL)->properties([ - new IntProperty(StateNames::RAIL_DIRECTION, 0, 9, fn(Rail $b) => $b->getShape(), fn(Rail $b, int $v) => $b->setShape($v)) + new ValueFromIntProperty(StateNames::RAIL_DIRECTION, EnumFromRawStateMap::int(RailShape::class, fn(RailShape $case) => match($case){ + RailShape::FLAT_AXIS_Z => BlockLegacyMetadata::RAIL_STRAIGHT_NORTH_SOUTH, + RailShape::FLAT_AXIS_X => BlockLegacyMetadata::RAIL_STRAIGHT_EAST_WEST, + RailShape::ASCENDING_EAST => BlockLegacyMetadata::RAIL_ASCENDING_EAST, + RailShape::ASCENDING_WEST => BlockLegacyMetadata::RAIL_ASCENDING_WEST, + RailShape::ASCENDING_NORTH => BlockLegacyMetadata::RAIL_ASCENDING_NORTH, + RailShape::ASCENDING_SOUTH => BlockLegacyMetadata::RAIL_ASCENDING_SOUTH, + RailShape::CURVED_NORTHEAST => BlockLegacyMetadata::RAIL_CURVE_NORTHEAST, + RailShape::CURVED_NORTHWEST => BlockLegacyMetadata::RAIL_CURVE_NORTHWEST, + RailShape::CURVED_SOUTHEAST => BlockLegacyMetadata::RAIL_CURVE_SOUTHEAST, + RailShape::CURVED_SOUTHWEST => BlockLegacyMetadata::RAIL_CURVE_SOUTHWEST, + }), fn(Rail $b) => $b->getShape(), fn(Rail $b, RailShape $v) => $b->setShape($v)) ])); $reg->mapModel(Model::create(Blocks::REDSTONE_WIRE(), Ids::REDSTONE_WIRE)->properties([$commonProperties->analogRedstoneSignal])); $reg->mapModel(Model::create(Blocks::RESPAWN_ANCHOR(), Ids::RESPAWN_ANCHOR)->properties([ diff --git a/src/data/bedrock/block/convert/property/CommonProperties.php b/src/data/bedrock/block/convert/property/CommonProperties.php index 4c039d9f4..beb2a421d 100644 --- a/src/data/bedrock/block/convert/property/CommonProperties.php +++ b/src/data/bedrock/block/convert/property/CommonProperties.php @@ -33,6 +33,7 @@ use pocketmine\block\SimplePressurePlate; use pocketmine\block\Slab; use pocketmine\block\Stair; use pocketmine\block\Stem; +use pocketmine\block\StraightOnlyRail; use pocketmine\block\Torch; use pocketmine\block\Trapdoor; use pocketmine\block\utils\Ageable; @@ -51,6 +52,7 @@ use pocketmine\block\utils\MultiAnyFacing; use pocketmine\block\utils\PillarRotation; use pocketmine\block\utils\SignLikeRotation; use pocketmine\block\utils\SlabType; +use pocketmine\block\utils\StraightOnlyRailShape; use pocketmine\block\Wall; use pocketmine\block\Wood; use pocketmine\data\bedrock\block\BlockLegacyMetadata; @@ -95,6 +97,8 @@ final class CommonProperties{ public readonly IntProperty $cropAgeMax7; /** @phpstan-var BoolProperty */ public readonly BoolProperty $doublePlantHalf; + /** @phpstan-var ValueFromIntProperty */ + public readonly ValueFromIntProperty $straightOnlyRailShape; /** @phpstan-var IntProperty */ public readonly IntProperty $liquidData; @@ -266,6 +270,15 @@ final class CommonProperties{ $this->cropAgeMax7 = new IntProperty(StateNames::GROWTH, 0, 7, fn(Ageable $b) => $b->getAge(), fn(Ageable $b, int $v) => $b->setAge($v)); $this->doublePlantHalf = new BoolProperty(StateNames::UPPER_BLOCK_BIT, fn(DoublePlant $b) => $b->isTop(), fn(DoublePlant $b, bool $v) => $b->setTop($v)); + $this->straightOnlyRailShape = new ValueFromIntProperty(StateNames::RAIL_DIRECTION, EnumFromRawStateMap::int(StraightOnlyRailShape::class, fn(StraightOnlyRailShape $case) => match($case){ + StraightOnlyRailShape::FLAT_AXIS_Z => BlockLegacyMetadata::RAIL_STRAIGHT_NORTH_SOUTH, + StraightOnlyRailShape::FLAT_AXIS_X => BlockLegacyMetadata::RAIL_STRAIGHT_EAST_WEST, + StraightOnlyRailShape::ASCENDING_EAST => BlockLegacyMetadata::RAIL_ASCENDING_EAST, + StraightOnlyRailShape::ASCENDING_WEST => BlockLegacyMetadata::RAIL_ASCENDING_WEST, + StraightOnlyRailShape::ASCENDING_NORTH => BlockLegacyMetadata::RAIL_ASCENDING_NORTH, + StraightOnlyRailShape::ASCENDING_SOUTH => BlockLegacyMetadata::RAIL_ASCENDING_SOUTH + }), fn(StraightOnlyRail $b) => $b->getShape(), fn(StraightOnlyRail $b, StraightOnlyRailShape $v) => $b->setShape($v)); + $fallingFlag = BlockLegacyMetadata::LIQUID_FALLING_FLAG; $this->liquidData = new IntProperty( StateNames::LIQUID_DEPTH, diff --git a/src/data/runtime/RuntimeDataDescriber.php b/src/data/runtime/RuntimeDataDescriber.php index addcc4164..4fab5fc34 100644 --- a/src/data/runtime/RuntimeDataDescriber.php +++ b/src/data/runtime/RuntimeDataDescriber.php @@ -67,10 +67,6 @@ interface RuntimeDataDescriber{ */ public function wallConnections(array &$connections) : void; - public function railShape(int &$railShape) : void; - - public function straightOnlyRailShape(int &$railShape) : void; - /** * @phpstan-template T of \UnitEnum * @phpstan-param T &$case diff --git a/src/data/runtime/RuntimeDataReader.php b/src/data/runtime/RuntimeDataReader.php index d79aafee4..abc4b2a84 100644 --- a/src/data/runtime/RuntimeDataReader.php +++ b/src/data/runtime/RuntimeDataReader.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace pocketmine\data\runtime; use pocketmine\block\utils\HorizontalFacingOption; -use pocketmine\block\utils\RailConnectionInfo; use pocketmine\block\utils\WallConnectionType; use pocketmine\math\Axis; use pocketmine\math\Facing; @@ -147,24 +146,6 @@ final class RuntimeDataReader implements RuntimeDataDescriber{ $connections = $result; } - public function railShape(int &$railShape) : void{ - $result = $this->readInt(4); - if(!isset(RailConnectionInfo::CONNECTIONS[$result]) && !isset(RailConnectionInfo::CURVE_CONNECTIONS[$result])){ - throw new InvalidSerializedRuntimeDataException("Invalid rail shape $result"); - } - - $railShape = $result; - } - - public function straightOnlyRailShape(int &$railShape) : void{ - $result = $this->readInt(3); - if(!isset(RailConnectionInfo::CONNECTIONS[$result])){ - throw new InvalidSerializedRuntimeDataException("No rail shape matches meta $result"); - } - - $railShape = $result; - } - public function enum(\UnitEnum &$case) : void{ $metadata = RuntimeEnumMetadata::from($case); $raw = $this->readInt($metadata->bits); diff --git a/src/data/runtime/RuntimeDataSizeCalculator.php b/src/data/runtime/RuntimeDataSizeCalculator.php index 09551ee1f..6efd7ed8a 100644 --- a/src/data/runtime/RuntimeDataSizeCalculator.php +++ b/src/data/runtime/RuntimeDataSizeCalculator.php @@ -72,14 +72,6 @@ final class RuntimeDataSizeCalculator implements RuntimeDataDescriber{ $this->addBits(7); } - public function railShape(int &$railShape) : void{ - $this->addBits(4); - } - - public function straightOnlyRailShape(int &$railShape) : void{ - $this->addBits(3); - } - public function enum(\UnitEnum &$case) : void{ $metadata = RuntimeEnumMetadata::from($case); $this->addBits($metadata->bits); diff --git a/src/data/runtime/RuntimeDataWriter.php b/src/data/runtime/RuntimeDataWriter.php index 1cab259de..e469ac26e 100644 --- a/src/data/runtime/RuntimeDataWriter.php +++ b/src/data/runtime/RuntimeDataWriter.php @@ -130,14 +130,6 @@ final class RuntimeDataWriter implements RuntimeDataDescriber{ $this->writeBoundedIntAuto(0, (3 ** 4) - 1, $packed); } - public function railShape(int &$railShape) : void{ - $this->int(4, $railShape); - } - - public function straightOnlyRailShape(int &$railShape) : void{ - $this->int(3, $railShape); - } - public function enum(\UnitEnum &$case) : void{ $metadata = RuntimeEnumMetadata::from($case); $this->writeInt($metadata->bits, $metadata->enumToInt($case));