mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-08-20 18:31:23 +00:00
55 KiB
55 KiB
4.0.0-SNAPSHOT-1907XX (2019-07-XX)
This major version features substantial changes throughout the core, including significant API changes, new world format support, performance improvements and a network revamp.
Core
General
- A new "plugin greylist" feature has been introduced, which allows whitelisting or blacklisting plugins from loading.
- The
/reloadcommand has been removed. - The
/effectcommand no longer supports numeric IDs - it's now required to use names. - The
/enchantcommand no longer supports numeric IDs - it's now required to use names. - Remote console (RCON) has been removed. The RconServer plugin is provided as a substitute.
- Spawn protection has been removed. The BasicSpawnProtection plugin is provided as a substitute.
- CTRL+C signal handling has been removed. The PcntlSignalHandler plugin is provided as a substitute.
- Player movement anti-cheat has been removed. Its corresponding
pocketmine.ymlsettingplayer.anti-cheat.allow-movement-cheatshas been removed. - The
pocketmine_chunkutilsPHP extension has been dropped. - New PHP extensions are required by this version:
World handling
Functional
- Modern Minecraft Bedrock world formats are now supported.
- Automatic conversion of deprecated world formats is now implemented.
- All formats except
leveldbhave been deprecated. The following world formats will be automatically converted on load to a new format:mcregionanvilpmanvil
- 256 build-height is now supported in all worlds (facilitated by automatic conversion).
- Extended blocks are now supported (facilitated by automatic conversion).
- Unsupported world formats no longer causes a crash, but a graceful shutdown instead.
- World corruption no longer causes a crash, but a graceful shutdown instead.
- Lighting is no longer stored or loaded from disk - instead, it's calculated on the fly as-needed. This fixes many long-standing bugs.
Performance
leveldbis now the primary supported world format. It is inherently faster than region-based formats thanks to better design.- Partial chunk saves (only saving modified subcomponents of chunks) has been implemented. This drastically reduces the amount of data that is usually necessary to write on chunk save, which in turn drastically reduces the time to complete world saves. This is possible thanks to the modular design of the
leveldbworld format - this enhancement is not possible with region-based formats. - Lighting is no longer guaranteed to be available on every chunk. It's now calculated on the fly as-needed.
/op,/deop,/whitelist addand/whitelist removeno longer cause player data to be loaded from disk for no reason.
Logger revamp
- Many components now have a dedicated logger which automatically adds [prefixes] to their messages.
- Main logger now includes milliseconds in timestamps.
Network
This version features substantial changes to the network system, improving coherency, reliability and modularity.
Minecraft Bedrock packet encryption
- This fixes replay attacks where hackers steal and replay player logins.
- A new setting has been added to
pocketmine.yml:network.enable-encryptionwhich istrueby default.
Packet receive error handling has been overhauled
- Only
BadPacketExceptionis now caught during packet decode and handling. This requires that all decoding MUST perform proper data error checking.- Throwing a
BadPacketExceptionfrom decoding will now cause players to be kicked with the messagePacket processing error. - The disconnect message includes a random hex ID to help server owners identify the problems reported by their players.
- Throwing a
- Throwing any other exception will now cause a server crash.
Internal server errorhas been removed. - It is now illegal to send a clientbound packet to the server. Doing so will result in the client being kicked with the message
Unexpected non-serverbound packet.
New packet handler system
- Packet handlers have been separated from NetworkSession into a dedicated packet handler structure.
- A network session may have exactly 1 handler at a time, which is mutable and may be replaced at any time. This allows packet handling logic to be broken up into multiple stages:
- preventing undefined behaviour when sending wrong packets at the wrong time (they'll now be silently dropped)
- allowing the existence of ephemeral state-specific logic (for example stricter resource packs download checks)
- Packet handlers are now almost entirely absent from
Playerand instead appear in their own dedicated units. - Almost all game logic that was previously locked up inside packet handlers in
Playerhas been extracted into new API methods. See Player API changes for details.
API
General
- Most places which previously allowed
callablenow only allow\Closure. This is because closures have more consistent behaviour and are more performant. voidand?nullableparameter and return types have been applied in many places.- Everything in the
pocketmine\metadatanamespace and related implementations have been removed.
Block
- A new
VanillaBlocksclass has been added, which contains static methods for creating any currently-known block type. This should be preferred instead of use ofBlockFactory::get()where constants were used. - Blocks now contain their positions instead of extending
Position.Block->getPos()has been added. - Blocks with IDs >= 256 are now supported.
- Block state and variant metadata have been separated.
- Variant is considered an extension of ID and is immutable.
Block->setDamage()has been removed.Block->readStateFromData()is now used for state deserialization.
- Tile entities are now created and deleted automatically when
World->setBlock()is used with a block that requires a tile entity. - Some tile entities' API has been exposed on their corresponding
Blockclasses, with the tile entity classes being deprecated. - The
pocketmine\tilenamespace has been relocated topocketmine\block\tile. Block->recalculateBoundingBox()andBlock->recalculateCollisionBoxes()are now expected to return AABBs relative to0,0,0instead of their own position.- Block break-info has been extracted into a new dynamic
BlockBreakInfounit. The following methods have been moved:Block->getBlastResistance()->BlockBreakInfo->getBlastResistance()Block->getBreakTime()->BlockBreakInfo->getBreakTime()Block->getHardness()->BlockBreakInfo->getHardness()Block->getToolHarvestLevel()->BlockBreakInfo->getToolHarvestLevel()Block->getToolType()->BlockBreakInfo->getToolType()Block->isBreakable()->BlockBreakInfo->isBreakable()Block->isCompatibleWithTool()->BlockBreakInfo->isToolCompatible()
- The following API methods have been added:
Block->asItem(): returns an itemstack corresponding to the blockBlock->isSameState(): returns whether the block is the same as the parameter, including state informationBlock->isSameType(): returns whether the block is the same as the parameter, without state informationBlock->isFullCube()
- The following hooks have been added:
Block->onAttack(): called when a player in survival left-clicks the block to try to start breaking itBlock->onPostPlace(): called directly after placement in the world, handles things like rail connections and chest pairing
- The following API methods have been renamed:
Block->getDamage()->Block->getMeta()Block->onActivate()->Block->onInteract()Block->onEntityCollide()->Block->onEntityInside()
- The following API methods have changed signatures:
Block->onInteract()now has the signatureonInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : boolBlock->getCollisionBoxes()is now final. Classes should overriderecalculateCollisionBoxes().
- The following API methods have been removed:
Block->canPassThrough()Block->setDamage()Block::get(): this was superseded byBlockFactory::get()a long time agoBlock->getBoundingBox()
- The following classes have been renamed:
BlockIds->BlockLegacyIdsCobblestoneWall->WallNoteBlock->NoteSignPost->SignStandingBanner->Banner
- The following classes have been removed:
BricksBurningFurnaceCobblestoneStairsDandelionDoubleSlabDoubleStoneSlabEndStoneGlowingRedstoneOreGoldOreGoldIronDoorIronOreIronTrapdoorIronLapisNetherBrickFenceNetherBrickStairsObsidianPurpurStairsPurpurQuartzStairsQuartzRedSandstoneStairsRedSandstoneSandstoneStairsSandstoneStainedClayStainedGlassPaneStainedGlassStoneBrickStairsStoneBricksStoneSlab2StoneSlabStoneWallBannerWallSignWood2
BlockToolTypeconstants have been renamed to remove theTYPE_prefix.
Command
- The following classes have been removed:
RemoteConsoleCommandSender
- The following API methods have signature changes:
Command->setPermission()argument is now mandatory (but still nullable).CommandSender->setScreenLineHeight()argument is now mandatory (but still nullable).
Entity
General
Entityno longer extends fromLocation.Entity->getLocation()andEntity->getPosition()should be used instead.- The following API methods have been added:
ItemEntity->getDespawnDelay()ItemEntity->setDespawnDelay()Human->getHungerManager()Human->getXpManager()
- The following methods have signature changes:
Entity->entityBaseTick()is nowprotected.Entity->move()is nowprotected.Living->knockBack()now acceptsfloat, float, float(the first two parameters have been removed).Living->getEffects()now returnsEffectManagerinstead ofEffect[].
- The following classes have been added:
effect\EffectManager: contains effect-management functionality extracted fromLivingHungerManager: contains hunger-management functionality extracted fromHumanExperienceManager: contains XP-management functionality extracted fromHuman
- The following API methods have been moved / renamed:
Living->removeAllEffects()->EffectManager->clear()Living->removeEffect()->EffectManager->remove()Living->addEffect()->EffectManager->add()Living->getEffect()->EffectManager->get()Living->hasEffect()->EffectManager->has()Living->hasEffects()->EffectManager->hasEffects()Living->getEffects()->EffectManager->all()Human->getFood()->HungerManager->getFood()Human->setFood()->HungerManager->setFood()Human->getMaxFood()->HungerManager->getMaxFood()Human->addFood()->HungerManager->addFood()Human->isHungry()->HungerManager->isHungry()Human->getSaturation()->HungerManager->getSaturation()Human->setSaturation()->HungerManager->setSaturation()Human->addSaturation()->HungerManager->addSaturation()Human->getExhaustion()->HungerManager->getExhaustion()Human->setExhaustion()->HungerManager->setExhaustion()Human->exhaust()->HungerManager->exhaust()Human->getXpLevel()->ExperienceManager->getXpLevel()Human->setXpLevel()->ExperienceManager->setXpLevel()Human->addXpLevels()->ExperienceManager->addXpLevels()Human->subtractXpLevels()->ExperienceManager->subtractXpLevels()Human->getXpProgress()->ExperienceManager->getXpProgress()Human->setXpProgress()->ExperienceManager->setXpProgress()Human->getRemainderXp()->ExperienceManager->getRemainderXp()Human->getCurrentTotalXp()->ExperienceManager->getCurrentTotalXp()Human->setCurrentTotalXp()->ExperienceManager->setCurrentTotalXp()Human->addXp()->ExperienceManager->addXp()Human->subtractXp()->ExperienceManager->subtractXp()Human->getLifetimeTotalXp()->ExperienceManager->getLifetimeTotalXp()Human->setLifetimeTotalXp()->ExperienceManager->setLifetimeTotalXp()Human->canPickupXp()->ExperienceManager->canPickupXp()Human->onPickupXp()->ExperienceManager->onPickupXp()Human->resetXpCooldown()->ExperienceManager->resetXpCooldown()
- The following API methods have been removed:
Human->getRawUniqueId(): useHuman->getUniqueId()->toBinary()instead
- The following classes have been removed:
CreatureDamageableMonsterNPCRideableVehicle
Skinnow throws exceptions on creation if given invalid data.
Effect
- All
Effectrelated classes have been moved to thepocketmine\entity\effectnamespace. - Effect functionality embedded in the
Effectclass has been separated out into several classes. The following classes have been added:AbsorptionEffectHealthBoostEffectHungerEffectInstantDamageEffectInstantEffectInstantHealthEffectInvisibilityEffectLevitationEffectPoisonEffectRegenerationEffectSaturationEffectSlownessEffectSpeedEffectWitherEffect
VanillaEffectsclass has been added. This exposes all vanilla effect types as static methods, replacing the oldEffect::getEffect()nastiness.- Example:
Effect::getEffect(Effect::NIGHT_VISION)can be replaced byVanillaEffects::NIGHT_VISION().
- Example:
- Negative effect amplifiers are now explicitly disallowed due to undefined behaviour they created.
- The boundaries between MCPE effect IDs and PocketMine-MP internals are now more clear.
- ID handling is moved to
pocketmine\data\bedrock\EffectIdMap. - All effect ID constants have been removed from
Effect.pocketmine\data\bedrock\EffectIdsif you still need legacy effect IDs for some reason.
- ID handling is moved to
- The following API methods have been moved:
Effect->getId()->EffectIdMap->toId()Effect::registerEffect()->EffectIdMap->register()Effect::getEffect()->EffectIdMap->fromId()Effect::getEffectByName()->VanillaEffects::fromString()
- The following API methods have been added:
Effect->getRuntimeId(): this is a dynamic ID which can be used for effect type comparisons. This cannot be stored, so don't use it in configs or NBT!
Removal of runtime entity NBT
- Entities no longer keep their NBT alive at runtime.
Entity->namedtaghas been removed.Entity->saveNBT()now returns a newly createdCompoundTaginstead of modifying the previous one in-place.Entity->initEntity()now accepts aCompoundTagparameter.
Entity creation
- Runtime entity creation no longer requires
EntityFactory- just usenew YourEntityinstead. - Entity constructors no longer require
CompoundTag. You can now make your entity constructors have any signature you want. EntityFactorynow requires a creation callback (usually a closure) with the signaturefunction(World, CompoundTag) : Entityto construct entities loaded from disk. This is required to allow entity classes to have custom constructor signatures. This callback should do any necessary actions to transform NBT into constructor parameters.- Example:
ItemEntitynow requires anItemin its constructor, so its creation callback decodes theItemfrom the NBT to be passed to the constructor. - Example:
Paintingnow requires aPaintingMotivein its constructor, so its creation callback decides whichPaintingMotiveto provide based on the NBT it receives. - See
EntityFactoryfor more examples.
- Example:
EntityFactory's responsibility as runtime entity creator has been removed. It's now solely responsible for restoring entities saved on disk.- Registering entities will now throw exceptions on error cases instead of returning
false. - The following API methods have been moved:
Entity::registerEntity()->EntityFactory::register()Entity::createBaseNBT()->EntityDataHelper::createBaseNBT()
- The following API methods have been removed:
Entity->getSaveId()Entity::getKnownEntityTypes()Entity::createEntity(): usenew YourEntityinstead (to be reviewed)
WIP removal of entity network metadata
- All network metadata related constants have been removed from the
Entityclass and moved to the protocol layer. It is intended to remove network metadata from the API entirely, but this has not yet been completed.Entity::DATA_FLAG_*constants have been moved topocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags.Entity::DATA_TYPE_*constants have been moved topocketmine\network\mcpe\protocol\types\entity\EntityMetadataTypes.Entity::DATA_*constants have been moved topocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties.
DataPropertyManagerhas been moved to thepocketmine\network\mcpe\protocol\types\entitynamespace, and as such isn't considered part of the API anymore.- Introduced internal
EntityhooksyncNetworkData(). This function is expected to synchronize entity properties with the entity's network data set. - Internal usage of network metadata sets to store internal entity properties has been removed. Entities are now expected to use regular class properties and synchronize with the network data set as-asked.
Entity->propertyManagerhas been renamed toEntity->networkProperties.Entity->getDataPropertyManager()has been renamed toEntity->getNetworkProperties().
Event
Internal event system no longer depends on Listeners
- The internal event processing system no longer depends on
Listenerobjects. Arbitrary closures can now be used, provided that they satisfy the standard requirements to be a handler.- This change improves performance of event handler calling by approximately 15%. This does not include anything plugins are doing.
- The following classes have been removed:
pocketmine\plugin\EventExecutorpocketmine\plugin\MethodEventExecutor
RegisteredListener->__construct()now requiresClosureinstead ofListener, EventExecutoras the leading parameters.RegisteredListener->getListener()has been removed.
Default cancelled handling behaviour has changed
- Handler functions will now not receive cancelled events by default. This is a silent BC break, i.e. it won't raise errors, but it might cause bugs.
@ignoreCancelledis now no longer respected.@handleCancelledhas been added. This allows opting into receiving cancelled events (it's the opposite of@ignoreCancelled).
PlayerPreLoginEvent changes
- The
Playerobject no longer exists at this phase of the login. Instead, aPlayerInfoobject is provided, along with connection information. - Ban, server-full and whitelist checks are now centralized to
PlayerPreLoginEvent. It's no longer necessary (or possible) to interceptPlayerKickEventto handle these types of disconnects.- Multiple kick reasons may be set to ensure that the player is still removed if there are other reasons for them to be disconnected and one of them is cleared. For example, if a player is banned and the server is full, clearing the ban flag will still cause the player to be disconnected because the server is full.
- Plugins may set custom kick reasons. Any custom reason has absolute priority.
- If multiple flags are set, the kick message corresponding to the highest priority reason will be shown. The priority (as of this snapshot) is as follows:
- Custom (highest priority)
- Server full
- Whitelisted
- Banned
- The
PlayerPreLoginEvent::KICK_REASON_PRIORITYconstant contains a list of kick reason priorities, highest first.
- The following constants have been added:
PlayerPreLoginEvent::KICK_REASON_PLUGINPlayerPreLoginEvent::KICK_REASON_SERVER_FULLPlayerPreLoginEvent::KICK_REASON_SERVER_WHITELISTEDPlayerPreLoginEvent::KICK_REASON_BANNEDPlayerPreLoginEvent::KICK_REASON_PRIORITY: ordered list of kick reason priorities, highest first
- The following API methods have been added:
PlayerPreLoginEvent->clearAllKickReasons()PlayerPreLoginEvent->clearKickReason()PlayerPreLoginEvent->getFinalKickMessage(): the message to be shown to the player with the current reason list in placePlayerPreLoginEvent->getIp()PlayerPreLoginEvent->getKickReasons(): returns an array of flags indicating kick reasons, must be empty to allow joiningPlayerPreLoginEvent->getPlayerInfo()PlayerPreLoginEvent->getPort()PlayerPreLoginEvent->isAllowed()PlayerPreLoginEvent->isAuthRequired(): whether XBL authentication will be enforcedPlayerPreLoginEvent->isKickReasonSet()PlayerPreLoginEvent->setAuthRequired()PlayerPreLoginEvent->setKickReason()
- The following API methods have been changed:
PlayerPreLoginEvent->getKickMessage()now has the signaturegetKickMessage(int $flag) : ?string
- The following API methods have been removed:
PlayerPreLoginEvent->setKickMessage()PlayerPreLoginEvent->getPlayer()
Other changes
- Disconnecting players during events no longer crashes the server (although it might cause other side effects).
PlayerKickEventis no longer fired for disconnects that occur before the player completes the initial login sequence (i.e. completing downloading resource packs).- Cancellable events must now implement
CancellableTraitto get the cancellable components needed to satisfy interface requirements. PlayerInteractEventis no longer fired when a player activates an item. This fixes the age-old complaint ofPlayerInteractEventfiring multiple times when interacting once. The following constants have been removed:PlayerInteractEvent::LEFT_CLICK_AIRPlayerInteractEvent::RIGHT_CLICK_AIRPlayerInteractEvent::PHYSICAL
- The following events have been added:
PlayerItemUseEvent: player activating their held item, for example to throw it.BlockTeleportEvent: block teleporting, for example dragon egg when attacked.
- The following events have been removed:
EntityArmorChangeEventEntityInventoryChangeEventEntityLevelChangeEvent-EntityTeleportEventwith world checks should be used instead.NetworkInterfaceCrashEventPlayerCheatEventPlayerIllegalMoveEvent
- The following API methods have been added:
EntityDeathEvent->getXpDropAmount()EntityDeathEvent->setXpDropAmount()PlayerDeathEvent->getXpDropAmount()PlayerDeathEvent->setXpDropAmount()
- The following API methods have been removed:
PlayerPreLoginEvent->getPlayer()
- The following API methods have been moved:
Event->isCancelled()->CancellableTrait->isCancelled(): this was a stub which threwBadMethodCallExceptionif the class didn't implementCancellable; now this is simply not available on non-cancellable eventsEvent->setCancelled()->CancellableTrait->setCancelled()HandlerList::unregisterAll()->HandlerListManager->unregisterAll()HandlerList::getHandlerListFor()->HandlerListManager->getListFor()HandlerList::getHandlerLists()->HandlerListManager->getAll()
- The following classes have been moved:
pocketmine\plugin\RegisteredListener->pocketmine\event\RegisteredListener
Inventory
- All crafting and recipe related classes have been moved to the
pocketmine\craftingnamespace. - The following classes have been added:
CallbackInventoryChangeListenerCreativeInventory: contains the creative functionality previously embedded inpocketmine\item\Item, see Item changes for detailsInventoryChangeListener: allows listening (but not interfering with) events in an inventory.transaction\CreateItemActiontransaction\DestroyItemAction
- The following classes have been renamed / moved:
ContainerInventory->pocketmine\block\inventory\BlockInventory
- The following classes have been moved to the
pocketmine\block\inventorynamespace:AnvilInventoryChestInventoryDoubleChestInventoryEnchantInventoryEnderChestInventoryFurnaceInventory
- The following classes have been removed:
CustomInventoryInventoryEventProcessorRecipetransaction\CreativeInventoryAction
- The following API methods have been added:
Inventory->addChangeListeners()Inventory->getChangeListeners()Inventory->removeChangeListeners()Inventory->swap(): swaps the contents of two slots
- The following API methods have been removed:
BaseInventory->getDefaultSize()BaseInventory->setSize()Inventory->close()Inventory->dropContents()Inventory->getName()Inventory->getTitle()Inventory->onSlotChange()Inventory->open()Inventory->sendContents()Inventory->sendSlot()InventoryAction->onExecuteFail()InventoryAction->onExecuteSuccess()PlayerInventory->sendCreativeContents()
- The following API methods have signature changes:
Inventory->clear()now returnsvoidinstead ofbool.Inventory->setItem()now returnsvoidinstead ofbool.InventoryAction->execute()now returnsvoidinstead ofbool.BaseInventory->construct()no longer accepts a list of items to initialize with.
PlayerInventory->setItemInHand()now sends the update to viewers of the player.
Item
General
- A new
VanillaItemsclass has been added, which contains static methods for creating any currently-known item type. This should be preferred instead of use ofItemFactory::get()where constants were used. Item->countis no longer public.- The hierarchy of writable books has been changed:
WritableBookandWrittenBooknow extendWritableBookBase. - The following API methods have signature changes:
WritableBookBase->setPages()now acceptsWritableBookPage[]instead ofCompoundTag[].ItemFactory::get()no longer acceptsstringfor thetagsparameter.ItemFactory::fromString()no longer accepts a$multipleparameter and now only returnsItem, notItem|Item[].
- The following methods are now fluent:
WritableBookBase->setPages()Item->addEnchantment()Item->removeEnchantment()Item->removeEnchantments()Armor->setCustomColor()WrittenBook->setTitle()WrittenBook->setAuthor()WrittenBook->setGeneration()
- The following API methods have been removed:
Item->getNamedTagEntry()Item->removeNamedTagEntry()Item->setDamage(): "Damage" is now immutable for all items exceptDurabledescendents.Item->setNamedTagEntry()Item::get(): this was superseded byItemFactory::get()a long time agoItem::fromString(): this was superseded byItemFactory::fromString()a long time agoItem->setCompoundTag()Item->getCompoundTag()Item->hasCompoundTag()ProjectileItem->getProjectileEntityType()
- The following methods have been renamed:
Item->getDamage()->Item->getMeta()
- The following methods have been moved to
pocketmine\inventory\CreativeInventory:Item::addCreativeItem()->CreativeInventory::add()Item::clearCreativeItems()->CreativeInventory::clear()Item::getCreativeItemIndex()->CreativeInventory::getItemIndex()Item::getCreativeItems()->CreativeInventory::getAll()Item::initCreativeItems()->CreativeInventory::init()Item::isCreativeItem()->CreativeInventory::contains()Item::removeCreativeItem()->CreativeInventory::remove()
- The following classes have been added:
ArmorTypeInfoFertilizerLiquidBucketMilkBucketWritableBookBaseWritableBookPage
- The following API methods have been added:
Armor->getArmorSlot()ProjectileItem->getProjectileEntityClass(): returns the class of projectile to be created when thrown
- The following classes have been removed:
ChainBootsChainChestplateChainHelmetChainLeggingsDiamondBootsDiamondChestplateDiamondHelmetDiamondLeggingsGoldBootsGoldChestplateGoldHelmetGoldLeggingsIronBootsIronChesplateIronHelmetIronLeggingsLeatherBootsLeatherCapLeatherPantsLeatherTunic
NBT handling
- Serialized NBT byte array caches are no longer stored on itemstacks. These caches were a premature optimization used for network layer serialization and as such were dependent on the network NBT format.
- Internal NBT usage has been marginalized. It's no longer necessary to immediately write changes to NBT. The following hooks have been added:
Item->serializeCompoundTag()Item->deserializeCompoundTag()
- It's planned to remove runtime NBT from items completely, but this currently presents unresolved backwards-compatibility problems.
Enchantment
VanillaEnchantmentsclass has been added. This exposes all vanilla enchantment types as static methods, replacing the oldEnchantment::get()nastiness.- Example:
Enchantment::get(Enchantment::PROTECTION)is replaced byVanillaEnchantments::PROTECTION() - These methods also provide proper type information to static analysers instead of just generic
Enchantment, making them easier to code with.
- Example:
- The boundaries between MCPE enchantment IDs and PocketMine-MP internals are now more clear.
- ID handling is moved to
pocketmine\data\bedrock\EnchantmentIdMap. - All enchantment ID constants have been removed from
Enchantment.pocketmine\data\bedrock\EnchantmentIdsif you still need legacy effect IDs for some reason.
- ID handling is moved to
Enchantment::RARITY_*constants were moved toRarityclass, and theRARITY_prefixes removed.Enchantment::SLOT_*constants were moved toItemFlagsclass, and theSLOT_prefixes removed.- The following API methods have been moved:
Enchantment::registerEnchantment()->EnchantmentIdMap->register()Enchantment::getEnchantment()->EnchantmentIdMap->fromId()Enchantment->getId()->EnchantmentIdMap->toId()Enchantment::getEnchantmentByName()->VanillaEnchantments::fromString()
- The following API methods have been added:
Enchantment->getRuntimeId(): this is a dynamic ID which can be used for enchantment type comparisons. This cannot be stored, so don't use it in configs or NBT!
Lang
- The following classes have been renamed:
BaseLang->Language
LanguageNotFoundExceptionhas been added. This is thrown when trying to construct aLanguagewhich doesn't exist in the server files.
Network
- The following fields have been removed:
Network::$BATCH_THRESHOLD
- The following classes have been renamed:
SourceInterface->NetworkInterfaceAdvancedSourceInterface->AdvancedNetworkInterface
- The following classes have been moved:
CompressBatchedTask->mcpe\CompressBatchTasklevel\format\io\ChunkRequestTask->mcpe\ChunkRequestTaskmcpe\RakLibInterface->mcpe\raklib\RakLibInterface
- The following classes have been removed:
mcpe\PlayerNetworkSessionAdapter
- The following methods have been removed:
NetworkInterface->putPacket()NetworkInterface->close()NetworkInterface->emergencyShutdown()
NetworkInterfacenow represents a more generic interface to be implemented by any network component, as opposed to specifically a player network interface.- Everything under the
rconsubnamespace has been removed. upnp\UPnPhas significant changes. It's now a network component instead of a pair of static methods.
Permission
- The following new permission nodes have been introduced:
pocketmine.group.everyone: granted to everyone by defaultpocketmine.group.operator: granted to operator players and the console These permission nodes can be assigned and overridden by permission attachments just like any other, which means it's now possible to grant temporary operator status which goes away when the player disconnects (or the attachment is removed).
- Permissions are now always false if they haven't been set explictly, or granted implicitly by another permission.
- Undefined permissions are now always
falseinstead of following the value ofPermission::$DEFAULT_PERMISSION. - Permissions internally no longer have default values. Instead, they are now assigned as a child of one of the
pocketmine.grouppermissions:true: add as child topocketmine.group.everyonewith valuetruefalse: do not add to any permissionop: add as child topocketmine.group.operatorwith valuetruenotop: add as child topocketmine.group.everyonewith valuetrue, and topocketmine.group.operatorwith valuefalseHowever, thedefaultkey inplugin.ymlpermission definitions continues to be supported.
- Added
PermissibleDelegateTraitto reduce boilerplate for users ofPermissibleBase. This trait is used byConsoleCommandSenderandPlayer. - The following API methods have been moved:
Permission::getByName()->PermissionParser::defaultFromString()Permission::loadPermissions()->PermissionParser::loadPermissions()Permission::loadPermission()->PermissionParser::loadPermission()
- The following constants have been moved:
Permission::DEFAULT_FALSE->PermissionParser::DEFAULT_FALSEPermission::DEFAULT_TRUE->PermissionParser::DEFAULT_TRUEPermission::DEFAULT_OP->PermissionParser::DEFAULT_OPPermission::DEFAULT_NOT_OP->PermissionParser::DEFAULT_NOT_OP
- The following API methods have been added:
Permission->addChild()Permission->removeChild()
- The following API methods have been removed:
Permissible->isOp(): usePermissible->hasPermission(DefaultPermissions::ROOT_OPERATOR)instead, but you really shouldn't directly depend on a player's op status, add your own permissions instead!Permissible->setOp(): useaddAttachment($plugin, DefaultPermissions::ROOT_OPERATOR, true)instead to add, andremoveAttachment()to remove it (or addAttachment() with false to explicitly deny it, just like any other permission)Permission->addParent()Permission->getDefault()Permission->setDefault()PermissionManager->getDefaultPermissions()PermissionManager->recalculatePermissionDefaults()PermissionManager->subscribeToDefaultPerms()PermissionManager->unsubscribeFromDefaultPerms()PermissionManager->getDefaultPermSubscriptions()
- The following fields have been removed:
Permission::$DEFAULT_PERMISSION
- The following API methods have changes:
PermissionParser::defaultFromString()now throwsInvalidArgumentExceptionon unknown values.Permission->__construct()no longer accepts a$defaultValueparameter (see notes above about defaults refactor).you should add your permission as a child ofpocketmine.group.everyoneorpocketmine.group.operatorinstead).
- The following classes have been removed:
ServerOperator
Player
- The following classes have moved to the new
pocketmine\playernamespace:AchievementGameModeIPlayerOfflinePlayerPlayerInfoPlayer
- The following constants have been removed:
Player::SURVIVAL- useGameMode::SURVIVAL()Player::CREATIVE- useGameMode::CREATIVE()Player::ADVENTURE- useGameMode::ADVENTURE()Player::SPECTATOR- useGameMode::SPECTATOR()Player::VIEW- useGameMode::SPECTATOR()
- (almost) all packet handlers have been removed from
Player. They are now encapsulated within the network layer. - The following API methods have been added:
Player->attackBlock(): attack (left click) the target block, e.g. to start destroying it (survival)Player->attackEntity(): melee-attack (left click) the target entity (if within range)Player->breakBlock(): destroy the target block in the current world (immediately)Player->consumeHeldItem(): consume the previously activated item, e.g. eating foodPlayer->continueBreakBlock(): punch the target block during destruction in survival, advancing break animation and creating particlesPlayer->getItemCooldownExpiry(): returns the tick on which the player's cooldown for a given item expiresPlayer->hasFiniteResources()Player->interactBlock(): interact (right click) the target block in the current worldPlayer->interactEntity(): interact (right click) the target entity, e.g. to apply a nametag (not implemented yet)Player->pickBlock(): picks (mousewheel click) the target block in the current worldPlayer->releaseHeldItem(): release the previously activated item, e.g. shooting a bowPlayer->selectHotbarSlot(): select the specified hotbar slotPlayer->stopBreakBlock(): cease attacking a previously attacked blockPlayer->toggleFlight(): tries to start / stop flying (fires events, may be cancelled)Player->updateNextPosition(): sets the player's next attempted move location (fires events, may be cancelled)Player->useHeldItem(): activate the held item, e.g. throwing a snowball
- The following API methods have been removed:
Player->addActionBarMessage(): replaced bysendActionBarMessage()Player->addSubTitle(): replaced bysendSubTitle()Player->addTitle(): replaced bysendTitle()Player->getAddress(): replaced byNetworkSession->getIp()Player->getPing(): moved toNetworkSessionPlayer->getPort(): moved toNetworkSessionPlayer->updatePing(): moved toNetworkSessionPlayer->dataPacket(): replaced byNetworkSession->sendDataPacket()Player->sendDataPacket(): replaced byNetworkSession->sendDataPacket()IPlayer->isWhitelisted(): useServer->isWhitelisted()insteadIPlayer->setWhitelisted(): useServer->setWhitelisted()insteadIPlayer->isBanned(): this was unreliable because it only checked name bans and didn't account for plugin custom ban systems. UseServer->getNameBans()->isBanned()andServer->getIPBans()->isBanned()instead.IPlayer->setBanned(): useServerAPIs insteadIPlayer->isOp(): useServerAPIs insteadIPlayer->setOp(): useServerAPIs instead
Plugin
- API version checks are now more strict. It is no longer legal to declare multiple minimum versions on the same major version. Doing so will now cause the plugin to fail to load with the message
Multiple minimum API versions found for some major versions. plugin.ymlYAML commands loading is now internalized insidePluginBase.PluginManager->registerEvent()now has a simpler signature:registerEvent(string $event, \Closure $handler, int $priority, Plugin $plugin, bool $handleCancelled = false). The provided closure must accept the specified event class as its only parameter. See Event API changes for more details.- The following classes have been removed:
PluginLogger
- The following interface requirements have been removed:
Plugin->onEnable(): this is now internalized insidePluginBasePlugin->onDisable(): same as abovePlugin->onLoad(): same as abovePluginno longer extendsCommandExecutor. This means thatPluginimplementations don't need to implementonCommand()anymore.
- The following hook methods have changed visibility:
PluginBase->onEnable()changed frompublictoprotectedPluginBase->onDisable()changed frompublictoprotectedPluginBase->onLoad()changed frompublictoprotected
- The following hook methods have been renamed:
Plugin->setEnabled()->Plugin->onEnableStateChange(). This change was made to force plugin developers misusing this hook to stop, and to give it a name that better describes what it does.
- The following (deprecated) API methods have been removed:
PluginManager->callEvent(): useEvent->call()insteadPluginManager->addPermission(): usePermissionManagerinsteadPluginManager->getDefaultPermSubscriptions(): usePermissionManagerinsteadPluginManager->getDefaultPermissions(): usePermissionManagerinsteadPluginManager->getPermission(): usePermissionManagerinsteadPluginManager->getPermissionSubscriptions(): usePermissionManagerinsteadPluginManager->getPermissions(): usePermissionManagerinsteadPluginManager->recalculatePermissionDefaults(): usePermissionManagerinsteadPluginManager->removePermission(): usePermissionManagerinsteadPluginManager->subscribeToDefaultPerms(): usePermissionManagerinsteadPluginManager->subscribeToPermission(): usePermissionManagerinsteadPluginManager->unsubscribeFromDefaultPerms(): usePermissionManagerinsteadPluginManager->unsubscribeFromPermission(): usePermissionManagerinstead
- It is no longer permitted to throw exceptions from
PluginBase->onEnable()orPluginBase->onLoad(). Doing so will now cause the server to crash.
Scheduler
Thread-local storage for AsyncTasks
- TLS has been completely rewritten in this release to be self contained, more robust and easier to use.
- Now behaves more like simple properties.
storeLocal()writes,fetchLocal()reads. - Self-contained and doesn't depend on the async pool to clean up after it.
- Values are automatically removed from storage when the
AsyncTaskis garbage-collected, just like a regular property. - Supports storing multiple values, differentiated by string names.
fetchLocal()can now be used multiple times. It no longer deletes the stored value.- The following classes have been removed:
FileWriteTask
- The following methods have been removed:
AsyncTask->peekLocal(): usefetchLocal()instead
- The following methods have signature changes:
AsyncTask->storeLocal()now has the signaturestoreLocal(string $key, mixed $complexData) : voidAsyncTask->fetchLocal()now has the signaturefetchLocal(string $key) : mixed
Other changes
AsyncPooluses a new, significantly more performant algorithm for task collection.BulkCurlTaskhas had the$complexDataconstructor parameter removed.pocketmine\Collectablehas been removed, and is no longer extended byAsyncTask.- The following hooks have been added:
AsyncTask->onError(): called on the main thread when an uncontrolled error was detected in the async task, such as a memory failure
- The following hooks have signature changes:
AsyncTask->onCompletion()no longer accepts aServerparameter, and has avoidreturn type.AsyncTask->onProgressUpdate()no longer accepts aServerparameter, and has avoidreturn type.
- The following API methods have been removed:
AsyncTask->getFromThreadStore(): useAsyncTask->worker->getFromThreadStore()AsyncTask->removeFromThreadStore(): useAsyncTask->worker->removeFromThreadStore()AsyncTask->saveToThreadStore(): useAsyncTask->worker->saveToThreadStore()
Server
- The following API methods have been added:
subscribeToBroadcastChannel()- allows subscribing aCommandSenderto receive chat messages (and other message types) on any channelunsubscribeFromBroadcastChannel()unsubscribeFromAllBroadcastChannels()getBroadcastChannelSubscribers()
- The following API methods have been removed:
reloadWhitelist()getLevelMetadata()getPlayerMetadata()getEntityMetadata()getDefaultGamemode()getLoggedInPlayers()onPlayerLogout()addPlayer()removePlayer()reload()getSpawnRadius()enablePlugin()disablePlugin()getGamemodeString()- replaced bypocketmine\player\GameMode->getTranslationKey()getGamemodeName()- replaced bypocketmine\player\GameMode->name()getGamemodeFromString()- replaced byGameMode::fromString()broadcast()- usebroadcastMessage()instead
- The following API methods have changed:
getOfflinePlayerData()no longer creates data when it doesn't exist.
- The following API methods have been renamed:
getPlayer()->getPlayerByPrefix()(consider usinggetPlayerExact()instead where possible)
Level / World
General
- All references to
Levelin the context of "world" have been changed toWorld.- The
pocketmine\levelnamespace has been renamed topocketmine\world - All classes containing the world
Levelin the name in the "world" context have been changed toWorld. Position->getLevel()has been renamed toPosition->getWorld(), andPosition->levelhas been renamed toPosition->world.
- The
- Extracted a
WorldManagerunit fromServerServer->findEntity()->WorldManager->findEntity()Server->generateLevel()->WorldManager->generateWorld()Server->getAutoSave()->WorldManager->getAutoSave()Server->getDefaultLevel()->WorldManager->getDefaultWorld()Server->getLevel()->WorldManager->getWorld()Server->getLevelByName()->WorldManager->getWorldByName()Server->getLevels()->WorldManager->getWorlds()Server->isLevelGenerated()->WorldManager->isWorldGenerated()Server->isLevelLoaded()->WorldManager->isWorldLoaded()Server->loadLevel()->WorldManager->loadWorld()WorldManager->loadWorld()may convert worlds if requested (the$autoUpgradeparameter must be provided).
Server->setAutoSave()->WorldManager->setAutoSave()Server->setDefaultLevel()->WorldManager->setDefaultWorld()Server->unloadLevel()->WorldManager->unloadWorld()
- Added
WorldManager->getAutoSaveTicks()andWorldManager->setAutoSaveTicks()to allow controlling the autosave interval. - The following classes have been added:
BlockTransaction: allows creating batch commits of block changes with validation conditions - if any block can't be applied, the whole transaction fails to apply.ChunkListenerNoOpTrait: contains default no-op stubs for chunk listener implementationsChunkListener: interface allowing subscribing to events happening on a given chunk
- The following classes have been renamed:
pocketmine\world\utils\SubChunkIteratorManager->pocketmine\world\utils\SubChunkExplorer
- The following API methods have been added:
World->registerChunkListener()World->unregisterChunkListener()Chunk->isDirty()(replacement forChunk->hasChanged())Chunk->getDirtyFlag()(more granular component-based chunk dirty-flagging, used to avoid saving unmodified parts of the chunk)Chunk->setDirty()Chunk->setDirtyFlag()
- The following API methods have been removed:
ChunkLoader->getLoaderId()(now object ID is used)ChunkLoader->isLoaderActive()ChunkLoader->getPosition()ChunkLoader->getLevel()Chunk->fastSerialize()(useFastChunkSerializer::serialize()instead)Chunk->getBlockData()Chunk->getBlockDataColumn()Chunk->getBlockId()Chunk->getBlockIdColumn()Chunk->getBlockLight()Chunk->getBlockLightColumn()Chunk->getBlockSkyLight()Chunk->getBlockSkyLightColumn()Chunk->getMaxY()Chunk->getSubChunkSendCount()(this was specialized for protocol usage)Chunk->getX()Chunk->getZ()Chunk->hasChanged()(useChunk->isDirty()orChunk->getDirtyFlag()instead)Chunk->isGenerated()Chunk->networkSerialize()(seeChunkSerializerin thenetwork\mcpe\serializerpackage)Chunk->populateSkyLight()(useSkyLightUpdate->recalculateChunk()instead)Chunk->recalculateHeightMap()(moved toSkyLightUpdate)Chunk->recalculateHeightMapColumn()(moved toSkyLightUpdate)Chunk->setAllBlockLight()Chunk->setAllBlockSkyLight()Chunk->setBlock()Chunk->setBlockData()Chunk->setBlockId()Chunk->setBlockLight()Chunk->setBlockSkyLight()Chunk->setChanged()(useChunk->setDirty()orChunk->setDirtyFlag()instead)Chunk->setGenerated()Chunk->setX()Chunk->setZ()Chunk::fastDeserialize()(useFastChunkSerializer::deserialize()instead)World->isFullBlock()World->getFullBlock()World->getBlockIdAt()World->setBlockIdAt()World->getBlockDataAt()World->setBlockDataAt()World->setBlockLightAt()World->setBlockSkyLightAt()World->getBlockSkyLightAt()(useWorld->getRealBlockSkyLightAt()orWorld->getPotentialBlockSkyLightAt(), depending on use-case)World->getHeightMap()(misleading name, only actually useful for sky light calculation - you probably wantgetHighestBlockAt()instead)World->setHeightMap()(misleading name, only actually useful for sky light calculation)World->getChunkEntities()World->getChunkTiles()World->getTileById()World->checkSpawnProtection()World->updateBlockLight()World->updateSkyLight()World->isFullBlock()(useBlock->isFullCube()instead)World->sendBlocks()World->sendTime()World->addGlobalPacket()World->broadcastGlobalPacket()World->addChunkPacket()World->broadcastLevelSoundEvent()World->broadcastLevelEvent()World->getTickRate()World->setTickRate()World::generateChunkLoaderId()
- The following API methods have changed signatures:
World->addParticle()now has the signatureaddParticle(Vector3 $pos, Particle $particle, ?Player[] $players = null) : voidWorld->addSound()now has the signatureaddSound(?Vector3 $pos, Sound $sound, ?Player[] $players = null) : voidWorld->getRandomTickedBlocks()now returnsbool[]instead ofSplFixedArray.World->addRandomTickedBlock()now acceptsBlockinstead ofint, int.World->removeRandomTickedBlock()now acceptsBlockinstead ofint, int.World->setBlock()has had the$directparameter removed.World->loadChunk()now returns?Chunk, and the$createparameter has been removed.World->getChunk()no longer accepts a$createparameter.World->updateAllLight()now acceptsint, int, intinstead ofVector3.Chunk->__construct()now has the signaturearray<int, SubChunk> $subChunks, ?list<CompoundTag> $entities, ?list<CompoundTag> $tiles, ?BiomeArray $biomeArray, ?HeightArray $heightArray.Chunk->getSubChunk()now returnsSubChunkinstead ofSubChunkInterface|null(and throwsInvalidArgumentExceptionon out-of-bounds coordinates).Chunk->setSubChunk()no longer acceptsSubChunkInterface, and the$allowEmptyparameter has been removed.
- The following API methods have been renamed / moved:
Level->getCollisionCubes()->World->getCollisionBoxes()World->getName()->World->getDisplayName()
- The following API methods have changed behaviour:
World->getChunk()no longer tries to load chunks from disk. If the chunk is not already in memory, null is returned. (This behaviour now properly matches otherChunkManagerimplementations.)- The following methods now throw
WorldExceptionwhen targeting ungenerated terrain:World->getSafeSpawn()(previously it just silently returned the input position)World->getHighestBlockAt()(previously it returned -1)
World->loadChunk()no longer creates an empty chunk when the target chunk doesn't exist on disk.World->setChunk()now firesChunkLoadEventandChunkListener->onChunkLoaded()when replacing a chunk that didn't previously exist.World->useBreakOn()now returnsfalsewhen the target position is in an ungenerated or unloaded chunk (or chunk locked for generation).World->useItemOn()now returnsfalsewhen the target position is in an ungenerated or unloaded chunk (or chunk locked for generation).
- A
ChunkListenerinterface has been extracted fromChunkLoader. The following methods have been moved:ChunkLoader->onBlockChanged()->ChunkListener->onBlockChanged()ChunkLoader->onChunkChanged()->ChunkListener->onChunkChanged()ChunkLoader->onChunkLoaded()->ChunkListener->onChunkLoaded()ChunkLoader->onChunkPopulated()->ChunkListener->onChunkPopulated()ChunkLoader->onChunkUnloaded()->ChunkListener->onChunkUnloaded()
Locationhas been moved topocketmine\entity\Location.
Particles
DustParticle->__construct()now accepts apocketmine\utils\Colorobject instead ofr, g, b, a.pocketmine\world\particle\Particleno longer extendspocketmine\math\Vector3, and has been converted to an interface.- Added the following
Particleclasses:DragonEggTeleportParticlePunchBlockParticle
Sounds
pocketmine\world\sound\Soundno longer extendspocketmine\math\Vector3, and has been converted to an interface.Sound->encode()now accepts?\pocketmine\math\Vector3.NULLmay be passed for sounds which are global.- Added the following classes:
ArrowHitSoundBlockBreakSoundBlockPlaceSoundBowShootSoundBucketEmptyLavaSoundBucketEmptyWaterSoundBucketFillLavaSoundBucketFillWaterSoundChestCloseSoundChestOpenSoundEnderChestCloseSoundEnderChestOpenSoundExplodeSoundFlintSteelSoundItemBreakSoundNoteInstrumentNoteSoundPaintingPlaceSoundPotionSplashSoundRedstonePowerOffSoundRedstonePowerOnSoundThrowSoundXpCollectSoundXpLevelUpSound
Utils
- The
Colorclass was removed. It's now found aspocketmine\color\Colorin thepocketmine/colorpackage. - The
UUIDclass was removed. It's now found aspocketmine\uuid\UUIDin thepocketmine/uuidpackage. Terminal::hasFormattingCodes()no longer auto-detects the availability of formatting codes. Instead it's necessary to useTerminal::init()with no parameters to initialize, ortrueorfalseto override.Config->save()no longer catches exceptions thrown during emitting to disk.- The following new classes have been added:
InternetExceptionInternetProcess
- The following API methods have been added:
Config->getPath(): returns the path to the config on diskTerminal::write(): emits a Minecraft-formatted text line without newlineTerminal::writeLine(): emits a Minecraft-formatted text line with newlineUtils::recursiveUnlink(): recursively deletes a directory and its contents
- The following deprecated API redirects have been removed:
Utils::execute(): moved toProcessUtils::getIP(): moved toInternetUtils::getMemoryUsage(): moved toProcessUtils::getRealMemoryUsage(): moved toProcessUtils::getThreadCount(): moved toProcessUtils::getURL(): moved toInternetUtils::kill(): moved toProcessUtils::postURL(): moved toInternetUtils::simpleCurl(): moved toInternet
- The following API fields have been removed / hidden:
Utils::$ipUtils::$onlineUtils::$os
- The following API methods have signature changes:
Internet::simpleCurl()now requires aClosurefor itsonSuccessparameter instead ofcallable.
- The following API methods have been removed:
Utils::getCallableIdentifier()