74 KiB
4.0.0-BETA1
Released 7th September 2021.
This major version features substantial changes throughout the core, including significant API changes, new world format support, performance improvements and a network revamp.
Please note that this is a BETA release and is not finalized. While no significant changes are expected between now and release, the API might still be changed.
Please also note that this changelog is provided on a best-effort basis, and it's possible some changes might not have been mentioned here. If you find any omissions, please submit pull requests to add them.
WARNING
This is NOT a stable release. PMMP accepts no responsibility or liability for any damages incurred by using this build. It should be used for TESTING purposes only.
Contents
- Core
- API
- Gameplay
Table of contents generated with markdown-toc
Core
General
- A new "plugin greylist" feature has been introduced, which allows whitelisting or blacklisting plugins from loading.
- 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.
- GS4 Query no longer breaks when disabling RakLib.
- The
pocketmine_chunkutils
PHP extension has been dropped. - New PHP extensions are required by this version:
- Many bugs in player respawning have been fixed, including:
- Spawning underneath bedrock when spawn position referred to ungenerated terrain
- Spawning underneath bedrock on first server join on very slow machines (or when the machine was under very high load)
- Spawning inside blocks (or above the ground) when respawning with a custom spawn position set
- Player spawn positions sticking to the old location when world spawn position changed - this was because the world spawn at time of player creation was used as the player's custom spawn, so the bug will persist for older player data, but will work as expected for new players.
- PreProcessor is removed from builds due to high maintenance cost and low benefit. Its usage is now discouraged.
Commands
- The
/reload
command has been removed. - The
/effect
command no longer supports numeric IDs - it's now required to use names. - The
/enchant
command no longer supports numeric IDs - it's now required to use names. - Added
/clear
command with functionality equivalent to that of vanilla Minecraft. - The following commands' outputs are now localized according to the chosen language settings:
/gc
/status
/op
/deop
Configuration
- World presets can now be provided as a
preset
key inpocketmine.yml
, instead of putting them in thegenerator
key. - The following new options have been added to
pocketmine.yml
:chunk-ticking.blocks-per-subchunk-per-tick
(default3
): Increasing this value will increase the rate at which random block updates happen (e.g. grass growth).network.enable-encryption
(defaulttrue
): Controls whether Minecraft network packets are encrypted or not.
- The following options have been removed from
pocketmine.yml
:chunk-ticking.light-updates
: Since lighting is needed for basic vanilla functionality to work, allowing this to be disabled without disabling chunk ticking made no sense. If you don't want light calculation to occur, you can disable chunk ticking altogether.player.anti-cheat.allow-movement-cheats
World handling
Interface
- Progress of spawn terrain chunk generation is now logged during initial world creation.
Functional
- Minecraft Bedrock worlds up to 1.12.x are now supported. (1.13+ are still not supported due to yet another format change, which is large and requires a lot of work).
- Automatic conversion of deprecated world formats is now implemented.
- All formats except
leveldb
have been deprecated. The following world formats will be automatically converted on load to a new format:mcregion
anvil
pmanvil
- 256 build-height is now supported in all worlds (facilitated by automatic conversion).
- Extended blocks are now supported (facilitated by automatic conversion).
- 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
leveldb
is 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
leveldb
world 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 add
and/whitelist remove
no longer cause player data to be loaded from disk for no reason.- Timings now use high-resolution timers provided by
hrtime()
to collect more accurate performance metrics. - Z-order curves (morton codes) are now used for block and chunk coordinate hashes. This substantially improves performance in many areas by resolving a hashtable key hash collision performance issue. Affected areas include explosions, light calculation, and more.
libdeflate
is now (optionally) used for outbound Minecraft packet compression. It's more than twice as fast as zlib in most cases, providing significant performance boosts to packet broadcasts and overall network performance.- Closures are now used for internal event handler calls. This provides a performance improvement of 10-20% over the 3.x system, which had to dynamically resolve callables for every event call.
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-encryption
which istrue
by default.
Packet receive error handling has been overhauled
- Only
BadPacketException
is now caught during packet decode and handling. This requires that all decoding MUST perform proper data error checking.- Throwing a
BadPacketException
from 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 error
has 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
Player
and instead appear in their own dedicated units. - Almost all game logic that was previously locked up inside packet handlers in
Player
has been extracted into new API methods. See Player API changes for details.
API
General
- Most places which previously allowed
callable
now only allow\Closure
. This is because closures have more consistent behaviour and are more performant. void
and?nullable
parameter and return types have been applied in many places.- Everything in the
pocketmine\metadata
namespace and related implementations have been removed.
Changes to plugin.yml
Permission nesting
Permission nesting is no longer supported in plugin.yml
. Grouping permissions (with defaults) in plugin.yml
had very confusing and inconsistent behaviour.
Instead of nesting permission declarations, they should each be declared separately.
Before:
permissions:
pmmp:
default: op
children:
pmmp.something:
default: op
pmmp.somethingElse
default: op
After:
permissions:
pmmp.something:
default: op
pmmp.somethingElse
default: op
src-namespace-prefix
A new directive src-namespace-prefix
has been introduced. This allows you to get rid of those useless subdirectories in a plugin's structure.
For example, a plugin whose main was pmmp\TesterPlugin\Main
used to have to be structured like this:
|-- plugin.yml
|-- src/
|-- pmmp/
|-- TesterPlugin/
|-- Main.php
|-- SomeOtherClass.php
|-- SomeNamespace/
|-- SomeNamespacedClass.php
However, if we add src-namespace-prefix: pmmp\TesterPlugin
to the plugin.yml
, now we can get rid of the useless directories and structure it like this instead:
|-- plugin.yml
|-- src/
|-- Main.php
|-- SomeOtherClass.php
|-- SomeNamespace/
|-- SomeNamespacedClass.php
Note: The old structure will also still work just fine. This is not a required change.
Block
- A new
VanillaBlocks
class 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->getPosition()
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.- All blocks now have getters and setters for their appropriate block properties, such as facing, lit/unlit, colour (in some cases), and many more. These should be used instead of metadata.
- 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
Block
classes, with the tile entity classes being deprecated. - The
pocketmine\tile
namespace has been relocated topocketmine\block\tile
. Block->recalculateBoundingBox()
andBlock->recalculateCollisionBoxes()
are now expected to return AABBs relative to0,0,0
instead of their own position.- Block break-info has been extracted into a new dynamic
BlockBreakInfo
unit. 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->onEntityLand()
: called when an entity lands on this block after falling (from any distance)Block->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) : bool
Block->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
->BlockLegacyIds
CobblestoneWall
->Wall
NoteBlock
->Note
SignPost
->Sign
StandingBanner
->Banner
- The following classes have been removed:
Bricks
BurningFurnace
CobblestoneStairs
Dandelion
DoubleSlab
DoubleStoneSlab
EndStone
GlowingRedstoneOre
GoldOre
Gold
IronDoor
IronOre
IronTrapdoor
Iron
Lapis
NetherBrickFence
NetherBrickStairs
Obsidian
PurpurStairs
Purpur
QuartzStairs
Quartz
RedSandstoneStairs
RedSandstone
SandstoneStairs
Sandstone
StainedClay
StainedGlassPane
StainedGlass
StoneBrickStairs
StoneBricks
StoneSlab2
StoneSlab
Stone
WallBanner
WallSign
Wood2
BlockToolType
constants 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).
- Commands with spaces in the name are no longer supported.
Entity
General
Entity
no longer extends fromLocation
.Entity->getLocation()
andEntity->getPosition()
should be used instead.- The following public fields have been removed:
Entity->chunk
: Entities no longer know which chunk they are in (theWorld
now manages this instead).Entity->height
: moved toEntitySizeInfo
; useEntity->size
insteadEntity->width
: moved toEntitySizeInfo
; useEntity->size
insteadEntity->eyeHeight
: moved toEntitySizeInfo
; useEntity->size
instead
- The following API methods have been added:
Entity->getFallDistance()
Entity->setFallDistance()
ItemEntity->getDespawnDelay()
ItemEntity->setDespawnDelay()
Living->calculateFallDamage()
: this isprotected
, and may be overridden by subclasses to provide custom damage logicHuman->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 returnsEffectManager
instead ofEffect[]
.
- The following classes have been added:
effect\EffectManager
: contains effect-management functionality extracted fromLiving
HungerManager
: contains hunger-management functionality extracted fromHuman
ExperienceManager
: contains XP-management functionality extracted fromHuman
- The following API methods have been moved / renamed:
Entity->fall()
->Entity->onHitGround()
(and visibility changed toprotected
frompublic
)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:
Creature
Damageable
Monster
NPC
Rideable
Vehicle
Skin
now throws exceptions on creation if given invalid data.
Effect
- All
Effect
related classes have been moved to thepocketmine\entity\effect
namespace. - Effect functionality embedded in the
Effect
class has been separated out into several classes. The following classes have been added:AbsorptionEffect
HealthBoostEffect
HungerEffect
InstantDamageEffect
InstantEffect
InstantHealthEffect
InvisibilityEffect
LevitationEffect
PoisonEffect
RegenerationEffect
SaturationEffect
SlownessEffect
SpeedEffect
WitherEffect
VanillaEffects
class 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\EffectIds
if 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->namedtag
has been removed.Entity->saveNBT()
now returns a newly createdCompoundTag
instead of modifying the previous one in-place.Entity->initEntity()
now accepts aCompoundTag
parameter.
Entity creation
Entity::createEntity()
has been removed. It's no longer needed for creating new entities at runtime - just usenew YourEntity
instead.Entity
subclass constructors can now have any signature, just like a normal class.- Loading entities from NBT is now handled by
EntityFactory
. It works quite a bit differently thanEntity::createEntity()
did. Instead of registeringYourEntity::class
to a set of Minecraft save IDs, you now need to provide a callback which will construct an entity when given some NBT and aWorld
.- The creation callback is registered using
EntityFactory::register()
. - The creation callback must have the signature
function(World, CompoundTag) : Entity
. - This enables
Entity
subclasses to have any constructor parameters they like. - It also allows requiring that certain data is always provided (for example, it doesn't make much sense to create a
FallingBlock
without specifying what type of block). - Examples:
ItemEntity
now requires anItem
in its constructor, so its creation callback decodes theItem
from the NBT to be passed to the constructor.Painting
now requires aPaintingMotive
in its constructor, so its creation callback decides whichPaintingMotive
to provide based on the NBT it receives.- See
EntityFactory
for more examples.
- The creation callback is registered using
EntityFactory::register()
(previouslyEntity::registerEntity()
) will now throw exceptions on error cases instead of returningfalse
.- The following API methods have been moved:
Entity::registerEntity()
->EntityFactory::register()
- The following classes have changed constructors:
- All projectile subclasses now require a
?Entity $thrower
parameter. Arrow->__construct()
now requires abool $critical
parameter (in addition to the$thrower
parameter).ExperienceOrb->__construct()
now requires aint $xpValue
parameter.FallingBlock->__construct()
now requires aBlock $block
parameter.ItemEntity->__construct()
now requires anItem $item
parameter.Painting->__construct()
now requires aPaintingMotive $motive
parameter.SplashPotion->__construct()
now requires aint $potionId
parameter.
- All projectile subclasses now require a
- The following API methods have been removed:
Entity::createBaseNBT()
:new YourEntity
and appropriate API methods should be used insteadEntity->getSaveId()
Entity::getKnownEntityTypes()
Entity::createEntity()
: usenew YourEntity
instead (to be reviewed)
WIP removal of entity network metadata
- All network metadata related constants have been removed from the
Entity
class 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
.
DataPropertyManager
has been moved to thepocketmine\network\mcpe\protocol\types\entity
namespace, and as such isn't considered part of the API anymore.- Introduced internal
Entity
hooksyncNetworkData()
. 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->propertyManager
has been renamed toEntity->networkProperties
.Entity->getDataPropertyManager()
has been renamed toEntity->getNetworkProperties()
.
Event
Internal event system no longer depends on Listener
s
- The internal event processing system no longer depends on
Listener
objects. 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\EventExecutor
pocketmine\plugin\MethodEventExecutor
RegisteredListener->__construct()
now requiresClosure
instead ofListener, EventExecutor
as 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.
@ignoreCancelled
is now no longer respected.@handleCancelled
has been added. This allows opting into receiving cancelled events (it's the opposite of@ignoreCancelled
).
PlayerPreLoginEvent
changes
- The
Player
object no longer exists at this phase of the login. Instead, aPlayerInfo
object 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 interceptPlayerKickEvent
to 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_PRIORITY
constant contains a list of kick reason priorities, highest first.
- The following constants have been added:
PlayerPreLoginEvent::KICK_REASON_PLUGIN
PlayerPreLoginEvent::KICK_REASON_SERVER_FULL
PlayerPreLoginEvent::KICK_REASON_SERVER_WHITELISTED
PlayerPreLoginEvent::KICK_REASON_BANNED
PlayerPreLoginEvent::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()
- The following API methods have been moved / renamed:
InventoryPickupItemEvent->getItem()
->InventoryPickupItemEvent->getItemEntity()
Other changes
- Disconnecting players during events no longer crashes the server (although it might cause other side effects).
PlayerKickEvent
is 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
CancellableTrait
to get the cancellable components needed to satisfy interface requirements.Event
no longer stubs these methods. PlayerInteractEvent
is no longer fired when a player activates an item. This fixes the age-old complaint ofPlayerInteractEvent
firing multiple times when interacting once. The following constants have been removed:PlayerInteractEvent::LEFT_CLICK_AIR
PlayerInteractEvent::RIGHT_CLICK_AIR
PlayerInteractEvent::PHYSICAL
- The following events have been added:
PlayerEntityInteractEvent
: player right-clicking (or long-clicking on mobile) on an entity.PlayerItemUseEvent
: player activating their held item, for example to throw it.BlockTeleportEvent
: block teleporting, for example dragon egg when attacked.PlayerDisplayNameChangeEvent
EntityItemPickupEvent
: player (or other entity) picks up a dropped item (or arrow). ReplacesInventoryPickupItemEvent
andInventoryPickupArrowEvent
.- Unlike its predecessors, this event supports changing the destination inventory.
- If the destination inventory is
null
, the item will be destroyed. This is usually seen for creative players with full inventories.
EntityTrampleFarmlandEvent
: mob (or player) jumping on farmland causing it to turn to dirtStructureGrowEvent
: called when trees or bamboo grow (or any other multi-block plant structure).
- The following events have been removed:
EntityArmorChangeEvent
EntityInventoryChangeEvent
EntityLevelChangeEvent
-EntityTeleportEvent
with world checks should be used instead.InventoryPickupItemEvent
- useEntityItemPickupEvent
insteadInventoryPickupArrowEvent
- useEntityItemPickupEvent
insteadNetworkInterfaceCrashEvent
PlayerCheatEvent
PlayerIllegalMoveEvent
- The following API methods have been added:
EntityDeathEvent->getXpDropAmount()
EntityDeathEvent->setXpDropAmount()
PlayerDeathEvent->getXpDropAmount()
PlayerDeathEvent->setXpDropAmount()
- The following API methods have been removed:
PlayerPreLoginEvent->getPlayer()
Cancellable->setCancelled()
: this allows implementors ofCancellable
to implement their own cancellation mechanisms, such as the complex one inPlayerPreLoginEvent
- The following API methods have been moved:
Event->isCancelled()
->CancellableTrait->isCancelled()
: this was a stub which threwBadMethodCallException
if the class didn't implementCancellable
; now this is simply not available on non-cancellable eventsEvent->setCancelled()
has been split intocancel()
anduncancel()
, and moved toCancellableTrait
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\crafting
namespace. - The following classes have been added:
CallbackInventoryChangeListener
CreativeInventory
: 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\CreateItemAction
transaction\DestroyItemAction
- The following classes have been renamed / moved:
ContainerInventory
->pocketmine\block\inventory\BlockInventory
- The following classes have been moved to the
pocketmine\block\inventory
namespace:AnvilInventory
ChestInventory
DoubleChestInventory
EnchantInventory
EnderChestInventory
FurnaceInventory
- The following classes have been removed:
CustomInventory
InventoryEventProcessor
Recipe
transaction\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 returnsvoid
instead ofbool
.Inventory->setItem()
now returnsvoid
instead ofbool
.InventoryAction->execute()
now returnsvoid
instead 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
VanillaItems
class 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. StringToItemParser
has been added, which allows mapping any string to any item, irrespective of IDs. These mappings are used by/give
and/clear
, and are made with custom plugin aliases in mind.- Yes, this means you can finally add your own custom aliases to
/give
without ugly hacks!
- Yes, this means you can finally add your own custom aliases to
LegacyStringToItemParser
has been added, which is a slightly more dynamic (but still inadvisable) replacement forItemFactory::fromString()
.Item->count
is no longer public.- The hierarchy of writable books has been changed:
WritableBook
andWrittenBook
now extendWritableBookBase
. - The following API methods have signature changes:
WritableBookBase->setPages()
now acceptsWritableBookPage[]
instead ofCompoundTag[]
.ItemFactory::get()
no longer acceptsstring
for thetags
parameter.ItemFactory::fromString()
no longer accepts a$multiple
parameter 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 exceptDurable
descendents.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()
Potion::getPotionEffectsById()
ProjectileItem->getProjectileEntityType()
- The following constants have been removed:
Potion::ALL
- usePotionType::getAll()
insteadPotion::WATER
Potion::MUNDANE
Potion::LONG_MUNDANE
Potion::THICK
Potion::AWKWARD
Potion::NIGHT_VISION
Potion::LONG_NIGHT_VISION
Potion::INVISIBILITY
Potion::LONG_INVISIBILITY
Potion::LEAPING
Potion::LONG_LEAPING
Potion::STRONG_LEAPING
Potion::FIRE_RESISTANCE
Potion::LONG_FIRE_RESISTANCE
Potion::SWIFTNESS
Potion::LONG_SWIFTNESS
Potion::STRONG_SWIFTNESS
Potion::SLOWNESS
Potion::LONG_SLOWNESS
Potion::WATER_BREATHING
Potion::LONG_WATER_BREATHING
Potion::HEALING
Potion::STRONG_HEALING
Potion::HARMING
Potion::STRONG_HARMING
Potion::POISON
Potion::LONG_POISON
Potion::STRONG_POISON
Potion::REGENERATION
Potion::LONG_REGENERATION
Potion::STRONG_REGENERATION
Potion::STRENGTH
Potion::LONG_STRENGTH
Potion::STRONG_STRENGTH
Potion::WEAKNESS
Potion::LONG_WEAKNESS
Potion::WITHER
- 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:
ArmorTypeInfo
Fertilizer
LiquidBucket
MilkBucket
PotionType
: enum class containing information about vanilla potion typesWritableBookBase
WritableBookPage
- The following API methods have been added:
Armor->getArmorSlot()
Item->canStackWith()
: returns whether the two items could be contained in the same inventory slot, ignoring count and stack size limitsPotion->getType()
: returns aPotionType
enum object containing information such as the applied effectsProjectileItem->createEntity()
: returns a new instance of the projectile entity that will be thrown
- The following classes have been removed:
ChainBoots
ChainChestplate
ChainHelmet
ChainLeggings
DiamondBoots
DiamondChestplate
DiamondHelmet
DiamondLeggings
GoldBoots
GoldChestplate
GoldHelmet
GoldLeggings
IronBoots
IronChesplate
IronHelmet
IronLeggings
LeatherBoots
LeatherCap
LeatherPants
LeatherTunic
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
VanillaEnchantments
class 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\EnchantmentIds
if you still need legacy effect IDs for some reason.
- ID handling is moved to
Enchantment::RARITY_*
constants were moved toRarity
class, and theRARITY_
prefixes removed.Enchantment::SLOT_*
constants were moved toItemFlags
class, 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
TranslationContainer
->Translatable
- The following classes have been removed:
TextContainer
- The following API methods have been added:
Translatable->format()
: allows adding formatting (such as color codes) to a translationTranslatable->prefix()
: allows prefixing formattingTranslatable->postfix()
: allows postfixing formatting
- The following API methods have changed signatures:
Translatable->__construct()
now acceptsarray<int|string, Translatable|string>
for parameters, instead of justlist<string>
.Translatable->getParameter()
now acceptsint|string
for the index instead of justint
.Translatable->getParameter()
now returnsTranslatable|string
instead of juststring
.Translatable->getParameters()
now returnsarray<int|string, Translatable|string>
.
LanguageNotFoundException
has been added. This is thrown when trying to construct aLanguage
which doesn't exist in the server files.Translatable
no longer discards keys for translation parameters. Previously, only the insertion order was considered.Translatable
now supports string keys for translation parameters.Translatable
now supports providing otherTranslatable
s as translation parameters.Language->translateString()
now supports providingTranslatable
s as translation parameters.Language->translateString()
no longer automatically attempts to translate string parameters. If you want them to be translated, translate them explicitly. This fixes bugs where player chat messages containing translation keys would be unexpectedly translated.Language->translate()
no longer attempts to translate string parameters ofTranslatable
(same rationale as previous point).
Network
- The following fields have been removed:
Network::$BATCH_THRESHOLD
- The following classes have been renamed:
SourceInterface
->NetworkInterface
AdvancedSourceInterface
->AdvancedNetworkInterface
- The following classes have been moved:
CompressBatchedTask
->mcpe\CompressBatchTask
level\format\io\ChunkRequestTask
->mcpe\ChunkRequestTask
mcpe\RakLibInterface
->mcpe\raklib\RakLibInterface
- The following classes have been removed:
mcpe\PlayerNetworkSessionAdapter
- The following methods have been removed:
NetworkInterface->putPacket()
NetworkInterface->close()
NetworkInterface->emergencyShutdown()
NetworkInterface
now represents a more generic interface to be implemented by any network component, as opposed to specifically a player network interface.- Everything under the
rcon
subnamespace has been removed. upnp\UPnP
has 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
false
instead 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.group
permissions:true
: add as child topocketmine.group.everyone
with valuetrue
false
: do not add to any permissionop
: add as child topocketmine.group.operator
with valuetrue
notop
: add as child topocketmine.group.everyone
with valuetrue
, and topocketmine.group.operator
with valuefalse
However, thedefault
key inplugin.yml
permission definitions continues to be supported.
- Added
PermissibleDelegateTrait
to reduce boilerplate for users ofPermissibleBase
. This trait is used byConsoleCommandSender
andPlayer
. - 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_FALSE
Permission::DEFAULT_TRUE
->PermissionParser::DEFAULT_TRUE
Permission::DEFAULT_OP
->PermissionParser::DEFAULT_OP
Permission::DEFAULT_NOT_OP
->PermissionParser::DEFAULT_NOT_OP
- The following API methods have been added:
Permission->addChild()
Permission->removeChild()
Permissible->getPermissionRecalculationCallbacks()
- allows reacting to changes of permissions, such as new permissions being granted or deniedPermissible->setBasePermission()
- used for assigning root permissions likepocketmine.group.operator
; plugins usually shouldn't use thisPermissible->unsetBasePermission()
PermissionAttachmentInfo->getGroupPermissionInfo()
- returns thePermissionAttachmentInfo
of the permission that caused the current permission value to be set, or null if the permission is explicit
- 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()
PermissionAttachment->getPermissible()
PermissionAttachmentInfo->getPermissible()
- The following fields have been removed:
Permission::$DEFAULT_PERMISSION
- The following API methods have changes:
PermissionParser::defaultFromString()
now throwsInvalidArgumentException
on unknown values.Permission->__construct()
no longer accepts a$defaultValue
parameter (see notes above about defaults refactor).you should add your permission as a child ofpocketmine.group.everyone
orpocketmine.group.operator
instead).
- The following classes have been removed:
ServerOperator
Player
- The following classes have moved to the new
pocketmine\player
namespace:Achievement
GameMode
IPlayer
OfflinePlayer
PlayerInfo
Player
- 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. Player->getSpawn()
no longer returns the world's safe spawn if the player's spawn position isn't set. Returning the safe spawn at the time of call made no sense, because it might not have been safe when actually used. You should pass the result of this function toWorld->getSafeSpawn()
to get a safe spawn position instead.- 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 snowballPlayer->getSaveData()
: returns save data generated on the fly
- 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 toNetworkSession
Player->getPort()
: moved toNetworkSession
Player->updatePing()
: moved toNetworkSession
Player->dataPacket()
: replaced byNetworkSession->sendDataPacket()
Player->sendDataPacket()
: replaced byNetworkSession->sendDataPacket()
Player->updateNextPosition()
: usePlayer->handleMovement()
insteadIPlayer->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()
: useServer
APIs insteadIPlayer->isOp()
: useServer
APIs insteadIPlayer->setOp()
: useServer
APIs 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.yml
YAML 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 insidePluginBase
Plugin->onDisable()
: same as abovePlugin->onLoad()
: same as abovePlugin->getServer()
is no longer required to be implemented. It's implemented inPluginBase
for convenience.Plugin->isDisabled()
was removed (usePlugin->isEnabled()
instead).Plugin
no longer extendsCommandExecutor
. This means thatPlugin
implementations don't need to implementonCommand()
anymore.
- The following hook methods have changed visibility:
PluginBase->onEnable()
changed frompublic
toprotected
PluginBase->onDisable()
changed frompublic
toprotected
PluginBase->onLoad()
changed frompublic
toprotected
- 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()
: usePermissionManager
insteadPluginManager->getDefaultPermSubscriptions()
: usePermissionManager
insteadPluginManager->getDefaultPermissions()
: usePermissionManager
insteadPluginManager->getPermission()
: usePermissionManager
insteadPluginManager->getPermissionSubscriptions()
: usePermissionManager
insteadPluginManager->getPermissions()
: usePermissionManager
insteadPluginManager->recalculatePermissionDefaults()
: usePermissionManager
insteadPluginManager->removePermission()
: usePermissionManager
insteadPluginManager->subscribeToDefaultPerms()
: usePermissionManager
insteadPluginManager->subscribeToPermission()
: usePermissionManager
insteadPluginManager->unsubscribeFromDefaultPerms()
: usePermissionManager
insteadPluginManager->unsubscribeFromPermission()
: usePermissionManager
instead
- 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
AsyncTask
is 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) : void
AsyncTask->fetchLocal()
now has the signaturefetchLocal(string $key) : mixed
Other changes
AsyncPool
uses a new, significantly more performant algorithm for task collection.BulkCurlTask
has had the$complexData
constructor parameter removed.BulkCurlTask->__construct()
now acceptsBulkCurlTaskOperation[]
instead ofmixed[]
.- Added
CancelTaskException
, which can be thrown fromTask::onRun()
to cancel a task (especially useful forClosureTask
). pocketmine\Collectable
has 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 aServer
parameter, and has avoid
return type.AsyncTask->onProgressUpdate()
no longer accepts aServer
parameter, and has avoid
return type.
- The following API methods have been removed:
AsyncTask->getFromThreadStore()
: useAsyncTask->worker->getFromThreadStore()
AsyncTask->removeFromThreadStore()
: useAsyncTask->worker->removeFromThreadStore()
AsyncTask->saveToThreadStore()
: useAsyncTask->worker->saveToThreadStore()
Server
- New chat broadcasting APIs have been implemented, which don't depend on the permission system.
- The following API methods have been added:
subscribeToBroadcastChannel()
- allows subscribing aCommandSender
to receive chat messages (and other message types) on any channelunsubscribeFromBroadcastChannel()
unsubscribeFromAllBroadcastChannels()
getBroadcastChannelSubscribers()
- Giving
Player
anypocketmine.broadcast.*
permissions will cause them to automatically subscribe to the corresponding broadcast channel (and removing them will unsubscribe it). - It's now possible to create and subscribe to custom broadcast channels without using permissions.
- However,
Player
s may automatically unsubscribe themselves from the builtin broadcast channels if they don't have the proper permissions. - Automatic subscribe/unsubscribe from custom broadcast channels can be implemented using the new
Permissible
permission recalculation callbacks API.
- The following API methods have been added:
- 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
Level
in the context of "world" have been changed toWorld
.- The
pocketmine\level
namespace has been renamed topocketmine\world
- All classes containing the world
Level
in the name in the "world" context have been changed toWorld
. Position->getLevel()
has been renamed toPosition->getWorld()
, andPosition->level
has been renamed toPosition->world
.
- The
- Extracted a
WorldManager
unit fromServer
Server->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$autoUpgrade
parameter 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 chunkTickingChunkLoader
: aChunkLoader
specialization that allows ticking chunks
ChunkLoader
no longer requires implementinggetX()
andgetZ()
.ChunkLoader
no longer causes chunks to get random updates. If this behaviour is needed, implementTickingChunkLoader
.- 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()
World->getBlockAt()
(accepts int x/y/z instead of Vector3, faster for some use cases)World->setBlockAt()
(accepts int x/y/z instead of Vector3, faster for some use cases)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()
(seeChunkSerializer
in thenetwork\mcpe\serializer
package)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) : void
World->addSound()
now has the signatureaddSound(?Vector3 $pos, Sound $sound, ?Player[] $players = null) : void
World->getRandomTickedBlocks()
now returnsbool[]
instead ofSplFixedArray
.World->addRandomTickedBlock()
now acceptsBlock
instead ofint, int
.World->removeRandomTickedBlock()
now acceptsBlock
instead ofint, int
.World->setBlock()
has had the$direct
parameter removed.World->loadChunk()
now returns?Chunk
, and the$create
parameter has been removed.World->getChunk()
no longer accepts a$create
parameter.World->updateAllLight()
now acceptsint, int, int
instead ofVector3
.ChunkManager->setChunk()
(and its notable implementations inWorld
andSimpleChunkManager
) no longer accepts NULL for the$chunk
parameter.Chunk->__construct()
now has the signaturearray<int, SubChunk> $subChunks, ?list<CompoundTag> $entities, ?list<CompoundTag> $tiles, ?BiomeArray $biomeArray, ?HeightArray $heightArray
.Chunk->getSubChunk()
now returnsSubChunk
instead ofSubChunkInterface|null
(and throwsInvalidArgumentException
on out-of-bounds coordinates).Chunk->setSubChunk()
no longer acceptsSubChunkInterface
, and the$allowEmpty
parameter has been removed.WorldManager->generateWorld()
(previouslyServer->generateWorld()
) now acceptsWorldCreationOptions
instead ofint $seed, class-string<Generator> $generator, mixed[] $options
.
- The following API methods have been renamed / moved:
Level->getChunks()
->World->getLoadedChunks()
Level->getCollisionCubes()
->World->getCollisionBoxes()
World->getName()
->World->getDisplayName()
World->populateChunk()
has been split intoWorld->requestChunkPopulation()
andWorld->orderChunkPopulation()
.
- 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 otherChunkManager
implementations.)World->getHighestBlockAt()
now returnsnull
instead of-1
if the target X/Z column contains no blocks.- The following methods now throw
WorldException
when 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 firesChunkLoadEvent
andChunkListener->onChunkLoaded()
when replacing a chunk that didn't previously exist.World->useBreakOn()
now returnsfalse
when the target position is in an ungenerated or unloaded chunk (or chunk locked for generation).World->useItemOn()
now returnsfalse
when the target position is in an ungenerated or unloaded chunk (or chunk locked for generation).
- A
ChunkListener
interface 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()
Location
has been moved topocketmine\entity\Location
.
Particles
DestroyBlockParticle
has been renamed toBlockBreakParticle
for consistency.DustParticle->__construct()
now accepts apocketmine\utils\Color
object instead ofr, g, b, a
.pocketmine\world\particle\Particle
no longer extendspocketmine\math\Vector3
, and has been converted to an interface.- Added the following
Particle
classes:DragonEggTeleportParticle
PunchBlockParticle
Sounds
pocketmine\world\sound\Sound
no longer extendspocketmine\math\Vector3
, and has been converted to an interface.Sound->encode()
now accepts?\pocketmine\math\Vector3
.NULL
may be passed for sounds which are global.- Added the following classes:
ArrowHitSound
BlockBreakSound
BlockPlaceSound
BowShootSound
BucketEmptyLavaSound
BucketEmptyWaterSound
BucketFillLavaSound
BucketFillWaterSound
ChestCloseSound
ChestOpenSound
EnderChestCloseSound
EnderChestOpenSound
ExplodeSound
FlintSteelSound
ItemBreakSound
NoteInstrument
NoteSound
PaintingPlaceSound
PotionSplashSound
RedstonePowerOffSound
RedstonePowerOnSound
ThrowSound
XpCollectSound
XpLevelUpSound
Utils
- The
Color
class was removed. It's now found aspocketmine\color\Color
in thepocketmine/color
package. - The
UUID
class was removed.ramsey/uuid
version 4.1 is now used instead.UUID::fromData()
can be replaced byRamsey\Uuid\Uuid::uuid3()
UUID::fromRandom()
can be replaced byRamsey\Uuid\Uuid::uuid4()
UUID::fromBinary()
can be replaced byRamsey\Uuid\Uuid::fromBytes()
(useRamsey\Uuid\Uuid::isValid()
to check validity)UUID::toBinary()
is replaced byRamsey\Uuid\UuidInterface::getBytes()
- See the documentation at https://uuid.ramsey.dev/en/latest/introduction.html for more information.
Terminal::hasFormattingCodes()
no longer auto-detects the availability of formatting codes. Instead it's necessary to useTerminal::init()
with no parameters to initialize, ortrue
orfalse
to override.Config->save()
no longer catches exceptions thrown during emitting to disk.- The following new classes have been added:
InternetException
Internet
Process
- 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 API class constants have been added:
TextFormat::COLORS
: lists all known color codesTextFormat::FORMATS
: lists all known formatting codes (e.g. italic, bold). (RESET
is not included because it removes formats, rather than adding them.)
- The following deprecated API redirects have been removed:
Utils::execute()
: moved toProcess
Utils::getIP()
: moved toInternet
Utils::getMemoryUsage()
: moved toProcess
Utils::getRealMemoryUsage()
: moved toProcess
Utils::getThreadCount()
: moved toProcess
Utils::getURL()
: moved toInternet
Utils::kill()
: moved toProcess
Utils::postURL()
: moved toInternet
Utils::simpleCurl()
: moved toInternet
- The following API fields have been removed / hidden:
Utils::$ip
Utils::$online
Utils::$os
- The following API methods have signature changes:
Internet::simpleCurl()
now requires aClosure
for itsonSuccess
parameter instead ofcallable
.
- The following API methods have been removed:
TextFormat::toJSON()
Utils::getCallableIdentifier()
Gameplay
Blocks
- Implemented the following blocks:
- bamboo
- bamboo sapling
- barrel
- barrier
- blast furnace
- blue ice
- carved pumpkin
- coral block
- daylight sensor
- dried kelp
- elements (from Minecraft: Education Edition)
- hard (stained and unstained) glass (from Minecraft: Education Edition)
- hard (stained and unstained) glass pane (from Minecraft: Education Edition)
- jukebox
- note block
- red, green, blue and purple torches (from Minecraft: Education Edition)
- sea pickle
- slime
- smoker
- underwater torches (from Minecraft: Education Edition)
- additional wood variants of the following:
- buttons
- pressure plates
- signs
- trapdoors
- stairs of the following materials:
- andesite (smooth and natural)
- diorite (smooth and natural)
- end stone
- end stone brick
- granite (smooth and natural)
- mossy cobblestone
- prismarine (natural, dark and bricks)
- red nether brick
- red sandstone (and variants)
- stone-like slabs of many variants
- Non-player entities now bounce when falling on beds.
- Players and mobs now receive reduced fall damage when falling on beds.
Items
- Implemented the following items:
- records
- compounds (from Minecraft: Education Edition)
- black, brown, blue and white dyes
Inventory
- Implemented offhand inventory.