# 5.26.0 Released 22nd March 2025. This is a minor feature release focused on performance improvements. **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. ## Performance - Significantly improved performance of entity movement. Load testing with item entities showed a 3x increase in the number of entities supported without lag. - Significantly improved performance of on-ground checks for player movement. This still needs further work, but optimisations implemented in this version should improve performance substantially. - Updated `pocketmine/nbt` dependency with performance improvements to `TAG_Compound` and `TAG_List` comparison. This should improve performance of inventory-related actions. - `InventoryTransaction` now avoids useless item clones when processing transactions, which should improve performance of inventory-related actions. ## Dependencies - `pocketmine/bedrock-protocol` has been updated to `36.2.0`, which adds new functions to access some packet fields. - `pocketmine/nbt` has been updated to `1.1.0`, which improves performance when comparing NBT object trees. ## Gameplay - Block breaking animation speed now takes into account the following: jumping, being in water, haste, mining fatigue ## Tools - `blockstate-upgrade-schema-utils.php` now has a new `dump-table` command, which turns a `.bin` palette table file into human-readable text for debugging. ## API ### `pocketmine\block` - The following methods have been added: - `public RuntimeBlockStateRegistry->hasStateId(int $stateId) : bool` - checks whether the given state ID is registered ### `pocketmine\crafting` - The following methods have been deprecated: - `CraftingManager::sort()` - this was implicitly internal anyway ### `pocketmine\utils` - The following constants have been added: - `TextFormat::MATERIAL_RESIN` - The following static properties have been added: - `Terminal::$COLOR_MATERIAL_RESIN` ### `pocketmine\data\bedrock\block` - `BlockStateToObjectDeserializer` now permits overriding **deserializers** for Bedrock IDs. This may be useful to implement custom state handling, or to implement missing block variants (such as snow cauldron). - This was originally prohibited since 5.0.0. However, there is no technical reason to disallow overriding **deserializers**. - Overriding **serializers** is still **not permitted**. Reusing type IDs doesn't make any sense and would break internal design contracts. - If you want to make a custom version of a vanilla block, create a custom type ID for it, exactly as you would for a regular custom block. - The following methods have been added: - `public BlockStateToObjectDeserializer->getDeserializerForId(string $id) : ?(\Closure(BlockStateReader) : Block)` ### `pocketmine\data\bedrock\item` - `ItemDeserializer` now permits overriding **deserializers** for Bedrock IDs. As above, this may be useful to implement custom data handling, or to implement missing variants of existing items. - This was originally prohibited since 5.0.0. However, there is no technical reason to disallow overriding **deserializers**. - Overriding **serializers** is still **not permitted**. Reusing type IDs doesn't make any sense and would break internal design contracts. - As above, if you want to make a custom version of a vanilla item, create a custom type ID for it, exactly as you would for a regular custom item. - The following methods have been added: - `public ItemDeserializer->getDeserializerForId(string $id) : ?(\Closure(SavedItemData) : Item)` ## Internals - `new $class` is now banned on new internals code by a PHPStan rule. Closures or factory objects should be used instead for greater flexibility and better static analysis. - `CraftingManager` now uses a more stable hash function for recipe output filtering. - `ChunkCache` now accepts `int $dimensionId` in the constructor. This may be useful for plugins which implement the nether. - `RuntimeBlockStateRegistry` now precomputes basic collision info about known states for fast paths. - This permits specialization for common shapes like cubes and collisionless blocks, which allows skipping complex logic in entity movement calculation. This vastly improves performance. - Any block whose class overrides `readStateFromWorld()` or `getModelPositionOffset()` will *not* be optimised. - `Block->recalculateCollisionBoxes()` now has a hard requirement not to depend on anything other than available properties. It must not use `World` or its position. - This change was problematic for `ChorusPlant`, which used nearby blocks to calculate its collision boxes. - Blocks which need nearby blocks should override `readStateFromWorld()` and set dynamic state properties, similar to fences. - This design flaw will be corrected with a major change to `Block` internals currently in planning for a future major version. - `Block->getCollisionBoxes()` may not be called at all during gameplay for blocks with shapes determined to be simple, like cubes and collisionless blocks. - `BlockStateToObjectDeserializer` now checks if the returned blockstate is registered in `RuntimeBlockStateRegistry` to promote earlier error detection (instead of crashing in random code paths).