diff --git a/src/network/mcpe/handler/PreSpawnPacketHandler.php b/src/network/mcpe/handler/PreSpawnPacketHandler.php index 007da0fb7..c4ee4c022 100644 --- a/src/network/mcpe/handler/PreSpawnPacketHandler.php +++ b/src/network/mcpe/handler/PreSpawnPacketHandler.php @@ -29,6 +29,7 @@ use pocketmine\network\mcpe\convert\TypeConverter; use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket; use pocketmine\network\mcpe\protocol\StartGamePacket; +use pocketmine\network\mcpe\protocol\types\BoolGameRule; use pocketmine\network\mcpe\protocol\types\DimensionIds; use pocketmine\network\mcpe\StaticPacketCache; use pocketmine\player\Player; @@ -76,6 +77,9 @@ class PreSpawnPacketHandler extends PacketHandler{ $pk->rainLevel = 0; //TODO: implement these properly $pk->lightningLevel = 0; $pk->commandsEnabled = true; + $pk->gameRules = [ + "naturalregeneration" => new BoolGameRule(false) //Hack for client side regeneration + ]; $pk->levelId = ""; $pk->worldName = $this->server->getMotd(); $pk->blockTable = RuntimeBlockMapping::getInstance()->getStartGamePaletteCache(); diff --git a/src/network/mcpe/protocol/GameRulesChangedPacket.php b/src/network/mcpe/protocol/GameRulesChangedPacket.php index d9647ea89..35aa036ba 100644 --- a/src/network/mcpe/protocol/GameRulesChangedPacket.php +++ b/src/network/mcpe/protocol/GameRulesChangedPacket.php @@ -26,13 +26,14 @@ namespace pocketmine\network\mcpe\protocol; #include use pocketmine\network\mcpe\protocol\serializer\PacketSerializer; +use pocketmine\network\mcpe\protocol\types\GameRule; class GameRulesChangedPacket extends DataPacket implements ClientboundPacket{ public const NETWORK_ID = ProtocolInfo::GAME_RULES_CHANGED_PACKET; /** - * @var mixed[][] - * @phpstan-var array + * @var GameRule[] + * @phpstan-var array */ public $gameRules = []; diff --git a/src/network/mcpe/protocol/StartGamePacket.php b/src/network/mcpe/protocol/StartGamePacket.php index 9e4911f21..809214dbb 100644 --- a/src/network/mcpe/protocol/StartGamePacket.php +++ b/src/network/mcpe/protocol/StartGamePacket.php @@ -30,7 +30,7 @@ use pocketmine\nbt\tag\ListTag; use pocketmine\network\mcpe\protocol\serializer\PacketSerializer; use pocketmine\network\mcpe\protocol\types\CacheableNbt; use pocketmine\network\mcpe\protocol\types\EducationEditionOffer; -use pocketmine\network\mcpe\protocol\types\GameRuleType; +use pocketmine\network\mcpe\protocol\types\GameRule; use pocketmine\network\mcpe\protocol\types\GeneratorType; use pocketmine\network\mcpe\protocol\types\MultiplayerGameVisibility; use pocketmine\network\mcpe\protocol\types\PlayerPermissions; @@ -97,12 +97,10 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{ /** @var bool */ public $isTexturePacksRequired = true; /** - * @var mixed[][] - * @phpstan-var array + * @var GameRule[] + * @phpstan-var array */ - public $gameRules = [ //TODO: implement this - "naturalregeneration" => [GameRuleType::BOOL, false] //Hack for client side regeneration - ]; + public $gameRules = []; /** @var bool */ public $hasBonusChestEnabled = false; /** @var bool */ diff --git a/src/network/mcpe/protocol/serializer/PacketSerializer.php b/src/network/mcpe/protocol/serializer/PacketSerializer.php index 5c40a4904..dc9bb2efe 100644 --- a/src/network/mcpe/protocol/serializer/PacketSerializer.php +++ b/src/network/mcpe/protocol/serializer/PacketSerializer.php @@ -30,6 +30,7 @@ use pocketmine\nbt\NbtDataException; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\TreeRoot; use pocketmine\network\mcpe\protocol\PacketDecodeException; +use pocketmine\network\mcpe\protocol\types\BoolGameRule; use pocketmine\network\mcpe\protocol\types\command\CommandOriginData; use pocketmine\network\mcpe\protocol\types\entity\Attribute; use pocketmine\network\mcpe\protocol\types\entity\BlockPosMetadataProperty; @@ -44,7 +45,10 @@ use pocketmine\network\mcpe\protocol\types\entity\ShortMetadataProperty; use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty; use pocketmine\network\mcpe\protocol\types\entity\Vec3MetadataProperty; use pocketmine\network\mcpe\protocol\types\FixedItemIds; +use pocketmine\network\mcpe\protocol\types\FloatGameRule; +use pocketmine\network\mcpe\protocol\types\GameRule; use pocketmine\network\mcpe\protocol\types\GameRuleType; +use pocketmine\network\mcpe\protocol\types\IntGameRule; use pocketmine\network\mcpe\protocol\types\inventory\ItemStack; use pocketmine\network\mcpe\protocol\types\PersonaPieceTintColor; use pocketmine\network\mcpe\protocol\types\PersonaSkinPiece; @@ -533,12 +537,21 @@ class PacketSerializer extends BinaryStream{ $this->putByte((int) ($rotation / (360 / 256))); } + private function readGameRule(int $type) : GameRule{ + switch($type){ + case GameRuleType::BOOL: return BoolGameRule::decode($this); + case GameRuleType::INT: return IntGameRule::decode($this); + case GameRuleType::FLOAT: return FloatGameRule::decode($this); + default: + throw new PacketDecodeException("Unknown gamerule type $type"); + } + } + /** * Reads gamerules - * TODO: implement this properly * - * @return mixed[][], members are in the structure [name => [type, value]] - * @phpstan-return array + * @return GameRule[] game rule name => value + * @phpstan-return array * * @throws PacketDecodeException * @throws BinaryDataException @@ -549,53 +562,24 @@ class PacketSerializer extends BinaryStream{ for($i = 0; $i < $count; ++$i){ $name = $this->getString(); $type = $this->getUnsignedVarInt(); - $value = null; - switch($type){ - case GameRuleType::BOOL: - $value = $this->getBool(); - break; - case GameRuleType::INT: - $value = $this->getUnsignedVarInt(); - break; - case GameRuleType::FLOAT: - $value = $this->getLFloat(); - break; - default: - throw new PacketDecodeException("Unknown gamerule type $type"); - } - - $rules[$name] = [$type, $value]; + $rules[$name] = $this->readGameRule($type); } return $rules; } /** - * Writes a gamerule array, members should be in the structure [name => [type, value]] - * TODO: implement this properly + * Writes a gamerule array * - * @param mixed[][] $rules - * - * @phpstan-param array $rules + * @param GameRule[] $rules + * @phpstan-param array $rules */ public function putGameRules(array $rules) : void{ $this->putUnsignedVarInt(count($rules)); foreach($rules as $name => $rule){ $this->putString($name); - $this->putUnsignedVarInt($rule[0]); - switch($rule[0]){ - case GameRuleType::BOOL: - $this->putBool($rule[1]); - break; - case GameRuleType::INT: - $this->putUnsignedVarInt($rule[1]); - break; - case GameRuleType::FLOAT: - $this->putLFloat($rule[1]); - break; - default: - throw new \InvalidArgumentException("Invalid gamerule type " . $rule[0]); - } + $this->putUnsignedVarInt($rule->getType()); + $rule->encode($this); } } diff --git a/src/network/mcpe/protocol/types/BoolGameRule.php b/src/network/mcpe/protocol/types/BoolGameRule.php new file mode 100644 index 000000000..c4fbe7290 --- /dev/null +++ b/src/network/mcpe/protocol/types/BoolGameRule.php @@ -0,0 +1,52 @@ +value = $value; + } + + public function getType() : int{ + return GameRuleType::BOOL; + } + + public function getValue() : bool{ + return $this->value; + } + + public function encode(PacketSerializer $out) : void{ + $out->putBool($this->value); + } + + public static function decode(PacketSerializer $in) : self{ + return new self($in->getBool()); + } +} diff --git a/src/network/mcpe/protocol/types/FloatGameRule.php b/src/network/mcpe/protocol/types/FloatGameRule.php new file mode 100644 index 000000000..d614d36a2 --- /dev/null +++ b/src/network/mcpe/protocol/types/FloatGameRule.php @@ -0,0 +1,51 @@ +value = $value; + } + + public function getType() : int{ + return GameRuleType::FLOAT; + } + + public function getValue() : float{ + return $this->value; + } + + public function encode(PacketSerializer $out) : void{ + $out->putLFloat($this->value); + } + + public static function decode(PacketSerializer $in) : self{ + return new self($in->getLFloat()); + } +} diff --git a/src/network/mcpe/protocol/types/GameRule.php b/src/network/mcpe/protocol/types/GameRule.php new file mode 100644 index 000000000..b578524a2 --- /dev/null +++ b/src/network/mcpe/protocol/types/GameRule.php @@ -0,0 +1,33 @@ +value = $value; + } + + public function getType() : int{ + return GameRuleType::INT; + } + + public function getValue() : int{ + return $this->value; + } + + public function encode(PacketSerializer $out) : void{ + $out->putUnsignedVarInt($this->value); + } + + public static function decode(PacketSerializer $in) : self{ + return new self($in->getUnsignedVarInt()); + } +} diff --git a/tests/phpstan/configs/l7-baseline.neon b/tests/phpstan/configs/l7-baseline.neon index da5dfc150..d371e9184 100644 --- a/tests/phpstan/configs/l7-baseline.neon +++ b/tests/phpstan/configs/l7-baseline.neon @@ -640,21 +640,6 @@ parameters: count: 1 path: ../../../src/network/mcpe/encryption/EncryptionUtils.php - - - message: "#^Parameter \\#1 \\$v of method pocketmine\\\\utils\\\\BinaryStream\\:\\:putBool\\(\\) expects bool, bool\\|float\\|int given\\.$#" - count: 1 - path: ../../../src/network/mcpe/protocol/serializer/PacketSerializer.php - - - - message: "#^Parameter \\#1 \\$v of method pocketmine\\\\utils\\\\BinaryStream\\:\\:putUnsignedVarInt\\(\\) expects int, bool\\|float\\|int given\\.$#" - count: 1 - path: ../../../src/network/mcpe/protocol/serializer/PacketSerializer.php - - - - message: "#^Parameter \\#1 \\$v of method pocketmine\\\\utils\\\\BinaryStream\\:\\:putLFloat\\(\\) expects float, bool\\|float\\|int given\\.$#" - count: 1 - path: ../../../src/network/mcpe/protocol/serializer/PacketSerializer.php - - message: "#^Parameter \\#1 \\$x of method pocketmine\\\\network\\\\mcpe\\\\protocol\\\\serializer\\\\PacketSerializer\\:\\:putSignedBlockPosition\\(\\) expects int, float\\|int given\\.$#" count: 1