Merge branch 'minor-next' into compressor-threads

This commit is contained in:
Dylan K. Taylor 2023-11-13 11:14:19 +00:00
commit 7e6550d05a
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
13 changed files with 112 additions and 64 deletions

View File

@ -15,7 +15,7 @@ jobs:
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.27.1
with:
php-version: 8.1
php-version: 8.2
- name: Restore Composer package cache
uses: actions/cache@v3

View File

@ -12,7 +12,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-version: [8.1]
php-version: [8.2]
steps:
- uses: actions/checkout@v4

View File

@ -175,8 +175,8 @@ jobs:
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.27.1
with:
php-version: 8.1
tools: php-cs-fixer:3.17
php-version: 8.2
tools: php-cs-fixer:3.38
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -2,7 +2,7 @@
## Pre-requisites
- A bash shell (git bash is sufficient for Windows)
- [`git`](https://git-scm.com) available in your shell
- PHP 8.1 or newer available in your shell
- PHP 8.2 or newer available in your shell
- [`composer`](https://getcomposer.org) available in your shell
## Custom PHP binaries

View File

@ -20,31 +20,61 @@
<a href="https://github.com/pmmp/PocketMine-MP/releases/latest"><img alt="GitHub release (latest by SemVer)" src="https://img.shields.io/github/downloads/pmmp/PocketMine-MP/latest/total?sort=semver"></a>
</p>
## Getting started
## What is this?
PocketMine-MP is a highly customisable server software for Minecraft: Bedrock Edition, built from scratch in PHP, with over 10 years of history.
If you're looking to create a Minecraft: Bedrock server with **custom functionality**, look no further.
- 🧩 **Powerful plugin API** - extend and customise gameplay as you see fit
- 🗺️ **Rich ecosystem** and **large developer community** - find plugins easily and learn to develop your own
- 🌐 **Multi-world support** - offer a more varied game experience to players without transferring them to other server nodes
- 🏎️ **Performance** - get 100+ players onto one server (depending on hardware and plugins)
- ⤴️ **Continuously updated** - new Minecraft versions are usually supported within days
## :x: PocketMine-MP is NOT a vanilla Minecraft server software.
**It is poorly suited to hosting vanilla survival servers.**
It doesn't have many features from the vanilla game, such as vanilla world generation, redstone, mob AI, and various other things.
If you just want to play **vanilla survival multiplayer**, consider using the [official Minecraft: Bedrock server software](https://minecraft.net/download/server/bedrock) instead of PocketMine-MP.
If that's not an option for you, you may be able to add some of PocketMine-MP's missing features using plugins from [Poggit](https://poggit.pmmp.io/plugins), or write plugins to implement them yourself.
## Getting Started
- [Documentation](http://pmmp.readthedocs.org/)
- [Installation instructions](https://pmmp.readthedocs.io/en/rtfd/installation.html)
- [Docker image](https://github.com/pmmp/PocketMine-MP/pkgs/container/pocketmine-mp)
- [Plugin repository](https://poggit.pmmp.io/plugins)
## Community & Support
- [Forums](https://forums.pmmp.io/)
- [Discord](https://discord.gg/bmSAZBG)
- [StackOverflow](https://stackoverflow.com/tags/pocketmine)
Join our [Discord](https://discord.gg/bmSAZBG) server to chat with other users and developers.
You can also post questions on [StackOverflow](https://stackoverflow.com/tags/pocketmine) under the tag `pocketmine`.
## Developing Plugins
If you want to write your own plugins, the following resources may be useful.
Don't forget you can always ask our community if you need help.
## For developers
* [Building and running from source](BUILDING.md)
* [Developer documentation](https://devdoc.pmmp.io) - General documentation for PocketMine-MP plugin developers
* [Latest release API documentation](https://apidoc.pmmp.io) - Doxygen API documentation generated for each release
* [Latest bleeding-edge API documentation](https://apidoc-dev.pmmp.io) - Doxygen API documentation generated weekly from `major-next` branch
* [DevTools](https://github.com/pmmp/DevTools/) - Development tools plugin for creating plugins
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
## Contributing to PocketMine-MP
PocketMine-MP accepts community contributions! The following resources will be useful if you want to contribute to PocketMine-MP.
* [Building and running PocketMine-MP from source](BUILDING.md)
* [Contributing Guidelines](CONTRIBUTING.md)
## Donate
- Bitcoin Cash (BCH): `qq3r46hn6ljnhnqnfwxt5pg3g447eq9jhvw5ddfear`
PocketMine-MP is free, but it requires a lot of time and effort from unpaid volunteers to develop. Donations enable us to keep delivering support for new versions and adding features your players love.
You can support development using the following methods:
- [Patreon](https://www.patreon.com/pocketminemp)
- Bitcoin (BTC): `171u8K9e4FtU6j3e5sqNoxKUgEw9qWQdRV`
- Stellar Lumens (XLM): `GAAC5WZ33HCTE3BFJFZJXONMEIBNHFLBXM2HJVAZHXXPYA3HP5XPPS7T`
- [Patreon](https://www.patreon.com/pocketminemp)
Thanks for your support!
## Licensing information
This project is licensed under LGPL-3.0. Please see the [LICENSE](/LICENSE) file for details.

@ -1 +1 @@
Subproject commit a34e48e7da753b633ffaa4a4f9516eae4bb97baa
Subproject commit 39885cf24826773bc3a0e8134e04a2032e97f477

View File

@ -117,3 +117,22 @@ Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if
- Removed code generation step for `RuntimeDataDescriber` enum serialization. All described enums now use PHP 8.1 native enums, which can be described without codegen using `RuntimeDataDescriber->enum()`.
- Added `DeprecatedLegacyEnumAccessRule` custom PHPStan rule to flag legacy `EnumTrait` case accessors.
- Cleaned up remaining hardcoded `Config` keys in `SetupWizard`. These usages now use auto-generated constants like the rest of the codebase.
# 5.8.2
Released 9th November 2023.
## Performance
- Improved performance of small packet zero-compression (unintended use of slow zlib compressor instead of fast libdeflate one).
- This affected the majority of outbound packets, as most packets are below the 256-byte threshold for compression.
- This faster method is over 20x faster than the old method, producing noticeable performance gains for large servers.
## Fixes
- Fixed melons and pumpkins not growing.
- Fixed melon and pumpkin stems not attaching to the grown melon/pumpkin.
- Fixed iron and gold ores not being affected by the Fortune enchantment.
- Fixed ancient debris burning in lava.
- Fixed sign (front) text loading from vanilla world saves (back text is not yet supported).
## Internals
- Removed bogus optimization from `tools/generate-blockstate-upgrade-schema.php` that could cause incorrect `remappedStates` generation when some of the states stayed under the old ID.
- Fixed possible crash in `BlockStateUpgrader` name flattening rule handling with invalid blockstate NBT data.

View File

@ -1371,6 +1371,7 @@ class Server{
}
/**
* @internal
* Broadcasts a list of packets in a batch to a list of players
*
* @param bool|null $sync Compression on the main thread (true) or workers (false). Default is automatic (null).

View File

@ -31,7 +31,7 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "5.8.2";
public const BASE_VERSION = "5.8.3";
public const IS_DEVELOPMENT_BUILD = true;
public const BUILD_CHANNEL = "stable";

View File

@ -868,6 +868,8 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("pink_petals", fn() => Blocks::PINK_PETALS());
$result->registerBlock("pink_tulip", fn() => Blocks::PINK_TULIP());
$result->registerBlock("piglin_head", fn() => Blocks::MOB_HEAD()->setMobHeadType(MobHeadType::PIGLIN));
$result->registerBlock("pitcher_plant", fn() => Blocks::PITCHER_PLANT());
$result->registerBlock("pitcher_pod", fn() => Blocks::PITCHER_CROP());
$result->registerBlock("plank", fn() => Blocks::OAK_PLANKS());
$result->registerBlock("planks", fn() => Blocks::OAK_PLANKS());
$result->registerBlock("player_head", fn() => Blocks::MOB_HEAD()->setMobHeadType(MobHeadType::PLAYER));

View File

@ -35,6 +35,7 @@ use function get_class;
use function str_starts_with;
abstract class Timings{
public const GROUP_MINECRAFT = "Minecraft";
public const GROUP_BREAKDOWN = "Minecraft - Breakdown";
private static bool $initialized = false;
@ -136,8 +137,8 @@ abstract class Timings{
self::$initialized = true;
self::$fullTick = new TimingsHandler("Full Server Tick");
self::$serverTick = new TimingsHandler("Server Tick Update Cycle", self::$fullTick, group: self::GROUP_BREAKDOWN);
self::$serverInterrupts = new TimingsHandler("Server Mid-Tick Processing", self::$fullTick, group: self::GROUP_BREAKDOWN);
self::$serverTick = new TimingsHandler("Server Tick Update Cycle", self::$fullTick);
self::$serverInterrupts = new TimingsHandler("Server Mid-Tick Processing", self::$fullTick);
self::$memoryManager = new TimingsHandler("Memory Manager");
self::$garbageCollector = new TimingsHandler("Garbage Collector", self::$memoryManager);
self::$titleTick = new TimingsHandler("Console Title Tick");
@ -145,53 +146,53 @@ abstract class Timings{
self::$connection = new TimingsHandler("Connection Handler");
self::$playerNetworkSend = new TimingsHandler("Player Network Send", self::$connection);
self::$playerNetworkSendCompress = new TimingsHandler("Player Network Send - Compression", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
self::$playerNetworkSendCompressBroadcast = new TimingsHandler("Player Network Send - Compression (Broadcast)", self::$playerNetworkSendCompress, group: self::GROUP_BREAKDOWN);
self::$playerNetworkSendCompressSessionBuffer = new TimingsHandler("Player Network Send - Compression (Session Buffer)", self::$playerNetworkSendCompress, group: self::GROUP_BREAKDOWN);
self::$playerNetworkSendCompressSync = new TimingsHandler("Player Network Send - Compression (Main Thread)", self::$playerNetworkSendCompress, group: self::GROUP_BREAKDOWN);
self::$playerNetworkSendCompressAsync = new TimingsHandler("Player Network Send - Compression (Handoff to Worker Thread)", self::$playerNetworkSendCompress, group: self::GROUP_BREAKDOWN);
self::$playerNetworkSendEncrypt = new TimingsHandler("Player Network Send - Encryption", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
self::$playerNetworkSendInventorySync = new TimingsHandler("Player Network Send - Inventory Sync", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
self::$playerNetworkSendPreSpawnGameData = new TimingsHandler("Player Network Send - Pre-Spawn Game Data", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
self::$playerNetworkSendCompress = new TimingsHandler("Player Network Send - Compression", self::$playerNetworkSend);
self::$playerNetworkSendCompressBroadcast = new TimingsHandler("Player Network Send - Compression (Broadcast)", self::$playerNetworkSendCompress);
self::$playerNetworkSendCompressSessionBuffer = new TimingsHandler("Player Network Send - Compression (Session Buffer)", self::$playerNetworkSendCompress);
self::$playerNetworkSendCompressSync = new TimingsHandler("Player Network Send - Compression (Main Thread)", self::$playerNetworkSendCompress);
self::$playerNetworkSendCompressAsync = new TimingsHandler("Player Network Send - Compression (Handoff to Worker Thread)", self::$playerNetworkSendCompress);
self::$playerNetworkSendEncrypt = new TimingsHandler("Player Network Send - Encryption", self::$playerNetworkSend);
self::$playerNetworkSendInventorySync = new TimingsHandler("Player Network Send - Inventory Sync", self::$playerNetworkSend);
self::$playerNetworkSendPreSpawnGameData = new TimingsHandler("Player Network Send - Pre-Spawn Game Data", self::$playerNetworkSend);
self::$playerNetworkReceive = new TimingsHandler("Player Network Receive", self::$connection);
self::$playerNetworkReceiveDecompress = new TimingsHandler("Player Network Receive - Decompression", self::$playerNetworkReceive, group: self::GROUP_BREAKDOWN);
self::$playerNetworkReceiveDecrypt = new TimingsHandler("Player Network Receive - Decryption", self::$playerNetworkReceive, group: self::GROUP_BREAKDOWN);
self::$playerNetworkReceiveDecompress = new TimingsHandler("Player Network Receive - Decompression", self::$playerNetworkReceive);
self::$playerNetworkReceiveDecrypt = new TimingsHandler("Player Network Receive - Decryption", self::$playerNetworkReceive);
self::$broadcastPackets = new TimingsHandler("Broadcast Packets", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
self::$broadcastPackets = new TimingsHandler("Broadcast Packets", self::$playerNetworkSend);
self::$playerMove = new TimingsHandler("Player Movement");
self::$playerChunkOrder = new TimingsHandler("Player Order Chunks");
self::$playerChunkSend = new TimingsHandler("Player Network Send - Chunks", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
self::$playerChunkSend = new TimingsHandler("Player Network Send - Chunks", self::$playerNetworkSend);
self::$scheduler = new TimingsHandler("Scheduler");
self::$serverCommand = new TimingsHandler("Server Command");
self::$permissibleCalculation = new TimingsHandler("Permissible Calculation");
self::$permissibleCalculationDiff = new TimingsHandler("Permissible Calculation - Diff", self::$permissibleCalculation, group: self::GROUP_BREAKDOWN);
self::$permissibleCalculationCallback = new TimingsHandler("Permissible Calculation - Callbacks", self::$permissibleCalculation, group: self::GROUP_BREAKDOWN);
self::$permissibleCalculationDiff = new TimingsHandler("Permissible Calculation - Diff", self::$permissibleCalculation);
self::$permissibleCalculationCallback = new TimingsHandler("Permissible Calculation - Callbacks", self::$permissibleCalculation);
self::$syncPlayerDataLoad = new TimingsHandler("Player Data Load");
self::$syncPlayerDataSave = new TimingsHandler("Player Data Save");
self::$entityMove = new TimingsHandler("Entity Movement", group: self::GROUP_BREAKDOWN);
self::$entityMoveCollision = new TimingsHandler("Entity Movement - Collision Checks", self::$entityMove, group: self::GROUP_BREAKDOWN);
self::$entityMove = new TimingsHandler("Entity Movement");
self::$entityMoveCollision = new TimingsHandler("Entity Movement - Collision Checks", self::$entityMove);
self::$projectileMove = new TimingsHandler("Projectile Movement", self::$entityMove, group: self::GROUP_BREAKDOWN);
self::$projectileMoveRayTrace = new TimingsHandler("Projectile Movement - Ray Tracing", self::$projectileMove, group: self::GROUP_BREAKDOWN);
self::$projectileMove = new TimingsHandler("Projectile Movement", self::$entityMove);
self::$projectileMoveRayTrace = new TimingsHandler("Projectile Movement - Ray Tracing", self::$projectileMove);
self::$playerCheckNearEntities = new TimingsHandler("checkNearEntities", group: self::GROUP_BREAKDOWN);
self::$entityBaseTick = new TimingsHandler("Entity Base Tick", group: self::GROUP_BREAKDOWN);
self::$livingEntityBaseTick = new TimingsHandler("Entity Base Tick - Living", group: self::GROUP_BREAKDOWN);
self::$itemEntityBaseTick = new TimingsHandler("Entity Base Tick - ItemEntity", group: self::GROUP_BREAKDOWN);
self::$playerCheckNearEntities = new TimingsHandler("checkNearEntities");
self::$entityBaseTick = new TimingsHandler("Entity Base Tick");
self::$livingEntityBaseTick = new TimingsHandler("Entity Base Tick - Living");
self::$itemEntityBaseTick = new TimingsHandler("Entity Base Tick - ItemEntity");
self::$schedulerSync = new TimingsHandler("Scheduler - Sync Tasks", group: self::GROUP_BREAKDOWN);
self::$schedulerSync = new TimingsHandler("Scheduler - Sync Tasks");
self::$schedulerAsync = new TimingsHandler("Scheduler - Async Tasks", group: self::GROUP_BREAKDOWN);
self::$asyncTaskProgressUpdateParent = new TimingsHandler("Async Tasks - Progress Updates", self::$schedulerAsync, group: self::GROUP_BREAKDOWN);
self::$asyncTaskCompletionParent = new TimingsHandler("Async Tasks - Completion Handlers", self::$schedulerAsync, group: self::GROUP_BREAKDOWN);
self::$asyncTaskErrorParent = new TimingsHandler("Async Tasks - Error Handlers", self::$schedulerAsync, group: self::GROUP_BREAKDOWN);
self::$schedulerAsync = new TimingsHandler("Scheduler - Async Tasks");
self::$asyncTaskProgressUpdateParent = new TimingsHandler("Async Tasks - Progress Updates", self::$schedulerAsync);
self::$asyncTaskCompletionParent = new TimingsHandler("Async Tasks - Completion Handlers", self::$schedulerAsync);
self::$asyncTaskErrorParent = new TimingsHandler("Async Tasks - Error Handlers", self::$schedulerAsync);
self::$playerCommand = new TimingsHandler("Player Command", group: self::GROUP_BREAKDOWN);
self::$craftingDataCacheRebuild = new TimingsHandler("Build CraftingDataPacket Cache", group: self::GROUP_BREAKDOWN);
self::$playerCommand = new TimingsHandler("Player Command");
self::$craftingDataCacheRebuild = new TimingsHandler("Build CraftingDataPacket Cache");
}
@ -233,7 +234,7 @@ abstract class Timings{
}else{
$displayName = self::shortenCoreClassName($entity::class, "pocketmine\\entity\\");
}
self::$entityTypeTimingMap[$entity::class] = new TimingsHandler("Entity Tick - " . $displayName, group: self::GROUP_BREAKDOWN);
self::$entityTypeTimingMap[$entity::class] = new TimingsHandler("Entity Tick - " . $displayName);
}
return self::$entityTypeTimingMap[$entity::class];
@ -243,8 +244,7 @@ abstract class Timings{
self::init();
if(!isset(self::$tileEntityTypeTimingMap[$tile::class])){
self::$tileEntityTypeTimingMap[$tile::class] = new TimingsHandler(
"Block Entity Tick - " . self::shortenCoreClassName($tile::class, "pocketmine\\block\\tile\\"),
group: self::GROUP_BREAKDOWN
"Block Entity Tick - " . self::shortenCoreClassName($tile::class, "pocketmine\\block\\tile\\")
);
}
@ -254,7 +254,7 @@ abstract class Timings{
public static function getReceiveDataPacketTimings(ServerboundPacket $pk) : TimingsHandler{
self::init();
if(!isset(self::$packetReceiveTimingMap[$pk::class])){
self::$packetReceiveTimingMap[$pk::class] = new TimingsHandler("Receive - " . $pk->getName(), self::$playerNetworkReceive, group: self::GROUP_BREAKDOWN);
self::$packetReceiveTimingMap[$pk::class] = new TimingsHandler("Receive - " . $pk->getName(), self::$playerNetworkReceive);
}
return self::$packetReceiveTimingMap[$pk::class];
@ -263,31 +263,28 @@ abstract class Timings{
public static function getDecodeDataPacketTimings(ServerboundPacket $pk) : TimingsHandler{
return self::$packetDecodeTimingMap[$pk::class] ??= new TimingsHandler(
"Decode - " . $pk->getName(),
self::getReceiveDataPacketTimings($pk),
group: self::GROUP_BREAKDOWN
self::getReceiveDataPacketTimings($pk)
);
}
public static function getHandleDataPacketTimings(ServerboundPacket $pk) : TimingsHandler{
return self::$packetHandleTimingMap[$pk::class] ??= new TimingsHandler(
"Handler - " . $pk->getName(),
self::getReceiveDataPacketTimings($pk),
group: self::GROUP_BREAKDOWN
self::getReceiveDataPacketTimings($pk)
);
}
public static function getEncodeDataPacketTimings(ClientboundPacket $pk) : TimingsHandler{
return self::$packetEncodeTimingMap[$pk::class] ??= new TimingsHandler(
"Encode - " . $pk->getName(),
self::getSendDataPacketTimings($pk),
group: self::GROUP_BREAKDOWN
self::getSendDataPacketTimings($pk)
);
}
public static function getSendDataPacketTimings(ClientboundPacket $pk) : TimingsHandler{
self::init();
if(!isset(self::$packetSendTimingMap[$pk::class])){
self::$packetSendTimingMap[$pk::class] = new TimingsHandler("Send - " . $pk->getName(), self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
self::$packetSendTimingMap[$pk::class] = new TimingsHandler("Send - " . $pk->getName(), self::$playerNetworkSend);
}
return self::$packetSendTimingMap[$pk::class];
@ -296,7 +293,7 @@ abstract class Timings{
public static function getCommandDispatchTimings(string $commandName) : TimingsHandler{
self::init();
return self::$commandTimingMap[$commandName] ??= new TimingsHandler("Command - " . $commandName, group: self::GROUP_BREAKDOWN);
return self::$commandTimingMap[$commandName] ??= new TimingsHandler("Command - " . $commandName);
}
public static function getEventTimings(Event $event) : TimingsHandler{
@ -320,7 +317,7 @@ abstract class Timings{
return self::$eventHandlers[$event][$handlerName];
}
public static function getAsyncTaskProgressUpdateTimings(AsyncTask $task, string $group = self::GROUP_BREAKDOWN) : TimingsHandler{
public static function getAsyncTaskProgressUpdateTimings(AsyncTask $task, string $group = self::GROUP_MINECRAFT) : TimingsHandler{
$taskClass = $task::class;
if(!isset(self::$asyncTaskProgressUpdate[$taskClass])){
self::init();
@ -334,7 +331,7 @@ abstract class Timings{
return self::$asyncTaskProgressUpdate[$taskClass];
}
public static function getAsyncTaskCompletionTimings(AsyncTask $task, string $group = self::GROUP_BREAKDOWN) : TimingsHandler{
public static function getAsyncTaskCompletionTimings(AsyncTask $task, string $group = self::GROUP_MINECRAFT) : TimingsHandler{
$taskClass = $task::class;
if(!isset(self::$asyncTaskCompletion[$taskClass])){
self::init();
@ -348,7 +345,7 @@ abstract class Timings{
return self::$asyncTaskCompletion[$taskClass];
}
public static function getAsyncTaskErrorTimings(AsyncTask $task, string $group = self::GROUP_BREAKDOWN) : TimingsHandler{
public static function getAsyncTaskErrorTimings(AsyncTask $task, string $group = self::GROUP_MINECRAFT) : TimingsHandler{
$taskClass = $task::class;
if(!isset(self::$asyncTaskError[$taskClass])){
self::init();

View File

@ -120,7 +120,7 @@ class TimingsHandler{
public function __construct(
private string $name,
private ?TimingsHandler $parent = null,
private string $group = "Minecraft"
private string $group = Timings::GROUP_MINECRAFT
){}
public function getName() : string{ return $this->name; }

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\world;
use pocketmine\timings\Timings;
use pocketmine\timings\TimingsHandler;
class WorldTimings{
@ -66,7 +65,7 @@ class WorldTimings{
private static function newTimer(string $worldName, string $timerName) : TimingsHandler{
$aggregator = self::$aggregators[$timerName] ??= new TimingsHandler("Worlds - $timerName"); //displayed in Minecraft primary table
return new TimingsHandler("$worldName - $timerName", $aggregator, Timings::GROUP_BREAKDOWN);
return new TimingsHandler("$worldName - $timerName", $aggregator);
}
public function __construct(World $world){