From 7dcd2592d4dd5d59dbd38069b859f57a14fcd895 Mon Sep 17 00:00:00 2001 From: Dylan T Date: Thu, 7 Sep 2023 20:07:14 +0100 Subject: [PATCH] RuntimeDataDescriber: Support dynamically describing arbitrary enums (#6039) Previously, we were using codegen to support describing a fixed set of enums. Instead, we implement an enum() function, allowing any native PHP enum to be described. All enums used in runtime data have been migrated to native PHP 8.1 enums in minor-next to facilitate this. This implementation: - is faster (in extreme cases by 40x, such as with PotionType) - requires way less code - does not require a build step - is way more flexible This fixes #5877, increasing the range of stuff that plugins are now able to do. EnumTrait enums are not supported, as it's easier and cleaner to just support native enums. Most core EnumTrait enums have been migrated to native enums by now to facilitate this. --- .github/workflows/main.yml | 3 - build/generate-runtime-enum-serializers.php | 265 ------------------ src/block/Bell.php | 2 +- src/block/BigDripleafHead.php | 2 +- src/block/Dirt.php | 2 +- src/block/Froglight.php | 2 +- src/block/Lever.php | 2 +- src/block/MobHead.php | 2 +- src/block/RedMushroomBlock.php | 2 +- src/block/Slab.php | 2 +- src/block/utils/ColoredTrait.php | 2 +- src/block/utils/CopperTrait.php | 2 +- src/block/utils/CoralTypeTrait.php | 2 +- ...hp => LegacyRuntimeEnumDescriberTrait.php} | 42 +-- src/data/runtime/RuntimeDataDescriber.php | 6 + src/data/runtime/RuntimeDataReader.php | 14 +- .../runtime/RuntimeDataSizeCalculator.php | 7 +- src/data/runtime/RuntimeDataWriter.php | 7 +- src/data/runtime/RuntimeEnumDescriber.php | 5 +- .../runtime/RuntimeEnumDeserializerTrait.php | 243 ---------------- src/data/runtime/RuntimeEnumMetadata.php | 114 ++++++++ .../runtime/RuntimeEnumSerializerTrait.php | 243 ---------------- src/item/Banner.php | 2 +- src/item/Dye.php | 2 +- src/item/Medicine.php | 2 +- src/item/Potion.php | 2 +- src/item/SplashPotion.php | 2 +- src/item/SuspiciousStew.php | 2 +- 28 files changed, 188 insertions(+), 795 deletions(-) delete mode 100644 build/generate-runtime-enum-serializers.php rename src/data/runtime/{RuntimeEnumSizeCalculatorTrait.php => LegacyRuntimeEnumDescriberTrait.php} (74%) delete mode 100644 src/data/runtime/RuntimeEnumDeserializerTrait.php create mode 100644 src/data/runtime/RuntimeEnumMetadata.php delete mode 100644 src/data/runtime/RuntimeEnumSerializerTrait.php diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f9046017ce0..5414deabcba 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -152,9 +152,6 @@ jobs: - name: Regenerate KnownTranslation APIs run: php build/generate-known-translation-apis.php - - name: Regenerate RuntimeEnum(De)serializer - run: php build/generate-runtime-enum-serializers.php - - name: Regenerate BedrockData available files constants run: php build/generate-bedrockdata-path-consts.php diff --git a/build/generate-runtime-enum-serializers.php b/build/generate-runtime-enum-serializers.php deleted file mode 100644 index d822fa53985..00000000000 --- a/build/generate-runtime-enum-serializers.php +++ /dev/null @@ -1,265 +0,0 @@ - $memberNames - * - * @return string[] - * @phpstan-return list - */ -function buildWriterFunc(string $virtualTypeName, string $nativeTypeName, array $memberNames, string $functionName) : array{ - $bits = getBitsRequired($memberNames); - $lines = []; - - $lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{"; - $lines[] = "\t\$this->writeInt($bits, match(\$value){"; - - foreach($memberNames as $key => $memberName){ - $lines[] = "\t\t$memberName => $key,"; - } - $lines[] = "\t\tdefault => throw new \pocketmine\utils\AssumptionFailedError(\"All $virtualTypeName cases should be covered\")"; - $lines[] = "\t});"; - $lines[] = "}"; - - return $lines; -} - -/** - * @param string[] $memberNames - * @phpstan-param list $memberNames - * - * @return string[] - * @phpstan-return list - */ -function buildReaderFunc(string $virtualTypeName, string $nativeTypeName, array $memberNames, string $functionName) : array{ - $bits = getBitsRequired($memberNames); - $lines = []; - - $lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{"; - $lines[] = "\t\$value = match(\$this->readInt($bits)){"; - - foreach($memberNames as $key => $memberName){ - $lines[] = "\t\t$key => $memberName,"; - } - $lines[] = "\t\tdefault => throw new InvalidSerializedRuntimeDataException(\"Invalid serialized value for $virtualTypeName\")"; - $lines[] = "\t};"; - $lines[] = "}"; - - return $lines; -} - -function buildInterfaceFunc(string $nativeTypeName, string $functionName) : string{ - return "public function $functionName(\\$nativeTypeName &\$value) : void;"; -} - -/** - * @param string[] $memberNames - * @phpstan-param list $memberNames - * - * @return string[] - * @phpstan-return list - */ -function buildSizeCalculationFunc(string $nativeTypeName, string $functionName, array $memberNames) : array{ - $lines = []; - $lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{"; - $lines[] = "\t\$this->addBits(" . getBitsRequired($memberNames) . ");"; - $lines[] = "}"; - - return $lines; -} - -/** - * @param mixed[] $members - */ -function getBitsRequired(array $members) : int{ - return (int) ceil(log(count($members), 2)); -} - -/** - * @param \UnitEnum[] $members - * @phpstan-param list<\UnitEnum> $members - * - * @return string[] - * @phpstan-return list - */ -function stringifyEnumMembers(array $members, string $enumClass) : array{ - usort($members, fn(\UnitEnum $a, \UnitEnum $b) => $a->name <=> $b->name); - return array_map(fn(\UnitEnum $case) => "\\$enumClass::$case->name", $members); -} - -$enumsUsed = [ - BellAttachmentType::cases(), - CopperOxidation::cases(), - CoralType::cases(), - DirtType::cases(), - DripleafState::cases(), - DyeColor::cases(), - FroglightType::cases(), - LeverFacing::cases(), - MedicineType::cases(), - MushroomBlockType::cases(), - MobHeadType::cases(), - SlabType::cases(), - SuspiciousStewType::cases(), - PotionType::cases() -]; - -$readerFuncs = [ - "" => [ - "abstract protected function readInt(int \$bits) : int;" - ] -]; -$writerFuncs = [ - "" => [ - "abstract protected function writeInt(int \$bits, int \$value) : void;" - ] -]; -$interfaceFuncs = []; -$sizeCalculationFuncs = [ - "" => [ - "abstract protected function addBits(int \$bits) : void;" - ] -]; - -foreach($enumsUsed as $enumMembers){ - if(count($enumMembers) === 0){ - throw new \InvalidArgumentException("Enum members cannot be empty"); - } - $reflect = new \ReflectionClass($enumMembers[array_key_first($enumMembers)]); - $virtualTypeName = $reflect->getShortName(); - $nativeTypeName = $reflect->getName(); - $functionName = lcfirst($virtualTypeName); - - $stringifiedMembers = stringifyEnumMembers($enumMembers, $nativeTypeName); - $writerFuncs[$functionName] = buildWriterFunc( - $virtualTypeName, - $nativeTypeName, - $stringifiedMembers, - $functionName - ); - $readerFuncs[$functionName] = buildReaderFunc( - $virtualTypeName, - $nativeTypeName, - $stringifiedMembers, - $functionName - ); - $interfaceFuncs[$functionName] = [buildInterfaceFunc( - $nativeTypeName, - $functionName - )]; - $sizeCalculationFuncs[$functionName] = buildSizeCalculationFunc( - $nativeTypeName, - $functionName, - $stringifiedMembers - ); -} - -/** - * @param string[][] $functions - * @phpstan-param array> $functions - */ -function printFunctions(array $functions, string $className, string $classType) : void{ - ksort($functions, SORT_STRING); - - ob_start(); - - echo <<<'HEADER' - "\t" . implode("\n\t", $functionLines), $functions)); - echo "\n\n}\n"; - - file_put_contents(dirname(__DIR__) . '/src/data/runtime/' . $className . '.php', ob_get_clean()); -} - -printFunctions($writerFuncs, "RuntimeEnumSerializerTrait", "trait"); -printFunctions($readerFuncs, "RuntimeEnumDeserializerTrait", "trait"); -printFunctions($interfaceFuncs, "RuntimeEnumDescriber", "interface"); -printFunctions($sizeCalculationFuncs, "RuntimeEnumSizeCalculatorTrait", "trait"); - -echo "Done. Don't forget to run CS fixup after generating code.\n"; diff --git a/src/block/Bell.php b/src/block/Bell.php index e91082a2672..ec033cef87a 100644 --- a/src/block/Bell.php +++ b/src/block/Bell.php @@ -44,7 +44,7 @@ final class Bell extends Transparent{ private BellAttachmentType $attachmentType = BellAttachmentType::FLOOR; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->bellAttachmentType($this->attachmentType); + $w->enum($this->attachmentType); $w->horizontalFacing($this->facing); } diff --git a/src/block/BigDripleafHead.php b/src/block/BigDripleafHead.php index cb64423d352..a9b87bf7f76 100644 --- a/src/block/BigDripleafHead.php +++ b/src/block/BigDripleafHead.php @@ -39,7 +39,7 @@ class BigDripleafHead extends BaseBigDripleaf{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ parent::describeBlockOnlyState($w); - $w->dripleafState($this->leafState); + $w->enum($this->leafState); } protected function isHead() : bool{ diff --git a/src/block/Dirt.php b/src/block/Dirt.php index 6f3d62e7f8d..b3a3c6090bb 100644 --- a/src/block/Dirt.php +++ b/src/block/Dirt.php @@ -41,7 +41,7 @@ class Dirt extends Opaque{ protected DirtType $dirtType = DirtType::NORMAL; public function describeBlockItemState(RuntimeDataDescriber $w) : void{ - $w->dirtType($this->dirtType); + $w->enum($this->dirtType); } public function getDirtType() : DirtType{ return $this->dirtType; } diff --git a/src/block/Froglight.php b/src/block/Froglight.php index 2c54b830a35..562b33f174e 100644 --- a/src/block/Froglight.php +++ b/src/block/Froglight.php @@ -31,7 +31,7 @@ final class Froglight extends SimplePillar{ private FroglightType $froglightType = FroglightType::OCHRE; public function describeBlockItemState(RuntimeDataDescriber $w) : void{ - $w->froglightType($this->froglightType); + $w->enum($this->froglightType); } public function getFroglightType() : FroglightType{ return $this->froglightType; } diff --git a/src/block/Lever.php b/src/block/Lever.php index 01aa892455d..d2b98efc34f 100644 --- a/src/block/Lever.php +++ b/src/block/Lever.php @@ -40,7 +40,7 @@ class Lever extends Flowable{ protected bool $activated = false; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->leverFacing($this->facing); + $w->enum($this->facing); $w->bool($this->activated); } diff --git a/src/block/MobHead.php b/src/block/MobHead.php index 125bafe8b17..f4e945841d2 100644 --- a/src/block/MobHead.php +++ b/src/block/MobHead.php @@ -45,7 +45,7 @@ class MobHead extends Flowable{ protected int $rotation = self::MIN_ROTATION; //TODO: split this into floor skull and wall skull handling public function describeBlockItemState(RuntimeDataDescriber $w) : void{ - $w->mobHeadType($this->mobHeadType); + $w->enum($this->mobHeadType); } protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ diff --git a/src/block/RedMushroomBlock.php b/src/block/RedMushroomBlock.php index cf368a30aaa..0a7cb30f253 100644 --- a/src/block/RedMushroomBlock.php +++ b/src/block/RedMushroomBlock.php @@ -34,7 +34,7 @@ class RedMushroomBlock extends Opaque{ public function describeBlockItemState(RuntimeDataDescriber $w) : void{ //these blocks always drop as all-cap, but may exist in other forms in the inventory (particularly creative), //so this information needs to be kept in the type info - $w->mushroomBlockType($this->mushroomBlockType); + $w->enum($this->mushroomBlockType); } public function getMushroomBlockType() : MushroomBlockType{ return $this->mushroomBlockType; } diff --git a/src/block/Slab.php b/src/block/Slab.php index bdf2bb5eb00..6000bec39e0 100644 --- a/src/block/Slab.php +++ b/src/block/Slab.php @@ -41,7 +41,7 @@ public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo } protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->slabType($this->slabType); + $w->enum($this->slabType); } public function isTransparent() : bool{ diff --git a/src/block/utils/ColoredTrait.php b/src/block/utils/ColoredTrait.php index 11e98167e44..2ecd58e2035 100644 --- a/src/block/utils/ColoredTrait.php +++ b/src/block/utils/ColoredTrait.php @@ -32,7 +32,7 @@ trait ColoredTrait{ /** @see Block::describeBlockItemState() */ public function describeBlockItemState(RuntimeDataDescriber $w) : void{ - $w->dyeColor($this->color); + $w->enum($this->color); } public function getColor() : DyeColor{ return $this->color; } diff --git a/src/block/utils/CopperTrait.php b/src/block/utils/CopperTrait.php index f0d708821fa..5ad8aa82d15 100644 --- a/src/block/utils/CopperTrait.php +++ b/src/block/utils/CopperTrait.php @@ -38,7 +38,7 @@ trait CopperTrait{ private bool $waxed = false; public function describeBlockItemState(RuntimeDataDescriber $w) : void{ - $w->copperOxidation($this->oxidation); + $w->enum($this->oxidation); $w->bool($this->waxed); } diff --git a/src/block/utils/CoralTypeTrait.php b/src/block/utils/CoralTypeTrait.php index fcd7dbf246c..a335bf9eccb 100644 --- a/src/block/utils/CoralTypeTrait.php +++ b/src/block/utils/CoralTypeTrait.php @@ -32,7 +32,7 @@ trait CoralTypeTrait{ /** @see Block::describeBlockItemState() */ public function describeBlockItemState(RuntimeDataDescriber $w) : void{ - $w->coralType($this->coralType); + $w->enum($this->coralType); $w->bool($this->dead); } diff --git a/src/data/runtime/RuntimeEnumSizeCalculatorTrait.php b/src/data/runtime/LegacyRuntimeEnumDescriberTrait.php similarity index 74% rename from src/data/runtime/RuntimeEnumSizeCalculatorTrait.php rename to src/data/runtime/LegacyRuntimeEnumDescriberTrait.php index 2ab62f03e6f..dd35fabfbf1 100644 --- a/src/data/runtime/RuntimeEnumSizeCalculatorTrait.php +++ b/src/data/runtime/LegacyRuntimeEnumDescriberTrait.php @@ -24,67 +24,71 @@ namespace pocketmine\data\runtime; /** - * This class is auto-generated. Do not edit it manually. - * @see build/generate-runtime-enum-serializers.php + * Provides backwards-compatible shims for the old codegen'd enum describer methods. + * This is kept for plugin backwards compatibility, but these functions should not be used in new code. + * @deprecated */ -trait RuntimeEnumSizeCalculatorTrait{ +trait LegacyRuntimeEnumDescriberTrait{ - abstract protected function addBits(int $bits) : void; + /** + * @phpstan-template T of \UnitEnum + * @phpstan-param T $case + */ + abstract protected function enum(\UnitEnum &$case) : void; public function bellAttachmentType(\pocketmine\block\utils\BellAttachmentType &$value) : void{ - $this->addBits(2); + $this->enum($value); } public function copperOxidation(\pocketmine\block\utils\CopperOxidation &$value) : void{ - $this->addBits(2); + $this->enum($value); } public function coralType(\pocketmine\block\utils\CoralType &$value) : void{ - $this->addBits(3); + $this->enum($value); } public function dirtType(\pocketmine\block\utils\DirtType &$value) : void{ - $this->addBits(2); + $this->enum($value); } public function dripleafState(\pocketmine\block\utils\DripleafState &$value) : void{ - $this->addBits(2); + $this->enum($value); } public function dyeColor(\pocketmine\block\utils\DyeColor &$value) : void{ - $this->addBits(4); + $this->enum($value); } public function froglightType(\pocketmine\block\utils\FroglightType &$value) : void{ - $this->addBits(2); + $this->enum($value); } public function leverFacing(\pocketmine\block\utils\LeverFacing &$value) : void{ - $this->addBits(3); + $this->enum($value); } public function medicineType(\pocketmine\item\MedicineType &$value) : void{ - $this->addBits(2); + $this->enum($value); } public function mobHeadType(\pocketmine\block\utils\MobHeadType &$value) : void{ - $this->addBits(3); + $this->enum($value); } public function mushroomBlockType(\pocketmine\block\utils\MushroomBlockType &$value) : void{ - $this->addBits(4); + $this->enum($value); } public function potionType(\pocketmine\item\PotionType &$value) : void{ - $this->addBits(6); + $this->enum($value); } public function slabType(\pocketmine\block\utils\SlabType &$value) : void{ - $this->addBits(2); + $this->enum($value); } public function suspiciousStewType(\pocketmine\item\SuspiciousStewType &$value) : void{ - $this->addBits(4); + $this->enum($value); } - } diff --git a/src/data/runtime/RuntimeDataDescriber.php b/src/data/runtime/RuntimeDataDescriber.php index 36822a6f396..2d8c52ec290 100644 --- a/src/data/runtime/RuntimeDataDescriber.php +++ b/src/data/runtime/RuntimeDataDescriber.php @@ -77,4 +77,10 @@ public function brewingStandSlots(array &$slots) : void; public function railShape(int &$railShape) : void; public function straightOnlyRailShape(int &$railShape) : void; + + /** + * @phpstan-template T of \UnitEnum + * @phpstan-param T $case + */ + public function enum(\UnitEnum &$case) : void; } diff --git a/src/data/runtime/RuntimeDataReader.php b/src/data/runtime/RuntimeDataReader.php index 1677cea3608..9b64450733a 100644 --- a/src/data/runtime/RuntimeDataReader.php +++ b/src/data/runtime/RuntimeDataReader.php @@ -29,11 +29,12 @@ use pocketmine\math\Axis; use pocketmine\math\Facing; use pocketmine\utils\AssumptionFailedError; +use function get_class; use function intdiv; use function spl_object_id; final class RuntimeDataReader implements RuntimeDataDescriber{ - use RuntimeEnumDeserializerTrait; + use LegacyRuntimeEnumDescriberTrait; private int $offset = 0; @@ -210,5 +211,16 @@ public function straightOnlyRailShape(int &$railShape) : void{ $railShape = $result; } + public function enum(\UnitEnum &$case) : void{ + $metadata = RuntimeEnumMetadata::from($case); + $raw = $this->readInt($metadata->bits); + $result = $metadata->intToEnum($raw); + if($result === null){ + throw new InvalidSerializedRuntimeDataException("Invalid serialized value $raw for " . get_class($case)); + } + + $case = $result; + } + public function getOffset() : int{ return $this->offset; } } diff --git a/src/data/runtime/RuntimeDataSizeCalculator.php b/src/data/runtime/RuntimeDataSizeCalculator.php index 352e8e1a1c8..82e36021352 100644 --- a/src/data/runtime/RuntimeDataSizeCalculator.php +++ b/src/data/runtime/RuntimeDataSizeCalculator.php @@ -28,7 +28,7 @@ use function count; final class RuntimeDataSizeCalculator implements RuntimeDataDescriber{ - use RuntimeEnumSizeCalculatorTrait; + use LegacyRuntimeEnumDescriberTrait; private int $bits = 0; @@ -95,4 +95,9 @@ public function railShape(int &$railShape) : void{ 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 3a5855a25a3..9e78875ea0d 100644 --- a/src/data/runtime/RuntimeDataWriter.php +++ b/src/data/runtime/RuntimeDataWriter.php @@ -31,7 +31,7 @@ use function spl_object_id; final class RuntimeDataWriter implements RuntimeDataDescriber{ - use RuntimeEnumSerializerTrait; + use LegacyRuntimeEnumDescriberTrait; private int $value = 0; private int $offset = 0; @@ -174,6 +174,11 @@ 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)); + } + public function getValue() : int{ return $this->value; } public function getOffset() : int{ return $this->offset; } diff --git a/src/data/runtime/RuntimeEnumDescriber.php b/src/data/runtime/RuntimeEnumDescriber.php index 7103017f75a..79550d041bb 100644 --- a/src/data/runtime/RuntimeEnumDescriber.php +++ b/src/data/runtime/RuntimeEnumDescriber.php @@ -24,8 +24,9 @@ namespace pocketmine\data\runtime; /** - * This class is auto-generated. Do not edit it manually. - * @see build/generate-runtime-enum-serializers.php + * Provides backwards-compatible shims for the old codegen'd enum describer methods. + * This is kept for plugin backwards compatibility, but these functions should not be used in new code. + * @deprecated */ interface RuntimeEnumDescriber{ diff --git a/src/data/runtime/RuntimeEnumDeserializerTrait.php b/src/data/runtime/RuntimeEnumDeserializerTrait.php deleted file mode 100644 index aa0c1bd7b0b..00000000000 --- a/src/data/runtime/RuntimeEnumDeserializerTrait.php +++ /dev/null @@ -1,243 +0,0 @@ -readInt(2)){ - 0 => \pocketmine\block\utils\BellAttachmentType::CEILING, - 1 => \pocketmine\block\utils\BellAttachmentType::FLOOR, - 2 => \pocketmine\block\utils\BellAttachmentType::ONE_WALL, - 3 => \pocketmine\block\utils\BellAttachmentType::TWO_WALLS, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for BellAttachmentType") - }; - } - - public function copperOxidation(\pocketmine\block\utils\CopperOxidation &$value) : void{ - $value = match($this->readInt(2)){ - 0 => \pocketmine\block\utils\CopperOxidation::EXPOSED, - 1 => \pocketmine\block\utils\CopperOxidation::NONE, - 2 => \pocketmine\block\utils\CopperOxidation::OXIDIZED, - 3 => \pocketmine\block\utils\CopperOxidation::WEATHERED, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for CopperOxidation") - }; - } - - public function coralType(\pocketmine\block\utils\CoralType &$value) : void{ - $value = match($this->readInt(3)){ - 0 => \pocketmine\block\utils\CoralType::BRAIN, - 1 => \pocketmine\block\utils\CoralType::BUBBLE, - 2 => \pocketmine\block\utils\CoralType::FIRE, - 3 => \pocketmine\block\utils\CoralType::HORN, - 4 => \pocketmine\block\utils\CoralType::TUBE, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for CoralType") - }; - } - - public function dirtType(\pocketmine\block\utils\DirtType &$value) : void{ - $value = match($this->readInt(2)){ - 0 => \pocketmine\block\utils\DirtType::COARSE, - 1 => \pocketmine\block\utils\DirtType::NORMAL, - 2 => \pocketmine\block\utils\DirtType::ROOTED, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for DirtType") - }; - } - - public function dripleafState(\pocketmine\block\utils\DripleafState &$value) : void{ - $value = match($this->readInt(2)){ - 0 => \pocketmine\block\utils\DripleafState::FULL_TILT, - 1 => \pocketmine\block\utils\DripleafState::PARTIAL_TILT, - 2 => \pocketmine\block\utils\DripleafState::STABLE, - 3 => \pocketmine\block\utils\DripleafState::UNSTABLE, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for DripleafState") - }; - } - - public function dyeColor(\pocketmine\block\utils\DyeColor &$value) : void{ - $value = match($this->readInt(4)){ - 0 => \pocketmine\block\utils\DyeColor::BLACK, - 1 => \pocketmine\block\utils\DyeColor::BLUE, - 2 => \pocketmine\block\utils\DyeColor::BROWN, - 3 => \pocketmine\block\utils\DyeColor::CYAN, - 4 => \pocketmine\block\utils\DyeColor::GRAY, - 5 => \pocketmine\block\utils\DyeColor::GREEN, - 6 => \pocketmine\block\utils\DyeColor::LIGHT_BLUE, - 7 => \pocketmine\block\utils\DyeColor::LIGHT_GRAY, - 8 => \pocketmine\block\utils\DyeColor::LIME, - 9 => \pocketmine\block\utils\DyeColor::MAGENTA, - 10 => \pocketmine\block\utils\DyeColor::ORANGE, - 11 => \pocketmine\block\utils\DyeColor::PINK, - 12 => \pocketmine\block\utils\DyeColor::PURPLE, - 13 => \pocketmine\block\utils\DyeColor::RED, - 14 => \pocketmine\block\utils\DyeColor::WHITE, - 15 => \pocketmine\block\utils\DyeColor::YELLOW, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for DyeColor") - }; - } - - public function froglightType(\pocketmine\block\utils\FroglightType &$value) : void{ - $value = match($this->readInt(2)){ - 0 => \pocketmine\block\utils\FroglightType::OCHRE, - 1 => \pocketmine\block\utils\FroglightType::PEARLESCENT, - 2 => \pocketmine\block\utils\FroglightType::VERDANT, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for FroglightType") - }; - } - - public function leverFacing(\pocketmine\block\utils\LeverFacing &$value) : void{ - $value = match($this->readInt(3)){ - 0 => \pocketmine\block\utils\LeverFacing::DOWN_AXIS_X, - 1 => \pocketmine\block\utils\LeverFacing::DOWN_AXIS_Z, - 2 => \pocketmine\block\utils\LeverFacing::EAST, - 3 => \pocketmine\block\utils\LeverFacing::NORTH, - 4 => \pocketmine\block\utils\LeverFacing::SOUTH, - 5 => \pocketmine\block\utils\LeverFacing::UP_AXIS_X, - 6 => \pocketmine\block\utils\LeverFacing::UP_AXIS_Z, - 7 => \pocketmine\block\utils\LeverFacing::WEST, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for LeverFacing") - }; - } - - public function medicineType(\pocketmine\item\MedicineType &$value) : void{ - $value = match($this->readInt(2)){ - 0 => \pocketmine\item\MedicineType::ANTIDOTE, - 1 => \pocketmine\item\MedicineType::ELIXIR, - 2 => \pocketmine\item\MedicineType::EYE_DROPS, - 3 => \pocketmine\item\MedicineType::TONIC, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for MedicineType") - }; - } - - public function mobHeadType(\pocketmine\block\utils\MobHeadType &$value) : void{ - $value = match($this->readInt(3)){ - 0 => \pocketmine\block\utils\MobHeadType::CREEPER, - 1 => \pocketmine\block\utils\MobHeadType::DRAGON, - 2 => \pocketmine\block\utils\MobHeadType::PIGLIN, - 3 => \pocketmine\block\utils\MobHeadType::PLAYER, - 4 => \pocketmine\block\utils\MobHeadType::SKELETON, - 5 => \pocketmine\block\utils\MobHeadType::WITHER_SKELETON, - 6 => \pocketmine\block\utils\MobHeadType::ZOMBIE, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for MobHeadType") - }; - } - - public function mushroomBlockType(\pocketmine\block\utils\MushroomBlockType &$value) : void{ - $value = match($this->readInt(4)){ - 0 => \pocketmine\block\utils\MushroomBlockType::ALL_CAP, - 1 => \pocketmine\block\utils\MushroomBlockType::CAP_EAST, - 2 => \pocketmine\block\utils\MushroomBlockType::CAP_MIDDLE, - 3 => \pocketmine\block\utils\MushroomBlockType::CAP_NORTH, - 4 => \pocketmine\block\utils\MushroomBlockType::CAP_NORTHEAST, - 5 => \pocketmine\block\utils\MushroomBlockType::CAP_NORTHWEST, - 6 => \pocketmine\block\utils\MushroomBlockType::CAP_SOUTH, - 7 => \pocketmine\block\utils\MushroomBlockType::CAP_SOUTHEAST, - 8 => \pocketmine\block\utils\MushroomBlockType::CAP_SOUTHWEST, - 9 => \pocketmine\block\utils\MushroomBlockType::CAP_WEST, - 10 => \pocketmine\block\utils\MushroomBlockType::PORES, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for MushroomBlockType") - }; - } - - public function potionType(\pocketmine\item\PotionType &$value) : void{ - $value = match($this->readInt(6)){ - 0 => \pocketmine\item\PotionType::AWKWARD, - 1 => \pocketmine\item\PotionType::FIRE_RESISTANCE, - 2 => \pocketmine\item\PotionType::HARMING, - 3 => \pocketmine\item\PotionType::HEALING, - 4 => \pocketmine\item\PotionType::INVISIBILITY, - 5 => \pocketmine\item\PotionType::LEAPING, - 6 => \pocketmine\item\PotionType::LONG_FIRE_RESISTANCE, - 7 => \pocketmine\item\PotionType::LONG_INVISIBILITY, - 8 => \pocketmine\item\PotionType::LONG_LEAPING, - 9 => \pocketmine\item\PotionType::LONG_MUNDANE, - 10 => \pocketmine\item\PotionType::LONG_NIGHT_VISION, - 11 => \pocketmine\item\PotionType::LONG_POISON, - 12 => \pocketmine\item\PotionType::LONG_REGENERATION, - 13 => \pocketmine\item\PotionType::LONG_SLOWNESS, - 14 => \pocketmine\item\PotionType::LONG_SLOW_FALLING, - 15 => \pocketmine\item\PotionType::LONG_STRENGTH, - 16 => \pocketmine\item\PotionType::LONG_SWIFTNESS, - 17 => \pocketmine\item\PotionType::LONG_TURTLE_MASTER, - 18 => \pocketmine\item\PotionType::LONG_WATER_BREATHING, - 19 => \pocketmine\item\PotionType::LONG_WEAKNESS, - 20 => \pocketmine\item\PotionType::MUNDANE, - 21 => \pocketmine\item\PotionType::NIGHT_VISION, - 22 => \pocketmine\item\PotionType::POISON, - 23 => \pocketmine\item\PotionType::REGENERATION, - 24 => \pocketmine\item\PotionType::SLOWNESS, - 25 => \pocketmine\item\PotionType::SLOW_FALLING, - 26 => \pocketmine\item\PotionType::STRENGTH, - 27 => \pocketmine\item\PotionType::STRONG_HARMING, - 28 => \pocketmine\item\PotionType::STRONG_HEALING, - 29 => \pocketmine\item\PotionType::STRONG_LEAPING, - 30 => \pocketmine\item\PotionType::STRONG_POISON, - 31 => \pocketmine\item\PotionType::STRONG_REGENERATION, - 32 => \pocketmine\item\PotionType::STRONG_SLOWNESS, - 33 => \pocketmine\item\PotionType::STRONG_STRENGTH, - 34 => \pocketmine\item\PotionType::STRONG_SWIFTNESS, - 35 => \pocketmine\item\PotionType::STRONG_TURTLE_MASTER, - 36 => \pocketmine\item\PotionType::SWIFTNESS, - 37 => \pocketmine\item\PotionType::THICK, - 38 => \pocketmine\item\PotionType::TURTLE_MASTER, - 39 => \pocketmine\item\PotionType::WATER, - 40 => \pocketmine\item\PotionType::WATER_BREATHING, - 41 => \pocketmine\item\PotionType::WEAKNESS, - 42 => \pocketmine\item\PotionType::WITHER, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for PotionType") - }; - } - - public function slabType(\pocketmine\block\utils\SlabType &$value) : void{ - $value = match($this->readInt(2)){ - 0 => \pocketmine\block\utils\SlabType::BOTTOM, - 1 => \pocketmine\block\utils\SlabType::DOUBLE, - 2 => \pocketmine\block\utils\SlabType::TOP, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for SlabType") - }; - } - - public function suspiciousStewType(\pocketmine\item\SuspiciousStewType &$value) : void{ - $value = match($this->readInt(4)){ - 0 => \pocketmine\item\SuspiciousStewType::ALLIUM, - 1 => \pocketmine\item\SuspiciousStewType::AZURE_BLUET, - 2 => \pocketmine\item\SuspiciousStewType::BLUE_ORCHID, - 3 => \pocketmine\item\SuspiciousStewType::CORNFLOWER, - 4 => \pocketmine\item\SuspiciousStewType::DANDELION, - 5 => \pocketmine\item\SuspiciousStewType::LILY_OF_THE_VALLEY, - 6 => \pocketmine\item\SuspiciousStewType::OXEYE_DAISY, - 7 => \pocketmine\item\SuspiciousStewType::POPPY, - 8 => \pocketmine\item\SuspiciousStewType::TULIP, - 9 => \pocketmine\item\SuspiciousStewType::WITHER_ROSE, - default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for SuspiciousStewType") - }; - } - -} diff --git a/src/data/runtime/RuntimeEnumMetadata.php b/src/data/runtime/RuntimeEnumMetadata.php new file mode 100644 index 00000000000..261b7a1bc3e --- /dev/null +++ b/src/data/runtime/RuntimeEnumMetadata.php @@ -0,0 +1,114 @@ + + */ + private readonly array $intToEnum; + /** + * @var int[] + * @phpstan-var array + */ + private readonly array $enumToInt; + + /** + * @param \UnitEnum[] $members + * @phpstan-param list $members + */ + public function __construct( + array $members + ){ + usort($members, fn(\UnitEnum $a, \UnitEnum $b) => $a->name <=> $b->name); //sort by name to ensure consistent ordering (and thus consistent bit assignments) + + $this->bits = (int) ceil(log(count($members), 2)); + $this->intToEnum = array_values($members); + + $reversed = []; + foreach($this->intToEnum as $int => $enum){ + $reversed[spl_object_id($enum)] = $int; + } + + $this->enumToInt = $reversed; + } + + /** + * @phpstan-return T|null + */ + public function intToEnum(int $value) : ?object{ + return $this->intToEnum[$value] ?? null; + } + + /** + * @phpstan-param T $enum + */ + public function enumToInt(object $enum) : int{ + return $this->enumToInt[spl_object_id($enum)]; + } + + /** + * @var self[] + * @phpstan-var array + */ + private static array $cache = []; + + /** + * @phpstan-template TEnum of \UnitEnum + * @phpstan-param TEnum $case + * + * @phpstan-return self + */ + public static function from(\UnitEnum $case) : self{ + $class = $case::class; + /** @phpstan-var self|null $metadata */ + $metadata = self::$cache[$class] ?? null; + if($metadata === null){ + /** + * PHPStan can't infer this correctly :( https://github.com/phpstan/phpstan/issues/7162 + * @phpstan-var list $cases + */ + $cases = $case::cases(); + self::$cache[$class] = $metadata = new self($cases); + } + + return $metadata; + } +} diff --git a/src/data/runtime/RuntimeEnumSerializerTrait.php b/src/data/runtime/RuntimeEnumSerializerTrait.php deleted file mode 100644 index 12a205a9ec1..00000000000 --- a/src/data/runtime/RuntimeEnumSerializerTrait.php +++ /dev/null @@ -1,243 +0,0 @@ -writeInt(2, match($value){ - \pocketmine\block\utils\BellAttachmentType::CEILING => 0, - \pocketmine\block\utils\BellAttachmentType::FLOOR => 1, - \pocketmine\block\utils\BellAttachmentType::ONE_WALL => 2, - \pocketmine\block\utils\BellAttachmentType::TWO_WALLS => 3, - default => throw new \pocketmine\utils\AssumptionFailedError("All BellAttachmentType cases should be covered") - }); - } - - public function copperOxidation(\pocketmine\block\utils\CopperOxidation &$value) : void{ - $this->writeInt(2, match($value){ - \pocketmine\block\utils\CopperOxidation::EXPOSED => 0, - \pocketmine\block\utils\CopperOxidation::NONE => 1, - \pocketmine\block\utils\CopperOxidation::OXIDIZED => 2, - \pocketmine\block\utils\CopperOxidation::WEATHERED => 3, - default => throw new \pocketmine\utils\AssumptionFailedError("All CopperOxidation cases should be covered") - }); - } - - public function coralType(\pocketmine\block\utils\CoralType &$value) : void{ - $this->writeInt(3, match($value){ - \pocketmine\block\utils\CoralType::BRAIN => 0, - \pocketmine\block\utils\CoralType::BUBBLE => 1, - \pocketmine\block\utils\CoralType::FIRE => 2, - \pocketmine\block\utils\CoralType::HORN => 3, - \pocketmine\block\utils\CoralType::TUBE => 4, - default => throw new \pocketmine\utils\AssumptionFailedError("All CoralType cases should be covered") - }); - } - - public function dirtType(\pocketmine\block\utils\DirtType &$value) : void{ - $this->writeInt(2, match($value){ - \pocketmine\block\utils\DirtType::COARSE => 0, - \pocketmine\block\utils\DirtType::NORMAL => 1, - \pocketmine\block\utils\DirtType::ROOTED => 2, - default => throw new \pocketmine\utils\AssumptionFailedError("All DirtType cases should be covered") - }); - } - - public function dripleafState(\pocketmine\block\utils\DripleafState &$value) : void{ - $this->writeInt(2, match($value){ - \pocketmine\block\utils\DripleafState::FULL_TILT => 0, - \pocketmine\block\utils\DripleafState::PARTIAL_TILT => 1, - \pocketmine\block\utils\DripleafState::STABLE => 2, - \pocketmine\block\utils\DripleafState::UNSTABLE => 3, - default => throw new \pocketmine\utils\AssumptionFailedError("All DripleafState cases should be covered") - }); - } - - public function dyeColor(\pocketmine\block\utils\DyeColor &$value) : void{ - $this->writeInt(4, match($value){ - \pocketmine\block\utils\DyeColor::BLACK => 0, - \pocketmine\block\utils\DyeColor::BLUE => 1, - \pocketmine\block\utils\DyeColor::BROWN => 2, - \pocketmine\block\utils\DyeColor::CYAN => 3, - \pocketmine\block\utils\DyeColor::GRAY => 4, - \pocketmine\block\utils\DyeColor::GREEN => 5, - \pocketmine\block\utils\DyeColor::LIGHT_BLUE => 6, - \pocketmine\block\utils\DyeColor::LIGHT_GRAY => 7, - \pocketmine\block\utils\DyeColor::LIME => 8, - \pocketmine\block\utils\DyeColor::MAGENTA => 9, - \pocketmine\block\utils\DyeColor::ORANGE => 10, - \pocketmine\block\utils\DyeColor::PINK => 11, - \pocketmine\block\utils\DyeColor::PURPLE => 12, - \pocketmine\block\utils\DyeColor::RED => 13, - \pocketmine\block\utils\DyeColor::WHITE => 14, - \pocketmine\block\utils\DyeColor::YELLOW => 15, - default => throw new \pocketmine\utils\AssumptionFailedError("All DyeColor cases should be covered") - }); - } - - public function froglightType(\pocketmine\block\utils\FroglightType &$value) : void{ - $this->writeInt(2, match($value){ - \pocketmine\block\utils\FroglightType::OCHRE => 0, - \pocketmine\block\utils\FroglightType::PEARLESCENT => 1, - \pocketmine\block\utils\FroglightType::VERDANT => 2, - default => throw new \pocketmine\utils\AssumptionFailedError("All FroglightType cases should be covered") - }); - } - - public function leverFacing(\pocketmine\block\utils\LeverFacing &$value) : void{ - $this->writeInt(3, match($value){ - \pocketmine\block\utils\LeverFacing::DOWN_AXIS_X => 0, - \pocketmine\block\utils\LeverFacing::DOWN_AXIS_Z => 1, - \pocketmine\block\utils\LeverFacing::EAST => 2, - \pocketmine\block\utils\LeverFacing::NORTH => 3, - \pocketmine\block\utils\LeverFacing::SOUTH => 4, - \pocketmine\block\utils\LeverFacing::UP_AXIS_X => 5, - \pocketmine\block\utils\LeverFacing::UP_AXIS_Z => 6, - \pocketmine\block\utils\LeverFacing::WEST => 7, - default => throw new \pocketmine\utils\AssumptionFailedError("All LeverFacing cases should be covered") - }); - } - - public function medicineType(\pocketmine\item\MedicineType &$value) : void{ - $this->writeInt(2, match($value){ - \pocketmine\item\MedicineType::ANTIDOTE => 0, - \pocketmine\item\MedicineType::ELIXIR => 1, - \pocketmine\item\MedicineType::EYE_DROPS => 2, - \pocketmine\item\MedicineType::TONIC => 3, - default => throw new \pocketmine\utils\AssumptionFailedError("All MedicineType cases should be covered") - }); - } - - public function mobHeadType(\pocketmine\block\utils\MobHeadType &$value) : void{ - $this->writeInt(3, match($value){ - \pocketmine\block\utils\MobHeadType::CREEPER => 0, - \pocketmine\block\utils\MobHeadType::DRAGON => 1, - \pocketmine\block\utils\MobHeadType::PIGLIN => 2, - \pocketmine\block\utils\MobHeadType::PLAYER => 3, - \pocketmine\block\utils\MobHeadType::SKELETON => 4, - \pocketmine\block\utils\MobHeadType::WITHER_SKELETON => 5, - \pocketmine\block\utils\MobHeadType::ZOMBIE => 6, - default => throw new \pocketmine\utils\AssumptionFailedError("All MobHeadType cases should be covered") - }); - } - - public function mushroomBlockType(\pocketmine\block\utils\MushroomBlockType &$value) : void{ - $this->writeInt(4, match($value){ - \pocketmine\block\utils\MushroomBlockType::ALL_CAP => 0, - \pocketmine\block\utils\MushroomBlockType::CAP_EAST => 1, - \pocketmine\block\utils\MushroomBlockType::CAP_MIDDLE => 2, - \pocketmine\block\utils\MushroomBlockType::CAP_NORTH => 3, - \pocketmine\block\utils\MushroomBlockType::CAP_NORTHEAST => 4, - \pocketmine\block\utils\MushroomBlockType::CAP_NORTHWEST => 5, - \pocketmine\block\utils\MushroomBlockType::CAP_SOUTH => 6, - \pocketmine\block\utils\MushroomBlockType::CAP_SOUTHEAST => 7, - \pocketmine\block\utils\MushroomBlockType::CAP_SOUTHWEST => 8, - \pocketmine\block\utils\MushroomBlockType::CAP_WEST => 9, - \pocketmine\block\utils\MushroomBlockType::PORES => 10, - default => throw new \pocketmine\utils\AssumptionFailedError("All MushroomBlockType cases should be covered") - }); - } - - public function potionType(\pocketmine\item\PotionType &$value) : void{ - $this->writeInt(6, match($value){ - \pocketmine\item\PotionType::AWKWARD => 0, - \pocketmine\item\PotionType::FIRE_RESISTANCE => 1, - \pocketmine\item\PotionType::HARMING => 2, - \pocketmine\item\PotionType::HEALING => 3, - \pocketmine\item\PotionType::INVISIBILITY => 4, - \pocketmine\item\PotionType::LEAPING => 5, - \pocketmine\item\PotionType::LONG_FIRE_RESISTANCE => 6, - \pocketmine\item\PotionType::LONG_INVISIBILITY => 7, - \pocketmine\item\PotionType::LONG_LEAPING => 8, - \pocketmine\item\PotionType::LONG_MUNDANE => 9, - \pocketmine\item\PotionType::LONG_NIGHT_VISION => 10, - \pocketmine\item\PotionType::LONG_POISON => 11, - \pocketmine\item\PotionType::LONG_REGENERATION => 12, - \pocketmine\item\PotionType::LONG_SLOWNESS => 13, - \pocketmine\item\PotionType::LONG_SLOW_FALLING => 14, - \pocketmine\item\PotionType::LONG_STRENGTH => 15, - \pocketmine\item\PotionType::LONG_SWIFTNESS => 16, - \pocketmine\item\PotionType::LONG_TURTLE_MASTER => 17, - \pocketmine\item\PotionType::LONG_WATER_BREATHING => 18, - \pocketmine\item\PotionType::LONG_WEAKNESS => 19, - \pocketmine\item\PotionType::MUNDANE => 20, - \pocketmine\item\PotionType::NIGHT_VISION => 21, - \pocketmine\item\PotionType::POISON => 22, - \pocketmine\item\PotionType::REGENERATION => 23, - \pocketmine\item\PotionType::SLOWNESS => 24, - \pocketmine\item\PotionType::SLOW_FALLING => 25, - \pocketmine\item\PotionType::STRENGTH => 26, - \pocketmine\item\PotionType::STRONG_HARMING => 27, - \pocketmine\item\PotionType::STRONG_HEALING => 28, - \pocketmine\item\PotionType::STRONG_LEAPING => 29, - \pocketmine\item\PotionType::STRONG_POISON => 30, - \pocketmine\item\PotionType::STRONG_REGENERATION => 31, - \pocketmine\item\PotionType::STRONG_SLOWNESS => 32, - \pocketmine\item\PotionType::STRONG_STRENGTH => 33, - \pocketmine\item\PotionType::STRONG_SWIFTNESS => 34, - \pocketmine\item\PotionType::STRONG_TURTLE_MASTER => 35, - \pocketmine\item\PotionType::SWIFTNESS => 36, - \pocketmine\item\PotionType::THICK => 37, - \pocketmine\item\PotionType::TURTLE_MASTER => 38, - \pocketmine\item\PotionType::WATER => 39, - \pocketmine\item\PotionType::WATER_BREATHING => 40, - \pocketmine\item\PotionType::WEAKNESS => 41, - \pocketmine\item\PotionType::WITHER => 42, - default => throw new \pocketmine\utils\AssumptionFailedError("All PotionType cases should be covered") - }); - } - - public function slabType(\pocketmine\block\utils\SlabType &$value) : void{ - $this->writeInt(2, match($value){ - \pocketmine\block\utils\SlabType::BOTTOM => 0, - \pocketmine\block\utils\SlabType::DOUBLE => 1, - \pocketmine\block\utils\SlabType::TOP => 2, - default => throw new \pocketmine\utils\AssumptionFailedError("All SlabType cases should be covered") - }); - } - - public function suspiciousStewType(\pocketmine\item\SuspiciousStewType &$value) : void{ - $this->writeInt(4, match($value){ - \pocketmine\item\SuspiciousStewType::ALLIUM => 0, - \pocketmine\item\SuspiciousStewType::AZURE_BLUET => 1, - \pocketmine\item\SuspiciousStewType::BLUE_ORCHID => 2, - \pocketmine\item\SuspiciousStewType::CORNFLOWER => 3, - \pocketmine\item\SuspiciousStewType::DANDELION => 4, - \pocketmine\item\SuspiciousStewType::LILY_OF_THE_VALLEY => 5, - \pocketmine\item\SuspiciousStewType::OXEYE_DAISY => 6, - \pocketmine\item\SuspiciousStewType::POPPY => 7, - \pocketmine\item\SuspiciousStewType::TULIP => 8, - \pocketmine\item\SuspiciousStewType::WITHER_ROSE => 9, - default => throw new \pocketmine\utils\AssumptionFailedError("All SuspiciousStewType cases should be covered") - }); - } - -} diff --git a/src/item/Banner.php b/src/item/Banner.php index db54e976663..2fc53f5ae60 100644 --- a/src/item/Banner.php +++ b/src/item/Banner.php @@ -58,7 +58,7 @@ public function setColor(DyeColor $color) : self{ } protected function describeState(RuntimeDataDescriber $w) : void{ - $w->dyeColor($this->color); + $w->enum($this->color); } /** diff --git a/src/item/Dye.php b/src/item/Dye.php index 6fd3f6dcb92..9fdfb96710b 100644 --- a/src/item/Dye.php +++ b/src/item/Dye.php @@ -30,7 +30,7 @@ class Dye extends Item{ private DyeColor $color = DyeColor::BLACK; protected function describeState(RuntimeDataDescriber $w) : void{ - $w->dyeColor($this->color); + $w->enum($this->color); } public function getColor() : DyeColor{ diff --git a/src/item/Medicine.php b/src/item/Medicine.php index 1df74841491..bd2f724649d 100644 --- a/src/item/Medicine.php +++ b/src/item/Medicine.php @@ -32,7 +32,7 @@ class Medicine extends Item implements ConsumableItem{ private MedicineType $medicineType = MedicineType::EYE_DROPS; protected function describeState(RuntimeDataDescriber $w) : void{ - $w->medicineType($this->medicineType); + $w->enum($this->medicineType); } public function getType() : MedicineType{ return $this->medicineType; } diff --git a/src/item/Potion.php b/src/item/Potion.php index 597430242a8..41b0f634a88 100644 --- a/src/item/Potion.php +++ b/src/item/Potion.php @@ -32,7 +32,7 @@ class Potion extends Item implements ConsumableItem{ private PotionType $potionType = PotionType::WATER; protected function describeState(RuntimeDataDescriber $w) : void{ - $w->potionType($this->potionType); + $w->enum($this->potionType); } public function getType() : PotionType{ return $this->potionType; } diff --git a/src/item/SplashPotion.php b/src/item/SplashPotion.php index 8c18fd54c0f..e1c9167ac34 100644 --- a/src/item/SplashPotion.php +++ b/src/item/SplashPotion.php @@ -34,7 +34,7 @@ class SplashPotion extends ProjectileItem{ private PotionType $potionType = PotionType::WATER; protected function describeState(RuntimeDataDescriber $w) : void{ - $w->potionType($this->potionType); + $w->enum($this->potionType); } public function getType() : PotionType{ return $this->potionType; } diff --git a/src/item/SuspiciousStew.php b/src/item/SuspiciousStew.php index 8d7c2ff3ac5..7d1d30cc091 100644 --- a/src/item/SuspiciousStew.php +++ b/src/item/SuspiciousStew.php @@ -30,7 +30,7 @@ class SuspiciousStew extends Food{ private SuspiciousStewType $suspiciousStewType = SuspiciousStewType::POPPY; protected function describeState(RuntimeDataDescriber $w) : void{ - $w->suspiciousStewType($this->suspiciousStewType); + $w->enum($this->suspiciousStewType); } public function getType() : SuspiciousStewType{ return $this->suspiciousStewType; }