[ci skip] added incomplete changelog for 4.0

This commit is contained in:
Dylan K. Taylor 2019-07-01 17:42:18 +01:00
parent a325b1f3a1
commit 601ba4264d

602
changelogs/4.0-snapshot.md Normal file
View File

@ -0,0 +1,602 @@
# 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 `/reload` command has been removed.
- Remote console (RCON) has been removed. The [RconServer](https://github.com/pmmp/RconServer) plugin is provided as a substitute.
- Spawn protection has been removed. The [BasicSpawnProtection](https://github.com/pmmp/BasicSpawnProtection) plugin is provided as a substitute.
- CTRL+C signal handling has been removed. The [PcntlSignalHandler](https://github.com/pmmp/PcntlSignalHandler) plugin is provided as a substitute.
- Player movement anti-cheat has been removed. Its corresponding `pocketmine.yml` setting `player.anti-cheat.allow-movement-cheats` has been removed.
- The `pocketmine_chunkutils` PHP extension has been dropped.
- New PHP extensions are required by this version:
- [ds](https://github.com/php-ds/ext-ds)
- [chunkutils2](https://github.com/pmmp/ext-chunkutils2)
### World format support
- Modern Minecraft Bedrock world formats are now supported.
- Automatic conversion of deprecated world formats is now implemented.
- The following world formats have been deprecated and 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).
- Unsupported world formats no longer causes a crash, but a graceful shutdown instead.
- World corruption no longer causes a crash.
### 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 is `true` 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 message `Packet processing error`.
- The disconnect message includes a random hex ID to help server owners identify the problems reported by their players.
- 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.
### Block
- 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 `Block` classes, with the tile entity classes being deprecated.
- The `pocketmine\tile` namespace has been relocated to `pocketmine\block\tile`.
- `Block->recalculateBoundingBox()` and `Block->recalculateCollisionBoxes()` are now expected to return AABBs relative to `0,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 block
- `Block->isSameState()`: returns whether the block is the same as the parameter, including state information
- `Block->isSameType()`: returns whether the block is the same as the parameter, without state information
- The following hooks have been added:
- `Block->onAttack()`: called when a player in survival left-clicks the block to try to start breaking it
- `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 signature `onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool`
- The following API methods have been removed:
- `Block->canPassThrough()`
- `Block->setDamage()`
- 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`
### 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
- The following API methods have been added:
- `ItemEntity->getDespawnDelay()`
- `ItemEntity->setDespawnDelay()`
- The following methods have signature changes:
- `Entity->entityBaseTick()` is now `protected`.
- `Entity->move()` is now `protected`.
- 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 the `pocketmine\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`
- Negative effect amplifiers are now explicitly disallowed due to undefined behaviour they created.
- The following API methods have been renamed:
- `Effect::registerEffect()` -> `Effect::register()`
- `Effect::getEffect()` -> `Effect::get()`
- `Effect::getEffectByName()` -> `Effect::fromString()`
- Static getter methods for all registered enchantment types have been added. `Effect::getEffect(Effect::WHATEVER)` should be replaced by `Effect::WHATEVER()`.
#### 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 created `CompoundTag` instead of modifying the previous one in-place.
- `Entity->initEntity()` now accepts a `CompoundTag` parameter.
#### Entity creation
- Entity class overriding is now explicitly supported, without needing to touch save IDs.
- Entity classes can be overridden using `EntityFactory::override()`. The provided replacement class **must** be a subclass of the existing class. If the existing class isn't there, an exception will be thrown.
- Attempting to register an entity to a save ID that is already registered will now cause an exception to be thrown.
- Registering entities will now throw exceptions on error cases instead of returning `false`.
- Entity creation has now been split into two paths:
- `EntityFactory::create()`: Creates an entity by the given class. This accepts arguments to be passed to the entity constructor. This function is guaranteed to return an entity which is an instanceof the given class.
- `EntityFactory::createFromData()`: Creates an entity from save data. This may return any `Entity` class or `NULL`. This function is internal and shouldn't be used by plugins.
- It is no longer possible to directly create an entity by save ID. This is discouraged because save IDs are internal and format-dependent.
- The following API methods have been moved:
- `Entity::registerEntity()` -> `EntityFactory::register()`
- `Entity::createEntity()` -> `EntityFactory::create()`
- `Entity::getKnownEntityTypes()` -> `EntityFactory::getKnownTypes()`
- `Entity::createBaseNBT()` -> `EntityFactory::createBaseNBT()`
- The following API methods have been removed:
- `Entity->getSaveId()`
#### 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 to `pocketmine\network\mcpe\protocol\types\EntityMetadataFlags`.
- `Entity::DATA_TYPE_*` constants have been moved to `pocketmine\network\mcpe\protocol\types\EntityMetadataTypes`.
- `Entity::DATA_*` constants have been moved to `pocketmine\network\mcpe\protocol\types\EntityMetadataProperties`.
- `DataPropertyManager` has been moved to the `pocketmine\network\mcpe\protocol\types` namespace, and as such isn't considered part of the API anymore.
### 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 requires `Closure` instead of `Listener, 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, a `PlayerInfo` 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 intercept `PlayerKickEvent` 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 place
- `PlayerPreLoginEvent->getIp()`
- `PlayerPreLoginEvent->getKickReasons()`: returns an array of flags indicating kick reasons, must be empty to allow joining
- `PlayerPreLoginEvent->getPlayerInfo()`
- `PlayerPreLoginEvent->getPort()`
- `PlayerPreLoginEvent->isAllowed()`
- `PlayerPreLoginEvent->isAuthRequired()`: whether XBL authentication will be enforced
- `PlayerPreLoginEvent->isKickReasonSet()`
- `PlayerPreLoginEvent->setAuthRequired()`
- `PlayerPreLoginEvent->setKickReason()`
- The following API methods have been changed:
- `PlayerPreLoginEvent->getKickMessage()` now has the signature `getKickMessage(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).
- `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.
- `PlayerInteractEvent` is no longer fired when a player activates an item. This fixes the age-old complaint of `PlayerInteractEvent` 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:
- `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:
- `EntityArmorChangeEvent`
- `EntityInventoryChangeEvent`
- `EntityLevelChangeEvent` - `EntityTeleportEvent` with world checks should be used instead.
- `NetworkInterfaceCrashEvent`
- `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()`
- The following API methods have been moved:
- `Event->isCancelled()` -> `CancellableTrait->isCancelled()`: this was a stub which threw `BadMethodCallException` if the class didn't implement `Cancellable`; now this is simply not available on non-cancellable events
- `Event->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
### Item
#### General
- `ProjectileItem->getProjectileEntityType()` now returns a ::class constant instead of an entity save ID.
- The following API methods have been removed:
- `Item->getNamedTagEntry()`
- `Item->removeNamedTagEntry()`
- `Item->setDamage()`: "Damage" is now immutable for all items except `Durable` descendents.
- `Item->setNamedTagEntry()`
- 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()`
#### Enchantment
- The following API methods have been renamed:
- `Enchantment::registerEnchantment()` -> `Enchantment::register()`
- `Enchantment::getEnchantment()` -> `Enchantment::get()`
- `Enchantment::getEnchantmentByName()` -> `Enchantment::fromString()`
- Static getter methods for all registered enchantment types have been added. `Enchantment::getEnchantment(Enchantment::WHATEVER)` should be replaced by `Enchantment::WHATEVER()`.
### Lang
- The following classes have been renamed:
- `BaseLang` -> `Language`
- `LanguageNotFoundException` has been added. This is thrown when trying to construct a `Language` which doesn't exist in the server files.
### 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
- Added `PermissibleDelegateTrait` to reduce boilerplate for users of `PermissibleBase`. This trait is used by `ConsoleCommandSender` and `Player`.
- The following API methods have been moved:
- `Permission::getByName()` -> `PermissionParser::defaultFromString()`
- `Permission::loadPermissions()` -> `PermissionParser::loadPermissions()`
- `Permission::loadPermission()` -> `PermissionParser::loadPermission()`
- The following API methods have been added:
- `PermissionParser::emitPermissions()`
- The following API methods have changes:
- `PermissionParser::defaultFromString()` now throws `InvalidArgumentException` on unknown values.
### 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` - use `GameMode::SURVIVAL()`
- `Player::CREATIVE` - use `GameMode::CREATIVE()`
- `Player::ADVENTURE` - use `GameMode::ADVENTURE()`
- `Player::SPECTATOR` - use `GameMode::SPECTATOR()`
- `Player::VIEW` - use `GameMode::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 food
- `Player->continueBreakBlock()`: punch the target block during destruction in survival, advancing break animation and creating particles
- `Player->hasFiniteResources()`
- `Player->interactBlock()`: interact (right click) the target block in the current world
- `Player->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 world
- `Player->releaseHeldItem()`: release the previously activated item, e.g. shooting a bow
- `Player->selectHotbarSlot()`: select the specified hotbar slot
- `Player->stopBreakBlock()`: cease attacking a previously attacked block
- `Player->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 by `sendActionBarMessage()`
- `Player->addSubTitle()`: replaced by `sendSubTitle()`
- `Player->addTitle()`: replaced by `sendTitle()`
- `Player->getAddress()`: replaced by `NetworkSession->getIp()`
- `Player->getPing()`: moved to `NetworkSession`
- `Player->getPort()`: moved to `NetworkSession`
- `Player->updatePing()`: moved to `NetworkSession`
### 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 inside `PluginBase`.
- `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](#event) for more details.
- The following interface requirements have been removed:
- `Plugin->onEnable()`: this is now internalized inside `PluginBase`
- `Plugin->onDisable()`: same as above
- `Plugin->onLoad()`: same as above
- `Plugin` no longer extends `CommandExecutor`. This means that `Plugin` implementations don't need to implement `onCommand()` anymore.
- The following hook methods have changed visibility:
- `PluginBase->onEnable()` changed from `public` to `protected`
- `PluginBase->onDisable()` changed from `public` to `protected`
- `PluginBase->onLoad()` changed from `public` to `protected`
- 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()`: use `Event->call()` instead
- `PluginManager->addPermission()`: use `PermissionManager` instead
- `PluginManager->getDefaultPermSubscriptions()`: use `PermissionManager` instead
- `PluginManager->getDefaultPermissions()`: use `PermissionManager` instead
- `PluginManager->getPermission()`: use `PermissionManager` instead
- `PluginManager->getPermissionSubscriptions()`: use `PermissionManager` instead
- `PluginManager->getPermissions()`: use `PermissionManager` instead
- `PluginManager->recalculatePermissionDefaults()`: use `PermissionManager` instead
- `PluginManager->removePermission()`: use `PermissionManager` instead
- `PluginManager->subscribeToDefaultPerms()`: use `PermissionManager` instead
- `PluginManager->subscribeToPermission()`: use `PermissionManager` instead
- `PluginManager->unsubscribeFromDefaultPerms()`: use `PermissionManager` instead
- `PluginManager->unsubscribeFromPermission()`: use `PermissionManager` instead
- It is no longer permitted to throw exceptions from `PluginBase->onEnable()` or `PluginBase->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 methods have been removed:
- `AsyncTask->peekLocal()`: use `fetchLocal()` instead
- The following methods have signature changes:
- `AsyncTask->storeLocal()` now has the signature `storeLocal(string $key, mixed $complexData) : void`
- `AsyncTask->fetchLocal()` now has the signature `fetchLocal(string $key) : mixed`
#### Other changes
- `AsyncPool` uses a new, significantly more performant algorithm for task collection.
- `BulkCurlTask` has had the `$complexData` constructor parameter removed.
- `pocketmine\Collectable` has been removed, and is no longer extended by `AsyncTask`.
- 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 a `Server` parameter, and has a `void` return type.
- `AsyncTask->onProgressUpdate()` no longer accepts a `Server` parameter, and has a `void` return type.
- The following API methods have been removed:
- `AsyncTask->getFromThreadStore()`: use `AsyncTask->worker->getFromThreadStore()`
- `AsyncTask->removeFromThreadStore()`: use `AsyncTask->worker->removeFromThreadStore()`
- `AsyncTask->saveToThreadStore()`: use `AsyncTask->worker->saveToThreadStore()`
### Server
- The following API methods have been removed:
- `reloadWhitelist()`
- `getLevelMetadata()`
- `getPlayerMetadata()`
- `getEntityMetadata()`
- `getDefaultGamemode()`
- `getLoggedInPlayers()`
- `onPlayerLogout()`
- `addPlayer()`
- `removePlayer()`
- `reload()`
- `getSpawnRadius()`
- `enablePlugin()`
- `disablePlugin()`
- `getGamemodeString()` - replaced by `pocketmine\player\GameMode->getTranslationKey()`
- `getGamemodeName()` - replaced by `pocketmine\player\GameMode->name()`
- `getGamemodeFromString()` - replaced by `GameMode::fromString()`
- The following API methods have changed:
- `getOfflinePlayerData()` no longer creates data when it doesn't exist.
### Level / World
#### General
- All references to `Level` in the context of "world" have been changed to `World`.
- The `pocketmine\level` namespace has been renamed to `pocketmine\world`
- All classes containing the world `Level` in the name in the "world" context have been changed to `World`.
- `Position->getLevel()` has been renamed to `Position->getWorld()`, and `Position->level` has been renamed to `Position->world`.
- Extracted a `WorldManager` unit from `Server`
- `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()`
- `Server->setAutoSave()` -> `WorldManager->setAutoSave()`
- `Server->setDefaultLevel()` -> `WorldManager->setDefaultWorld()`
- `Server->unloadLevel()` -> `WorldManager->unloadWorld()`
- Added `WorldManager->getAutoSaveTicks()` and `WorldManager->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 implementations
- `ChunkListener`: interface allowing subscribing to events happening on a given chunk
- The following API methods have been added:
- `World->registerChunkListener()`
- `World->unregisterChunkListener()`
- The following API methods have been removed:
- `ChunkLoader->getLoaderId()` (now object ID is used)
- The following API methods have changed signatures:
- `World->addParticle()` now has the signature `addParticle(Vector3 $pos, Particle $particle, ?Player[] $players = null) : void`
- `World->addSound()` now has the signature `addSound(?Vector3 $pos, Sound $sound, ?Player[] $players = null) : void`
- The following API methods have been renamed / moved:
- `Level->getCollisionCubes()` -> `World->getCollisionBoxes()`
- Extracted a unit `pocketmine\world\format\io\FastChunkSerializer` from `Chunk`:
- `Chunk->fastDeserialize()` -> `FastChunkSerializer::deserialize()`
- `Chunk->fastSerialize()` -> `FastChunkSerializer::serialize()`
- A `ChunkListener` interface has been extracted from `ChunkLoader`. 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()`
#### Particles
- `pocketmine\world\particle\Particle` no longer extends `pocketmine\math\Vector3`, and has been converted to an interface.
- Added the following `Particle` classes:
- `DragonEggTeleportParticle`
- `PunchBlockParticle`
#### Sounds
- `pocketmine\world\sound\Sound` no longer extends `pocketmine\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
- `Terminal::hasFormattingCodes()` no longer auto-detects the availability of formatting codes. Instead it's necessary to use `Terminal::init()` with no parameters to initialize, or `true` or `false` 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:
- `Color::fromRGBA()`
- `Config->getPath()`: returns the path to the config on disk
- `Terminal::write()`: emits a Minecraft-formatted text line without newline
- `Terminal::writeLine()`: emits a Minecraft-formatted text line with newline
- `Utils::recursiveUnlink()`: recursively deletes a directory and its contents
- The following deprecated API redirects have been removed:
- `Utils::execute()`: moved to `Process`
- `Utils::getIP()`: moved to `Internet`
- `Utils::getMemoryUsage()`: moved to `Process`
- `Utils::getRealMemoryUsage()`: moved to `Process`
- `Utils::getThreadCount()`: moved to `Process`
- `Utils::getURL()`: moved to `Internet`
- `Utils::kill()`: moved to `Process`
- `Utils::postURL()`: moved to `Internet`
- `Utils::simpleCurl()`: moved to `Internet`
- 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 a `Closure` for its `onSuccess` parameter instead of `callable`.
- The following API methods have been removed:
- `Color->toABGR()`
- `Color->toBGRA()`
- `Color::fromABGR()`
- `Utils::getCallableIdentifier()`