diff --git a/src/block/Anvil.php b/src/block/Anvil.php index a859210fd..ef8ef3f62 100644 --- a/src/block/Anvil.php +++ b/src/block/Anvil.php @@ -54,7 +54,7 @@ class Anvil extends Transparent implements Fallable{ } protected function encodeType(RuntimeDataWriter $w) : void{ - $w->writeInt(2, $this->getDamage()); + $w->writeBoundedInt(2, self::UNDAMAGED, self::VERY_DAMAGED, $this->getDamage()); } public function getRequiredStateDataBits() : int{ return 2; } diff --git a/src/block/Bamboo.php b/src/block/Bamboo.php index eaf6c26db..c8be857b0 100644 --- a/src/block/Bamboo.php +++ b/src/block/Bamboo.php @@ -65,7 +65,7 @@ class Bamboo extends Transparent{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(2, $this->getLeafSize()); + $w->writeBoundedInt(2, self::NO_LEAVES, self::LARGE_LEAVES, $this->getLeafSize()); $w->writeBool($this->isThick()); $w->writeBool($this->isReady()); } diff --git a/src/block/Cactus.php b/src/block/Cactus.php index cc8c602bf..f1c4a5909 100644 --- a/src/block/Cactus.php +++ b/src/block/Cactus.php @@ -49,7 +49,7 @@ class Cactus extends Transparent{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(4, $this->age); + $w->writeBoundedInt(4, 0, self::MAX_AGE, $this->age); } public function getAge() : int{ return $this->age; } diff --git a/src/block/Cake.php b/src/block/Cake.php index cbb8f9389..d3841e9ef 100644 --- a/src/block/Cake.php +++ b/src/block/Cake.php @@ -48,7 +48,7 @@ class Cake extends Transparent implements FoodSource{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(3, $this->bites); + $w->writeBoundedInt(3, 0, self::MAX_BITES, $this->bites); } /** diff --git a/src/block/CocoaBlock.php b/src/block/CocoaBlock.php index 5056598c3..bc6b892ca 100644 --- a/src/block/CocoaBlock.php +++ b/src/block/CocoaBlock.php @@ -56,7 +56,7 @@ class CocoaBlock extends Transparent{ protected function encodeState(RuntimeDataWriter $w) : void{ $w->writeHorizontalFacing($this->facing); - $w->writeInt(2, $this->age); + $w->writeBoundedInt(2, 0, self::MAX_AGE, $this->age); } public function getAge() : int{ return $this->age; } diff --git a/src/block/Crops.php b/src/block/Crops.php index f916dfb7d..52242cfe4 100644 --- a/src/block/Crops.php +++ b/src/block/Crops.php @@ -46,7 +46,7 @@ abstract class Crops extends Flowable{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(3, $this->age); + $w->writeBoundedInt(3, 0, self::MAX_AGE, $this->age); } public function getAge() : int{ return $this->age; } diff --git a/src/block/DaylightSensor.php b/src/block/DaylightSensor.php index 8718b89c2..93ea4ce60 100644 --- a/src/block/DaylightSensor.php +++ b/src/block/DaylightSensor.php @@ -50,7 +50,7 @@ class DaylightSensor extends Transparent{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(4, $this->signalStrength); + $w->writeBoundedInt(4, 0, 15, $this->signalStrength); $w->writeBool($this->inverted); } diff --git a/src/block/Farmland.php b/src/block/Farmland.php index 989254bc9..9cbb55c93 100644 --- a/src/block/Farmland.php +++ b/src/block/Farmland.php @@ -45,7 +45,7 @@ class Farmland extends Transparent{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(3, $this->wetness); + $w->writeBoundedInt(3, 0, self::MAX_WETNESS, $this->wetness); } public function getWetness() : int{ return $this->wetness; } diff --git a/src/block/Fire.php b/src/block/Fire.php index 503dd1dc3..45546c720 100644 --- a/src/block/Fire.php +++ b/src/block/Fire.php @@ -47,7 +47,7 @@ class Fire extends BaseFire{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(4, $this->age); + $w->writeBoundedInt(4, 0, self::MAX_AGE, $this->age); } public function getAge() : int{ return $this->age; } diff --git a/src/block/FrostedIce.php b/src/block/FrostedIce.php index 60a42a4a5..8aba73644 100644 --- a/src/block/FrostedIce.php +++ b/src/block/FrostedIce.php @@ -40,7 +40,7 @@ class FrostedIce extends Ice{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(2, $this->age); + $w->writeBoundedInt(2, 0, self::MAX_AGE, $this->age); } public function getAge() : int{ return $this->age; } diff --git a/src/block/Light.php b/src/block/Light.php index b2d39fb9f..9313cb19f 100644 --- a/src/block/Light.php +++ b/src/block/Light.php @@ -42,7 +42,7 @@ final class Light extends Flowable{ } protected function encodeType(RuntimeDataWriter $w) : void{ - $w->writeInt(4, $this->level); + $w->writeBoundedInt(4, 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 93c8219f5..81f34e6f6 100644 --- a/src/block/Liquid.php +++ b/src/block/Liquid.php @@ -58,7 +58,7 @@ abstract class Liquid extends Transparent{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(3, $this->decay); + $w->writeBoundedInt(3, 0, self::MAX_DECAY, $this->decay); $w->writeBool($this->falling); $w->writeBool($this->still); } diff --git a/src/block/NetherWartPlant.php b/src/block/NetherWartPlant.php index d6c2287b1..13da176e7 100644 --- a/src/block/NetherWartPlant.php +++ b/src/block/NetherWartPlant.php @@ -45,7 +45,7 @@ class NetherWartPlant extends Flowable{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(2, $this->age); + $w->writeBoundedInt(2, 0, self::MAX_AGE, $this->age); } public function getAge() : int{ return $this->age; } diff --git a/src/block/RedstoneRepeater.php b/src/block/RedstoneRepeater.php index 3b77bb262..b680d52cc 100644 --- a/src/block/RedstoneRepeater.php +++ b/src/block/RedstoneRepeater.php @@ -48,13 +48,13 @@ class RedstoneRepeater extends Flowable{ protected function decodeState(RuntimeDataReader $r) : void{ $this->facing = $r->readHorizontalFacing(); - $this->delay = $r->readBoundedInt(2, self::MIN_DELAY - 1, self::MAX_DELAY - 1) + 1; + $this->delay = $r->readBoundedInt(2, self::MIN_DELAY, self::MAX_DELAY); $this->powered = $r->readBool(); } protected function encodeState(RuntimeDataWriter $w) : void{ $w->writeHorizontalFacing($this->facing); - $w->writeInt(2, $this->delay - 1); + $w->writeBoundedInt(2, self::MIN_DELAY, self::MAX_DELAY, $this->delay); $w->writeBool($this->powered); } diff --git a/src/block/SeaPickle.php b/src/block/SeaPickle.php index 4be3b89d7..d6e0f32a7 100644 --- a/src/block/SeaPickle.php +++ b/src/block/SeaPickle.php @@ -42,12 +42,12 @@ class SeaPickle extends Transparent{ public function getRequiredStateDataBits() : int{ return 3; } protected function decodeState(RuntimeDataReader $r) : void{ - $this->count = $r->readBoundedInt(2, self::MIN_COUNT - 1, self::MAX_COUNT - 1) + 1; + $this->count = $r->readBoundedInt(2, self::MIN_COUNT, self::MAX_COUNT); $this->underwater = $r->readBool(); } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(2, $this->count - 1); + $w->writeBoundedInt(2, self::MIN_COUNT, self::MAX_COUNT, $this->count); $w->writeBool($this->underwater); } diff --git a/src/block/SnowLayer.php b/src/block/SnowLayer.php index d629d4d04..f45afc9f9 100644 --- a/src/block/SnowLayer.php +++ b/src/block/SnowLayer.php @@ -50,11 +50,11 @@ class SnowLayer extends Flowable implements Fallable{ public function getRequiredStateDataBits() : int{ return 3; } protected function decodeState(RuntimeDataReader $r) : void{ - $this->layers = $r->readBoundedInt(3, self::MIN_LAYERS - 1, self::MAX_LAYERS - 1) + 1; + $this->layers = $r->readBoundedInt(3, self::MIN_LAYERS, self::MAX_LAYERS); } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(3, $this->layers - 1); + $w->writeBoundedInt(3, self::MIN_LAYERS, self::MAX_LAYERS, $this->layers); } public function getLayers() : int{ return $this->layers; } diff --git a/src/block/Sugarcane.php b/src/block/Sugarcane.php index f91f13a5e..6985cd487 100644 --- a/src/block/Sugarcane.php +++ b/src/block/Sugarcane.php @@ -45,7 +45,7 @@ class Sugarcane extends Flowable{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(4, $this->age); + $w->writeBoundedInt(4, 0, self::MAX_AGE, $this->age); } private function grow() : bool{ diff --git a/src/block/SweetBerryBush.php b/src/block/SweetBerryBush.php index 54e785664..1fa1e180c 100644 --- a/src/block/SweetBerryBush.php +++ b/src/block/SweetBerryBush.php @@ -53,7 +53,7 @@ class SweetBerryBush extends Flowable{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(3, $this->age); + $w->writeBoundedInt(3, self::STAGE_SAPLING, self::STAGE_MATURE, $this->age); } public function getAge() : int{ return $this->age; } diff --git a/src/block/utils/AnalogRedstoneSignalEmitterTrait.php b/src/block/utils/AnalogRedstoneSignalEmitterTrait.php index 22d266aa7..1b9f5b26b 100644 --- a/src/block/utils/AnalogRedstoneSignalEmitterTrait.php +++ b/src/block/utils/AnalogRedstoneSignalEmitterTrait.php @@ -36,7 +36,7 @@ trait AnalogRedstoneSignalEmitterTrait{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(4, $this->signalStrength); + $w->writeBoundedInt(4, 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 e5773dbbd..96d0b9ef6 100644 --- a/src/block/utils/SignLikeRotationTrait.php +++ b/src/block/utils/SignLikeRotationTrait.php @@ -38,7 +38,7 @@ trait SignLikeRotationTrait{ } protected function encodeState(RuntimeDataWriter $w) : void{ - $w->writeInt(4, $this->rotation); + $w->writeBoundedInt(4, 0, 15, $this->rotation); } public function getRotation() : int{ return $this->rotation; } diff --git a/src/data/runtime/RuntimeDataReader.php b/src/data/runtime/RuntimeDataReader.php index 46c59cb27..a5bcc72cf 100644 --- a/src/data/runtime/RuntimeDataReader.php +++ b/src/data/runtime/RuntimeDataReader.php @@ -49,7 +49,7 @@ final class RuntimeDataReader{ } public function readBoundedInt(int $bits, int $min, int $max) : int{ - $result = $this->readInt($bits); + $result = $this->readInt($bits) + $min; if($result < $min || $result > $max){ throw new InvalidSerializedRuntimeDataException("Value is outside the range $min - $max"); } diff --git a/src/data/runtime/RuntimeDataWriter.php b/src/data/runtime/RuntimeDataWriter.php index c00759237..c10de5cea 100644 --- a/src/data/runtime/RuntimeDataWriter.php +++ b/src/data/runtime/RuntimeDataWriter.php @@ -52,6 +52,15 @@ final class RuntimeDataWriter{ return $this; } + /** @param int $bits *@return $this */ + public function writeBoundedInt(int $bits, int $min, int $max, int $value) : self{ + if($value < $min || $value > $max){ + throw new \InvalidArgumentException("Value $value is outside the range $min - $max"); + } + $this->writeInt($bits, $value - $min); + return $this; + } + /** @return $this */ public function writeBool(bool $value) : self{ return $this->writeInt(1, $value ? 1 : 0); @@ -104,7 +113,7 @@ final class RuntimeDataWriter{ public function writeWallConnections(array $connections) : self{ //TODO: we can pack this into 7 bits instead of 8 foreach(Facing::HORIZONTAL as $facing){ - $this->writeInt(2, match($connections[$facing] ?? null){ + $this->writeBoundedInt(2, 0, 2, match($connections[$facing] ?? null){ null => 0, WallConnectionType::SHORT() => 1, WallConnectionType::TALL() => 2,