From d0d16cdeb73656b5ed1c46e0246f3b3fa7f4e29d Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Tue, 17 Oct 2023 12:03:43 +0100 Subject: [PATCH] RuntimeDataDescriber: Introduce boundedIntAuto, replacing boundedInt closes #6096 boundedIntAuto automatically calculates the correct number of bits to use based on the given bounds. The bounds must be constant, of course. --- src/block/AmethystCluster.php | 2 +- src/block/Anvil.php | 2 +- src/block/Bamboo.php | 2 +- src/block/Cake.php | 2 +- src/block/Candle.php | 2 +- src/block/CaveVines.php | 2 +- src/block/CocoaBlock.php | 2 +- src/block/DaylightSensor.php | 2 +- src/block/Farmland.php | 2 +- src/block/FillableCauldron.php | 2 +- src/block/Light.php | 2 +- src/block/Liquid.php | 2 +- src/block/PinkPetals.php | 2 +- src/block/RedstoneRepeater.php | 2 +- src/block/SeaPickle.php | 2 +- src/block/SnowLayer.php | 2 +- src/block/utils/AgeableTrait.php | 3 +-- .../AnalogRedstoneSignalEmitterTrait.php | 2 +- src/block/utils/SignLikeRotationTrait.php | 2 +- src/data/runtime/RuntimeDataDescriber.php | 9 ++++++++ src/data/runtime/RuntimeDataReader.php | 22 +++++++++++++++---- .../runtime/RuntimeDataSizeCalculator.php | 15 ++++++++++++- src/data/runtime/RuntimeDataWriter.php | 22 +++++++++++++++---- 23 files changed, 78 insertions(+), 29 deletions(-) diff --git a/src/block/AmethystCluster.php b/src/block/AmethystCluster.php index 5e23d4463..639490456 100644 --- a/src/block/AmethystCluster.php +++ b/src/block/AmethystCluster.php @@ -50,7 +50,7 @@ final class AmethystCluster extends Transparent{ private int $stage = self::STAGE_CLUSTER; public function describeBlockItemState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(2, self::STAGE_SMALL_BUD, self::STAGE_CLUSTER, $this->stage); + $w->boundedIntAuto(self::STAGE_SMALL_BUD, self::STAGE_CLUSTER, $this->stage); } public function getStage() : int{ return $this->stage; } diff --git a/src/block/Anvil.php b/src/block/Anvil.php index b4677e075..916c390ef 100644 --- a/src/block/Anvil.php +++ b/src/block/Anvil.php @@ -52,7 +52,7 @@ class Anvil extends Transparent implements Fallable{ private int $damage = self::UNDAMAGED; public function describeBlockItemState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(2, self::UNDAMAGED, self::VERY_DAMAGED, $this->damage); + $w->boundedIntAuto(self::UNDAMAGED, self::VERY_DAMAGED, $this->damage); } protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ diff --git a/src/block/Bamboo.php b/src/block/Bamboo.php index 255cd2857..5df71f696 100644 --- a/src/block/Bamboo.php +++ b/src/block/Bamboo.php @@ -58,7 +58,7 @@ class Bamboo extends Transparent{ protected int $leafSize = self::NO_LEAVES; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(2, self::NO_LEAVES, self::LARGE_LEAVES, $this->leafSize); + $w->boundedIntAuto(self::NO_LEAVES, self::LARGE_LEAVES, $this->leafSize); $w->bool($this->thick); $w->bool($this->ready); } diff --git a/src/block/Cake.php b/src/block/Cake.php index 5d4e3cfca..073fc62ac 100644 --- a/src/block/Cake.php +++ b/src/block/Cake.php @@ -37,7 +37,7 @@ class Cake extends BaseCake{ protected int $bites = 0; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(3, 0, self::MAX_BITES, $this->bites); + $w->boundedIntAuto(0, self::MAX_BITES, $this->bites); } /** diff --git a/src/block/Candle.php b/src/block/Candle.php index afcf5bb45..7f22641e1 100644 --- a/src/block/Candle.php +++ b/src/block/Candle.php @@ -48,7 +48,7 @@ class Candle extends Transparent{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ $this->encodeLitState($w); - $w->boundedInt(2, self::MIN_COUNT, self::MAX_COUNT, $this->count); + $w->boundedIntAuto(self::MIN_COUNT, self::MAX_COUNT, $this->count); } public function getCount() : int{ return $this->count; } diff --git a/src/block/CaveVines.php b/src/block/CaveVines.php index bc42a6788..daa973507 100644 --- a/src/block/CaveVines.php +++ b/src/block/CaveVines.php @@ -49,7 +49,7 @@ class CaveVines extends Flowable{ protected bool $head = false; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(5, 0, self::MAX_AGE, $this->age); + $w->boundedIntAuto(0, self::MAX_AGE, $this->age); $w->bool($this->berries); $w->bool($this->head); } diff --git a/src/block/CocoaBlock.php b/src/block/CocoaBlock.php index 25c53b23a..5cec4b933 100644 --- a/src/block/CocoaBlock.php +++ b/src/block/CocoaBlock.php @@ -48,7 +48,7 @@ class CocoaBlock extends Transparent{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ $w->horizontalFacing($this->facing); - $w->boundedInt(2, 0, self::MAX_AGE, $this->age); + $w->boundedIntAuto(0, self::MAX_AGE, $this->age); } /** diff --git a/src/block/DaylightSensor.php b/src/block/DaylightSensor.php index 0c0ec8820..4141a2b7e 100644 --- a/src/block/DaylightSensor.php +++ b/src/block/DaylightSensor.php @@ -42,7 +42,7 @@ class DaylightSensor extends Transparent{ protected bool $inverted = false; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(4, 0, 15, $this->signalStrength); + $w->boundedIntAuto(0, 15, $this->signalStrength); $w->bool($this->inverted); } diff --git a/src/block/Farmland.php b/src/block/Farmland.php index 2dd795eec..70a6eeba7 100644 --- a/src/block/Farmland.php +++ b/src/block/Farmland.php @@ -39,7 +39,7 @@ class Farmland extends Transparent{ protected int $wetness = 0; //"moisture" blockstate property in PC protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(3, 0, self::MAX_WETNESS, $this->wetness); + $w->boundedIntAuto(0, self::MAX_WETNESS, $this->wetness); } public function getWetness() : int{ return $this->wetness; } diff --git a/src/block/FillableCauldron.php b/src/block/FillableCauldron.php index 6c9b2940b..ceef35299 100644 --- a/src/block/FillableCauldron.php +++ b/src/block/FillableCauldron.php @@ -38,7 +38,7 @@ abstract class FillableCauldron extends Transparent{ private int $fillLevel = self::MIN_FILL_LEVEL; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(3, self::MIN_FILL_LEVEL, self::MAX_FILL_LEVEL, $this->fillLevel); + $w->boundedIntAuto(self::MIN_FILL_LEVEL, self::MAX_FILL_LEVEL, $this->fillLevel); } public function getFillLevel() : int{ return $this->fillLevel; } diff --git a/src/block/Light.php b/src/block/Light.php index 239e1c048..29a3a8dfc 100644 --- a/src/block/Light.php +++ b/src/block/Light.php @@ -35,7 +35,7 @@ final class Light extends Flowable{ private int $level = self::MAX_LIGHT_LEVEL; public function describeBlockItemState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(4, self::MIN_LIGHT_LEVEL, self::MAX_LIGHT_LEVEL, $this->level); + $w->boundedIntAuto(self::MIN_LIGHT_LEVEL, self::MAX_LIGHT_LEVEL, $this->level); } public function getLightLevel() : int{ return $this->level; } diff --git a/src/block/Liquid.php b/src/block/Liquid.php index 2299f7d71..9a9e49af4 100644 --- a/src/block/Liquid.php +++ b/src/block/Liquid.php @@ -49,7 +49,7 @@ abstract class Liquid extends Transparent{ protected bool $still = false; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(3, 0, self::MAX_DECAY, $this->decay); + $w->boundedIntAuto(0, self::MAX_DECAY, $this->decay); $w->bool($this->falling); $w->bool($this->still); } diff --git a/src/block/PinkPetals.php b/src/block/PinkPetals.php index 5f1130206..872798df0 100644 --- a/src/block/PinkPetals.php +++ b/src/block/PinkPetals.php @@ -47,7 +47,7 @@ class PinkPetals extends Flowable{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ $w->horizontalFacing($this->facing); - $w->boundedInt(2, self::MIN_COUNT, self::MAX_COUNT, $this->count); + $w->boundedIntAuto(self::MIN_COUNT, self::MAX_COUNT, $this->count); } public function getCount() : int{ diff --git a/src/block/RedstoneRepeater.php b/src/block/RedstoneRepeater.php index 1306456d4..7e6e73da8 100644 --- a/src/block/RedstoneRepeater.php +++ b/src/block/RedstoneRepeater.php @@ -47,7 +47,7 @@ class RedstoneRepeater extends Flowable{ protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ $w->horizontalFacing($this->facing); - $w->boundedInt(2, self::MIN_DELAY, self::MAX_DELAY, $this->delay); + $w->boundedIntAuto(self::MIN_DELAY, self::MAX_DELAY, $this->delay); $w->bool($this->powered); } diff --git a/src/block/SeaPickle.php b/src/block/SeaPickle.php index 62662f9cf..627af9bac 100644 --- a/src/block/SeaPickle.php +++ b/src/block/SeaPickle.php @@ -39,7 +39,7 @@ class SeaPickle extends Transparent{ protected bool $underwater = false; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(2, self::MIN_COUNT, self::MAX_COUNT, $this->count); + $w->boundedIntAuto(self::MIN_COUNT, self::MAX_COUNT, $this->count); $w->bool($this->underwater); } diff --git a/src/block/SnowLayer.php b/src/block/SnowLayer.php index fd7258d91..cca8424a9 100644 --- a/src/block/SnowLayer.php +++ b/src/block/SnowLayer.php @@ -47,7 +47,7 @@ class SnowLayer extends Flowable implements Fallable{ protected int $layers = self::MIN_LAYERS; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(3, self::MIN_LAYERS, self::MAX_LAYERS, $this->layers); + $w->boundedIntAuto(self::MIN_LAYERS, self::MAX_LAYERS, $this->layers); } public function getLayers() : int{ return $this->layers; } diff --git a/src/block/utils/AgeableTrait.php b/src/block/utils/AgeableTrait.php index 8e2793e81..dc1369c87 100644 --- a/src/block/utils/AgeableTrait.php +++ b/src/block/utils/AgeableTrait.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace pocketmine\block\utils; use pocketmine\data\runtime\RuntimeDataDescriber; -use function log; /** * This trait is used for blocks that have an age property. @@ -34,7 +33,7 @@ trait AgeableTrait{ protected int $age = 0; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(((int) log(self::MAX_AGE, 2)) + 1, 0, self::MAX_AGE, $this->age); + $w->boundedIntAuto(0, self::MAX_AGE, $this->age); } public function getAge() : int{ return $this->age; } diff --git a/src/block/utils/AnalogRedstoneSignalEmitterTrait.php b/src/block/utils/AnalogRedstoneSignalEmitterTrait.php index fe61f652c..4b8694643 100644 --- a/src/block/utils/AnalogRedstoneSignalEmitterTrait.php +++ b/src/block/utils/AnalogRedstoneSignalEmitterTrait.php @@ -29,7 +29,7 @@ trait AnalogRedstoneSignalEmitterTrait{ protected int $signalStrength = 0; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(4, 0, 15, $this->signalStrength); + $w->boundedIntAuto(0, 15, $this->signalStrength); } public function getOutputSignalStrength() : int{ return $this->signalStrength; } diff --git a/src/block/utils/SignLikeRotationTrait.php b/src/block/utils/SignLikeRotationTrait.php index 233c75095..36b2dce3f 100644 --- a/src/block/utils/SignLikeRotationTrait.php +++ b/src/block/utils/SignLikeRotationTrait.php @@ -31,7 +31,7 @@ trait SignLikeRotationTrait{ private $rotation = 0; protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ - $w->boundedInt(4, 0, 15, $this->rotation); + $w->boundedIntAuto(0, 15, $this->rotation); } public function getRotation() : int{ return $this->rotation; } diff --git a/src/data/runtime/RuntimeDataDescriber.php b/src/data/runtime/RuntimeDataDescriber.php index 8eba38a1d..04217f5df 100644 --- a/src/data/runtime/RuntimeDataDescriber.php +++ b/src/data/runtime/RuntimeDataDescriber.php @@ -38,8 +38,17 @@ use pocketmine\math\Facing; interface RuntimeDataDescriber extends RuntimeEnumDescriber{ public function int(int $bits, int &$value) : void; + /** + * @deprecated Use {@link RuntimeDataDescriber::boundedIntAuto()} instead. + */ public function boundedInt(int $bits, int $min, int $max, int &$value) : void; + /** + * Same as boundedInt() but automatically calculates the required number of bits from the range. + * The range bounds must be constant. + */ + public function boundedIntAuto(int $min, int $max, int &$value) : void; + public function bool(bool &$value) : void; public function horizontalFacing(int &$facing) : void; diff --git a/src/data/runtime/RuntimeDataReader.php b/src/data/runtime/RuntimeDataReader.php index e4ccc892d..84239f411 100644 --- a/src/data/runtime/RuntimeDataReader.php +++ b/src/data/runtime/RuntimeDataReader.php @@ -31,6 +31,7 @@ use pocketmine\math\Facing; use pocketmine\utils\AssumptionFailedError; use function get_class; use function intdiv; +use function log; use function spl_object_id; final class RuntimeDataReader implements RuntimeDataDescriber{ @@ -58,7 +59,20 @@ final class RuntimeDataReader implements RuntimeDataDescriber{ $value = $this->readInt($bits); } - protected function readBoundedInt(int $bits, int $min, int $max) : int{ + /** + * @deprecated Use {@link self::boundedIntAuto()} instead. + */ + public function boundedInt(int $bits, int $min, int $max, int &$value) : void{ + $offset = $this->offset; + $this->boundedIntAuto($min, $max, $value); + $actualBits = $this->offset - $offset; + if($this->offset !== $offset + $bits){ + throw new \InvalidArgumentException("Bits should be $actualBits for the given bounds, but received $bits. Use boundedIntAuto() for automatic bits calculation."); + } + } + + private function readBoundedIntAuto(int $min, int $max) : int{ + $bits = ((int) log($max - $min, 2)) + 1; $result = $this->readInt($bits) + $min; if($result < $min || $result > $max){ throw new InvalidSerializedRuntimeDataException("Value is outside the range $min - $max"); @@ -66,8 +80,8 @@ final class RuntimeDataReader implements RuntimeDataDescriber{ return $result; } - public function boundedInt(int $bits, int $min, int $max, int &$value) : void{ - $value = $this->readBoundedInt($bits, $min, $max); + public function boundedIntAuto(int $min, int $max, int &$value) : void{ + $value = $this->readBoundedIntAuto($min, $max); } protected function readBool() : bool{ @@ -162,7 +176,7 @@ final class RuntimeDataReader implements RuntimeDataDescriber{ public function wallConnections(array &$connections) : void{ $result = []; $offset = 0; - $packed = $this->readBoundedInt(7, 0, (3 ** 4) - 1); + $packed = $this->readBoundedIntAuto(0, (3 ** 4) - 1); foreach(Facing::HORIZONTAL as $facing){ $type = intdiv($packed, (3 ** $offset)) % 3; if($type !== 0){ diff --git a/src/data/runtime/RuntimeDataSizeCalculator.php b/src/data/runtime/RuntimeDataSizeCalculator.php index 28ddaa673..18c703cb8 100644 --- a/src/data/runtime/RuntimeDataSizeCalculator.php +++ b/src/data/runtime/RuntimeDataSizeCalculator.php @@ -26,6 +26,7 @@ namespace pocketmine\data\runtime; use pocketmine\block\utils\BrewingStandSlot; use pocketmine\math\Facing; use function count; +use function log; final class RuntimeDataSizeCalculator implements RuntimeDataDescriber{ use LegacyRuntimeEnumDescriberTrait; @@ -44,8 +45,20 @@ final class RuntimeDataSizeCalculator implements RuntimeDataDescriber{ $this->addBits($bits); } + /** + * @deprecated Use {@link self::boundedIntAuto()} instead. + */ public function boundedInt(int $bits, int $min, int $max, int &$value) : void{ - $this->addBits($bits); + $currentBits = $this->bits; + $this->boundedIntAuto($min, $max, $value); + $actualBits = $this->bits - $currentBits; + if($actualBits !== $bits){ + throw new \InvalidArgumentException("Bits should be $actualBits for the given bounds, but received $bits. Use boundedIntAuto() for automatic bits calculation."); + } + } + + public function boundedIntAuto(int $min, int $max, int &$value) : void{ + $this->addBits(((int) log($max - $min, 2)) + 1); } public function bool(bool &$value) : void{ diff --git a/src/data/runtime/RuntimeDataWriter.php b/src/data/runtime/RuntimeDataWriter.php index 5224b3417..0fbdd869f 100644 --- a/src/data/runtime/RuntimeDataWriter.php +++ b/src/data/runtime/RuntimeDataWriter.php @@ -28,6 +28,7 @@ use pocketmine\block\utils\WallConnectionType; use pocketmine\math\Axis; use pocketmine\math\Facing; use function array_flip; +use function log; use function spl_object_id; final class RuntimeDataWriter implements RuntimeDataDescriber{ @@ -56,15 +57,28 @@ final class RuntimeDataWriter implements RuntimeDataDescriber{ $this->writeInt($bits, $value); } - protected function writeBoundedInt(int $bits, int $min, int $max, int $value) : void{ + /** + * @deprecated Use {@link self::boundedIntAuto()} instead. + */ + public function boundedInt(int $bits, int $min, int $max, int &$value) : void{ + $offset = $this->offset; + $this->writeBoundedIntAuto($min, $max, $value); + $actualBits = $this->offset - $offset; + if($actualBits !== $bits){ + throw new \InvalidArgumentException("Bits should be $actualBits for the given bounds, but received $bits. Use boundedIntAuto() for automatic bits calculation."); + } + } + + private function writeBoundedIntAuto(int $min, int $max, int $value) : void{ if($value < $min || $value > $max){ throw new \InvalidArgumentException("Value $value is outside the range $min - $max"); } + $bits = ((int) log($max - $min, 2)) + 1; $this->writeInt($bits, $value - $min); } - public function boundedInt(int $bits, int $min, int $max, int &$value) : void{ - $this->writeBoundedInt($bits, $min, $max, $value); + public function boundedIntAuto(int $min, int $max, int &$value) : void{ + $this->writeBoundedIntAuto($min, $max, $value); } protected function writeBool(bool $value) : void{ @@ -153,7 +167,7 @@ final class RuntimeDataWriter implements RuntimeDataDescriber{ } * (3 ** $offset); $offset++; } - $this->writeBoundedInt(7, 0, (3 ** 4) - 1, $packed); + $this->writeBoundedIntAuto(0, (3 ** 4) - 1, $packed); } /**