From e8be6aa449d6a7395c35a0f9be6ab37e90b8d023 Mon Sep 17 00:00:00 2001 From: Dries C Date: Wed, 7 May 2025 00:31:26 +0200 Subject: [PATCH 1/9] Bedrock 1.21.80 support --- composer.json | 4 +- composer.lock | 31 +++++----- src/data/bedrock/BedrockDataFiles.php | 3 +- src/data/bedrock/block/BlockStateNames.php | 1 + src/data/bedrock/block/BlockTypeNames.php | 1 + src/data/bedrock/item/ItemTypeNames.php | 17 +++++ src/network/mcpe/cache/StaticPacketCache.php | 62 ++++++++++++++++++- .../mcpe/handler/InGamePacketHandler.php | 5 -- .../biome/model/BiomeDefinitionEntryData.php | 54 ++++++++++++++++ src/world/biome/model/ColorData.php | 41 ++++++++++++ tools/generate-bedrock-data-from-packets.php | 59 +++++++++--------- 11 files changed, 225 insertions(+), 53 deletions(-) create mode 100644 src/world/biome/model/BiomeDefinitionEntryData.php create mode 100644 src/world/biome/model/ColorData.php diff --git a/composer.json b/composer.json index 87086f456d4..ffb34705523 100644 --- a/composer.json +++ b/composer.json @@ -34,9 +34,9 @@ "adhocore/json-comment": "~1.2.0", "netresearch/jsonmapper": "~v5.0.0", "pocketmine/bedrock-block-upgrade-schema": "~5.1.0+bedrock-1.21.60", - "pocketmine/bedrock-data": "~4.1.0+bedrock-1.21.70", + "pocketmine/bedrock-data": "dev-feature/1.21.80", "pocketmine/bedrock-item-upgrade-schema": "~1.14.0+bedrock-1.21.50", - "pocketmine/bedrock-protocol": "~37.0.0+bedrock-1.21.70", + "pocketmine/bedrock-protocol": "dev-bedrock-1.21.80", "pocketmine/binaryutils": "^0.2.1", "pocketmine/callback-validator": "^1.0.2", "pocketmine/color": "^0.3.0", diff --git a/composer.lock b/composer.lock index 23f31231797..76760d2b6e0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "818c679a25da8e6b466bc454ad48dec3", + "content-hash": "3569b0323d32db1cbcd25e540d91044d", "packages": [ { "name": "adhocore/json-comment", @@ -204,16 +204,16 @@ }, { "name": "pocketmine/bedrock-data", - "version": "4.1.0+bedrock-1.21.70", + "version": "dev-feature/1.21.80", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockData.git", - "reference": "d53fe98cb3b596ac016e275df5bd5e89b04a4817" + "reference": "a5f1fc12aa8c7666267e003a66fc58633840e5d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockData/zipball/d53fe98cb3b596ac016e275df5bd5e89b04a4817", - "reference": "d53fe98cb3b596ac016e275df5bd5e89b04a4817", + "url": "https://api.github.com/repos/pmmp/BedrockData/zipball/a5f1fc12aa8c7666267e003a66fc58633840e5d0", + "reference": "a5f1fc12aa8c7666267e003a66fc58633840e5d0", "shasum": "" }, "type": "library", @@ -224,9 +224,9 @@ "description": "Blobs of data generated from Minecraft: Bedrock Edition, used by PocketMine-MP", "support": { "issues": "https://github.com/pmmp/BedrockData/issues", - "source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.21.70" + "source": "https://github.com/pmmp/BedrockData/tree/feature/1.21.80" }, - "time": "2025-03-25T19:43:31+00:00" + "time": "2025-05-06T22:25:16+00:00" }, { "name": "pocketmine/bedrock-item-upgrade-schema", @@ -256,16 +256,16 @@ }, { "name": "pocketmine/bedrock-protocol", - "version": "37.0.0+bedrock-1.21.70", + "version": "dev-bedrock-1.21.80", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockProtocol.git", - "reference": "7091dad2c12ed4a4106432df21fc698960c6be9e" + "reference": "39a5f0cbe57834aeba5a7550803191999039e3c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/7091dad2c12ed4a4106432df21fc698960c6be9e", - "reference": "7091dad2c12ed4a4106432df21fc698960c6be9e", + "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/39a5f0cbe57834aeba5a7550803191999039e3c6", + "reference": "39a5f0cbe57834aeba5a7550803191999039e3c6", "shasum": "" }, "require": { @@ -296,9 +296,9 @@ "description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP", "support": { "issues": "https://github.com/pmmp/BedrockProtocol/issues", - "source": "https://github.com/pmmp/BedrockProtocol/tree/37.0.0+bedrock-1.21.70" + "source": "https://github.com/pmmp/BedrockProtocol/tree/bedrock-1.21.80" }, - "time": "2025-03-27T15:19:36+00:00" + "time": "2025-05-06T20:30:40+00:00" }, { "name": "pocketmine/binaryutils", @@ -2921,7 +2921,10 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "pocketmine/bedrock-data": 20, + "pocketmine/bedrock-protocol": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/src/data/bedrock/BedrockDataFiles.php b/src/data/bedrock/BedrockDataFiles.php index 1ecb707cc5f..53bd9b11e05 100644 --- a/src/data/bedrock/BedrockDataFiles.php +++ b/src/data/bedrock/BedrockDataFiles.php @@ -31,8 +31,7 @@ private function __construct(){ } public const BANNER_PATTERNS_JSON = BEDROCK_DATA_PATH . '/banner_patterns.json'; - public const BIOME_DEFINITIONS_NBT = BEDROCK_DATA_PATH . '/biome_definitions.nbt'; - public const BIOME_DEFINITIONS_FULL_NBT = BEDROCK_DATA_PATH . '/biome_definitions_full.nbt'; + public const BIOME_DEFINITIONS_JSON = BEDROCK_DATA_PATH . '/biome_definitions.json'; public const BIOME_ID_MAP_JSON = BEDROCK_DATA_PATH . '/biome_id_map.json'; public const BLOCK_ID_TO_ITEM_ID_MAP_JSON = BEDROCK_DATA_PATH . '/block_id_to_item_id_map.json'; public const BLOCK_PROPERTIES_TABLE_JSON = BEDROCK_DATA_PATH . '/block_properties_table.json'; diff --git a/src/data/bedrock/block/BlockStateNames.php b/src/data/bedrock/block/BlockStateNames.php index 9fed77e4a30..704798d1d5b 100644 --- a/src/data/bedrock/block/BlockStateNames.php +++ b/src/data/bedrock/block/BlockStateNames.php @@ -113,6 +113,7 @@ private function __construct(){ public const RAIL_DATA_BIT = "rail_data_bit"; public const RAIL_DIRECTION = "rail_direction"; public const REDSTONE_SIGNAL = "redstone_signal"; + public const REHYDRATION_LEVEL = "rehydration_level"; public const REPEATER_DELAY = "repeater_delay"; public const RESPAWN_ANCHOR_CHARGE = "respawn_anchor_charge"; public const ROTATION = "rotation"; diff --git a/src/data/bedrock/block/BlockTypeNames.php b/src/data/bedrock/block/BlockTypeNames.php index bc30800fc83..527a01345e6 100644 --- a/src/data/bedrock/block/BlockTypeNames.php +++ b/src/data/bedrock/block/BlockTypeNames.php @@ -392,6 +392,7 @@ private function __construct(){ public const DOUBLE_CUT_COPPER_SLAB = "minecraft:double_cut_copper_slab"; public const DRAGON_EGG = "minecraft:dragon_egg"; public const DRAGON_HEAD = "minecraft:dragon_head"; + public const DRIED_GHAST = "minecraft:dried_ghast"; public const DRIED_KELP_BLOCK = "minecraft:dried_kelp_block"; public const DRIPSTONE_BLOCK = "minecraft:dripstone_block"; public const DROPPER = "minecraft:dropper"; diff --git a/src/data/bedrock/item/ItemTypeNames.php b/src/data/bedrock/item/ItemTypeNames.php index ea95d57f08e..5f86cde9666 100644 --- a/src/data/bedrock/item/ItemTypeNames.php +++ b/src/data/bedrock/item/ItemTypeNames.php @@ -68,6 +68,7 @@ final class ItemTypeNames{ public const BIRCH_SIGN = "minecraft:birch_sign"; public const BLACK_BUNDLE = "minecraft:black_bundle"; public const BLACK_DYE = "minecraft:black_dye"; + public const BLACK_HARNESS = "minecraft:black_harness"; public const BLADE_POTTERY_SHERD = "minecraft:blade_pottery_sherd"; public const BLAZE_POWDER = "minecraft:blaze_powder"; public const BLAZE_ROD = "minecraft:blaze_rod"; @@ -76,6 +77,7 @@ final class ItemTypeNames{ public const BLUE_BUNDLE = "minecraft:blue_bundle"; public const BLUE_DYE = "minecraft:blue_dye"; public const BLUE_EGG = "minecraft:blue_egg"; + public const BLUE_HARNESS = "minecraft:blue_harness"; public const BOARD = "minecraft:board"; public const BOAT = "minecraft:boat"; public const BOGGED_SPAWN_EGG = "minecraft:bogged_spawn_egg"; @@ -95,6 +97,7 @@ final class ItemTypeNames{ public const BROWN_BUNDLE = "minecraft:brown_bundle"; public const BROWN_DYE = "minecraft:brown_dye"; public const BROWN_EGG = "minecraft:brown_egg"; + public const BROWN_HARNESS = "minecraft:brown_harness"; public const BRUSH = "minecraft:brush"; public const BUCKET = "minecraft:bucket"; public const BUNDLE = "minecraft:bundle"; @@ -166,6 +169,7 @@ final class ItemTypeNames{ public const CROSSBOW = "minecraft:crossbow"; public const CYAN_BUNDLE = "minecraft:cyan_bundle"; public const CYAN_DYE = "minecraft:cyan_dye"; + public const CYAN_HARNESS = "minecraft:cyan_harness"; public const DANGER_POTTERY_SHERD = "minecraft:danger_pottery_sherd"; public const DARK_OAK_BOAT = "minecraft:dark_oak_boat"; public const DARK_OAK_CHEST_BOAT = "minecraft:dark_oak_chest_boat"; @@ -265,12 +269,15 @@ final class ItemTypeNames{ public const GOLDEN_SWORD = "minecraft:golden_sword"; public const GRAY_BUNDLE = "minecraft:gray_bundle"; public const GRAY_DYE = "minecraft:gray_dye"; + public const GRAY_HARNESS = "minecraft:gray_harness"; public const GREEN_BUNDLE = "minecraft:green_bundle"; public const GREEN_DYE = "minecraft:green_dye"; + public const GREEN_HARNESS = "minecraft:green_harness"; public const GUARDIAN_SPAWN_EGG = "minecraft:guardian_spawn_egg"; public const GUNPOWDER = "minecraft:gunpowder"; public const GUSTER_BANNER_PATTERN = "minecraft:guster_banner_pattern"; public const GUSTER_POTTERY_SHERD = "minecraft:guster_pottery_sherd"; + public const HAPPY_GHAST_SPAWN_EGG = "minecraft:happy_ghast_spawn_egg"; public const HARD_STAINED_GLASS = "minecraft:hard_stained_glass"; public const HARD_STAINED_GLASS_PANE = "minecraft:hard_stained_glass_pane"; public const HEART_OF_THE_SEA = "minecraft:heart_of_the_sea"; @@ -321,10 +328,13 @@ final class ItemTypeNames{ public const LIGHT_BLOCK = "minecraft:light_block"; public const LIGHT_BLUE_BUNDLE = "minecraft:light_blue_bundle"; public const LIGHT_BLUE_DYE = "minecraft:light_blue_dye"; + public const LIGHT_BLUE_HARNESS = "minecraft:light_blue_harness"; public const LIGHT_GRAY_BUNDLE = "minecraft:light_gray_bundle"; public const LIGHT_GRAY_DYE = "minecraft:light_gray_dye"; + public const LIGHT_GRAY_HARNESS = "minecraft:light_gray_harness"; public const LIME_BUNDLE = "minecraft:lime_bundle"; public const LIME_DYE = "minecraft:lime_dye"; + public const LIME_HARNESS = "minecraft:lime_harness"; public const LINGERING_POTION = "minecraft:lingering_potion"; public const LLAMA_SPAWN_EGG = "minecraft:llama_spawn_egg"; public const LODESTONE_COMPASS = "minecraft:lodestone_compass"; @@ -333,6 +343,7 @@ final class ItemTypeNames{ public const MACE = "minecraft:mace"; public const MAGENTA_BUNDLE = "minecraft:magenta_bundle"; public const MAGENTA_DYE = "minecraft:magenta_dye"; + public const MAGENTA_HARNESS = "minecraft:magenta_harness"; public const MAGMA_CREAM = "minecraft:magma_cream"; public const MAGMA_CUBE_SPAWN_EGG = "minecraft:magma_cube_spawn_egg"; public const MANGROVE_BOAT = "minecraft:mangrove_boat"; @@ -400,6 +411,7 @@ final class ItemTypeNames{ public const OMINOUS_TRIAL_KEY = "minecraft:ominous_trial_key"; public const ORANGE_BUNDLE = "minecraft:orange_bundle"; public const ORANGE_DYE = "minecraft:orange_dye"; + public const ORANGE_HARNESS = "minecraft:orange_harness"; public const OXIDIZED_COPPER_DOOR = "minecraft:oxidized_copper_door"; public const PAINTING = "minecraft:painting"; public const PALE_OAK_BOAT = "minecraft:pale_oak_boat"; @@ -419,6 +431,7 @@ final class ItemTypeNames{ public const PILLAGER_SPAWN_EGG = "minecraft:pillager_spawn_egg"; public const PINK_BUNDLE = "minecraft:pink_bundle"; public const PINK_DYE = "minecraft:pink_dye"; + public const PINK_HARNESS = "minecraft:pink_harness"; public const PITCHER_POD = "minecraft:pitcher_pod"; public const PLANKS = "minecraft:planks"; public const PLENTY_POTTERY_SHERD = "minecraft:plenty_pottery_sherd"; @@ -439,6 +452,7 @@ final class ItemTypeNames{ public const PUMPKIN_SEEDS = "minecraft:pumpkin_seeds"; public const PURPLE_BUNDLE = "minecraft:purple_bundle"; public const PURPLE_DYE = "minecraft:purple_dye"; + public const PURPLE_HARNESS = "minecraft:purple_harness"; public const QUARTZ = "minecraft:quartz"; public const RABBIT = "minecraft:rabbit"; public const RABBIT_FOOT = "minecraft:rabbit_foot"; @@ -455,6 +469,7 @@ final class ItemTypeNames{ public const RED_BUNDLE = "minecraft:red_bundle"; public const RED_DYE = "minecraft:red_dye"; public const RED_FLOWER = "minecraft:red_flower"; + public const RED_HARNESS = "minecraft:red_harness"; public const REDSTONE = "minecraft:redstone"; public const REPEATER = "minecraft:repeater"; public const RESIN_BRICK = "minecraft:resin_brick"; @@ -563,6 +578,7 @@ final class ItemTypeNames{ public const WHEAT_SEEDS = "minecraft:wheat_seeds"; public const WHITE_BUNDLE = "minecraft:white_bundle"; public const WHITE_DYE = "minecraft:white_dye"; + public const WHITE_HARNESS = "minecraft:white_harness"; public const WILD_ARMOR_TRIM_SMITHING_TEMPLATE = "minecraft:wild_armor_trim_smithing_template"; public const WIND_CHARGE = "minecraft:wind_charge"; public const WITCH_SPAWN_EGG = "minecraft:witch_spawn_egg"; @@ -583,6 +599,7 @@ final class ItemTypeNames{ public const WRITTEN_BOOK = "minecraft:written_book"; public const YELLOW_BUNDLE = "minecraft:yellow_bundle"; public const YELLOW_DYE = "minecraft:yellow_dye"; + public const YELLOW_HARNESS = "minecraft:yellow_harness"; public const ZOGLIN_SPAWN_EGG = "minecraft:zoglin_spawn_egg"; public const ZOMBIE_HORSE_SPAWN_EGG = "minecraft:zombie_horse_spawn_egg"; public const ZOMBIE_PIGMAN_SPAWN_EGG = "minecraft:zombie_pigman_spawn_egg"; diff --git a/src/network/mcpe/cache/StaticPacketCache.php b/src/network/mcpe/cache/StaticPacketCache.php index 88a52260026..64fc09ae3ac 100644 --- a/src/network/mcpe/cache/StaticPacketCache.php +++ b/src/network/mcpe/cache/StaticPacketCache.php @@ -23,13 +23,22 @@ namespace pocketmine\network\mcpe\cache; +use pocketmine\color\Color; use pocketmine\data\bedrock\BedrockDataFiles; +use pocketmine\data\SavedDataLoadingException; use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket; use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket; use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer; +use pocketmine\network\mcpe\protocol\types\biome\BiomeDefinitionEntry; use pocketmine\network\mcpe\protocol\types\CacheableNbt; use pocketmine\utils\Filesystem; use pocketmine\utils\SingletonTrait; +use pocketmine\world\biome\model\BiomeDefinitionEntryData; +use function count; +use function get_debug_type; +use function is_array; +use function is_object; +use function json_decode; class StaticPacketCache{ use SingletonTrait; @@ -41,9 +50,60 @@ private static function loadCompoundFromFile(string $filePath) : CacheableNbt{ return new CacheableNbt((new NetworkNbtSerializer())->read(Filesystem::fileGetContents($filePath))->mustGetCompoundTag()); } + /** + * @return list + */ + private static function loadBiomeDefinitionModel(string $filePath) : array{ + $biomeEntries = json_decode(Filesystem::fileGetContents($filePath), false); + if(!is_array($biomeEntries)){ + throw new SavedDataLoadingException("$filePath root should be an array, got " . get_debug_type($biomeEntries)); + } + + $jsonMapper = new \JsonMapper(); + $jsonMapper->bExceptionOnMissingData = true; + $jsonMapper->bStrictObjectTypeChecking = true; + + $entries = []; + foreach($biomeEntries as $entry){ + if(!is_object($entry)){ + throw new SavedDataLoadingException("$filePath should be an array of objects, got " . get_debug_type($entry)); + } + + try{ + $biomeDefinition = $jsonMapper->map($entry, new BiomeDefinitionEntryData()); + + $mapWaterColour = $biomeDefinition->mapWaterColour; + $entries[] = new BiomeDefinitionEntry( + $biomeDefinition->name, + $biomeDefinition->id, + $biomeDefinition->temperature, + $biomeDefinition->downfall, + $biomeDefinition->redSporeDensity, + $biomeDefinition->blueSporeDensity, + $biomeDefinition->ashDensity, + $biomeDefinition->whiteAshDensity, + $biomeDefinition->depth, + $biomeDefinition->scale, + new Color( + $mapWaterColour->r, + $mapWaterColour->g, + $mapWaterColour->b, + $mapWaterColour->a + ), + $biomeDefinition->rain, + count($biomeDefinition->tags) > 0 ? $biomeDefinition->tags : null, + ); + }catch(\JsonMapper_Exception $e){ + throw new \RuntimeException($e->getMessage(), 0, $e); + } + } + + return $entries; + } + private static function make() : self{ return new self( - BiomeDefinitionListPacket::create(self::loadCompoundFromFile(BedrockDataFiles::BIOME_DEFINITIONS_NBT)), + BiomeDefinitionListPacket::create(self::loadBiomeDefinitionModel(BedrockDataFiles::BIOME_DEFINITIONS_JSON)), AvailableActorIdentifiersPacket::create(self::loadCompoundFromFile(BedrockDataFiles::ENTITY_IDENTIFIERS_NBT)) ); } diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index 93a01fdcc09..eec200e4b9c 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -73,7 +73,6 @@ use pocketmine\network\mcpe\protocol\PlayerActionPacket; use pocketmine\network\mcpe\protocol\PlayerAuthInputPacket; use pocketmine\network\mcpe\protocol\PlayerHotbarPacket; -use pocketmine\network\mcpe\protocol\PlayerInputPacket; use pocketmine\network\mcpe\protocol\PlayerSkinPacket; use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket; use pocketmine\network\mcpe\protocol\serializer\BitSet; @@ -781,10 +780,6 @@ public function handleBlockActorData(BlockActorDataPacket $packet) : bool{ return false; } - public function handlePlayerInput(PlayerInputPacket $packet) : bool{ - return false; //TODO - } - public function handleSetPlayerGameType(SetPlayerGameTypePacket $packet) : bool{ $gameMode = $this->session->getTypeConverter()->protocolGameModeToCore($packet->gamemode); if($gameMode !== $this->player->getGamemode()){ diff --git a/src/world/biome/model/BiomeDefinitionEntryData.php b/src/world/biome/model/BiomeDefinitionEntryData.php new file mode 100644 index 00000000000..cf70e3c2211 --- /dev/null +++ b/src/world/biome/model/BiomeDefinitionEntryData.php @@ -0,0 +1,54 @@ + + */ + public array $tags; + + /** + * @return mixed[] + */ + public function jsonSerialize() : array{ + return (array) $this; + } +} diff --git a/src/world/biome/model/ColorData.php b/src/world/biome/model/ColorData.php new file mode 100644 index 00000000000..9428c37af20 --- /dev/null +++ b/src/world/biome/model/ColorData.php @@ -0,0 +1,41 @@ +bedrockDataPath . '/biome_definitions_full.nbt', $packet->definitions->getEncodedNbt()); - - $nbt = $packet->definitions->getRoot(); - if(!$nbt instanceof CompoundTag){ - throw new AssumptionFailedError(); - } - $strippedNbt = clone $nbt; - foreach($strippedNbt as $compound){ - if($compound instanceof CompoundTag){ - foreach([ - "minecraft:capped_surface", - "minecraft:consolidated_features", - "minecraft:frozen_ocean_surface", - "minecraft:legacy_world_generation_rules", - "minecraft:mesa_surface", - "minecraft:mountain_parameters", - "minecraft:multinoise_generation_rules", - "minecraft:overworld_generation_rules", - "minecraft:surface_material_adjustments", - "minecraft:surface_parameters", - "minecraft:swamp_surface", - ] as $remove){ - $compound->removeTag($remove); - } - } - } - - file_put_contents($this->bedrockDataPath . '/biome_definitions.nbt', (new CacheableNbt($strippedNbt))->getEncodedNbt()); + $definitions = []; + foreach($packet->getEntries() as $entry){ + $mapWaterColor = new ColorData(); + $mapWaterColor->r = $entry->getMapWaterColor()->getR(); + $mapWaterColor->g = $entry->getMapWaterColor()->getG(); + $mapWaterColor->b = $entry->getMapWaterColor()->getB(); + $mapWaterColor->a = $entry->getMapWaterColor()->getA(); + + $data = new BiomeDefinitionEntryData(); + $data->name = $entry->getBiomeName(); + $data->id = $entry->getId(); + $data->temperature = round($entry->getTemperature(), 3); + $data->downfall = round($entry->getDownfall(), 3); + $data->redSporeDensity = round($entry->getRedSporeDensity(), 3); + $data->blueSporeDensity = round($entry->getBlueSporeDensity(), 3); + $data->ashDensity = round($entry->getAshDensity(), 3); + $data->whiteAshDensity = round($entry->getWhiteAshDensity(), 3); + $data->depth = round($entry->getDepth(), 3); + $data->scale = round($entry->getScale(), 3); + $data->mapWaterColour = $mapWaterColor; + $data->rain = $entry->hasRain(); + $data->tags = $entry->getTags() ?? []; + + $definitions[] = self::objectToOrderedArray($data); + } + + file_put_contents($this->bedrockDataPath . '/biome_definitions.json', json_encode($definitions, JSON_PRETTY_PRINT) . "\n"); return true; } From 58c0aecc0c8a9dc813cd421df1ee59828f6d6deb Mon Sep 17 00:00:00 2001 From: Dries C Date: Wed, 7 May 2025 22:55:23 +0200 Subject: [PATCH 2/9] Update bedrock-data --- composer.lock | 8 ++++---- src/network/mcpe/cache/StaticPacketCache.php | 4 ++-- src/world/biome/model/BiomeDefinitionEntryData.php | 1 - tools/generate-bedrock-data-from-packets.php | 5 +++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.lock b/composer.lock index 76760d2b6e0..634b21efba4 100644 --- a/composer.lock +++ b/composer.lock @@ -208,12 +208,12 @@ "source": { "type": "git", "url": "https://github.com/pmmp/BedrockData.git", - "reference": "a5f1fc12aa8c7666267e003a66fc58633840e5d0" + "reference": "a8932e40388c7280783ab78a8853d9491cb5dd40" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockData/zipball/a5f1fc12aa8c7666267e003a66fc58633840e5d0", - "reference": "a5f1fc12aa8c7666267e003a66fc58633840e5d0", + "url": "https://api.github.com/repos/pmmp/BedrockData/zipball/a8932e40388c7280783ab78a8853d9491cb5dd40", + "reference": "a8932e40388c7280783ab78a8853d9491cb5dd40", "shasum": "" }, "type": "library", @@ -226,7 +226,7 @@ "issues": "https://github.com/pmmp/BedrockData/issues", "source": "https://github.com/pmmp/BedrockData/tree/feature/1.21.80" }, - "time": "2025-05-06T22:25:16+00:00" + "time": "2025-05-07T20:54:24+00:00" }, { "name": "pocketmine/bedrock-item-upgrade-schema", diff --git a/src/network/mcpe/cache/StaticPacketCache.php b/src/network/mcpe/cache/StaticPacketCache.php index 64fc09ae3ac..222f5a852dc 100644 --- a/src/network/mcpe/cache/StaticPacketCache.php +++ b/src/network/mcpe/cache/StaticPacketCache.php @@ -64,7 +64,7 @@ private static function loadBiomeDefinitionModel(string $filePath) : array{ $jsonMapper->bStrictObjectTypeChecking = true; $entries = []; - foreach($biomeEntries as $entry){ + foreach($biomeEntries as $biomeName => $entry){ if(!is_object($entry)){ throw new SavedDataLoadingException("$filePath should be an array of objects, got " . get_debug_type($entry)); } @@ -74,7 +74,7 @@ private static function loadBiomeDefinitionModel(string $filePath) : array{ $mapWaterColour = $biomeDefinition->mapWaterColour; $entries[] = new BiomeDefinitionEntry( - $biomeDefinition->name, + $biomeName, $biomeDefinition->id, $biomeDefinition->temperature, $biomeDefinition->downfall, diff --git a/src/world/biome/model/BiomeDefinitionEntryData.php b/src/world/biome/model/BiomeDefinitionEntryData.php index cf70e3c2211..40ff5ae0535 100644 --- a/src/world/biome/model/BiomeDefinitionEntryData.php +++ b/src/world/biome/model/BiomeDefinitionEntryData.php @@ -27,7 +27,6 @@ * Model for loading biome definition entries data from JSON. */ final class BiomeDefinitionEntryData implements \JsonSerializable{ - public string $name; public ?int $id; public float $temperature; public float $downfall; diff --git a/tools/generate-bedrock-data-from-packets.php b/tools/generate-bedrock-data-from-packets.php index e9e2c38ba7f..7dcf23a6a20 100644 --- a/tools/generate-bedrock-data-from-packets.php +++ b/tools/generate-bedrock-data-from-packets.php @@ -583,7 +583,6 @@ public function handleBiomeDefinitionList(BiomeDefinitionListPacket $packet) : b $mapWaterColor->a = $entry->getMapWaterColor()->getA(); $data = new BiomeDefinitionEntryData(); - $data->name = $entry->getBiomeName(); $data->id = $entry->getId(); $data->temperature = round($entry->getTemperature(), 3); $data->downfall = round($entry->getDownfall(), 3); @@ -597,9 +596,11 @@ public function handleBiomeDefinitionList(BiomeDefinitionListPacket $packet) : b $data->rain = $entry->hasRain(); $data->tags = $entry->getTags() ?? []; - $definitions[] = self::objectToOrderedArray($data); + $definitions[$entry->getBiomeName()] = self::objectToOrderedArray($data); } + ksort($definitions, SORT_STRING); + file_put_contents($this->bedrockDataPath . '/biome_definitions.json', json_encode($definitions, JSON_PRETTY_PRINT) . "\n"); return true; From 4b85e577b9159cb32c404e2db866e85f1bb49d02 Mon Sep 17 00:00:00 2001 From: Dries C Date: Wed, 7 May 2025 23:09:48 +0200 Subject: [PATCH 3/9] Add required tags to models --- .../biome/model/BiomeDefinitionEntryData.php | 32 ++++++++++++++----- src/world/biome/model/ColorData.php | 16 +++++----- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/world/biome/model/BiomeDefinitionEntryData.php b/src/world/biome/model/BiomeDefinitionEntryData.php index 40ff5ae0535..8a5c3d35424 100644 --- a/src/world/biome/model/BiomeDefinitionEntryData.php +++ b/src/world/biome/model/BiomeDefinitionEntryData.php @@ -26,28 +26,44 @@ /** * Model for loading biome definition entries data from JSON. */ -final class BiomeDefinitionEntryData implements \JsonSerializable{ +final class BiomeDefinitionEntryData{ + /** @required */ public ?int $id; + + /** @required */ public float $temperature; + + /** @required */ public float $downfall; + + /** @required */ public float $redSporeDensity; + + /** @required */ public float $blueSporeDensity; + + /** @required */ public float $ashDensity; + + /** @required */ public float $whiteAshDensity; + + /** @required */ public float $depth; + + /** @required */ public float $scale; + + /** @required */ public ColorData $mapWaterColour; + + /** @required */ public bool $rain; + /** + * @required * @var string[] * @phpstan-var list */ public array $tags; - - /** - * @return mixed[] - */ - public function jsonSerialize() : array{ - return (array) $this; - } } diff --git a/src/world/biome/model/ColorData.php b/src/world/biome/model/ColorData.php index 9428c37af20..f70a77d1559 100644 --- a/src/world/biome/model/ColorData.php +++ b/src/world/biome/model/ColorData.php @@ -26,16 +26,16 @@ /** * Model for loading color data from JSON. */ -final class ColorData implements \JsonSerializable{ +final class ColorData{ + /** @required */ public int $r; + + /** @required */ public int $g; + + /** @required */ public int $b; - public int $a; - /** - * @return mixed[] - */ - public function jsonSerialize() : array{ - return (array) $this; - } + /** @required */ + public int $a; } From a5d88ab07a889a359aabe61a606d4a93862fdb6d Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 8 May 2025 23:29:41 +0100 Subject: [PATCH 4/9] Fixed biome data loading --- src/network/mcpe/cache/StaticPacketCache.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/network/mcpe/cache/StaticPacketCache.php b/src/network/mcpe/cache/StaticPacketCache.php index 222f5a852dc..b54d0ac3262 100644 --- a/src/network/mcpe/cache/StaticPacketCache.php +++ b/src/network/mcpe/cache/StaticPacketCache.php @@ -33,6 +33,7 @@ use pocketmine\network\mcpe\protocol\types\CacheableNbt; use pocketmine\utils\Filesystem; use pocketmine\utils\SingletonTrait; +use pocketmine\utils\Utils; use pocketmine\world\biome\model\BiomeDefinitionEntryData; use function count; use function get_debug_type; @@ -54,7 +55,7 @@ private static function loadCompoundFromFile(string $filePath) : CacheableNbt{ * @return list */ private static function loadBiomeDefinitionModel(string $filePath) : array{ - $biomeEntries = json_decode(Filesystem::fileGetContents($filePath), false); + $biomeEntries = json_decode(Filesystem::fileGetContents($filePath), associative: true); if(!is_array($biomeEntries)){ throw new SavedDataLoadingException("$filePath root should be an array, got " . get_debug_type($biomeEntries)); } @@ -62,10 +63,11 @@ private static function loadBiomeDefinitionModel(string $filePath) : array{ $jsonMapper = new \JsonMapper(); $jsonMapper->bExceptionOnMissingData = true; $jsonMapper->bStrictObjectTypeChecking = true; + $jsonMapper->bEnforceMapType = false; $entries = []; - foreach($biomeEntries as $biomeName => $entry){ - if(!is_object($entry)){ + foreach(Utils::promoteKeys($biomeEntries) as $biomeName => $entry){ + if(!is_array($entry)){ throw new SavedDataLoadingException("$filePath should be an array of objects, got " . get_debug_type($entry)); } @@ -74,7 +76,7 @@ private static function loadBiomeDefinitionModel(string $filePath) : array{ $mapWaterColour = $biomeDefinition->mapWaterColour; $entries[] = new BiomeDefinitionEntry( - $biomeName, + (string) $biomeName, $biomeDefinition->id, $biomeDefinition->temperature, $biomeDefinition->downfall, From 000341d316c1c11a1a6ea48aab1c04fd0352f244 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 8 May 2025 23:43:06 +0100 Subject: [PATCH 5/9] Support newest world format apparently I messed up the blockstate data version last time around... it hasn't changed since 1.21.60 --- src/data/bedrock/block/BlockStateData.php | 4 ++-- src/world/format/io/data/BedrockWorldData.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/data/bedrock/block/BlockStateData.php b/src/data/bedrock/block/BlockStateData.php index 600eba938cd..e90410ac7f0 100644 --- a/src/data/bedrock/block/BlockStateData.php +++ b/src/data/bedrock/block/BlockStateData.php @@ -45,8 +45,8 @@ final class BlockStateData{ public const CURRENT_VERSION = (1 << 24) | //major (21 << 16) | //minor - (70 << 8) | //patch - (1); //revision + (60 << 8) | //patch + (33); //revision public const TAG_NAME = "name"; public const TAG_STATES = "states"; diff --git a/src/world/format/io/data/BedrockWorldData.php b/src/world/format/io/data/BedrockWorldData.php index 5b19457392b..d39c17a4711 100644 --- a/src/world/format/io/data/BedrockWorldData.php +++ b/src/world/format/io/data/BedrockWorldData.php @@ -51,11 +51,11 @@ class BedrockWorldData extends BaseNbtWorldData{ public const CURRENT_STORAGE_VERSION = 10; - public const CURRENT_STORAGE_NETWORK_VERSION = 786; + public const CURRENT_STORAGE_NETWORK_VERSION = 800; public const CURRENT_CLIENT_VERSION_TARGET = [ 1, //major 21, //minor - 70, //patch + 80, //patch 3, //revision 0 //is beta ]; From 9fb77920813398bfecb051380fbfdb1ec7ede740 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 8 May 2025 23:44:34 +0100 Subject: [PATCH 6/9] always CS has to complain... --- src/network/mcpe/cache/StaticPacketCache.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/network/mcpe/cache/StaticPacketCache.php b/src/network/mcpe/cache/StaticPacketCache.php index b54d0ac3262..2b0f116b685 100644 --- a/src/network/mcpe/cache/StaticPacketCache.php +++ b/src/network/mcpe/cache/StaticPacketCache.php @@ -38,7 +38,6 @@ use function count; use function get_debug_type; use function is_array; -use function is_object; use function json_decode; class StaticPacketCache{ From 0aa8936469572b2687d49d0ea941e31157e33a58 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 9 May 2025 15:18:56 +0100 Subject: [PATCH 7/9] Sync with release versions --- composer.json | 4 +-- composer.lock | 33 +++++++++----------- src/network/mcpe/cache/StaticPacketCache.php | 2 +- tools/generate-bedrock-data-from-packets.php | 2 +- 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/composer.json b/composer.json index ffb34705523..7545806b4dc 100644 --- a/composer.json +++ b/composer.json @@ -34,9 +34,9 @@ "adhocore/json-comment": "~1.2.0", "netresearch/jsonmapper": "~v5.0.0", "pocketmine/bedrock-block-upgrade-schema": "~5.1.0+bedrock-1.21.60", - "pocketmine/bedrock-data": "dev-feature/1.21.80", + "pocketmine/bedrock-data": "5.0.0+bedrock-1.21.80", "pocketmine/bedrock-item-upgrade-schema": "~1.14.0+bedrock-1.21.50", - "pocketmine/bedrock-protocol": "dev-bedrock-1.21.80", + "pocketmine/bedrock-protocol": "38.0.0+bedrock-1.21.80", "pocketmine/binaryutils": "^0.2.1", "pocketmine/callback-validator": "^1.0.2", "pocketmine/color": "^0.3.0", diff --git a/composer.lock b/composer.lock index 634b21efba4..d45311018c3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3569b0323d32db1cbcd25e540d91044d", + "content-hash": "4dfc7b8c912d8d5fa194ddc0e97903fb", "packages": [ { "name": "adhocore/json-comment", @@ -204,16 +204,16 @@ }, { "name": "pocketmine/bedrock-data", - "version": "dev-feature/1.21.80", + "version": "5.0.0+bedrock-1.21.80", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockData.git", - "reference": "a8932e40388c7280783ab78a8853d9491cb5dd40" + "reference": "e38d5ea19f794ec5216e5f96742237e8c4e7f080" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockData/zipball/a8932e40388c7280783ab78a8853d9491cb5dd40", - "reference": "a8932e40388c7280783ab78a8853d9491cb5dd40", + "url": "https://api.github.com/repos/pmmp/BedrockData/zipball/e38d5ea19f794ec5216e5f96742237e8c4e7f080", + "reference": "e38d5ea19f794ec5216e5f96742237e8c4e7f080", "shasum": "" }, "type": "library", @@ -224,9 +224,9 @@ "description": "Blobs of data generated from Minecraft: Bedrock Edition, used by PocketMine-MP", "support": { "issues": "https://github.com/pmmp/BedrockData/issues", - "source": "https://github.com/pmmp/BedrockData/tree/feature/1.21.80" + "source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.21.80" }, - "time": "2025-05-07T20:54:24+00:00" + "time": "2025-05-09T14:15:18+00:00" }, { "name": "pocketmine/bedrock-item-upgrade-schema", @@ -256,16 +256,16 @@ }, { "name": "pocketmine/bedrock-protocol", - "version": "dev-bedrock-1.21.80", + "version": "38.0.0+bedrock-1.21.80", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockProtocol.git", - "reference": "39a5f0cbe57834aeba5a7550803191999039e3c6" + "reference": "a626561eaefeb6333c0d2726e2789ceb0aac0724" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/39a5f0cbe57834aeba5a7550803191999039e3c6", - "reference": "39a5f0cbe57834aeba5a7550803191999039e3c6", + "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/a626561eaefeb6333c0d2726e2789ceb0aac0724", + "reference": "a626561eaefeb6333c0d2726e2789ceb0aac0724", "shasum": "" }, "require": { @@ -296,9 +296,9 @@ "description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP", "support": { "issues": "https://github.com/pmmp/BedrockProtocol/issues", - "source": "https://github.com/pmmp/BedrockProtocol/tree/bedrock-1.21.80" + "source": "https://github.com/pmmp/BedrockProtocol/tree/38.0.0+bedrock-1.21.80" }, - "time": "2025-05-06T20:30:40+00:00" + "time": "2025-05-09T14:17:07+00:00" }, { "name": "pocketmine/binaryutils", @@ -2921,10 +2921,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "pocketmine/bedrock-data": 20, - "pocketmine/bedrock-protocol": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -2955,7 +2952,7 @@ "ext-zlib": ">=1.2.11", "composer-runtime-api": "^2.0" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { "php": "8.1.0" }, diff --git a/src/network/mcpe/cache/StaticPacketCache.php b/src/network/mcpe/cache/StaticPacketCache.php index 2b0f116b685..861881437b9 100644 --- a/src/network/mcpe/cache/StaticPacketCache.php +++ b/src/network/mcpe/cache/StaticPacketCache.php @@ -104,7 +104,7 @@ private static function loadBiomeDefinitionModel(string $filePath) : array{ private static function make() : self{ return new self( - BiomeDefinitionListPacket::create(self::loadBiomeDefinitionModel(BedrockDataFiles::BIOME_DEFINITIONS_JSON)), + BiomeDefinitionListPacket::fromDefinitions(self::loadBiomeDefinitionModel(BedrockDataFiles::BIOME_DEFINITIONS_JSON)), AvailableActorIdentifiersPacket::create(self::loadCompoundFromFile(BedrockDataFiles::ENTITY_IDENTIFIERS_NBT)) ); } diff --git a/tools/generate-bedrock-data-from-packets.php b/tools/generate-bedrock-data-from-packets.php index 7dcf23a6a20..b0aae57df2a 100644 --- a/tools/generate-bedrock-data-from-packets.php +++ b/tools/generate-bedrock-data-from-packets.php @@ -575,7 +575,7 @@ public function handleBiomeDefinitionList(BiomeDefinitionListPacket $packet) : b echo "storing biome definitions" . PHP_EOL; $definitions = []; - foreach($packet->getEntries() as $entry){ + foreach($packet->buildDefinitionsFromData() as $entry){ $mapWaterColor = new ColorData(); $mapWaterColor->r = $entry->getMapWaterColor()->getR(); $mapWaterColor->g = $entry->getMapWaterColor()->getG(); From bbb9e223bccd980671c71fbffc2505c96fddbd8d Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 9 May 2025 15:23:02 +0100 Subject: [PATCH 8/9] Ready 5.28.0 release --- changelogs/5.28.md | 21 +++++++++++++++++++++ src/VersionInfo.php | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 changelogs/5.28.md diff --git a/changelogs/5.28.md b/changelogs/5.28.md new file mode 100644 index 00000000000..f368e819e3e --- /dev/null +++ b/changelogs/5.28.md @@ -0,0 +1,21 @@ +# 5.28.0 +Released 9th May 2025. + +This is a support release for Minecraft: Bedrock Edition 1.21.80. + +**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace. +Do not update plugin minimum API versions unless you need new features added in this release. + +**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.** +Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly. + +## General +- Aded support for Minecraft: Bedrock Edition 1.21.70. +- Removed support for earlier versions. + +## Fixes +- `AvailableEnchantmentRegistry` now requires provided tags to always be `string`. Previously, this wasn't enforced, leading to random crashes in core code related to enchanting. +- `Entity->setFireTicks()` and `Entity->setOnFire()` now truncate the fire time to the max value instead of throwing exceptions. + +## Internals +- Improved PHPStan error reporting for unsafe foreaches. Foreach on an array with implicit keys now generates different errors than foreach on an array with string keys. diff --git a/src/VersionInfo.php b/src/VersionInfo.php index 44238dba3a6..d23a4b4964b 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -31,7 +31,7 @@ final class VersionInfo{ public const NAME = "PocketMine-MP"; - public const BASE_VERSION = "5.27.2"; + public const BASE_VERSION = "5.28.0"; public const IS_DEVELOPMENT_BUILD = true; public const BUILD_CHANNEL = "stable"; From 245b329c2644781be1827d7f7020127f8b1fecbf Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 9 May 2025 15:24:24 +0100 Subject: [PATCH 9/9] this might help... --- src/VersionInfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VersionInfo.php b/src/VersionInfo.php index d23a4b4964b..c5b38f07228 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -32,7 +32,7 @@ final class VersionInfo{ public const NAME = "PocketMine-MP"; public const BASE_VERSION = "5.28.0"; - public const IS_DEVELOPMENT_BUILD = true; + public const IS_DEVELOPMENT_BUILD = false; public const BUILD_CHANNEL = "stable"; /**