From d44e0e87d0106ff003de830a1296974cbd13e8ee Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Aug 2023 16:14:43 +0100 Subject: [PATCH 01/48] BaseSign: implement sign editing this was originally submitted by #6000, but considering the overcomplicated PR and the triviality of the feature, I figured it would be quicker to do it myself instead of having a bunch of back-and-forth bikeshedding over it. --- src/block/BaseSign.php | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/block/BaseSign.php b/src/block/BaseSign.php index 7f65b59f4..abb10dffe 100644 --- a/src/block/BaseSign.php +++ b/src/block/BaseSign.php @@ -159,20 +159,25 @@ abstract class BaseSign extends Transparent{ }; if($dyeColor !== null){ $color = $dyeColor->equals(DyeColor::BLACK()) ? new Color(0, 0, 0) : $dyeColor->getRgbValue(); - if($color->toARGB() === $this->text->getBaseColor()->toARGB()){ - return false; - } - - if($this->doSignChange(new SignText($this->text->getLines(), $color, $this->text->isGlowing()), $player, $item)){ + if( + $color->toARGB() !== $this->text->getBaseColor()->toARGB() && + $this->doSignChange(new SignText($this->text->getLines(), $color, $this->text->isGlowing()), $player, $item) + ){ $this->position->getWorld()->addSound($this->position, new DyeUseSound()); return true; } - }elseif($item->getTypeId() === ItemTypeIds::INK_SAC){ - return $this->changeSignGlowingState(false, $player, $item); - }elseif($item->getTypeId() === ItemTypeIds::GLOW_INK_SAC){ - return $this->changeSignGlowingState(true, $player, $item); + }elseif(match($item->getTypeId()){ + ItemTypeIds::INK_SAC => $this->changeSignGlowingState(false, $player, $item), + ItemTypeIds::GLOW_INK_SAC => $this->changeSignGlowingState(true, $player, $item), + default => false + }){ + return true; } - return false; + + //TODO: editor should not open for waxed signs + $player->openSignEditor($this->position); + + return true; } /** @@ -217,7 +222,7 @@ abstract class BaseSign extends Transparent{ } $ev = new SignChangeEvent($this, $author, new SignText(array_map(function(string $line) : string{ return TextFormat::clean($line, false); - }, $text->getLines()))); + }, $text->getLines()), $this->text->getBaseColor(), $this->text->isGlowing())); if($this->editorEntityRuntimeId === null || $this->editorEntityRuntimeId !== $author->getId()){ $ev->cancel(); } From 22778583cf8108a1007f741f86815f9d181d520a Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Aug 2023 16:28:17 +0100 Subject: [PATCH 02/48] Sign: implement waxing using honeycomb --- src/block/BaseSign.php | 35 +++++++++++++++++++++++++++++++++-- src/block/tile/Sign.php | 10 +++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/block/BaseSign.php b/src/block/BaseSign.php index abb10dffe..a3556054b 100644 --- a/src/block/BaseSign.php +++ b/src/block/BaseSign.php @@ -49,6 +49,8 @@ abstract class BaseSign extends Transparent{ use WoodTypeTrait; protected SignText $text; + private bool $waxed = false; + protected ?int $editorEntityRuntimeId = null; /** @var \Closure() : Item */ @@ -69,6 +71,7 @@ abstract class BaseSign extends Transparent{ $tile = $this->position->getWorld()->getTile($this->position); if($tile instanceof TileSign){ $this->text = $tile->getText(); + $this->waxed = $tile->isWaxed(); $this->editorEntityRuntimeId = $tile->getEditorEntityRuntimeId(); } @@ -80,6 +83,7 @@ abstract class BaseSign extends Transparent{ $tile = $this->position->getWorld()->getTile($this->position); assert($tile instanceof TileSign); $tile->setText($this->text); + $tile->setWaxed($this->waxed); $tile->setEditorEntityRuntimeId($this->editorEntityRuntimeId); } @@ -147,10 +151,26 @@ abstract class BaseSign extends Transparent{ return false; } + private function wax(Player $player, Item $item) : bool{ + if($this->waxed){ + return false; + } + + $this->waxed = true; + $this->position->getWorld()->setBlock($this->position, $this); + $item->pop(); + + return true; + } + public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{ if($player === null){ return false; } + if($this->waxed){ + return true; + } + $dyeColor = $item instanceof Dye ? $item->getColor() : match($item->getTypeId()){ ItemTypeIds::BONE_MEAL => DyeColor::WHITE(), ItemTypeIds::LAPIS_LAZULI => DyeColor::BLUE(), @@ -169,12 +189,12 @@ abstract class BaseSign extends Transparent{ }elseif(match($item->getTypeId()){ ItemTypeIds::INK_SAC => $this->changeSignGlowingState(false, $player, $item), ItemTypeIds::GLOW_INK_SAC => $this->changeSignGlowingState(true, $player, $item), + ItemTypeIds::HONEYCOMB => $this->wax($player, $item), default => false }){ return true; } - //TODO: editor should not open for waxed signs $player->openSignEditor($this->position); return true; @@ -193,6 +213,17 @@ abstract class BaseSign extends Transparent{ return $this; } + /** + * Returns whether the sign has been waxed using a honeycomb. If true, the sign cannot be edited by a player. + */ + public function isWaxed() : bool{ return $this->waxed; } + + /** @return $this */ + public function setWaxed(bool $waxed) : self{ + $this->waxed = $waxed; + return $this; + } + /** * Sets the runtime entity ID of the player editing this sign. Only this player will be able to edit the sign. * This is used to prevent multiple players from editing the same sign at the same time, and to prevent players @@ -223,7 +254,7 @@ abstract class BaseSign extends Transparent{ $ev = new SignChangeEvent($this, $author, new SignText(array_map(function(string $line) : string{ return TextFormat::clean($line, false); }, $text->getLines()), $this->text->getBaseColor(), $this->text->isGlowing())); - if($this->editorEntityRuntimeId === null || $this->editorEntityRuntimeId !== $author->getId()){ + if($this->waxed || $this->editorEntityRuntimeId === null || $this->editorEntityRuntimeId !== $author->getId()){ $ev->cancel(); } $ev->call(); diff --git a/src/block/tile/Sign.php b/src/block/tile/Sign.php index 047c54703..d5d314ee3 100644 --- a/src/block/tile/Sign.php +++ b/src/block/tile/Sign.php @@ -68,6 +68,8 @@ class Sign extends Spawnable{ } protected SignText $text; + private bool $waxed = false; + protected ?int $editorEntityRuntimeId = null; public function __construct(World $world, Vector3 $pos){ @@ -101,6 +103,7 @@ class Sign extends Spawnable{ } $this->text = new SignText($text); } + $this->waxed = $nbt->getByte(self::TAG_WAXED, 0) !== 0; } protected function writeSaveData(CompoundTag $nbt) : void{ @@ -113,6 +116,7 @@ class Sign extends Spawnable{ $nbt->setInt(self::TAG_TEXT_COLOR, Binary::signInt($this->text->getBaseColor()->toARGB())); $nbt->setByte(self::TAG_GLOWING_TEXT, $this->text->isGlowing() ? 1 : 0); $nbt->setByte(self::TAG_LEGACY_BUG_RESOLVE, 1); + $nbt->setByte(self::TAG_WAXED, $this->waxed ? 1 : 0); } public function getText() : SignText{ @@ -123,6 +127,10 @@ class Sign extends Spawnable{ $this->text = $text; } + public function isWaxed() : bool{ return $this->waxed; } + + public function setWaxed(bool $waxed) : void{ $this->waxed = $waxed; } + /** * Returns the entity runtime ID of the player who placed this sign. Only the player whose entity ID matches this * one may edit the sign text. @@ -153,7 +161,7 @@ class Sign extends Spawnable{ ->setByte(self::TAG_GLOWING_TEXT, 0) ->setByte(self::TAG_PERSIST_FORMATTING, 1) ); - $nbt->setByte(self::TAG_WAXED, 0); + $nbt->setByte(self::TAG_WAXED, $this->waxed ? 1 : 0); $nbt->setLong(self::TAG_LOCKED_FOR_EDITING_BY, $this->editorEntityRuntimeId ?? -1); } } From cd6abbe0bb3ffbfa2c1797db2971e98593305c38 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Aug 2023 16:30:16 +0100 Subject: [PATCH 03/48] BaseSign: remove redundant condition --- src/block/BaseSign.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/block/BaseSign.php b/src/block/BaseSign.php index a3556054b..d7a22f3b8 100644 --- a/src/block/BaseSign.php +++ b/src/block/BaseSign.php @@ -254,7 +254,7 @@ abstract class BaseSign extends Transparent{ $ev = new SignChangeEvent($this, $author, new SignText(array_map(function(string $line) : string{ return TextFormat::clean($line, false); }, $text->getLines()), $this->text->getBaseColor(), $this->text->isGlowing())); - if($this->waxed || $this->editorEntityRuntimeId === null || $this->editorEntityRuntimeId !== $author->getId()){ + if($this->waxed || $this->editorEntityRuntimeId !== $author->getId()){ $ev->cancel(); } $ev->call(); From 9d4c37fc3ab28b0ef2097c4044e45543d0065095 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Aug 2023 18:26:47 +0100 Subject: [PATCH 04/48] Release 4.23.6 --- changelogs/4.23.md | 6 ++++++ src/VersionInfo.php | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/changelogs/4.23.md b/changelogs/4.23.md index 750261e4b..317b6b458 100644 --- a/changelogs/4.23.md +++ b/changelogs/4.23.md @@ -60,3 +60,9 @@ Released 9th August 2023. - Fixed `PluginBase->saveResource()` leaking file resources when the data file already exists in the plugin's data folder. This bug existed since 2014 and was only discovered recently. - Fixed coral blocks becoming dead after calling `getDropsForCompatibleTool()` on them. - Fixed `BlockDeathEvent->getOldState()` returning a block which is already dead. + +# 4.23.6 +Released 21st August 2023. + +## Fixes +- Added a workaround for armor and other inventories not working correctly after inventory sync. This is caused by a client bug. diff --git a/src/VersionInfo.php b/src/VersionInfo.php index efcfdaaf1..a2ff7cf93 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -32,7 +32,7 @@ use function str_repeat; final class VersionInfo{ public const NAME = "PocketMine-MP"; public const BASE_VERSION = "4.23.6"; - public const IS_DEVELOPMENT_BUILD = true; + public const IS_DEVELOPMENT_BUILD = false; public const BUILD_CHANNEL = "stable"; private function __construct(){ From 7aaef8cb89cddf1c01438d92c4f1aeb24b97297c Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Aug 2023 18:26:50 +0100 Subject: [PATCH 05/48] 4.23.7 is next --- src/VersionInfo.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VersionInfo.php b/src/VersionInfo.php index a2ff7cf93..905c16824 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -31,8 +31,8 @@ use function str_repeat; final class VersionInfo{ public const NAME = "PocketMine-MP"; - public const BASE_VERSION = "4.23.6"; - public const IS_DEVELOPMENT_BUILD = false; + public const BASE_VERSION = "4.23.7"; + public const IS_DEVELOPMENT_BUILD = true; public const BUILD_CHANNEL = "stable"; private function __construct(){ From e852a4382116705d7558fd808f1b388666b0c0cb Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Aug 2023 18:31:45 +0100 Subject: [PATCH 06/48] Release 5.4.3 --- changelogs/5.4.md | 12 ++++++++++++ src/VersionInfo.php | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/changelogs/5.4.md b/changelogs/5.4.md index bdaec51cb..7dd95a657 100644 --- a/changelogs/5.4.md +++ b/changelogs/5.4.md @@ -107,3 +107,15 @@ Released 9th August 2023. ## Fixes - Fixed cake accepting candle placement when slices have already been eaten. - Fixed fire charges not lighting candles. + +# 5.4.3 +Released 21st August 2023. + +## Included releases +- [4.23.6](https://github.com/pmmp/PocketMine-MP/blob/4.23.6/changelogs/4.23.md#4236) - Armor inventory client bug workaround + +## Fixes +- Fixed crashdumps not generating correctly on fatal errors. +- Fixed `PotionCauldron::setPotionItem()` not validating the item type. +- Fixed chorus fruit not considering teleport destinations below y=0. +- Fixed cake dropping itself when mined. diff --git a/src/VersionInfo.php b/src/VersionInfo.php index bec9638ea..82bc2d46e 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -32,7 +32,7 @@ use function str_repeat; final class VersionInfo{ public const NAME = "PocketMine-MP"; public const BASE_VERSION = "5.4.3"; - public const IS_DEVELOPMENT_BUILD = true; + public const IS_DEVELOPMENT_BUILD = false; public const BUILD_CHANNEL = "stable"; /** From 4cc858829f9b952b8e6df717f8ead42a6c02c88b Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 21 Aug 2023 18:31:45 +0100 Subject: [PATCH 07/48] 5.4.4 is next --- src/VersionInfo.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VersionInfo.php b/src/VersionInfo.php index 82bc2d46e..c9109487b 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -31,8 +31,8 @@ use function str_repeat; final class VersionInfo{ public const NAME = "PocketMine-MP"; - public const BASE_VERSION = "5.4.3"; - public const IS_DEVELOPMENT_BUILD = false; + public const BASE_VERSION = "5.4.4"; + public const IS_DEVELOPMENT_BUILD = true; public const BUILD_CHANNEL = "stable"; /** From d03e4d17ec79e29745e8b94ee8b6f0da9f52e9cf Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 14:26:17 +0100 Subject: [PATCH 08/48] Use hasHandlers() for events in player movement processing pathway this should offer a minor performance improvement. --- src/entity/HungerManager.php | 16 ++++++++++------ src/player/Player.php | 20 +++++++++++--------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/entity/HungerManager.php b/src/entity/HungerManager.php index 304dcd30b..a31855891 100644 --- a/src/entity/HungerManager.php +++ b/src/entity/HungerManager.php @@ -133,14 +133,18 @@ class HungerManager{ if(!$this->enabled){ return 0; } - $ev = new PlayerExhaustEvent($this->entity, $amount, $cause); - $ev->call(); - if($ev->isCancelled()){ - return 0.0; + $evAmount = $amount; + if(PlayerExhaustEvent::hasHandlers()){ + $ev = new PlayerExhaustEvent($this->entity, $amount, $cause); + $ev->call(); + if($ev->isCancelled()){ + return 0.0; + } + $evAmount = $ev->getAmount(); } $exhaustion = $this->getExhaustion(); - $exhaustion += $ev->getAmount(); + $exhaustion += $evAmount; while($exhaustion >= 4.0){ $exhaustion -= 4.0; @@ -159,7 +163,7 @@ class HungerManager{ } $this->setExhaustion($exhaustion); - return $ev->getAmount(); + return $evAmount; } public function getFoodTickTimer() : int{ diff --git a/src/player/Player.php b/src/player/Player.php index f62485242..d34a357ee 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -1330,18 +1330,20 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ $deltaAngle = abs($this->lastLocation->yaw - $to->yaw) + abs($this->lastLocation->pitch - $to->pitch); if($delta > 0.0001 || $deltaAngle > 1.0){ - $ev = new PlayerMoveEvent($this, $from, $to); + if(PlayerMoveEvent::hasHandlers()){ + $ev = new PlayerMoveEvent($this, $from, $to); - $ev->call(); + $ev->call(); - if($ev->isCancelled()){ - $this->revertMovement($from); - return; - } + if($ev->isCancelled()){ + $this->revertMovement($from); + return; + } - if($to->distanceSquared($ev->getTo()) > 0.01){ //If plugins modify the destination - $this->teleport($ev->getTo()); - return; + if($to->distanceSquared($ev->getTo()) > 0.01){ //If plugins modify the destination + $this->teleport($ev->getTo()); + return; + } } $this->lastLocation = $to; From f4d5605de13f3f67179d4d144710e98abc556376 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 14:35:53 +0100 Subject: [PATCH 09/48] Use hasHandlers() on more warm-hot events --- src/world/World.php | 56 ++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/src/world/World.php b/src/world/World.php index 3ff5632cb..d917a3e82 100644 --- a/src/world/World.php +++ b/src/world/World.php @@ -694,16 +694,19 @@ class World implements ChunkManager{ */ public function addSound(Vector3 $pos, Sound $sound, ?array $players = null) : void{ $players ??= $this->getViewersForPosition($pos); - $ev = new WorldSoundEvent($this, $sound, $pos, $players); - $ev->call(); + if(WorldSoundEvent::hasHandlers()){ + $ev = new WorldSoundEvent($this, $sound, $pos, $players); + $ev->call(); + if($ev->isCancelled()){ + return; + } - if($ev->isCancelled()){ - return; + $sound = $ev->getSound(); + $players = $ev->getRecipients(); } - $pk = $ev->getSound()->encode($pos); - $players = $ev->getRecipients(); + $pk = $sound->encode($pos); if(count($pk) > 0){ if($players === $this->getViewersForPosition($pos)){ foreach($pk as $e){ @@ -720,23 +723,26 @@ class World implements ChunkManager{ */ public function addParticle(Vector3 $pos, Particle $particle, ?array $players = null) : void{ $players ??= $this->getViewersForPosition($pos); - $ev = new WorldParticleEvent($this, $particle, $pos, $players); - $ev->call(); + if(WorldParticleEvent::hasHandlers()){ + $ev = new WorldParticleEvent($this, $particle, $pos, $players); + $ev->call(); + if($ev->isCancelled()){ + return; + } - if($ev->isCancelled()){ - return; + $particle = $ev->getParticle(); + $players = $ev->getRecipients(); } - $pk = $ev->getParticle()->encode($pos); - $players = $ev->getRecipients(); + $pk = $particle->encode($pos); if(count($pk) > 0){ if($players === $this->getViewersForPosition($pos)){ foreach($pk as $e){ $this->broadcastPacketToViewers($pos, $e); } }else{ - NetworkBroadcastUtils::broadcastPackets($this->filterViewersForPosition($pos, $ev->getRecipients()), $pk); + NetworkBroadcastUtils::broadcastPackets($this->filterViewersForPosition($pos, $players), $pk); } } } @@ -2517,7 +2523,9 @@ class World implements ChunkManager{ } if($oldChunk === null){ - (new ChunkLoadEvent($this, $chunkX, $chunkZ, $chunk, true))->call(); + if(ChunkLoadEvent::hasHandlers()){ + (new ChunkLoadEvent($this, $chunkX, $chunkZ, $chunk, true))->call(); + } foreach($this->getChunkListeners($chunkX, $chunkZ) as $listener){ $listener->onChunkLoaded($chunkX, $chunkZ, $chunk); @@ -2791,7 +2799,9 @@ class World implements ChunkManager{ $this->initChunk($x, $z, $chunkData); - (new ChunkLoadEvent($this, $x, $z, $this->chunks[$chunkHash], false))->call(); + if(ChunkLoadEvent::hasHandlers()){ + (new ChunkLoadEvent($this, $x, $z, $this->chunks[$chunkHash], false))->call(); + } if(!$this->isChunkInUse($x, $z)){ $this->logger->debug("Newly loaded chunk $x $z has no loaders registered, will be unloaded at next available opportunity"); @@ -2904,12 +2914,14 @@ class World implements ChunkManager{ $chunk = $this->chunks[$chunkHash] ?? null; if($chunk !== null){ - $ev = new ChunkUnloadEvent($this, $x, $z, $chunk); - $ev->call(); - if($ev->isCancelled()){ - $this->timings->doChunkUnload->stopTiming(); + if(ChunkUnloadEvent::hasHandlers()){ + $ev = new ChunkUnloadEvent($this, $x, $z, $chunk); + $ev->call(); + if($ev->isCancelled()){ + $this->timings->doChunkUnload->stopTiming(); - return false; + return false; + } } if($trySave && $this->getAutoSave()){ @@ -3366,7 +3378,9 @@ class World implements ChunkManager{ } if(($oldChunk === null || !$oldChunk->isPopulated()) && $chunk->isPopulated()){ - (new ChunkPopulateEvent($this, $x, $z, $chunk))->call(); + if(ChunkPopulateEvent::hasHandlers()){ + (new ChunkPopulateEvent($this, $x, $z, $chunk))->call(); + } foreach($this->getChunkListeners($x, $z) as $listener){ $listener->onChunkPopulated($x, $z, $chunk); From df96e023dcd2fc887bcc7d06f5ce958788840ce6 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 14:42:50 +0100 Subject: [PATCH 10/48] Require pocketmine/nbt 1.0.0 --- composer.json | 2 +- composer.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 5a875d218..5f59f64d5 100644 --- a/composer.json +++ b/composer.json @@ -44,7 +44,7 @@ "pocketmine/locale-data": "~2.19.0", "pocketmine/log": "^0.4.0", "pocketmine/math": "~1.0.0", - "pocketmine/nbt": "^0.3.2", + "pocketmine/nbt": "~1.0.0", "pocketmine/raklib": "^0.15.0", "pocketmine/raklib-ipc": "^0.2.0", "pocketmine/snooze": "^0.5.0", diff --git a/composer.lock b/composer.lock index d908bca41..c5f2018d1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2d51c1adf069760587b6d36f9c4a5db3", + "content-hash": "9237955fd97ba7c1697d80314fa9ad6f", "packages": [ { "name": "adhocore/json-comment", @@ -521,16 +521,16 @@ }, { "name": "pocketmine/nbt", - "version": "0.3.4", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/pmmp/NBT.git", - "reference": "62c02464c6708b2467c1e1a2af01af09d5114eda" + "reference": "20540271cb59e04672cb163dca73366f207974f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/NBT/zipball/62c02464c6708b2467c1e1a2af01af09d5114eda", - "reference": "62c02464c6708b2467c1e1a2af01af09d5114eda", + "url": "https://api.github.com/repos/pmmp/NBT/zipball/20540271cb59e04672cb163dca73366f207974f1", + "reference": "20540271cb59e04672cb163dca73366f207974f1", "shasum": "" }, "require": { @@ -540,7 +540,7 @@ }, "require-dev": { "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "1.10.3", + "phpstan/phpstan": "1.10.25", "phpstan/phpstan-strict-rules": "^1.0", "phpunit/phpunit": "^9.5" }, @@ -557,9 +557,9 @@ "description": "PHP library for working with Named Binary Tags", "support": { "issues": "https://github.com/pmmp/NBT/issues", - "source": "https://github.com/pmmp/NBT/tree/0.3.4" + "source": "https://github.com/pmmp/NBT/tree/1.0.0" }, - "time": "2023-04-10T11:31:20+00:00" + "time": "2023-07-14T13:01:49+00:00" }, { "name": "pocketmine/netresearch-jsonmapper", From 20a41b00bacda8514e97fc48bc786edc5595d534 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 15:24:29 +0100 Subject: [PATCH 11/48] StringToTParser: added registerAlias() --- src/utils/StringToTParser.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/utils/StringToTParser.php b/src/utils/StringToTParser.php index 0166e2a28..d98153ac1 100644 --- a/src/utils/StringToTParser.php +++ b/src/utils/StringToTParser.php @@ -58,6 +58,21 @@ abstract class StringToTParser{ $this->callbackMap[$this->reprocess($alias)] = $callback; } + /** + * Registers a new alias for an existing known alias. + */ + public function registerAlias(string $existing, string $alias) : void{ + $existingKey = $this->reprocess($existing); + if(!isset($this->callbackMap[$existingKey])){ + throw new \InvalidArgumentException("Cannot register new alias for unknown existing alias \"$existing\""); + } + $newKey = $this->reprocess($alias); + if(isset($this->callbackMap[$newKey])){ + throw new \InvalidArgumentException("Alias \"$newKey\" is already registered"); + } + $this->callbackMap[$newKey] = $this->callbackMap[$existingKey]; + } + /** * Tries to parse the specified string into a corresponding instance of T. * @phpstan-return T|null From 29fdc8b08d38ae153a932bb2820045ee37b61538 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 15:49:31 +0100 Subject: [PATCH 12/48] Private constructor for EnchantmentHelper --- src/item/enchantment/EnchantmentHelper.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/item/enchantment/EnchantmentHelper.php b/src/item/enchantment/EnchantmentHelper.php index bd4b68963..a427eb4a4 100644 --- a/src/item/enchantment/EnchantmentHelper.php +++ b/src/item/enchantment/EnchantmentHelper.php @@ -43,6 +43,10 @@ use function round; final class EnchantmentHelper{ private const MAX_BOOKSHELF_COUNT = 15; + private function __construct(){ + //NOOP + } + /** * @param EnchantmentInstance[] $enchantments */ From d942748203c27546be6f37ec8818aa8cb40916b3 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 15:52:49 +0100 Subject: [PATCH 13/48] Move enchanting seed generation to EnchantmentHelper --- src/entity/Human.php | 9 ++++----- src/inventory/transaction/EnchantTransaction.php | 2 +- src/item/enchantment/EnchantmentHelper.php | 9 +++++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/entity/Human.php b/src/entity/Human.php index 30142b91d..7ee729655 100644 --- a/src/entity/Human.php +++ b/src/entity/Human.php @@ -37,6 +37,7 @@ use pocketmine\inventory\InventoryHolder; use pocketmine\inventory\PlayerEnderInventory; use pocketmine\inventory\PlayerInventory; use pocketmine\inventory\PlayerOffHandInventory; +use pocketmine\item\enchantment\EnchantmentHelper; use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\item\Item; use pocketmine\item\Totem; @@ -66,7 +67,6 @@ use pocketmine\network\mcpe\protocol\types\PlayerListEntry; use pocketmine\network\mcpe\protocol\types\PlayerPermissions; use pocketmine\network\mcpe\protocol\UpdateAbilitiesPacket; use pocketmine\player\Player; -use pocketmine\utils\Limits; use pocketmine\world\sound\TotemUseSound; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; @@ -76,7 +76,6 @@ use function array_key_exists; use function array_merge; use function array_values; use function min; -use function mt_rand; class Human extends Living implements ProjectileSource, InventoryHolder{ @@ -219,8 +218,8 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ $this->xpSeed = $seed; } - public function generateEnchantmentSeed() : int{ - return mt_rand(Limits::INT32_MIN, Limits::INT32_MAX); + public function regenerateEnchantmentSeed() : void{ + $this->xpSeed = EnchantmentHelper::generateSeed(); } public function getXpDropAmount() : int{ @@ -346,7 +345,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ if(($xpSeedTag = $nbt->getTag(self::TAG_XP_SEED)) instanceof IntTag){ $this->xpSeed = $xpSeedTag->getValue(); }else{ - $this->xpSeed = $this->generateEnchantmentSeed(); + $this->xpSeed = EnchantmentHelper::generateSeed(); } } diff --git a/src/inventory/transaction/EnchantTransaction.php b/src/inventory/transaction/EnchantTransaction.php index 5ea8a997f..7ddcd36c2 100644 --- a/src/inventory/transaction/EnchantTransaction.php +++ b/src/inventory/transaction/EnchantTransaction.php @@ -119,7 +119,7 @@ class EnchantTransaction extends InventoryTransaction{ //In this case, as much XP as possible will be taken. $this->source->getXpManager()->subtractXpLevels(min($this->cost, $this->source->getXpManager()->getXpLevel())); } - $this->source->setEnchantmentSeed($this->source->generateEnchantmentSeed()); + $this->source->regenerateEnchantmentSeed(); } protected function callExecuteEvent() : bool{ diff --git a/src/item/enchantment/EnchantmentHelper.php b/src/item/enchantment/EnchantmentHelper.php index a427eb4a4..c1e0af5bd 100644 --- a/src/item/enchantment/EnchantmentHelper.php +++ b/src/item/enchantment/EnchantmentHelper.php @@ -28,6 +28,7 @@ use pocketmine\item\enchantment\AvailableEnchantmentRegistry as EnchantmentRegis use pocketmine\item\Item; use pocketmine\item\ItemTypeIds; use pocketmine\item\VanillaItems as Items; +use pocketmine\utils\Limits; use pocketmine\utils\Random; use pocketmine\world\Position; use function abs; @@ -37,6 +38,7 @@ use function count; use function floor; use function max; use function min; +use function mt_rand; use function ord; use function round; @@ -47,6 +49,13 @@ final class EnchantmentHelper{ //NOOP } + /** + * Generates a new random seed for enchant option randomization. + */ + public static function generateSeed() : int{ + return mt_rand(Limits::INT32_MIN, Limits::INT32_MAX); + } + /** * @param EnchantmentInstance[] $enchantments */ From bf668c0f6ce7f1c3923cf862de30e783e4549607 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 16:07:02 +0100 Subject: [PATCH 14/48] Rename EnchantHelper related stuff Perhaps this and EnchantOption should be called EnchantingHelper and EnchantingOption respectively. The terminology used is rather inconsistent, but 'enchantment' definitely isn't the right word here. --- src/block/inventory/EnchantInventory.php | 4 ++-- src/command/defaults/EnchantCommand.php | 4 ++-- src/entity/Human.php | 6 +++--- src/inventory/transaction/EnchantTransaction.php | 4 ++-- .../{EnchantmentHelper.php => EnchantHelper.php} | 7 +++++-- 5 files changed, 14 insertions(+), 11 deletions(-) rename src/item/enchantment/{EnchantmentHelper.php => EnchantHelper.php} (97%) diff --git a/src/block/inventory/EnchantInventory.php b/src/block/inventory/EnchantInventory.php index 5d7e45259..7b79ef21c 100644 --- a/src/block/inventory/EnchantInventory.php +++ b/src/block/inventory/EnchantInventory.php @@ -26,7 +26,7 @@ namespace pocketmine\block\inventory; use pocketmine\event\player\PlayerEnchantOptionsRequestEvent; use pocketmine\inventory\SimpleInventory; use pocketmine\inventory\TemporaryInventory; -use pocketmine\item\enchantment\EnchantmentHelper as Helper; +use pocketmine\item\enchantment\EnchantHelper as Helper; use pocketmine\item\enchantment\EnchantOption; use pocketmine\item\Item; use pocketmine\world\Position; @@ -52,7 +52,7 @@ class EnchantInventory extends SimpleInventory implements BlockInventory, Tempor foreach($this->viewers as $viewer){ $this->options = []; $item = $this->getInput(); - $options = Helper::getEnchantOptions($this->holder, $item, $viewer->getEnchantmentSeed()); + $options = Helper::generateOptions($this->holder, $item, $viewer->getEnchantmentSeed()); $event = new PlayerEnchantOptionsRequestEvent($viewer, $this, $options); $event->call(); diff --git a/src/command/defaults/EnchantCommand.php b/src/command/defaults/EnchantCommand.php index 189931b99..ea1ead195 100644 --- a/src/command/defaults/EnchantCommand.php +++ b/src/command/defaults/EnchantCommand.php @@ -25,7 +25,7 @@ namespace pocketmine\command\defaults; use pocketmine\command\CommandSender; use pocketmine\command\utils\InvalidCommandSyntaxException; -use pocketmine\item\enchantment\EnchantmentHelper; +use pocketmine\item\enchantment\EnchantHelper; use pocketmine\item\enchantment\EnchantmentInstance; use pocketmine\item\enchantment\StringToEnchantmentParser; use pocketmine\lang\KnownTranslationFactory; @@ -78,7 +78,7 @@ class EnchantCommand extends VanillaCommand{ } //this is necessary to deal with enchanted books, which are a different item type than regular books - $enchantedItem = EnchantmentHelper::enchantItem($item, [new EnchantmentInstance($enchantment, $level)]); + $enchantedItem = EnchantHelper::enchantItem($item, [new EnchantmentInstance($enchantment, $level)]); $player->getInventory()->setItemInHand($enchantedItem); self::broadcastCommandMessage($sender, KnownTranslationFactory::commands_enchant_success($player->getName())); diff --git a/src/entity/Human.php b/src/entity/Human.php index 7ee729655..01da0cf9a 100644 --- a/src/entity/Human.php +++ b/src/entity/Human.php @@ -37,7 +37,7 @@ use pocketmine\inventory\InventoryHolder; use pocketmine\inventory\PlayerEnderInventory; use pocketmine\inventory\PlayerInventory; use pocketmine\inventory\PlayerOffHandInventory; -use pocketmine\item\enchantment\EnchantmentHelper; +use pocketmine\item\enchantment\EnchantHelper; use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\item\Item; use pocketmine\item\Totem; @@ -219,7 +219,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ } public function regenerateEnchantmentSeed() : void{ - $this->xpSeed = EnchantmentHelper::generateSeed(); + $this->xpSeed = EnchantHelper::generateSeed(); } public function getXpDropAmount() : int{ @@ -345,7 +345,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ if(($xpSeedTag = $nbt->getTag(self::TAG_XP_SEED)) instanceof IntTag){ $this->xpSeed = $xpSeedTag->getValue(); }else{ - $this->xpSeed = EnchantmentHelper::generateSeed(); + $this->xpSeed = EnchantHelper::generateSeed(); } } diff --git a/src/inventory/transaction/EnchantTransaction.php b/src/inventory/transaction/EnchantTransaction.php index 7ddcd36c2..01e8043ec 100644 --- a/src/inventory/transaction/EnchantTransaction.php +++ b/src/inventory/transaction/EnchantTransaction.php @@ -24,7 +24,7 @@ declare(strict_types=1); namespace pocketmine\inventory\transaction; use pocketmine\event\player\PlayerItemEnchantEvent; -use pocketmine\item\enchantment\EnchantmentHelper; +use pocketmine\item\enchantment\EnchantHelper; use pocketmine\item\enchantment\EnchantOption; use pocketmine\item\Item; use pocketmine\item\ItemTypeIds; @@ -51,7 +51,7 @@ class EnchantTransaction extends InventoryTransaction{ throw new AssumptionFailedError("Expected that inputItem and outputItem are not null before validating output"); } - $enchantedInput = EnchantmentHelper::enchantItem($this->inputItem, $this->option->getEnchantments()); + $enchantedInput = EnchantHelper::enchantItem($this->inputItem, $this->option->getEnchantments()); if(!$this->outputItem->equalsExact($enchantedInput)){ throw new TransactionValidationException("Invalid output item"); } diff --git a/src/item/enchantment/EnchantmentHelper.php b/src/item/enchantment/EnchantHelper.php similarity index 97% rename from src/item/enchantment/EnchantmentHelper.php rename to src/item/enchantment/EnchantHelper.php index c1e0af5bd..23ac11ddb 100644 --- a/src/item/enchantment/EnchantmentHelper.php +++ b/src/item/enchantment/EnchantHelper.php @@ -42,7 +42,10 @@ use function mt_rand; use function ord; use function round; -final class EnchantmentHelper{ +/** + * Helper methods used for enchanting using the enchanting table. + */ +final class EnchantHelper{ private const MAX_BOOKSHELF_COUNT = 15; private function __construct(){ @@ -72,7 +75,7 @@ final class EnchantmentHelper{ /** * @return EnchantOption[] */ - public static function getEnchantOptions(Position $tablePos, Item $input, int $seed) : array{ + public static function generateOptions(Position $tablePos, Item $input, int $seed) : array{ if($input->isNull() || $input->hasEnchantments()){ return []; } From 1504fdca248b72c2f842cf62c9351f916fdf8baf Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 16:14:17 +0100 Subject: [PATCH 15/48] Use 'enchanting' terminology 'enchant' just didn't feel right, being a verb. All these things pertain to the act of enchanting. This is now also consistent with CraftingTransaction etc. The ship already sailed on EnchantInventory, which will have to be renamed at a later datte. However, that was already inconsistent with 'enchanting table', so that's the odd one out here. --- src/block/inventory/EnchantInventory.php | 12 ++++++------ src/command/defaults/EnchantCommand.php | 4 ++-- src/entity/Human.php | 6 +++--- ...=> PlayerEnchantingOptionsRequestEvent.php} | 18 +++++++++--------- src/event/player/PlayerItemEnchantEvent.php | 12 ++++++------ ...ansaction.php => EnchantingTransaction.php} | 10 +++++----- ...{EnchantHelper.php => EnchantingHelper.php} | 14 +++++++------- ...{EnchantOption.php => EnchantingOption.php} | 2 +- src/network/mcpe/InventoryManager.php | 4 ++-- .../mcpe/handler/ItemStackRequestExecutor.php | 6 +++--- 10 files changed, 44 insertions(+), 44 deletions(-) rename src/event/player/{PlayerEnchantOptionsRequestEvent.php => PlayerEnchantingOptionsRequestEvent.php} (78%) rename src/inventory/transaction/{EnchantTransaction.php => EnchantingTransaction.php} (93%) rename src/item/enchantment/{EnchantHelper.php => EnchantingHelper.php} (93%) rename src/item/enchantment/{EnchantOption.php => EnchantingOption.php} (98%) diff --git a/src/block/inventory/EnchantInventory.php b/src/block/inventory/EnchantInventory.php index 7b79ef21c..b726dbedf 100644 --- a/src/block/inventory/EnchantInventory.php +++ b/src/block/inventory/EnchantInventory.php @@ -23,11 +23,11 @@ declare(strict_types=1); namespace pocketmine\block\inventory; -use pocketmine\event\player\PlayerEnchantOptionsRequestEvent; +use pocketmine\event\player\PlayerEnchantingOptionsRequestEvent; use pocketmine\inventory\SimpleInventory; use pocketmine\inventory\TemporaryInventory; -use pocketmine\item\enchantment\EnchantHelper as Helper; -use pocketmine\item\enchantment\EnchantOption; +use pocketmine\item\enchantment\EnchantingHelper as Helper; +use pocketmine\item\enchantment\EnchantingOption; use pocketmine\item\Item; use pocketmine\world\Position; use function array_values; @@ -39,7 +39,7 @@ class EnchantInventory extends SimpleInventory implements BlockInventory, Tempor public const SLOT_INPUT = 0; public const SLOT_LAPIS = 1; - /** @var EnchantOption[] $options */ + /** @var EnchantingOption[] $options */ private array $options = []; public function __construct(Position $holder){ @@ -54,7 +54,7 @@ class EnchantInventory extends SimpleInventory implements BlockInventory, Tempor $item = $this->getInput(); $options = Helper::generateOptions($this->holder, $item, $viewer->getEnchantmentSeed()); - $event = new PlayerEnchantOptionsRequestEvent($viewer, $this, $options); + $event = new PlayerEnchantingOptionsRequestEvent($viewer, $this, $options); $event->call(); if(!$event->isCancelled() && count($event->getOptions()) > 0){ $this->options = array_values($event->getOptions()); @@ -79,7 +79,7 @@ class EnchantInventory extends SimpleInventory implements BlockInventory, Tempor return $option === null ? null : Helper::enchantItem($this->getInput(), $option->getEnchantments()); } - public function getOption(int $optionId) : ?EnchantOption{ + public function getOption(int $optionId) : ?EnchantingOption{ return $this->options[$optionId] ?? null; } } diff --git a/src/command/defaults/EnchantCommand.php b/src/command/defaults/EnchantCommand.php index ea1ead195..191a146b0 100644 --- a/src/command/defaults/EnchantCommand.php +++ b/src/command/defaults/EnchantCommand.php @@ -25,7 +25,7 @@ namespace pocketmine\command\defaults; use pocketmine\command\CommandSender; use pocketmine\command\utils\InvalidCommandSyntaxException; -use pocketmine\item\enchantment\EnchantHelper; +use pocketmine\item\enchantment\EnchantingHelper; use pocketmine\item\enchantment\EnchantmentInstance; use pocketmine\item\enchantment\StringToEnchantmentParser; use pocketmine\lang\KnownTranslationFactory; @@ -78,7 +78,7 @@ class EnchantCommand extends VanillaCommand{ } //this is necessary to deal with enchanted books, which are a different item type than regular books - $enchantedItem = EnchantHelper::enchantItem($item, [new EnchantmentInstance($enchantment, $level)]); + $enchantedItem = EnchantingHelper::enchantItem($item, [new EnchantmentInstance($enchantment, $level)]); $player->getInventory()->setItemInHand($enchantedItem); self::broadcastCommandMessage($sender, KnownTranslationFactory::commands_enchant_success($player->getName())); diff --git a/src/entity/Human.php b/src/entity/Human.php index 01da0cf9a..f2c4c7a74 100644 --- a/src/entity/Human.php +++ b/src/entity/Human.php @@ -37,7 +37,7 @@ use pocketmine\inventory\InventoryHolder; use pocketmine\inventory\PlayerEnderInventory; use pocketmine\inventory\PlayerInventory; use pocketmine\inventory\PlayerOffHandInventory; -use pocketmine\item\enchantment\EnchantHelper; +use pocketmine\item\enchantment\EnchantingHelper; use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\item\Item; use pocketmine\item\Totem; @@ -219,7 +219,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ } public function regenerateEnchantmentSeed() : void{ - $this->xpSeed = EnchantHelper::generateSeed(); + $this->xpSeed = EnchantingHelper::generateSeed(); } public function getXpDropAmount() : int{ @@ -345,7 +345,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ if(($xpSeedTag = $nbt->getTag(self::TAG_XP_SEED)) instanceof IntTag){ $this->xpSeed = $xpSeedTag->getValue(); }else{ - $this->xpSeed = EnchantHelper::generateSeed(); + $this->xpSeed = EnchantingHelper::generateSeed(); } } diff --git a/src/event/player/PlayerEnchantOptionsRequestEvent.php b/src/event/player/PlayerEnchantingOptionsRequestEvent.php similarity index 78% rename from src/event/player/PlayerEnchantOptionsRequestEvent.php rename to src/event/player/PlayerEnchantingOptionsRequestEvent.php index d0448bfd8..833185f76 100644 --- a/src/event/player/PlayerEnchantOptionsRequestEvent.php +++ b/src/event/player/PlayerEnchantingOptionsRequestEvent.php @@ -27,7 +27,7 @@ use pocketmine\block\inventory\EnchantInventory; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; use pocketmine\event\Event; -use pocketmine\item\enchantment\EnchantOption; +use pocketmine\item\enchantment\EnchantingOption; use pocketmine\player\Player; use pocketmine\utils\Utils; use function count; @@ -36,36 +36,36 @@ use function count; * Called when a player inserts an item into an enchanting table's input slot. * The options provided by the event will be shown on the enchanting table menu. */ -class PlayerEnchantOptionsRequestEvent extends PlayerEvent implements Cancellable{ +class PlayerEnchantingOptionsRequestEvent extends PlayerEvent implements Cancellable{ use CancellableTrait; /** - * @param EnchantOption[] $options + * @param EnchantingOption[] $options */ public function __construct( Player $player, - private readonly EnchantInventory $enchantInventory, + private readonly EnchantInventory $inventory, private array $options ){ $this->player = $player; } - public function getEnchantInventory() : EnchantInventory{ - return $this->enchantInventory; + public function getInventory() : EnchantInventory{ + return $this->inventory; } /** - * @return EnchantOption[] + * @return EnchantingOption[] */ public function getOptions() : array{ return $this->options; } /** - * @param EnchantOption[] $options + * @param EnchantingOption[] $options */ public function setOptions(array $options) : void{ - Utils::validateArrayValueType($options, function(EnchantOption $_) : void{ }); + Utils::validateArrayValueType($options, function(EnchantingOption $_) : void{ }); if(($optionCount = count($options)) > 3){ throw new \LogicException("The maximum number of options for an enchanting table is 3, but $optionCount have been passed"); } diff --git a/src/event/player/PlayerItemEnchantEvent.php b/src/event/player/PlayerItemEnchantEvent.php index 9974ab40a..76151384d 100644 --- a/src/event/player/PlayerItemEnchantEvent.php +++ b/src/event/player/PlayerItemEnchantEvent.php @@ -25,8 +25,8 @@ namespace pocketmine\event\player; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; -use pocketmine\inventory\transaction\EnchantTransaction; -use pocketmine\item\enchantment\EnchantOption; +use pocketmine\inventory\transaction\EnchantingTransaction; +use pocketmine\item\enchantment\EnchantingOption; use pocketmine\item\Item; use pocketmine\player\Player; @@ -38,8 +38,8 @@ class PlayerItemEnchantEvent extends PlayerEvent implements Cancellable{ public function __construct( Player $player, - private readonly EnchantTransaction $transaction, - private readonly EnchantOption $option, + private readonly EnchantingTransaction $transaction, + private readonly EnchantingOption $option, private readonly Item $inputItem, private readonly Item $outputItem, private readonly int $cost @@ -50,14 +50,14 @@ class PlayerItemEnchantEvent extends PlayerEvent implements Cancellable{ /** * Returns the inventory transaction involved in this enchant event. */ - public function getTransaction() : EnchantTransaction{ + public function getTransaction() : EnchantingTransaction{ return $this->transaction; } /** * Returns the enchantment option used. */ - public function getOption() : EnchantOption{ + public function getOption() : EnchantingOption{ return $this->option; } diff --git a/src/inventory/transaction/EnchantTransaction.php b/src/inventory/transaction/EnchantingTransaction.php similarity index 93% rename from src/inventory/transaction/EnchantTransaction.php rename to src/inventory/transaction/EnchantingTransaction.php index 01e8043ec..d00df97e2 100644 --- a/src/inventory/transaction/EnchantTransaction.php +++ b/src/inventory/transaction/EnchantingTransaction.php @@ -24,8 +24,8 @@ declare(strict_types=1); namespace pocketmine\inventory\transaction; use pocketmine\event\player\PlayerItemEnchantEvent; -use pocketmine\item\enchantment\EnchantHelper; -use pocketmine\item\enchantment\EnchantOption; +use pocketmine\item\enchantment\EnchantingHelper; +use pocketmine\item\enchantment\EnchantingOption; use pocketmine\item\Item; use pocketmine\item\ItemTypeIds; use pocketmine\player\Player; @@ -33,14 +33,14 @@ use pocketmine\utils\AssumptionFailedError; use function count; use function min; -class EnchantTransaction extends InventoryTransaction{ +class EnchantingTransaction extends InventoryTransaction{ private ?Item $inputItem = null; private ?Item $outputItem = null; public function __construct( Player $source, - private readonly EnchantOption $option, + private readonly EnchantingOption $option, private readonly int $cost ){ parent::__construct($source); @@ -51,7 +51,7 @@ class EnchantTransaction extends InventoryTransaction{ throw new AssumptionFailedError("Expected that inputItem and outputItem are not null before validating output"); } - $enchantedInput = EnchantHelper::enchantItem($this->inputItem, $this->option->getEnchantments()); + $enchantedInput = EnchantingHelper::enchantItem($this->inputItem, $this->option->getEnchantments()); if(!$this->outputItem->equalsExact($enchantedInput)){ throw new TransactionValidationException("Invalid output item"); } diff --git a/src/item/enchantment/EnchantHelper.php b/src/item/enchantment/EnchantingHelper.php similarity index 93% rename from src/item/enchantment/EnchantHelper.php rename to src/item/enchantment/EnchantingHelper.php index 23ac11ddb..fb4e8f27c 100644 --- a/src/item/enchantment/EnchantHelper.php +++ b/src/item/enchantment/EnchantingHelper.php @@ -45,7 +45,7 @@ use function round; /** * Helper methods used for enchanting using the enchanting table. */ -final class EnchantHelper{ +final class EnchantingHelper{ private const MAX_BOOKSHELF_COUNT = 15; private function __construct(){ @@ -73,7 +73,7 @@ final class EnchantHelper{ } /** - * @return EnchantOption[] + * @return EnchantingOption[] */ public static function generateOptions(Position $tablePos, Item $input, int $seed) : array{ if($input->isNull() || $input->hasEnchantments()){ @@ -89,9 +89,9 @@ final class EnchantHelper{ $bottomRequiredLevel = max($baseRequiredLevel, $bookshelfCount * 2); return [ - self::createEnchantOption($random, $input, $topRequiredLevel), - self::createEnchantOption($random, $input, $middleRequiredLevel), - self::createEnchantOption($random, $input, $bottomRequiredLevel), + self::createOption($random, $input, $topRequiredLevel), + self::createOption($random, $input, $middleRequiredLevel), + self::createOption($random, $input, $bottomRequiredLevel), ]; } @@ -133,7 +133,7 @@ final class EnchantHelper{ return $bookshelfCount; } - private static function createEnchantOption(Random $random, Item $inputItem, int $requiredXpLevel) : EnchantOption{ + private static function createOption(Random $random, Item $inputItem, int $requiredXpLevel) : EnchantingOption{ $enchantingPower = $requiredXpLevel; $enchantability = $inputItem->getEnchantability(); @@ -171,7 +171,7 @@ final class EnchantHelper{ } } - return new EnchantOption($requiredXpLevel, self::getRandomOptionName($random), $resultEnchantments); + return new EnchantingOption($requiredXpLevel, self::getRandomOptionName($random), $resultEnchantments); } /** diff --git a/src/item/enchantment/EnchantOption.php b/src/item/enchantment/EnchantingOption.php similarity index 98% rename from src/item/enchantment/EnchantOption.php rename to src/item/enchantment/EnchantingOption.php index b1c3a7af5..2bedb0cc4 100644 --- a/src/item/enchantment/EnchantOption.php +++ b/src/item/enchantment/EnchantingOption.php @@ -27,7 +27,7 @@ namespace pocketmine\item\enchantment; * Represents an option on the enchanting table menu. * If selected, all the enchantments in the option will be applied to the item. */ -class EnchantOption{ +class EnchantingOption{ /** * @param EnchantmentInstance[] $enchantments diff --git a/src/network/mcpe/InventoryManager.php b/src/network/mcpe/InventoryManager.php index 8bdce489a..ebbd71146 100644 --- a/src/network/mcpe/InventoryManager.php +++ b/src/network/mcpe/InventoryManager.php @@ -39,8 +39,8 @@ use pocketmine\data\bedrock\EnchantmentIdMap; use pocketmine\inventory\Inventory; use pocketmine\inventory\transaction\action\SlotChangeAction; use pocketmine\inventory\transaction\InventoryTransaction; +use pocketmine\item\enchantment\EnchantingOption; use pocketmine\item\enchantment\EnchantmentInstance; -use pocketmine\item\enchantment\EnchantOption; use pocketmine\network\mcpe\cache\CreativeInventoryCache; use pocketmine\network\mcpe\protocol\ClientboundPacket; use pocketmine\network\mcpe\protocol\ContainerClosePacket; @@ -645,7 +645,7 @@ class InventoryManager{ } /** - * @param EnchantOption[] $options + * @param EnchantingOption[] $options */ public function syncEnchantingTableOptions(array $options) : void{ $protocolOptions = []; diff --git a/src/network/mcpe/handler/ItemStackRequestExecutor.php b/src/network/mcpe/handler/ItemStackRequestExecutor.php index 8273068ab..a36ae9f40 100644 --- a/src/network/mcpe/handler/ItemStackRequestExecutor.php +++ b/src/network/mcpe/handler/ItemStackRequestExecutor.php @@ -29,7 +29,7 @@ use pocketmine\inventory\transaction\action\CreateItemAction; use pocketmine\inventory\transaction\action\DestroyItemAction; use pocketmine\inventory\transaction\action\DropItemAction; use pocketmine\inventory\transaction\CraftingTransaction; -use pocketmine\inventory\transaction\EnchantTransaction; +use pocketmine\inventory\transaction\EnchantingTransaction; use pocketmine\inventory\transaction\InventoryTransaction; use pocketmine\inventory\transaction\TransactionBuilder; use pocketmine\inventory\transaction\TransactionBuilderInventory; @@ -289,7 +289,7 @@ class ItemStackRequestExecutor{ * @throws ItemStackRequestProcessException */ private function assertDoingCrafting() : void{ - if(!$this->specialTransaction instanceof CraftingTransaction && !$this->specialTransaction instanceof EnchantTransaction){ + if(!$this->specialTransaction instanceof CraftingTransaction && !$this->specialTransaction instanceof EnchantingTransaction){ if($this->specialTransaction === null){ throw new ItemStackRequestProcessException("Expected CraftRecipe or CraftRecipeAuto action to precede this action"); }else{ @@ -339,7 +339,7 @@ class ItemStackRequestExecutor{ if($window instanceof EnchantInventory){ $optionId = $this->inventoryManager->getEnchantingTableOptionIndex($action->getRecipeId()); if($optionId !== null && ($option = $window->getOption($optionId)) !== null){ - $this->specialTransaction = new EnchantTransaction($this->player, $option, $optionId + 1); + $this->specialTransaction = new EnchantingTransaction($this->player, $option, $optionId + 1); $this->setNextCreatedItem($window->getOutput($optionId)); } }else{ From 998fcf20dba652991b9d194f5217b6a02d155472 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 16:52:22 +0100 Subject: [PATCH 16/48] Remove useless Cancellable from PressurePlateUpdateEvent --- src/event/block/PressurePlateUpdateEvent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/event/block/PressurePlateUpdateEvent.php b/src/event/block/PressurePlateUpdateEvent.php index 485a3a6be..eefade935 100644 --- a/src/event/block/PressurePlateUpdateEvent.php +++ b/src/event/block/PressurePlateUpdateEvent.php @@ -31,7 +31,7 @@ use pocketmine\event\Cancellable; * Called whenever the list of entities on a pressure plate changes. * Depending on the type of pressure plate, this might turn on/off its signal, or change the signal strength. */ -final class PressurePlateUpdateEvent extends BaseBlockChangeEvent implements Cancellable{ +final class PressurePlateUpdateEvent extends BaseBlockChangeEvent{ /** * @param Entity[] $activatingEntities */ From f4e1c31dcf4dccb9b7c517e4540ed2edd9f249c0 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 16:52:47 +0100 Subject: [PATCH 17/48] Change some weird constant names --- src/item/enchantment/AvailableEnchantmentRegistry.php | 6 +++--- src/item/enchantment/IncompatibleEnchantmentGroups.php | 2 +- src/item/enchantment/IncompatibleEnchantmentRegistry.php | 2 +- src/item/enchantment/ItemEnchantmentTagRegistry.php | 4 ++-- src/item/enchantment/ItemEnchantmentTags.php | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/item/enchantment/AvailableEnchantmentRegistry.php b/src/item/enchantment/AvailableEnchantmentRegistry.php index af8484049..2c6f421ed 100644 --- a/src/item/enchantment/AvailableEnchantmentRegistry.php +++ b/src/item/enchantment/AvailableEnchantmentRegistry.php @@ -59,9 +59,9 @@ final class AvailableEnchantmentRegistry{ $this->register(Enchantments::SHARPNESS(), [Tags::SWORD, Tags::AXE], []); $this->register(Enchantments::KNOCKBACK(), [Tags::SWORD], []); $this->register(Enchantments::FIRE_ASPECT(), [Tags::SWORD], []); - $this->register(Enchantments::EFFICIENCY(), [Tags::DIG_TOOLS], [Tags::SHEARS]); - $this->register(Enchantments::FORTUNE(), [Tags::DIG_TOOLS], []); - $this->register(Enchantments::SILK_TOUCH(), [Tags::DIG_TOOLS], [Tags::SHEARS]); + $this->register(Enchantments::EFFICIENCY(), [Tags::BLOCK_TOOLS], [Tags::SHEARS]); + $this->register(Enchantments::FORTUNE(), [Tags::BLOCK_TOOLS], []); + $this->register(Enchantments::SILK_TOUCH(), [Tags::BLOCK_TOOLS], [Tags::SHEARS]); $this->register( Enchantments::UNBREAKING(), [Tags::ARMOR, Tags::WEAPONS, Tags::FISHING_ROD], diff --git a/src/item/enchantment/IncompatibleEnchantmentGroups.php b/src/item/enchantment/IncompatibleEnchantmentGroups.php index ed1141bee..74574562c 100644 --- a/src/item/enchantment/IncompatibleEnchantmentGroups.php +++ b/src/item/enchantment/IncompatibleEnchantmentGroups.php @@ -30,5 +30,5 @@ namespace pocketmine\item\enchantment; final class IncompatibleEnchantmentGroups{ public const PROTECTION = "protection"; public const BOW_INFINITE = "bow_infinite"; - public const DIG_DROP = "dig_drop"; + public const BLOCK_DROPS = "block_drops"; } diff --git a/src/item/enchantment/IncompatibleEnchantmentRegistry.php b/src/item/enchantment/IncompatibleEnchantmentRegistry.php index 8dce4777e..629a15970 100644 --- a/src/item/enchantment/IncompatibleEnchantmentRegistry.php +++ b/src/item/enchantment/IncompatibleEnchantmentRegistry.php @@ -46,7 +46,7 @@ final class IncompatibleEnchantmentRegistry{ private function __construct(){ $this->register(Groups::PROTECTION, [Enchantments::PROTECTION(), Enchantments::FIRE_PROTECTION(), Enchantments::BLAST_PROTECTION(), Enchantments::PROJECTILE_PROTECTION()]); $this->register(Groups::BOW_INFINITE, [Enchantments::INFINITY(), Enchantments::MENDING()]); - $this->register(Groups::DIG_DROP, [Enchantments::FORTUNE(), Enchantments::SILK_TOUCH()]); + $this->register(Groups::BLOCK_DROPS, [Enchantments::FORTUNE(), Enchantments::SILK_TOUCH()]); } /** diff --git a/src/item/enchantment/ItemEnchantmentTagRegistry.php b/src/item/enchantment/ItemEnchantmentTagRegistry.php index 9c607f9d2..210cd8e86 100644 --- a/src/item/enchantment/ItemEnchantmentTagRegistry.php +++ b/src/item/enchantment/ItemEnchantmentTagRegistry.php @@ -56,7 +56,7 @@ final class ItemEnchantmentTagRegistry{ $this->register(Tags::CROSSBOW); $this->register(Tags::SHEARS); $this->register(Tags::FLINT_AND_STEEL); - $this->register(Tags::DIG_TOOLS, [Tags::AXE, Tags::PICKAXE, Tags::SHOVEL, Tags::HOE]); + $this->register(Tags::BLOCK_TOOLS, [Tags::AXE, Tags::PICKAXE, Tags::SHOVEL, Tags::HOE]); $this->register(Tags::FISHING_ROD); $this->register(Tags::CARROT_ON_STICK); $this->register(Tags::COMPASS); @@ -68,7 +68,7 @@ final class ItemEnchantmentTagRegistry{ Tags::TRIDENT, Tags::BOW, Tags::CROSSBOW, - Tags::DIG_TOOLS, + Tags::BLOCK_TOOLS, ]); } diff --git a/src/item/enchantment/ItemEnchantmentTags.php b/src/item/enchantment/ItemEnchantmentTags.php index 485cb5d0c..50abf8db3 100644 --- a/src/item/enchantment/ItemEnchantmentTags.php +++ b/src/item/enchantment/ItemEnchantmentTags.php @@ -42,7 +42,7 @@ final class ItemEnchantmentTags{ public const CROSSBOW = "crossbow"; public const SHEARS = "shears"; public const FLINT_AND_STEEL = "flint_and_steel"; - public const DIG_TOOLS = "dig_tools"; + public const BLOCK_TOOLS = "block_tools"; public const AXE = "axe"; public const PICKAXE = "pickaxe"; public const SHOVEL = "shovel"; From 923f7561fbcebed82955df80ed76a6ee6e384345 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 16:53:09 +0100 Subject: [PATCH 18/48] Enchantment: added @see tags to @deprecated methods --- src/item/enchantment/Enchantment.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/item/enchantment/Enchantment.php b/src/item/enchantment/Enchantment.php index 22c0cdb01..948f4648b 100644 --- a/src/item/enchantment/Enchantment.php +++ b/src/item/enchantment/Enchantment.php @@ -83,6 +83,7 @@ class Enchantment{ * Returns a bitset indicating what item types can have this item applied from an enchanting table. * * @deprecated + * @see AvailableEnchantmentRegistry::getPrimaryItemTags() */ public function getPrimaryItemFlags() : int{ return $this->primaryItemFlags; @@ -93,6 +94,7 @@ class Enchantment{ * an anvil. * * @deprecated + * @see AvailableEnchantmentRegistry::getSecondaryItemTags() */ public function getSecondaryItemFlags() : int{ return $this->secondaryItemFlags; @@ -102,6 +104,7 @@ class Enchantment{ * Returns whether this enchantment can apply to the item type from an enchanting table. * * @deprecated + * @see AvailableEnchantmentRegistry */ public function hasPrimaryItemType(int $flag) : bool{ return ($this->primaryItemFlags & $flag) !== 0; @@ -111,6 +114,7 @@ class Enchantment{ * Returns whether this enchantment can apply to the item type from an anvil, if it is not a primary item. * * @deprecated + * @see AvailableEnchantmentRegistry */ public function hasSecondaryItemType(int $flag) : bool{ return ($this->secondaryItemFlags & $flag) !== 0; From 8814d06dfd0ce9702c784c95aff1adb87349f985 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 17:00:18 +0100 Subject: [PATCH 19/48] Fix CS --- src/event/block/PressurePlateUpdateEvent.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/event/block/PressurePlateUpdateEvent.php b/src/event/block/PressurePlateUpdateEvent.php index eefade935..e6f2e92ba 100644 --- a/src/event/block/PressurePlateUpdateEvent.php +++ b/src/event/block/PressurePlateUpdateEvent.php @@ -25,7 +25,6 @@ namespace pocketmine\event\block; use pocketmine\block\Block; use pocketmine\entity\Entity; -use pocketmine\event\Cancellable; /** * Called whenever the list of entities on a pressure plate changes. From c8100480ac494562fff12bbe905d73be109e1f12 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 17:09:34 +0100 Subject: [PATCH 20/48] Release 5.5.0-BETA1 --- changelogs/5.5-beta.md | 156 +++++++++++++++++++++++++++++++++++++++++ src/VersionInfo.php | 6 +- 2 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 changelogs/5.5-beta.md diff --git a/changelogs/5.5-beta.md b/changelogs/5.5-beta.md new file mode 100644 index 000000000..efd1c822c --- /dev/null +++ b/changelogs/5.5-beta.md @@ -0,0 +1,156 @@ +# 5.5.0-BETA1 +Released 23rd August 2023. + +**For Minecraft: Bedrock Edition 1.20.0** + +This is a minor feature release, including performance improvements, new API methods, and new gameplay features. + +**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace. +Do not update plugin minimum API versions unless you need new features added in this release. + +**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.** +Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly. + +## Dependencies +- Updated `pocketmine/math` dependency to [`1.0.0`](https://github.com/pmmp/Math/releases/tag/1.0.0). +- Updated `pocketmine/nbt` dependency to [`1.0.0`](https://github.com/pmmp/NBT/releases/tag/1.0.0). + +## Performance +- Some events are now no longer fired if no handlers are registered. + - This improves performance by avoiding unnecessary object allocations and function calls. + - Events such as `DataPacketReceiveEvent`, `DataPacketSendEvent` and `PlayerMoveEvent` are optimized away almost completely by this change, offering some much-needed performance gains. +- Significantly improved performance of small moving entities, such as dropped items. + - This was achieved by a combination of changes, which together improved observed performance with 2000 item entities moving in water by 30-40%. + - The benefit of this will be most noticeable in SkyBlock servers, where large cactus farms can generate thousands of dropped items. +- `World->getCollisionBoxes()` now uses an improved search method, which reduces the work done by the function by almost 90% for small entities. + - This improves performance of collision detection for small entities, such as dropped items. + +## Gameplay +### General +- Implemented enchanting using an enchanting table (yes, finally!) + - Thanks to [@S3v3Nice](https://github.com/S3v3Nice) for investing lots of time and effort into developing this. + - Since this feature is quite complex, it's possible there may be bugs. Please be vigilant and report any issues you find. + +### Blocks +- The following new blocks have been implemented: + - Pink Petals +- Pressure plates are now functional, in the sense that they react when entities stand on them and perform the correct logic. + - Note that since redstone is not yet implemented, pressure plates do not activate any redstone devices, similar to buttons and levers. +- Signs can now be edited by right-clicking them. +- Signs can now be waxed using a honeycomb, which prevents them from being edited. + +### Items +- The following new items have been implemented: + - Enchanted Book + +## API +### `pocketmine\block` +- The following new API methods have been added: + - `public Block->getEnchantmentTags() : list` returns a list of strings indicating which types of enchantment can be applied to the block when in item form + - `public BlockTypeInfo->getEnchantmentTags() : list` + - `protected PressurePlate->getActivationBox() : AxisAlignedBB` - returns the AABB entities must intersect with in order to activate the pressure plate (not the same as the visual shape) + - `protected PressurePlate->hasOutputSignal() : bool` - returns whether the pressure plate has an output signal - this should be implemented by subclasses + - `protected PressurePlate->calculatePlateState() : array{Block, ?bool}` - returns the state the pressure plate will change to if the given list of entities are standing on it, and a bool indicating whether the plate activated or deactivated this tick + - `protected PressurePlate->filterIrrelevantEntities(list $entities) : list` - returns the given list filtered of entities that don't affect the plate's state (e.g. dropped items don't affect stone pressure plates) + - `public BaseSign->isWaxed() : bool` + - `public BaseSign->setWaxed(bool $waxed) : $this` + - `public inventory\EnchantInventory->getInput() : Item` + - `public inventory\EnchantInventory->getLapis() : Item` + - `public inventory\EnchantInventory->getOutput(int $optionId) : ?Item` - returns the item that would be produced if the input item was enchanted with the selected option, or `null` if the option is invalid + - `public inventory\EnchantInventory->getOption(int $optionId) : EnchantOption` - returns the enchanting option at the given index +- The following API methods have signature changes: + - `BlockTypeInfo->__construct()` now accepts an optional `list $enchantmentTags` parameter + - `PressurePlate->__construct()` now accepts an optional `int $deactivationDelayTicks` parameter + - `WeightedPressurePlate->__construct()` now accepts optional `int $deactivationDelayTicks` and `float $signalStrengthFactor` parameters + - `SimplePressurePlate->__construct()` now accepts an optional `int $deactivationDelayTicks` parameter +- The following new classes have been added: + - `PinkPetals` + - `utils\BlockEventHelper` - provides helper methods for calling block-related events +- The following classes have been deprecated: + - `WeightedPressurePlateLight` + - `WeightedPressurePlateHeavy` + +### `pocketmine\entity` +- The following new API methods have been added: + - `public Human->getEnchantmentSeed() : int` - returns the current seed used to randomize options shown on the enchanting table for this human + - `public Human->setEnchantmentSeed(int $seed) : void` + - `public Human->regenerateEnchantmentSeed() : void` - returns a new randomly generated seed which can be set with `setEnchantmentSeed()` + +### `pocketmine\event` +- The following new classes have been added: + - `block\FarmlandHydrationChangeEvent` - called when farmland is hydrated or dehydrated + - `block\PressurePlateUpdateEvent` - called when a pressure plate is activated or changes its power output + - `player\PlayerEnchantingOptionsRequestEvent` - called when a player puts an item to be enchanted into an enchanting table, to allow plugins to modify the enchanting options shown + - `player\PlayerItemEnchantEvent` - called when a player enchants an item in an enchanting table + - `world\WorldDifficultyChangeEvent` - called when a world's difficulty is changed +- The following new API methods have been added: + - `public static Event::hasHandlers() : bool` - returns whether the event class has any registered handlers - used like `SomeEvent::hasHandlers()` + - `public HandlerListManager->getHandlersFor(class-string $event) : list` - returns a list of all registered listeners for the given event class, using cache if available + +### `pocketmine\inventory\transaction` +- The following new classes have been added: + - `EnchantingTransaction` - used when a player enchants an item in an enchanting table + +### `pocketmine\item` +- The following new API methods have been added: + - `public Armor->getMaterial() : ArmorMaterial` - returns an object containing properties shared by all items of the same armor material + - `public ArmorTypeInfo->getMaterial() : ArmorMaterial` + - `public Item->getEnchantability() : int` - returns the enchantability value of the item - higher values increase the chance of more powerful enchantments being offered by an enchanting table + - `public Item->getEnchantmentTags() : list` - returns a list of strings indicating which types of enchantment can be applied to the item + - `public ToolTier->getEnchantability() : int` +- The following API methods have signature changes: + - `Item->__construct()` now accepts an optional `list $enchantmentTags` parameter + - `ArmorTypeInfo->__construct()` now accepts an optional `?ArmorMaterial $material` parameter +- The following new classes have been added: + - `ArmorMaterial` - container for shared armor properties + - `VanillaArmorMaterials` - all vanilla armor materials + - `EnchantedBook` - represents an enchanted book item + +### `pocketmine\item\enchantment` +- The following new classes have been added: + - `AvailableEnchantmentRegistry` - enchantments to be displayed on the enchanting table are selected from here - custom enchantments may be added + - `EnchantingHelper` - static class containing various helper methods for enchanting tables + - `EnchantingOption` - represents an option on the enchanting table menu + - `IncompatibleEnchantmentGroups` - list of constants naming groups of enchantments that are incompatible with each other - custom enchantments may be added using these group names to make them incompatible with existing enchantments in the same group + - `IncompatibleEnchantmentRegistry` - manages which enchantments are considered incompatible with each other - custom enchantments may be added using existing group names to make them incompatible with existing enchantments in the same group, or to entirely new groups + - `ItemEnchantmentTagRegistry` - manages item enchantment compatibility tags and which tags include which other tags + - `ItemEnchantmentTags` - list of constants naming item types for enchantment compatibility checks +- The following classes have been deprecated + - `ItemFlags` +- The following API methods have been added: + - `public Enchantment->isCompatibleWith(Enchantment $other) : bool` + - `public Enchantment->getMinEnchantingPower()` - returns the minimum enchanting power (derived from enchantability and number of bookshelves) needed to allow this enchantment to show on the enchanting table with a given level + - `public Enchantment->getMaxEnchantingPower()` - upper limit of enchanting power for this enchantment to be offered on the enchanting table with a given level +- The following API methods have signature changes: + - `Enchantment->__construct()` now accepts optional `(\Closure(int $level) : int)|null $minEnchantingPower` and `int $enchantingPowerRange` parameters + - `Enchantment->__construct()` parameters `$primaryItemFlags` and `$secondaryItemFlags` are now deprecated and no longer used + - `ProtectionEnchantment->__construct()` has extra parameters to reflect `Enchantment->__construct()` changes +- The following API methods have been deprecated: + - `Enchantment->getPrimaryItemFlags()` - use API methods provided by `AvailableEnchantmentRegistry` instead + - `Enchantment->getSecondaryItemFlags()` - use API methods provided by `AvailableEnchantmentRegistry` instead + - `Enchantment->hasPrimaryItemType()` + - `Enchantment->hasSecondaryItemType()` + +### `pocketmine\plugin` +- The following new API methods have been added: + - `public PluginBase->getResourcePath(string $filename) : string` - returns a URI to an embedded resource file that can be used with `file_get_contents()` and similar functions + - `public PluginBase->getResourceFolder() : string` - returns a URI to the plugin's folder of embedded resources +- The following API methods have been deprecated: + - `PluginBase->getResource()` - prefer using `getResourcePath()` with `file_get_contents()` or other PHP built-in functions instead + +### `pocketmine\resourcepacks` +- The following new API methods have been added: + - `public ResourcePackManager->setResourcePacksRequired(bool $value) : void` - sets whether players must accept resource packs in order to join + +### `pocketmine\world\generator` +- The following new API methods have been added: + - `public GeneratorManager->addAlias(string $name, string $alias) : void` - allows registering a generator alias without copying the generator registration parameters + +### `pocketmine\world\sound` +- The following new classes have been added: +- `PressurePlateActivateSound` +- `PressurePlateDeactivateSound` + +### `pocketmine\utils` +- The following new API methods have been added: + - `public StringToTParser->registerAlias(string $existing, string $alias) : void` - allows registering a string alias without copying registration parameters diff --git a/src/VersionInfo.php b/src/VersionInfo.php index bec9638ea..80d6ecaf6 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -31,9 +31,9 @@ use function str_repeat; final class VersionInfo{ public const NAME = "PocketMine-MP"; - public const BASE_VERSION = "5.4.3"; - public const IS_DEVELOPMENT_BUILD = true; - public const BUILD_CHANNEL = "stable"; + public const BASE_VERSION = "5.5.0-BETA1"; + public const IS_DEVELOPMENT_BUILD = false; + public const BUILD_CHANNEL = "beta"; /** * PocketMine-MP-specific version ID for world data. Used to determine what fixes need to be applied to old world From ce53a221a5cd0c735206b5084a0ee08bba480ced Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 17:09:34 +0100 Subject: [PATCH 21/48] 5.5.0-BETA2 is next --- src/VersionInfo.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VersionInfo.php b/src/VersionInfo.php index 80d6ecaf6..f792fe0a4 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -31,8 +31,8 @@ use function str_repeat; final class VersionInfo{ public const NAME = "PocketMine-MP"; - public const BASE_VERSION = "5.5.0-BETA1"; - public const IS_DEVELOPMENT_BUILD = false; + public const BASE_VERSION = "5.5.0-BETA2"; + public const IS_DEVELOPMENT_BUILD = true; public const BUILD_CHANNEL = "beta"; /** From c7a311c17a8ec25ae31ca0ec7cb81602714cfc3b Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Aug 2023 17:14:56 +0100 Subject: [PATCH 22/48] COPILOT --- changelogs/5.5-beta.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/5.5-beta.md b/changelogs/5.5-beta.md index efd1c822c..84153c279 100644 --- a/changelogs/5.5-beta.md +++ b/changelogs/5.5-beta.md @@ -1,7 +1,7 @@ # 5.5.0-BETA1 Released 23rd August 2023. -**For Minecraft: Bedrock Edition 1.20.0** +**For Minecraft: Bedrock Edition 1.20.10** This is a minor feature release, including performance improvements, new API methods, and new gameplay features. From f2b710c083799e0dcd7e04d95545f6f8c5f2c116 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 08:31:31 +0100 Subject: [PATCH 23/48] Bump build/php from `a053f65` to `d75f83e` (#6017) Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `a053f65` to `d75f83e`. - [Release notes](https://github.com/pmmp/php-build-scripts/releases) - [Commits](https://github.com/pmmp/php-build-scripts/compare/a053f65e1897e432478229071383fe1ba16032c3...d75f83e7ef784d6581310901800a47d179602e94) --- updated-dependencies: - dependency-name: build/php dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build/php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/php b/build/php index a053f65e1..d75f83e7e 160000 --- a/build/php +++ b/build/php @@ -1 +1 @@ -Subproject commit a053f65e1897e432478229071383fe1ba16032c3 +Subproject commit d75f83e7ef784d6581310901800a47d179602e94 From 09c9dfb576cec5ff4029c31f8cb77d57c4095246 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Aug 2023 09:43:05 +0100 Subject: [PATCH 24/48] Bump build/php from `d75f83e` to `8884039` (#6018) Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `d75f83e` to `8884039`. - [Release notes](https://github.com/pmmp/php-build-scripts/releases) - [Commits](https://github.com/pmmp/php-build-scripts/compare/d75f83e7ef784d6581310901800a47d179602e94...8884039bee1db64acca83edd57ed5e25d69287b9) --- updated-dependencies: - dependency-name: build/php dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build/php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/php b/build/php index d75f83e7e..8884039be 160000 --- a/build/php +++ b/build/php @@ -1 +1 @@ -Subproject commit d75f83e7ef784d6581310901800a47d179602e94 +Subproject commit 8884039bee1db64acca83edd57ed5e25d69287b9 From 1a18e32011ad5c9f554afd8ff2042986d8ec8ac8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Aug 2023 09:43:31 +0100 Subject: [PATCH 25/48] Bump ncipollo/release-action from 1.12.0 to 1.13.0 (#6019) Bumps [ncipollo/release-action](https://github.com/ncipollo/release-action) from 1.12.0 to 1.13.0. - [Release notes](https://github.com/ncipollo/release-action/releases) - [Commits](https://github.com/ncipollo/release-action/compare/v1.12.0...v1.13.0) --- updated-dependencies: - dependency-name: ncipollo/release-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/draft-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index d135d0cc4..7dc9f08b1 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -86,7 +86,7 @@ jobs: ${{ github.workspace }}/build_info.json - name: Create draft release - uses: ncipollo/release-action@v1.12.0 + uses: ncipollo/release-action@v1.13.0 with: artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json commit: ${{ github.sha }} From b56f1b679ea49aab81222e08a7d36f97d95a895e Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 25 Aug 2023 12:30:54 +0100 Subject: [PATCH 26/48] Deduplicate a bunch of repeated type ID map code --- build/php | 2 +- src/data/bedrock/DyeColorIdMap.php | 27 ++----- src/data/bedrock/EffectIdMap.php | 34 +------- src/data/bedrock/EnchantmentIdMap.php | 31 +------- src/data/bedrock/IntSaveIdMapTrait.php | 82 ++++++++++++++++++++ src/data/bedrock/MedicineTypeIdMap.php | 30 +------ src/data/bedrock/MobHeadTypeIdMap.php | 30 +------ src/data/bedrock/MushroomBlockTypeIdMap.php | 29 +------ src/data/bedrock/NoteInstrumentIdMap.php | 30 +------ src/data/bedrock/PotionTypeIdMap.php | 30 +------ src/data/bedrock/SuspiciousStewTypeIdMap.php | 30 +------ 11 files changed, 104 insertions(+), 251 deletions(-) create mode 100644 src/data/bedrock/IntSaveIdMapTrait.php diff --git a/build/php b/build/php index a053f65e1..9f984a1dc 160000 --- a/build/php +++ b/build/php @@ -1 +1 @@ -Subproject commit a053f65e1897e432478229071383fe1ba16032c3 +Subproject commit 9f984a1dc154603a27543ecdcebc6d6a5871f425 diff --git a/src/data/bedrock/DyeColorIdMap.php b/src/data/bedrock/DyeColorIdMap.php index 35db72c3e..0d10edad5 100644 --- a/src/data/bedrock/DyeColorIdMap.php +++ b/src/data/bedrock/DyeColorIdMap.php @@ -29,18 +29,10 @@ use pocketmine\utils\SingletonTrait; final class DyeColorIdMap{ use SingletonTrait; - - /** - * @var DyeColor[] - * @phpstan-var array - */ - private array $idToEnum = []; - - /** - * @var int[] - * @phpstan-var array - */ - private array $enumToId = []; + /** @phpstan-use IntSaveIdMapTrait */ + use IntSaveIdMapTrait { + register as registerInt; + } /** * @var DyeColor[] @@ -74,16 +66,11 @@ final class DyeColorIdMap{ } private function register(int $id, string $itemId, DyeColor $color) : void{ - $this->idToEnum[$id] = $color; - $this->enumToId[$color->id()] = $id; + $this->registerInt($id, $color); $this->itemIdToEnum[$itemId] = $color; $this->enumToItemId[$color->id()] = $itemId; } - public function toId(DyeColor $color) : int{ - return $this->enumToId[$color->id()]; //TODO: is it possible for this to be missing? - } - public function toInvertedId(DyeColor $color) : int{ return ~$this->toId($color) & 0xf; } @@ -92,10 +79,6 @@ final class DyeColorIdMap{ return $this->enumToItemId[$color->id()]; } - public function fromId(int $id) : ?DyeColor{ - return $this->idToEnum[$id] ?? null; - } - public function fromInvertedId(int $id) : ?DyeColor{ return $this->fromId(~$id & 0xf); } diff --git a/src/data/bedrock/EffectIdMap.php b/src/data/bedrock/EffectIdMap.php index 6dce86d9b..6efa10b41 100644 --- a/src/data/bedrock/EffectIdMap.php +++ b/src/data/bedrock/EffectIdMap.php @@ -31,18 +31,8 @@ use function spl_object_id; final class EffectIdMap{ use SingletonTrait; - - /** - * @var Effect[] - * @phpstan-var array - */ - private array $idToEffect = []; - - /** - * @var int[] - * @phpstan-var array - */ - private array $effectToId = []; + /** @phpstan-use IntSaveIdMapTrait */ + use IntSaveIdMapTrait; private function __construct(){ $this->register(EffectIds::SPEED, VanillaEffects::SPEED()); @@ -76,24 +66,4 @@ final class EffectIdMap{ //TODO: VILLAGE_HERO $this->register(EffectIds::DARKNESS, VanillaEffects::DARKNESS()); } - - //TODO: not a big fan of the code duplication here :( - - public function register(int $mcpeId, Effect $effect) : void{ - $this->idToEffect[$mcpeId] = $effect; - $this->effectToId[spl_object_id($effect)] = $mcpeId; - } - - public function fromId(int $id) : ?Effect{ - //we might not have all the effect IDs registered - return $this->idToEffect[$id] ?? null; - } - - public function toId(Effect $effect) : int{ - if(!array_key_exists(spl_object_id($effect), $this->effectToId)){ - //this should never happen, so we treat it as an exceptional condition - throw new \InvalidArgumentException("Effect does not have a mapped ID"); - } - return $this->effectToId[spl_object_id($effect)]; - } } diff --git a/src/data/bedrock/EnchantmentIdMap.php b/src/data/bedrock/EnchantmentIdMap.php index 1d974ed6e..c06080e3e 100644 --- a/src/data/bedrock/EnchantmentIdMap.php +++ b/src/data/bedrock/EnchantmentIdMap.php @@ -34,17 +34,8 @@ use function spl_object_id; */ final class EnchantmentIdMap{ use SingletonTrait; - - /** - * @var Enchantment[] - * @phpstan-var array - */ - private array $idToEnch = []; - /** - * @var int[] - * @phpstan-var array - */ - private array $enchToId = []; + /** @phpstan-use IntSaveIdMapTrait */ + use IntSaveIdMapTrait; private function __construct(){ $this->register(EnchantmentIds::PROTECTION, VanillaEnchantments::PROTECTION()); @@ -77,22 +68,4 @@ final class EnchantmentIdMap{ $this->register(EnchantmentIds::SWIFT_SNEAK, VanillaEnchantments::SWIFT_SNEAK()); } - - public function register(int $mcpeId, Enchantment $enchantment) : void{ - $this->idToEnch[$mcpeId] = $enchantment; - $this->enchToId[spl_object_id($enchantment)] = $mcpeId; - } - - public function fromId(int $id) : ?Enchantment{ - //we might not have all the enchantment IDs registered - return $this->idToEnch[$id] ?? null; - } - - public function toId(Enchantment $enchantment) : int{ - if(!array_key_exists(spl_object_id($enchantment), $this->enchToId)){ - //this should never happen, so we treat it as an exceptional condition - throw new \InvalidArgumentException("Enchantment does not have a mapped ID"); - } - return $this->enchToId[spl_object_id($enchantment)]; - } } diff --git a/src/data/bedrock/IntSaveIdMapTrait.php b/src/data/bedrock/IntSaveIdMapTrait.php new file mode 100644 index 000000000..041dfa9e6 --- /dev/null +++ b/src/data/bedrock/IntSaveIdMapTrait.php @@ -0,0 +1,82 @@ + + */ + private array $idToEnum = []; + + /** + * @var int[] + * @phpstan-var array + */ + private array $enumToId = []; + + /** + * @phpstan-param TObject $enum + */ + protected function getRuntimeId(object $enum) : int{ + //this is fine for enums and non-cloning object registries + return spl_object_id($enum); + } + + /** + * @phpstan-param TObject $enum + */ + public function register(int $saveId, object $enum) : void{ + $this->idToEnum[$saveId] = $enum; + $this->enumToId[$this->getRuntimeId($enum)] = $saveId; + } + + /** + * @phpstan-return TObject|null + */ + public function fromId(int $id) : ?object{ + //we might not have all the effect IDs registered + return $this->idToEnum[$id] ?? null; + } + + /** + * @phpstan-param TObject $enum + */ + public function toId(object $enum) : int{ + $runtimeId = $this->getRuntimeId($enum); + if(!array_key_exists($runtimeId, $this->enumToId)){ + //this should never happen, so we treat it as an exceptional condition + throw new \InvalidArgumentException("Object does not have a mapped save ID"); + } + return $this->enumToId[$runtimeId]; + } +} diff --git a/src/data/bedrock/MedicineTypeIdMap.php b/src/data/bedrock/MedicineTypeIdMap.php index a85dbb7a8..2d9deb380 100644 --- a/src/data/bedrock/MedicineTypeIdMap.php +++ b/src/data/bedrock/MedicineTypeIdMap.php @@ -28,18 +28,8 @@ use pocketmine\utils\SingletonTrait; final class MedicineTypeIdMap{ use SingletonTrait; - - /** - * @var MedicineType[] - * @phpstan-var array - */ - private array $idToEnum = []; - - /** - * @var int[] - * @phpstan-var array - */ - private array $enumToId = []; + /** @phpstan-use IntSaveIdMapTrait */ + use IntSaveIdMapTrait; private function __construct(){ $this->register(MedicineTypeIds::ANTIDOTE, MedicineType::ANTIDOTE()); @@ -47,20 +37,4 @@ final class MedicineTypeIdMap{ $this->register(MedicineTypeIds::EYE_DROPS, MedicineType::EYE_DROPS()); $this->register(MedicineTypeIds::TONIC, MedicineType::TONIC()); } - - private function register(int $id, MedicineType $type) : void{ - $this->idToEnum[$id] = $type; - $this->enumToId[$type->id()] = $id; - } - - public function fromId(int $id) : ?MedicineType{ - return $this->idToEnum[$id] ?? null; - } - - public function toId(MedicineType $type) : int{ - if(!isset($this->enumToId[$type->id()])){ - throw new \InvalidArgumentException("Type does not have a mapped ID"); - } - return $this->enumToId[$type->id()]; - } } diff --git a/src/data/bedrock/MobHeadTypeIdMap.php b/src/data/bedrock/MobHeadTypeIdMap.php index 99213fa46..b99b1097b 100644 --- a/src/data/bedrock/MobHeadTypeIdMap.php +++ b/src/data/bedrock/MobHeadTypeIdMap.php @@ -28,18 +28,8 @@ use pocketmine\utils\SingletonTrait; final class MobHeadTypeIdMap{ use SingletonTrait; - - /** - * @var MobHeadType[] - * @phpstan-var array - */ - private array $idToEnum = []; - - /** - * @var int[] - * @phpstan-var array - */ - private array $enumToId = []; + /** @phpstan-use IntSaveIdMapTrait */ + use IntSaveIdMapTrait; private function __construct(){ $this->register(0, MobHeadType::SKELETON()); @@ -50,20 +40,4 @@ final class MobHeadTypeIdMap{ $this->register(5, MobHeadType::DRAGON()); $this->register(6, MobHeadType::PIGLIN()); } - - private function register(int $id, MobHeadType $type) : void{ - $this->idToEnum[$id] = $type; - $this->enumToId[$type->id()] = $id; - } - - public function fromId(int $id) : ?MobHeadType{ - return $this->idToEnum[$id] ?? null; - } - - public function toId(MobHeadType $type) : int{ - if(!isset($this->enumToId[$type->id()])){ - throw new \InvalidArgumentException("Type does not have a mapped ID"); - } - return $this->enumToId[$type->id()]; - } } diff --git a/src/data/bedrock/MushroomBlockTypeIdMap.php b/src/data/bedrock/MushroomBlockTypeIdMap.php index 2eec17549..5e195ebb2 100644 --- a/src/data/bedrock/MushroomBlockTypeIdMap.php +++ b/src/data/bedrock/MushroomBlockTypeIdMap.php @@ -30,17 +30,8 @@ use function array_key_exists; final class MushroomBlockTypeIdMap{ use SingletonTrait; - - /** - * @var MushroomBlockType[] - * @phpstan-var array - */ - private array $idToEnum = []; - /** - * @var int[] - * @phpstan-var array - */ - private array $enumToId = []; + /** @phpstan-use IntSaveIdMapTrait */ + use IntSaveIdMapTrait; public function __construct(){ $this->register(LegacyMeta::MUSHROOM_BLOCK_ALL_PORES, MushroomBlockType::PORES()); @@ -55,20 +46,4 @@ final class MushroomBlockTypeIdMap{ $this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHEAST_CORNER, MushroomBlockType::CAP_SOUTHEAST()); $this->register(LegacyMeta::MUSHROOM_BLOCK_ALL_CAP, MushroomBlockType::ALL_CAP()); } - - public function register(int $id, MushroomBlockType $type) : void{ - $this->idToEnum[$id] = $type; - $this->enumToId[$type->id()] = $id; - } - - public function fromId(int $id) : ?MushroomBlockType{ - return $this->idToEnum[$id] ?? null; - } - - public function toId(MushroomBlockType $type) : int{ - if(!array_key_exists($type->id(), $this->enumToId)){ - throw new \InvalidArgumentException("Mushroom block type does not have a mapped ID"); //this should never happen - } - return $this->enumToId[$type->id()]; - } } diff --git a/src/data/bedrock/NoteInstrumentIdMap.php b/src/data/bedrock/NoteInstrumentIdMap.php index 0b8a43735..22d7e5cb1 100644 --- a/src/data/bedrock/NoteInstrumentIdMap.php +++ b/src/data/bedrock/NoteInstrumentIdMap.php @@ -28,18 +28,8 @@ use pocketmine\world\sound\NoteInstrument; final class NoteInstrumentIdMap{ use SingletonTrait; - - /** - * @var NoteInstrument[] - * @phpstan-var array - */ - private array $idToEnum = []; - - /** - * @var int[] - * @phpstan-var array - */ - private array $enumToId = []; + /** @phpstan-use IntSaveIdMapTrait */ + use IntSaveIdMapTrait; private function __construct(){ $this->register(0, NoteInstrument::PIANO()); @@ -59,20 +49,4 @@ final class NoteInstrumentIdMap{ $this->register(14, NoteInstrument::BANJO()); $this->register(15, NoteInstrument::PLING()); } - - private function register(int $id, NoteInstrument $instrument) : void{ - $this->idToEnum[$id] = $instrument; - $this->enumToId[$instrument->id()] = $id; - } - - public function fromId(int $id) : ?NoteInstrument{ - return $this->idToEnum[$id] ?? null; - } - - public function toId(NoteInstrument $instrument) : int{ - if(!isset($this->enumToId[$instrument->id()])){ - throw new \InvalidArgumentException("Type does not have a mapped ID"); - } - return $this->enumToId[$instrument->id()]; - } } diff --git a/src/data/bedrock/PotionTypeIdMap.php b/src/data/bedrock/PotionTypeIdMap.php index 8194f24a2..3e9858217 100644 --- a/src/data/bedrock/PotionTypeIdMap.php +++ b/src/data/bedrock/PotionTypeIdMap.php @@ -28,18 +28,8 @@ use pocketmine\utils\SingletonTrait; final class PotionTypeIdMap{ use SingletonTrait; - - /** - * @var PotionType[] - * @phpstan-var array - */ - private array $idToEnum = []; - - /** - * @var int[] - * @phpstan-var array - */ - private array $enumToId = []; + /** @phpstan-use IntSaveIdMapTrait */ + use IntSaveIdMapTrait; private function __construct(){ $this->register(PotionTypeIds::WATER, PotionType::WATER()); @@ -86,20 +76,4 @@ final class PotionTypeIdMap{ $this->register(PotionTypeIds::LONG_SLOW_FALLING, PotionType::LONG_SLOW_FALLING()); $this->register(PotionTypeIds::STRONG_SLOWNESS, PotionType::STRONG_SLOWNESS()); } - - private function register(int $id, PotionType $type) : void{ - $this->idToEnum[$id] = $type; - $this->enumToId[$type->id()] = $id; - } - - public function fromId(int $id) : ?PotionType{ - return $this->idToEnum[$id] ?? null; - } - - public function toId(PotionType $type) : int{ - if(!isset($this->enumToId[$type->id()])){ - throw new \InvalidArgumentException("Type does not have a mapped ID"); - } - return $this->enumToId[$type->id()]; - } } diff --git a/src/data/bedrock/SuspiciousStewTypeIdMap.php b/src/data/bedrock/SuspiciousStewTypeIdMap.php index 1dc86abf1..37d121517 100644 --- a/src/data/bedrock/SuspiciousStewTypeIdMap.php +++ b/src/data/bedrock/SuspiciousStewTypeIdMap.php @@ -28,18 +28,8 @@ use pocketmine\utils\SingletonTrait; final class SuspiciousStewTypeIdMap{ use SingletonTrait; - - /** - * @var SuspiciousStewType[] - * @phpstan-var array - */ - private array $idToEnum = []; - - /** - * @var int[] - * @phpstan-var array - */ - private array $enumToId = []; + /** @phpstan-use IntSaveIdMapTrait */ + use IntSaveIdMapTrait; private function __construct(){ $this->register(SuspiciousStewTypeIds::POPPY, SuspiciousStewType::POPPY()); @@ -53,20 +43,4 @@ final class SuspiciousStewTypeIdMap{ $this->register(SuspiciousStewTypeIds::OXEYE_DAISY, SuspiciousStewType::OXEYE_DAISY()); $this->register(SuspiciousStewTypeIds::WITHER_ROSE, SuspiciousStewType::WITHER_ROSE()); } - - private function register(int $id, SuspiciousStewType $type) : void{ - $this->idToEnum[$id] = $type; - $this->enumToId[$type->id()] = $id; - } - - public function fromId(int $id) : ?SuspiciousStewType{ - return $this->idToEnum[$id] ?? null; - } - - public function toId(SuspiciousStewType $type) : int{ - if(!isset($this->enumToId[$type->id()])){ - throw new \InvalidArgumentException("Type does not have a mapped ID"); - } - return $this->enumToId[$type->id()]; - } } From d1a7c1d4539e465b6acf5d84fa949c6b6d2a5968 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 25 Aug 2023 12:49:39 +0100 Subject: [PATCH 27/48] Constify server.properties references --- src/Server.php | 88 +++++++++---------- src/ServerProperties.php | 50 +++++++++++ .../defaults/DefaultGamemodeCommand.php | 3 +- src/command/defaults/DifficultyCommand.php | 3 +- src/command/defaults/WhitelistCommand.php | 5 +- src/player/Player.php | 3 +- 6 files changed, 103 insertions(+), 49 deletions(-) create mode 100644 src/ServerProperties.php diff --git a/src/Server.php b/src/Server.php index 148c93b8e..77d2ae393 100644 --- a/src/Server.php +++ b/src/Server.php @@ -357,15 +357,15 @@ class Server{ } public function getPort() : int{ - return $this->configGroup->getConfigInt("server-port", self::DEFAULT_PORT_IPV4); + return $this->configGroup->getConfigInt(ServerProperties::SERVER_PORT_IPV4, self::DEFAULT_PORT_IPV4); } public function getPortV6() : int{ - return $this->configGroup->getConfigInt("server-portv6", self::DEFAULT_PORT_IPV6); + return $this->configGroup->getConfigInt(ServerProperties::SERVER_PORT_IPV6, self::DEFAULT_PORT_IPV6); } public function getViewDistance() : int{ - return max(2, $this->configGroup->getConfigInt("view-distance", self::DEFAULT_MAX_VIEW_DISTANCE)); + return max(2, $this->configGroup->getConfigInt(ServerProperties::VIEW_DISTANCE, self::DEFAULT_MAX_VIEW_DISTANCE)); } /** @@ -376,12 +376,12 @@ class Server{ } public function getIp() : string{ - $str = $this->configGroup->getConfigString("server-ip"); + $str = $this->configGroup->getConfigString(ServerProperties::SERVER_IPV4); return $str !== "" ? $str : "0.0.0.0"; } public function getIpV6() : string{ - $str = $this->configGroup->getConfigString("server-ipv6"); + $str = $this->configGroup->getConfigString(ServerProperties::SERVER_IPV6); return $str !== "" ? $str : "::"; } @@ -390,30 +390,30 @@ class Server{ } public function getGamemode() : GameMode{ - return GameMode::fromString($this->configGroup->getConfigString("gamemode", GameMode::SURVIVAL()->name())) ?? GameMode::SURVIVAL(); + return GameMode::fromString($this->configGroup->getConfigString(ServerProperties::GAME_MODE, GameMode::SURVIVAL()->name())) ?? GameMode::SURVIVAL(); } public function getForceGamemode() : bool{ - return $this->configGroup->getConfigBool("force-gamemode", false); + return $this->configGroup->getConfigBool(ServerProperties::FORCE_GAME_MODE, false); } /** * Returns Server global difficulty. Note that this may be overridden in individual worlds. */ public function getDifficulty() : int{ - return $this->configGroup->getConfigInt("difficulty", World::DIFFICULTY_NORMAL); + return $this->configGroup->getConfigInt(ServerProperties::DIFFICULTY, World::DIFFICULTY_NORMAL); } public function hasWhitelist() : bool{ - return $this->configGroup->getConfigBool("white-list", false); + return $this->configGroup->getConfigBool(ServerProperties::WHITELIST, false); } public function isHardcore() : bool{ - return $this->configGroup->getConfigBool("hardcore", false); + return $this->configGroup->getConfigBool(ServerProperties::HARDCORE, false); } public function getMotd() : string{ - return $this->configGroup->getConfigString("motd", self::DEFAULT_SERVER_NAME); + return $this->configGroup->getConfigString(ServerProperties::MOTD, self::DEFAULT_SERVER_NAME); } public function getLoader() : ThreadSafeClassLoader{ @@ -811,26 +811,26 @@ class Server{ $this->configGroup = new ServerConfigGroup( new Config($pocketmineYmlPath, Config::YAML, []), new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES, [ - "motd" => self::DEFAULT_SERVER_NAME, - "server-port" => self::DEFAULT_PORT_IPV4, - "server-portv6" => self::DEFAULT_PORT_IPV6, - "enable-ipv6" => true, - "white-list" => false, - "max-players" => self::DEFAULT_MAX_PLAYERS, - "gamemode" => GameMode::SURVIVAL()->name(), - "force-gamemode" => false, - "hardcore" => false, - "pvp" => true, - "difficulty" => World::DIFFICULTY_NORMAL, - "generator-settings" => "", - "level-name" => "world", - "level-seed" => "", - "level-type" => "DEFAULT", - "enable-query" => true, - "auto-save" => true, - "view-distance" => self::DEFAULT_MAX_VIEW_DISTANCE, - "xbox-auth" => true, - "language" => "eng" + ServerProperties::MOTD => self::DEFAULT_SERVER_NAME, + ServerProperties::SERVER_PORT_IPV4 => self::DEFAULT_PORT_IPV4, + ServerProperties::SERVER_PORT_IPV6 => self::DEFAULT_PORT_IPV6, + ServerProperties::ENABLE_IPV6 => true, + ServerProperties::WHITELIST => false, + ServerProperties::MAX_PLAYERS => self::DEFAULT_MAX_PLAYERS, + ServerProperties::GAME_MODE => GameMode::SURVIVAL()->name(), + ServerProperties::FORCE_GAME_MODE => false, + ServerProperties::HARDCORE => false, + ServerProperties::PVP => true, + ServerProperties::DIFFICULTY => World::DIFFICULTY_NORMAL, + ServerProperties::DEFAULT_WORLD_GENERATOR_SETTINGS => "", + ServerProperties::DEFAULT_WORLD_NAME => "world", + ServerProperties::DEFAULT_WORLD_SEED => "", + ServerProperties::DEFAULT_WORLD_GENERATOR => "DEFAULT", + ServerProperties::ENABLE_QUERY => true, + ServerProperties::AUTO_SAVE => true, + ServerProperties::VIEW_DISTANCE => self::DEFAULT_MAX_VIEW_DISTANCE, + ServerProperties::XBOX_AUTH => true, + ServerProperties::LANGUAGE => "eng" ]) ); @@ -840,7 +840,7 @@ class Server{ } $this->forceLanguage = $this->configGroup->getPropertyBool("settings.force-language", false); - $selectedLang = $this->configGroup->getConfigString("language", $this->configGroup->getPropertyString("settings.language", Language::FALLBACK_LANGUAGE)); + $selectedLang = $this->configGroup->getConfigString(ServerProperties::LANGUAGE, $this->configGroup->getPropertyString("settings.language", Language::FALLBACK_LANGUAGE)); try{ $this->language = new Language($selectedLang); }catch(LanguageNotFoundException $e){ @@ -932,9 +932,9 @@ class Server{ $this->banByIP = new BanList($bannedIpsTxt); $this->banByIP->load(); - $this->maxPlayers = $this->configGroup->getConfigInt("max-players", self::DEFAULT_MAX_PLAYERS); + $this->maxPlayers = $this->configGroup->getConfigInt(ServerProperties::MAX_PLAYERS, self::DEFAULT_MAX_PLAYERS); - $this->onlineMode = $this->configGroup->getConfigBool("xbox-auth", true); + $this->onlineMode = $this->configGroup->getConfigBool(ServerProperties::XBOX_AUTH, true); if($this->onlineMode){ $this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_auth_enabled())); }else{ @@ -943,8 +943,8 @@ class Server{ $this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_authProperty_disabled())); } - if($this->configGroup->getConfigBool("hardcore", false) && $this->getDifficulty() < World::DIFFICULTY_HARD){ - $this->configGroup->setConfigInt("difficulty", World::DIFFICULTY_HARD); + if($this->configGroup->getConfigBool(ServerProperties::HARDCORE, false) && $this->getDifficulty() < World::DIFFICULTY_HARD){ + $this->configGroup->setConfigInt(ServerProperties::DIFFICULTY, World::DIFFICULTY_HARD); } @cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion()); @@ -1001,7 +1001,7 @@ class Server{ } $this->worldManager = new WorldManager($this, Path::join($this->dataPath, "worlds"), $providerManager); - $this->worldManager->setAutoSave($this->configGroup->getConfigBool("auto-save", $this->worldManager->getAutoSave())); + $this->worldManager->setAutoSave($this->configGroup->getConfigBool(ServerProperties::AUTO_SAVE, $this->worldManager->getAutoSave())); $this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", $this->worldManager->getAutoSaveInterval())); $this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString("auto-updater.host", "update.pmmp.io")); @@ -1136,11 +1136,11 @@ class Server{ } if($this->worldManager->getDefaultWorld() === null){ - $default = $this->configGroup->getConfigString("level-name", "world"); + $default = $this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_NAME, "world"); if(trim($default) == ""){ $this->getLogger()->warning("level-name cannot be null, using default"); $default = "world"; - $this->configGroup->setConfigString("level-name", "world"); + $this->configGroup->setConfigString(ServerProperties::DEFAULT_WORLD_NAME, "world"); } if(!$this->worldManager->loadWorld($default, true)){ if($this->worldManager->isWorldGenerated($default)){ @@ -1148,8 +1148,8 @@ class Server{ return false; } - $generatorName = $this->configGroup->getConfigString("level-type"); - $generatorOptions = $this->configGroup->getConfigString("generator-settings"); + $generatorName = $this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_GENERATOR); + $generatorOptions = $this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_GENERATOR_SETTINGS); $generatorClass = $getGenerator($generatorName, $generatorOptions, $default); if($generatorClass === null){ @@ -1159,7 +1159,7 @@ class Server{ $creationOptions = WorldCreationOptions::create() ->setGeneratorClass($generatorClass) ->setGeneratorOptions($generatorOptions); - $convertedSeed = Generator::convertSeed($this->configGroup->getConfigString("level-seed")); + $convertedSeed = Generator::convertSeed($this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_SEED)); if($convertedSeed !== null){ $creationOptions->setSeed($convertedSeed); } @@ -1213,7 +1213,7 @@ class Server{ } private function startupPrepareNetworkInterfaces() : bool{ - $useQuery = $this->configGroup->getConfigBool("enable-query", true); + $useQuery = $this->configGroup->getConfigBool(ServerProperties::ENABLE_QUERY, true); $typeConverter = TypeConverter::getInstance(); $packetSerializerContext = new PacketSerializerContext($typeConverter->getItemTypeDictionary()); @@ -1223,7 +1223,7 @@ class Server{ if( !$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter) || ( - $this->configGroup->getConfigBool("enable-ipv6", true) && + $this->configGroup->getConfigBool(ServerProperties::ENABLE_IPV6, true) && !$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter) ) ){ diff --git a/src/ServerProperties.php b/src/ServerProperties.php new file mode 100644 index 000000000..884ff4f67 --- /dev/null +++ b/src/ServerProperties.php @@ -0,0 +1,50 @@ +getServer()->getConfigGroup()->setConfigString("gamemode", $gameMode->name()); + $sender->getServer()->getConfigGroup()->setConfigString(ServerProperties::GAME_MODE, $gameMode->name()); $sender->sendMessage(KnownTranslationFactory::commands_defaultgamemode_success($gameMode->getTranslatableName())); return true; } diff --git a/src/command/defaults/DifficultyCommand.php b/src/command/defaults/DifficultyCommand.php index 98eb3be3b..dee75e025 100644 --- a/src/command/defaults/DifficultyCommand.php +++ b/src/command/defaults/DifficultyCommand.php @@ -28,6 +28,7 @@ use pocketmine\command\CommandSender; use pocketmine\command\utils\InvalidCommandSyntaxException; use pocketmine\lang\KnownTranslationFactory; use pocketmine\permission\DefaultPermissionNames; +use pocketmine\ServerProperties; use pocketmine\world\World; use function count; @@ -54,7 +55,7 @@ class DifficultyCommand extends VanillaCommand{ } if($difficulty !== -1){ - $sender->getServer()->getConfigGroup()->setConfigInt("difficulty", $difficulty); + $sender->getServer()->getConfigGroup()->setConfigInt(ServerProperties::DIFFICULTY, $difficulty); //TODO: add per-world support foreach($sender->getServer()->getWorldManager()->getWorlds() as $world){ diff --git a/src/command/defaults/WhitelistCommand.php b/src/command/defaults/WhitelistCommand.php index 65860aefa..fdf01ff56 100644 --- a/src/command/defaults/WhitelistCommand.php +++ b/src/command/defaults/WhitelistCommand.php @@ -30,6 +30,7 @@ use pocketmine\lang\KnownTranslationFactory; use pocketmine\permission\DefaultPermissionNames; use pocketmine\player\Player; use pocketmine\Server; +use pocketmine\ServerProperties; use function count; use function implode; use function sort; @@ -71,7 +72,7 @@ class WhitelistCommand extends VanillaCommand{ case "on": if($this->testPermission($sender, DefaultPermissionNames::COMMAND_WHITELIST_ENABLE)){ $server = $sender->getServer(); - $server->getConfigGroup()->setConfigBool("white-list", true); + $server->getConfigGroup()->setConfigBool(ServerProperties::WHITELIST, true); $this->kickNonWhitelistedPlayers($server); Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_whitelist_enabled()); } @@ -79,7 +80,7 @@ class WhitelistCommand extends VanillaCommand{ return true; case "off": if($this->testPermission($sender, DefaultPermissionNames::COMMAND_WHITELIST_DISABLE)){ - $sender->getServer()->getConfigGroup()->setConfigBool("white-list", false); + $sender->getServer()->getConfigGroup()->setConfigBool(ServerProperties::WHITELIST, false); Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_whitelist_disabled()); } diff --git a/src/player/Player.php b/src/player/Player.php index d34a357ee..33f9e16f4 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -119,6 +119,7 @@ use pocketmine\permission\PermissibleBase; use pocketmine\permission\PermissibleDelegateTrait; use pocketmine\player\chat\StandardChatFormatter; use pocketmine\Server; +use pocketmine\ServerProperties; use pocketmine\timings\Timings; use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\TextFormat; @@ -1844,7 +1845,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ if(!$this->canInteract($entity->getLocation(), self::MAX_REACH_DISTANCE_ENTITY_INTERACTION)){ $this->logger->debug("Cancelled attack of entity " . $entity->getId() . " due to not currently being interactable"); $ev->cancel(); - }elseif($this->isSpectator() || ($entity instanceof Player && !$this->server->getConfigGroup()->getConfigBool("pvp"))){ + }elseif($this->isSpectator() || ($entity instanceof Player && !$this->server->getConfigGroup()->getConfigBool(ServerProperties::PVP))){ $ev->cancel(); } From 506d8d10642e1c6af64b39788cba129f406ee499 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 25 Aug 2023 12:49:56 +0100 Subject: [PATCH 28/48] CS --- src/data/bedrock/EffectIdMap.php | 2 -- src/data/bedrock/EnchantmentIdMap.php | 2 -- src/data/bedrock/IntSaveIdMapTrait.php | 1 - src/data/bedrock/MushroomBlockTypeIdMap.php | 1 - 4 files changed, 6 deletions(-) diff --git a/src/data/bedrock/EffectIdMap.php b/src/data/bedrock/EffectIdMap.php index 6efa10b41..cadd8c397 100644 --- a/src/data/bedrock/EffectIdMap.php +++ b/src/data/bedrock/EffectIdMap.php @@ -26,8 +26,6 @@ namespace pocketmine\data\bedrock; use pocketmine\entity\effect\Effect; use pocketmine\entity\effect\VanillaEffects; use pocketmine\utils\SingletonTrait; -use function array_key_exists; -use function spl_object_id; final class EffectIdMap{ use SingletonTrait; diff --git a/src/data/bedrock/EnchantmentIdMap.php b/src/data/bedrock/EnchantmentIdMap.php index c06080e3e..ae2460cfe 100644 --- a/src/data/bedrock/EnchantmentIdMap.php +++ b/src/data/bedrock/EnchantmentIdMap.php @@ -26,8 +26,6 @@ namespace pocketmine\data\bedrock; use pocketmine\item\enchantment\Enchantment; use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\utils\SingletonTrait; -use function array_key_exists; -use function spl_object_id; /** * Handles translation of internal enchantment types to and from Minecraft: Bedrock IDs. diff --git a/src/data/bedrock/IntSaveIdMapTrait.php b/src/data/bedrock/IntSaveIdMapTrait.php index 041dfa9e6..cf1631fd5 100644 --- a/src/data/bedrock/IntSaveIdMapTrait.php +++ b/src/data/bedrock/IntSaveIdMapTrait.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace pocketmine\data\bedrock; -use function abs; use function array_key_exists; use function spl_object_id; diff --git a/src/data/bedrock/MushroomBlockTypeIdMap.php b/src/data/bedrock/MushroomBlockTypeIdMap.php index 5e195ebb2..927b52c76 100644 --- a/src/data/bedrock/MushroomBlockTypeIdMap.php +++ b/src/data/bedrock/MushroomBlockTypeIdMap.php @@ -26,7 +26,6 @@ namespace pocketmine\data\bedrock; use pocketmine\block\utils\MushroomBlockType; use pocketmine\data\bedrock\block\BlockLegacyMetadata as LegacyMeta; use pocketmine\utils\SingletonTrait; -use function array_key_exists; final class MushroomBlockTypeIdMap{ use SingletonTrait; From 31d8cc1cb556c9a95960e56de0fffbef13833b72 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 25 Aug 2023 13:23:38 +0100 Subject: [PATCH 29/48] Generate and use constants for pocketmine.yml constant names a couple of usages of properties that no longer exist couldn't be migrated. in addition, this revealed a couple of dead properties in the default file. this is not an ideal solution (I'd much rather model the configs using classes and map them) but in the absence of a good and reliable library to do that, this is the next best thing. --- .github/workflows/main.yml | 3 + ...enerate-pocketmine-yml-property-consts.php | 76 +++++++++++++ src/MemoryManager.php | 29 ++--- src/Server.php | 59 +++++----- src/YmlServerProperties.php | 107 ++++++++++++++++++ src/command/defaults/TimingsCommand.php | 3 +- src/crash/CrashDump.php | 7 +- src/network/mcpe/NetworkSession.php | 3 +- src/network/mcpe/raklib/RakLibInterface.php | 3 +- src/network/query/QueryInfo.php | 3 +- src/player/Player.php | 7 +- src/stats/SendUsageTask.php | 3 +- src/updater/UpdateChecker.php | 7 +- src/world/World.php | 9 +- 14 files changed, 258 insertions(+), 61 deletions(-) create mode 100644 build/generate-pocketmine-yml-property-consts.php create mode 100644 src/YmlServerProperties.php diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 022e0ab3a..a888d4254 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -158,6 +158,9 @@ jobs: - name: Regenerate BedrockData available files constants run: php build/generate-bedrockdata-path-consts.php + - name: Regenerate YmlServerProperties constants + run: php build/generate-pocketmine-yml-property-consts.php + - name: Verify code is unchanged run: | git diff diff --git a/build/generate-pocketmine-yml-property-consts.php b/build/generate-pocketmine-yml-property-consts.php new file mode 100644 index 000000000..b0e79519a --- /dev/null +++ b/build/generate-pocketmine-yml-property-consts.php @@ -0,0 +1,76 @@ + $constants + * @phpstan-param-out array $constants + */ +function collectProperties(string $prefix, array $properties, array &$constants) : void{ + foreach($properties as $propertyName => $property){ + $fullPropertyName = ($prefix !== "" ? $prefix . "." : "") . $propertyName; + + $constName = str_replace([".", "-"], "_", strtoupper($fullPropertyName)); + $constants[$constName] = $fullPropertyName; + + if(is_array($property)){ + collectProperties($fullPropertyName, $property, $constants); + } + } +} + +collectProperties("", $defaultConfig, $constants); +ksort($constants, SORT_STRING); + +$file = fopen(dirname(__DIR__) . '/src/YmlServerProperties.php', 'wb'); +if($file === false){ + fwrite(STDERR, "Failed to open output file\n"); + exit(1); +} +fwrite($file, " $propertyName){ + fwrite($file, "\tpublic const $constName = '$propertyName';\n"); +} +fwrite($file, "}\n"); + +fclose($file); + +echo "Done. Don't forget to run CS fixup after generating code.\n"; diff --git a/src/MemoryManager.php b/src/MemoryManager.php index 0e8502ff8..053498e7e 100644 --- a/src/MemoryManager.php +++ b/src/MemoryManager.php @@ -30,6 +30,7 @@ use pocketmine\scheduler\GarbageCollectionTask; use pocketmine\timings\Timings; use pocketmine\utils\Process; use pocketmine\utils\Utils; +use pocketmine\YmlServerProperties as Yml; use Symfony\Component\Filesystem\Path; use function arsort; use function count; @@ -109,7 +110,7 @@ class MemoryManager{ } private function init(ServerConfigGroup $config) : void{ - $this->memoryLimit = $config->getPropertyInt("memory.main-limit", 0) * 1024 * 1024; + $this->memoryLimit = $config->getPropertyInt(Yml::MEMORY_MAIN_LIMIT, 0) * 1024 * 1024; $defaultMemory = 1024; @@ -127,7 +128,7 @@ class MemoryManager{ } } - $hardLimit = $config->getPropertyInt("memory.main-hard-limit", $defaultMemory); + $hardLimit = $config->getPropertyInt(Yml::MEMORY_MAIN_HARD_LIMIT, $defaultMemory); if($hardLimit <= 0){ ini_set("memory_limit", '-1'); @@ -135,22 +136,22 @@ class MemoryManager{ ini_set("memory_limit", $hardLimit . "M"); } - $this->globalMemoryLimit = $config->getPropertyInt("memory.global-limit", 0) * 1024 * 1024; - $this->checkRate = $config->getPropertyInt("memory.check-rate", self::DEFAULT_CHECK_RATE); - $this->continuousTrigger = $config->getPropertyBool("memory.continuous-trigger", true); - $this->continuousTriggerRate = $config->getPropertyInt("memory.continuous-trigger-rate", self::DEFAULT_CONTINUOUS_TRIGGER_RATE); + $this->globalMemoryLimit = $config->getPropertyInt(Yml::MEMORY_GLOBAL_LIMIT, 0) * 1024 * 1024; + $this->checkRate = $config->getPropertyInt(Yml::MEMORY_CHECK_RATE, self::DEFAULT_CHECK_RATE); + $this->continuousTrigger = $config->getPropertyBool(Yml::MEMORY_CONTINUOUS_TRIGGER, true); + $this->continuousTriggerRate = $config->getPropertyInt(Yml::MEMORY_CONTINUOUS_TRIGGER_RATE, self::DEFAULT_CONTINUOUS_TRIGGER_RATE); - $this->garbageCollectionPeriod = $config->getPropertyInt("memory.garbage-collection.period", self::DEFAULT_TICKS_PER_GC); - $this->garbageCollectionTrigger = $config->getPropertyBool("memory.garbage-collection.low-memory-trigger", true); - $this->garbageCollectionAsync = $config->getPropertyBool("memory.garbage-collection.collect-async-worker", true); + $this->garbageCollectionPeriod = $config->getPropertyInt(Yml::MEMORY_GARBAGE_COLLECTION_PERIOD, self::DEFAULT_TICKS_PER_GC); + $this->garbageCollectionTrigger = $config->getPropertyBool(Yml::MEMORY_GARBAGE_COLLECTION_LOW_MEMORY_TRIGGER, true); + $this->garbageCollectionAsync = $config->getPropertyBool(Yml::MEMORY_GARBAGE_COLLECTION_COLLECT_ASYNC_WORKER, true); - $this->lowMemChunkRadiusOverride = $config->getPropertyInt("memory.max-chunks.chunk-radius", 4); - $this->lowMemChunkGC = $config->getPropertyBool("memory.max-chunks.trigger-chunk-collect", true); + $this->lowMemChunkRadiusOverride = $config->getPropertyInt(Yml::MEMORY_MAX_CHUNKS_CHUNK_RADIUS, 4); + $this->lowMemChunkGC = $config->getPropertyBool(Yml::MEMORY_MAX_CHUNKS_TRIGGER_CHUNK_COLLECT, true); - $this->lowMemDisableChunkCache = $config->getPropertyBool("memory.world-caches.disable-chunk-cache", true); - $this->lowMemClearWorldCache = $config->getPropertyBool("memory.world-caches.low-memory-trigger", true); + $this->lowMemDisableChunkCache = $config->getPropertyBool(Yml::MEMORY_WORLD_CACHES_DISABLE_CHUNK_CACHE, true); + $this->lowMemClearWorldCache = $config->getPropertyBool(Yml::MEMORY_WORLD_CACHES_LOW_MEMORY_TRIGGER, true); - $this->dumpWorkers = $config->getPropertyBool("memory.memory-dump.dump-async-worker", true); + $this->dumpWorkers = $config->getPropertyBool(Yml::MEMORY_MEMORY_DUMP_DUMP_ASYNC_WORKER, true); gc_enable(); } diff --git a/src/Server.php b/src/Server.php index 77d2ae393..00951c10a 100644 --- a/src/Server.php +++ b/src/Server.php @@ -120,6 +120,7 @@ use pocketmine\world\Position; use pocketmine\world\World; use pocketmine\world\WorldCreationOptions; use pocketmine\world\WorldManager; +use pocketmine\YmlServerProperties as Yml; use Ramsey\Uuid\UuidInterface; use Symfony\Component\Filesystem\Path; use function array_fill; @@ -496,7 +497,7 @@ class Server{ } public function shouldSavePlayerData() : bool{ - return $this->configGroup->getPropertyBool("player.save-player-data", true); + return $this->configGroup->getPropertyBool(Yml::PLAYER_SAVE_PLAYER_DATA, true); } public function getOfflinePlayer(string $name) : Player|OfflinePlayer|null{ @@ -736,7 +737,7 @@ class Server{ * @return string[][] */ public function getCommandAliases() : array{ - $section = $this->configGroup->getProperty("aliases"); + $section = $this->configGroup->getProperty(YmlServerProperties::ALIASES); $result = []; if(is_array($section)){ foreach($section as $key => $value){ @@ -834,12 +835,12 @@ class Server{ ]) ); - $debugLogLevel = $this->configGroup->getPropertyInt("debug.level", 1); + $debugLogLevel = $this->configGroup->getPropertyInt(Yml::DEBUG_LEVEL, 1); if($this->logger instanceof MainLogger){ $this->logger->setLogDebug($debugLogLevel > 1); } - $this->forceLanguage = $this->configGroup->getPropertyBool("settings.force-language", false); + $this->forceLanguage = $this->configGroup->getPropertyBool(Yml::SETTINGS_FORCE_LANGUAGE, false); $selectedLang = $this->configGroup->getConfigString(ServerProperties::LANGUAGE, $this->configGroup->getPropertyString("settings.language", Language::FALLBACK_LANGUAGE)); try{ $this->language = new Language($selectedLang); @@ -856,11 +857,11 @@ class Server{ $this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::language_selected($this->getLanguage()->getName(), $this->getLanguage()->getLang()))); if(VersionInfo::IS_DEVELOPMENT_BUILD){ - if(!$this->configGroup->getPropertyBool("settings.enable-dev-builds", false)){ + if(!$this->configGroup->getPropertyBool(Yml::SETTINGS_ENABLE_DEV_BUILDS, false)){ $this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error1(VersionInfo::NAME))); $this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error2())); $this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error3())); - $this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4("settings.enable-dev-builds"))); + $this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4(YmlServerProperties::SETTINGS_ENABLE_DEV_BUILDS))); $this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error5("https://github.com/pmmp/PocketMine-MP/releases"))); $this->forceShutdownExit(); @@ -878,7 +879,7 @@ class Server{ $this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_start(TextFormat::AQUA . $this->getVersion() . TextFormat::RESET))); - if(($poolSize = $this->configGroup->getPropertyString("settings.async-workers", "auto")) === "auto"){ + if(($poolSize = $this->configGroup->getPropertyString(Yml::SETTINGS_ASYNC_WORKERS, "auto")) === "auto"){ $poolSize = 2; $processors = Utils::getCoreCount() - 2; @@ -889,32 +890,32 @@ class Server{ $poolSize = max(1, (int) $poolSize); } - $this->asyncPool = new AsyncPool($poolSize, max(-1, $this->configGroup->getPropertyInt("memory.async-worker-hard-limit", 256)), $this->autoloader, $this->logger, $this->tickSleeper); + $this->asyncPool = new AsyncPool($poolSize, max(-1, $this->configGroup->getPropertyInt(Yml::MEMORY_ASYNC_WORKER_HARD_LIMIT, 256)), $this->autoloader, $this->logger, $this->tickSleeper); $netCompressionThreshold = -1; - if($this->configGroup->getPropertyInt("network.batch-threshold", 256) >= 0){ - $netCompressionThreshold = $this->configGroup->getPropertyInt("network.batch-threshold", 256); + if($this->configGroup->getPropertyInt(Yml::NETWORK_BATCH_THRESHOLD, 256) >= 0){ + $netCompressionThreshold = $this->configGroup->getPropertyInt(Yml::NETWORK_BATCH_THRESHOLD, 256); } if($netCompressionThreshold < 0){ $netCompressionThreshold = null; } - $netCompressionLevel = $this->configGroup->getPropertyInt("network.compression-level", 6); + $netCompressionLevel = $this->configGroup->getPropertyInt(Yml::NETWORK_COMPRESSION_LEVEL, 6); if($netCompressionLevel < 1 || $netCompressionLevel > 9){ $this->logger->warning("Invalid network compression level $netCompressionLevel set, setting to default 6"); $netCompressionLevel = 6; } ZlibCompressor::setInstance(new ZlibCompressor($netCompressionLevel, $netCompressionThreshold, ZlibCompressor::DEFAULT_MAX_DECOMPRESSION_SIZE)); - $this->networkCompressionAsync = $this->configGroup->getPropertyBool("network.async-compression", true); + $this->networkCompressionAsync = $this->configGroup->getPropertyBool(Yml::NETWORK_ASYNC_COMPRESSION, true); $this->networkCompressionAsyncThreshold = max( - $this->configGroup->getPropertyInt("network.async-compression-threshold", self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD), + $this->configGroup->getPropertyInt(Yml::NETWORK_ASYNC_COMPRESSION_THRESHOLD, self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD), $netCompressionThreshold ?? self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD ); - EncryptionContext::$ENABLED = $this->configGroup->getPropertyBool("network.enable-encryption", true); + EncryptionContext::$ENABLED = $this->configGroup->getPropertyBool(Yml::NETWORK_ENABLE_ENCRYPTION, true); - $this->doTitleTick = $this->configGroup->getPropertyBool("console.title-tick", true) && Terminal::hasFormattingCodes(); + $this->doTitleTick = $this->configGroup->getPropertyBool(Yml::CONSOLE_TITLE_TICK, true) && Terminal::hasFormattingCodes(); $this->operators = new Config(Path::join($this->dataPath, "ops.txt"), Config::ENUM); $this->whitelist = new Config(Path::join($this->dataPath, "white-list.txt"), Config::ENUM); @@ -963,8 +964,8 @@ class Server{ ))); $this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_license($this->getName()))); - TimingsHandler::setEnabled($this->configGroup->getPropertyBool("settings.enable-profiling", false)); - $this->profilingTickRate = $this->configGroup->getPropertyInt("settings.profile-report-trigger", self::TARGET_TICKS_PER_SECOND); + TimingsHandler::setEnabled($this->configGroup->getPropertyBool(Yml::SETTINGS_ENABLE_PROFILING, false)); + $this->profilingTickRate = $this->configGroup->getPropertyInt(Yml::SETTINGS_PROFILE_REPORT_TRIGGER, self::TARGET_TICKS_PER_SECOND); DefaultPermissions::registerCorePermissions(); @@ -986,13 +987,13 @@ class Server{ $this->forceShutdownExit(); return; } - $this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool("plugins.legacy-data-dir", true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist); + $this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool(Yml::PLUGINS_LEGACY_DATA_DIR, true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist); $this->pluginManager->registerInterface(new PharPluginLoader($this->autoloader)); $this->pluginManager->registerInterface(new ScriptPluginLoader()); $providerManager = new WorldProviderManager(); if( - ($format = $providerManager->getProviderByName($formatName = $this->configGroup->getPropertyString("level-settings.default-format", ""))) !== null && + ($format = $providerManager->getProviderByName($formatName = $this->configGroup->getPropertyString(Yml::LEVEL_SETTINGS_DEFAULT_FORMAT, ""))) !== null && $format instanceof WritableWorldProviderManagerEntry ){ $providerManager->setDefault($format); @@ -1002,9 +1003,9 @@ class Server{ $this->worldManager = new WorldManager($this, Path::join($this->dataPath, "worlds"), $providerManager); $this->worldManager->setAutoSave($this->configGroup->getConfigBool(ServerProperties::AUTO_SAVE, $this->worldManager->getAutoSave())); - $this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", $this->worldManager->getAutoSaveInterval())); + $this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt(Yml::TICKS_PER_AUTOSAVE, $this->worldManager->getAutoSaveInterval())); - $this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString("auto-updater.host", "update.pmmp.io")); + $this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString(Yml::AUTO_UPDATER_HOST, "update.pmmp.io")); $this->queryInfo = new QueryInfo($this); @@ -1041,7 +1042,7 @@ class Server{ return; } - if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){ + if($this->configGroup->getPropertyBool(Yml::ANONYMOUS_STATISTICS_ENABLED, true)){ $this->sendUsageTicker = self::TICKS_PER_STATS_REPORT; $this->sendUsage(SendUsageTask::TYPE_OPEN); } @@ -1057,7 +1058,7 @@ class Server{ $this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_USERS, $forwarder); //TODO: move console parts to a separate component - if($this->configGroup->getPropertyBool("console.enable-input", true)){ + if($this->configGroup->getPropertyBool(Yml::CONSOLE_ENABLE_INPUT, true)){ $this->console = new ConsoleReaderChildProcessDaemon($this->logger); } @@ -1092,7 +1093,7 @@ class Server{ $anyWorldFailedToLoad = false; - foreach((array) $this->configGroup->getProperty("worlds", []) as $name => $options){ + foreach((array) $this->configGroup->getProperty(Yml::WORLDS, []) as $name => $options){ if($options === null){ $options = []; }elseif(!is_array($options)){ @@ -1238,7 +1239,7 @@ class Server{ $this->network->blockAddress($entry->getName(), -1); } - if($this->configGroup->getPropertyBool("network.upnp-forwarding", false)){ + if($this->configGroup->getPropertyBool(Yml::NETWORK_UPNP_FORWARDING, false)){ $this->network->registerInterface(new UPnPNetworkInterface($this->logger, Internet::getInternalIP(), $this->getPort())); } @@ -1458,7 +1459,7 @@ class Server{ } if(isset($this->network)){ - $this->network->getSessionManager()->close($this->configGroup->getPropertyString("settings.shutdown-message", "Server closed")); + $this->network->getSessionManager()->close($this->configGroup->getPropertyString(YmlServerProperties::SETTINGS_SHUTDOWN_MESSAGE, "Server closed")); } if(isset($this->worldManager)){ @@ -1595,7 +1596,7 @@ class Server{ $this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_submit($crashDumpPath))); - if($this->configGroup->getPropertyBool("auto-report.enabled", true)){ + if($this->configGroup->getPropertyBool(Yml::AUTO_REPORT_ENABLED, true)){ $report = true; $stamp = Path::join($this->getDataPath(), "crashdumps", ".last_crash"); @@ -1625,7 +1626,7 @@ class Server{ } if($report){ - $url = ($this->configGroup->getPropertyBool("auto-report.use-https", true) ? "https" : "http") . "://" . $this->configGroup->getPropertyString("auto-report.host", "crash.pmmp.io") . "/submit/api"; + $url = ($this->configGroup->getPropertyBool(Yml::AUTO_REPORT_USE_HTTPS, true) ? "https" : "http") . "://" . $this->configGroup->getPropertyString(Yml::AUTO_REPORT_HOST, "crash.pmmp.io") . "/submit/api"; $postUrlError = "Unknown error"; $reply = Internet::postURL($url, [ "report" => "yes", @@ -1736,7 +1737,7 @@ class Server{ } public function sendUsage(int $type = SendUsageTask::TYPE_STATUS) : void{ - if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){ + if($this->configGroup->getPropertyBool(Yml::ANONYMOUS_STATISTICS_ENABLED, true)){ $this->asyncPool->submitTask(new SendUsageTask($this, $type, $this->uniquePlayers)); } $this->uniquePlayers = []; diff --git a/src/YmlServerProperties.php b/src/YmlServerProperties.php new file mode 100644 index 000000000..920f0797a --- /dev/null +++ b/src/YmlServerProperties.php @@ -0,0 +1,107 @@ +getServer()->getConfigGroup()->getPropertyString("timings.host", "timings.pmmp.io"); + $host = $sender->getServer()->getConfigGroup()->getPropertyString(YmlServerProperties::TIMINGS_HOST, "timings.pmmp.io"); $sender->getServer()->getAsyncPool()->submitTask(new BulkCurlTask( [new BulkCurlTaskOperation( diff --git a/src/crash/CrashDump.php b/src/crash/CrashDump.php index ded1e5d88..9d2eb39e9 100644 --- a/src/crash/CrashDump.php +++ b/src/crash/CrashDump.php @@ -34,6 +34,7 @@ use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\Filesystem; use pocketmine\utils\Utils; use pocketmine\VersionInfo; +use pocketmine\YmlServerProperties; use Symfony\Component\Filesystem\Path; use function array_map; use function base64_encode; @@ -152,7 +153,7 @@ class CrashDump{ private function extraData() : void{ global $argv; - if($this->server->getConfigGroup()->getPropertyBool("auto-report.send-settings", true)){ + if($this->server->getConfigGroup()->getPropertyBool(YmlServerProperties::AUTO_REPORT_SEND_SETTINGS, true)){ $this->data->parameters = (array) $argv; if(($serverDotProperties = @file_get_contents(Path::join($this->server->getDataPath(), "server.properties"))) !== false){ $this->data->serverDotProperties = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $serverDotProperties) ?? throw new AssumptionFailedError("Pattern is valid"); @@ -170,7 +171,7 @@ class CrashDump{ $this->data->jit_mode = Utils::getOpcacheJitMode(); - if($this->server->getConfigGroup()->getPropertyBool("auto-report.send-phpinfo", true)){ + if($this->server->getConfigGroup()->getPropertyBool(YmlServerProperties::AUTO_REPORT_SEND_PHPINFO, true)){ ob_start(); phpinfo(); $this->data->phpinfo = ob_get_contents(); // @phpstan-ignore-line @@ -225,7 +226,7 @@ class CrashDump{ } } - if($this->server->getConfigGroup()->getPropertyBool("auto-report.send-code", true) && file_exists($error["fullFile"])){ + if($this->server->getConfigGroup()->getPropertyBool(YmlServerProperties::AUTO_REPORT_SEND_CODE, true) && file_exists($error["fullFile"])){ $file = @file($error["fullFile"], FILE_IGNORE_NEW_LINES); if($file !== false){ for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10 && isset($file[$l]); ++$l){ diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 100d9c989..5b65ca1b5 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -108,6 +108,7 @@ use pocketmine\utils\BinaryStream; use pocketmine\utils\ObjectSet; use pocketmine\utils\TextFormat; use pocketmine\world\Position; +use pocketmine\YmlServerProperties; use function array_map; use function array_values; use function base64_encode; @@ -740,7 +741,7 @@ class NetworkSession{ } $this->logger->debug("Xbox Live authenticated: " . ($this->authenticated ? "YES" : "NO")); - $checkXUID = $this->server->getConfigGroup()->getPropertyBool("player.verify-xuid", true); + $checkXUID = $this->server->getConfigGroup()->getPropertyBool(YmlServerProperties::PLAYER_VERIFY_XUID, true); $myXUID = $this->info instanceof XboxLivePlayerInfo ? $this->info->getXuid() : ""; $kickForXUIDMismatch = function(string $xuid) use ($checkXUID, $myXUID) : bool{ if($checkXUID && $myXUID !== $xuid){ diff --git a/src/network/mcpe/raklib/RakLibInterface.php b/src/network/mcpe/raklib/RakLibInterface.php index 4bf8ffb15..759a992e8 100644 --- a/src/network/mcpe/raklib/RakLibInterface.php +++ b/src/network/mcpe/raklib/RakLibInterface.php @@ -42,6 +42,7 @@ use pocketmine\Server; use pocketmine\thread\ThreadCrashException; use pocketmine\timings\Timings; use pocketmine\utils\Utils; +use pocketmine\YmlServerProperties; use raklib\generic\DisconnectReason; use raklib\generic\SocketException; use raklib\protocol\EncapsulatedPacket; @@ -125,7 +126,7 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{ $threadToMainBuffer, new InternetAddress($ip, $port, $ipV6 ? 6 : 4), $this->rakServerId, - $this->server->getConfigGroup()->getPropertyInt("network.max-mtu-size", 1492), + $this->server->getConfigGroup()->getPropertyInt(YmlServerProperties::NETWORK_MAX_MTU_SIZE, 1492), self::MCPE_RAKNET_PROTOCOL_VERSION, $sleeperEntry ); diff --git a/src/network/query/QueryInfo.php b/src/network/query/QueryInfo.php index 2d36ac7e6..cdb1c66db 100644 --- a/src/network/query/QueryInfo.php +++ b/src/network/query/QueryInfo.php @@ -29,6 +29,7 @@ use pocketmine\plugin\Plugin; use pocketmine\Server; use pocketmine\utils\Binary; use pocketmine\utils\Utils; +use pocketmine\YmlServerProperties; use function array_map; use function chr; use function count; @@ -66,7 +67,7 @@ final class QueryInfo{ public function __construct(Server $server){ $this->serverName = $server->getMotd(); - $this->listPlugins = $server->getConfigGroup()->getPropertyBool("settings.query-plugins", true); + $this->listPlugins = $server->getConfigGroup()->getPropertyBool(YmlServerProperties::SETTINGS_QUERY_PLUGINS, true); $this->plugins = $server->getPluginManager()->getPlugins(); $this->players = array_map(fn(Player $p) => $p->getName(), $server->getOnlinePlayers()); diff --git a/src/player/Player.php b/src/player/Player.php index 33f9e16f4..2059613ad 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -135,6 +135,7 @@ use pocketmine\world\sound\FireExtinguishSound; use pocketmine\world\sound\ItemBreakSound; use pocketmine\world\sound\Sound; use pocketmine\world\World; +use pocketmine\YmlServerProperties; use Ramsey\Uuid\UuidInterface; use function abs; use function array_filter; @@ -318,8 +319,8 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ $rootPermissions[DefaultPermissions::ROOT_OPERATOR] = true; } $this->perm = new PermissibleBase($rootPermissions); - $this->chunksPerTick = $this->server->getConfigGroup()->getPropertyInt("chunk-sending.per-tick", 4); - $this->spawnThreshold = (int) (($this->server->getConfigGroup()->getPropertyInt("chunk-sending.spawn-radius", 4) ** 2) * M_PI); + $this->chunksPerTick = $this->server->getConfigGroup()->getPropertyInt(YmlServerProperties::CHUNK_SENDING_PER_TICK, 4); + $this->spawnThreshold = (int) (($this->server->getConfigGroup()->getPropertyInt(YmlServerProperties::CHUNK_SENDING_SPAWN_RADIUS, 4) ** 2) * M_PI); $this->chunkSelector = new ChunkSelector(); $this->chunkLoader = new class implements ChunkLoader{}; @@ -584,7 +585,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ $this->viewDistance = $newViewDistance; - $this->spawnThreshold = (int) (min($this->viewDistance, $this->server->getConfigGroup()->getPropertyInt("chunk-sending.spawn-radius", 4)) ** 2 * M_PI); + $this->spawnThreshold = (int) (min($this->viewDistance, $this->server->getConfigGroup()->getPropertyInt(YmlServerProperties::CHUNK_SENDING_SPAWN_RADIUS, 4)) ** 2 * M_PI); $this->nextChunkOrderRun = 0; diff --git a/src/stats/SendUsageTask.php b/src/stats/SendUsageTask.php index 08c17c73a..d218774b5 100644 --- a/src/stats/SendUsageTask.php +++ b/src/stats/SendUsageTask.php @@ -31,6 +31,7 @@ use pocketmine\utils\Internet; use pocketmine\utils\Process; use pocketmine\utils\Utils; use pocketmine\VersionInfo; +use pocketmine\YmlServerProperties; use Ramsey\Uuid\Uuid; use function array_map; use function array_values; @@ -57,7 +58,7 @@ class SendUsageTask extends AsyncTask{ * @phpstan-param array $playerList */ public function __construct(Server $server, int $type, array $playerList = []){ - $endpoint = "http://" . $server->getConfigGroup()->getPropertyString("anonymous-statistics.host", "stats.pocketmine.net") . "/"; + $endpoint = "http://" . $server->getConfigGroup()->getPropertyString(YmlServerProperties::ANONYMOUS_STATISTICS_HOST, "stats.pocketmine.net") . "/"; $data = []; $data["uniqueServerId"] = $server->getServerUniqueId()->toString(); diff --git a/src/updater/UpdateChecker.php b/src/updater/UpdateChecker.php index ddb0f4d66..4a3ee3444 100644 --- a/src/updater/UpdateChecker.php +++ b/src/updater/UpdateChecker.php @@ -27,6 +27,7 @@ use pocketmine\event\server\UpdateNotifyEvent; use pocketmine\Server; use pocketmine\utils\VersionString; use pocketmine\VersionInfo; +use pocketmine\YmlServerProperties; use function date; use function strtolower; use function ucfirst; @@ -43,7 +44,7 @@ class UpdateChecker{ $this->logger = new \PrefixedLogger($server->getLogger(), "Update Checker"); $this->endpoint = "http://$endpoint/api/"; - if($server->getConfigGroup()->getPropertyBool("auto-updater.enabled", true)){ + if($server->getConfigGroup()->getPropertyBool(YmlServerProperties::AUTO_UPDATER_ENABLED, true)){ $this->doCheck(); } } @@ -59,7 +60,7 @@ class UpdateChecker{ $this->checkUpdate($updateInfo); if($this->hasUpdate()){ (new UpdateNotifyEvent($this))->call(); - if($this->server->getConfigGroup()->getPropertyBool("auto-updater.on-update.warn-console", true)){ + if($this->server->getConfigGroup()->getPropertyBool(YmlServerProperties::AUTO_UPDATER_ON_UPDATE_WARN_CONSOLE, true)){ $this->showConsoleUpdate(); } }else{ @@ -157,7 +158,7 @@ class UpdateChecker{ * Returns the channel used for update checking (stable, beta, dev) */ public function getChannel() : string{ - return strtolower($this->server->getConfigGroup()->getPropertyString("auto-updater.preferred-channel", "stable")); + return strtolower($this->server->getConfigGroup()->getPropertyString(YmlServerProperties::AUTO_UPDATER_PREFERRED_CHANNEL, "stable")); } /** diff --git a/src/world/World.php b/src/world/World.php index d917a3e82..903cc60e2 100644 --- a/src/world/World.php +++ b/src/world/World.php @@ -104,6 +104,7 @@ use pocketmine\world\particle\Particle; use pocketmine\world\sound\BlockPlaceSound; use pocketmine\world\sound\Sound; use pocketmine\world\utils\SubChunkExplorer; +use pocketmine\YmlServerProperties; use function abs; use function array_filter; use function array_key_exists; @@ -513,14 +514,14 @@ class World implements ChunkManager{ $this->time = $this->provider->getWorldData()->getTime(); $cfg = $this->server->getConfigGroup(); - $this->chunkTickRadius = min($this->server->getViewDistance(), max(0, $cfg->getPropertyInt("chunk-ticking.tick-radius", 4))); + $this->chunkTickRadius = min($this->server->getViewDistance(), max(0, $cfg->getPropertyInt(YmlServerProperties::CHUNK_TICKING_TICK_RADIUS, 4))); if($cfg->getPropertyInt("chunk-ticking.per-tick", 40) <= 0){ //TODO: this needs l10n $this->logger->warning("\"chunk-ticking.per-tick\" setting is deprecated, but you've used it to disable chunk ticking. Set \"chunk-ticking.tick-radius\" to 0 in \"pocketmine.yml\" instead."); $this->chunkTickRadius = 0; } - $this->tickedBlocksPerSubchunkPerTick = $cfg->getPropertyInt("chunk-ticking.blocks-per-subchunk-per-tick", self::DEFAULT_TICKED_BLOCKS_PER_SUBCHUNK_PER_TICK); - $this->maxConcurrentChunkPopulationTasks = $cfg->getPropertyInt("chunk-generation.population-queue-size", 2); + $this->tickedBlocksPerSubchunkPerTick = $cfg->getPropertyInt(YmlServerProperties::CHUNK_TICKING_BLOCKS_PER_SUBCHUNK_PER_TICK, self::DEFAULT_TICKED_BLOCKS_PER_SUBCHUNK_PER_TICK); + $this->maxConcurrentChunkPopulationTasks = $cfg->getPropertyInt(YmlServerProperties::CHUNK_GENERATION_POPULATION_QUEUE_SIZE, 2); $this->initRandomTickBlocksFromConfig($cfg); @@ -541,7 +542,7 @@ class World implements ChunkManager{ private function initRandomTickBlocksFromConfig(ServerConfigGroup $cfg) : void{ $dontTickBlocks = []; $parser = StringToItemParser::getInstance(); - foreach($cfg->getProperty("chunk-ticking.disable-block-ticking", []) as $name){ + foreach($cfg->getProperty(YmlServerProperties::CHUNK_TICKING_DISABLE_BLOCK_TICKING, []) as $name){ $name = (string) $name; $item = $parser->parse($name); if($item !== null){ From 2912e7ca2962495aaf7e0d2e54fa13b572186055 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 25 Aug 2023 13:27:07 +0100 Subject: [PATCH 30/48] ... --- ...enerate-pocketmine-yml-property-consts.php | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/build/generate-pocketmine-yml-property-consts.php b/build/generate-pocketmine-yml-property-consts.php index b0e79519a..93d623918 100644 --- a/build/generate-pocketmine-yml-property-consts.php +++ b/build/generate-pocketmine-yml-property-consts.php @@ -62,9 +62,34 @@ if($file === false){ fwrite(STDERR, "Failed to open output file\n"); exit(1); } -fwrite($file, " $propertyName){ fwrite($file, "\tpublic const $constName = '$propertyName';\n"); From 4a0a538278edbb375d228093c3947d7a208d817d Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 25 Aug 2023 13:27:40 +0100 Subject: [PATCH 31/48] CS --- build/generate-pocketmine-yml-property-consts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/generate-pocketmine-yml-property-consts.php b/build/generate-pocketmine-yml-property-consts.php index 93d623918..23d1de04a 100644 --- a/build/generate-pocketmine-yml-property-consts.php +++ b/build/generate-pocketmine-yml-property-consts.php @@ -36,7 +36,7 @@ if(!is_array($defaultConfig)){ $constants = []; /** - * @param mixed[] $properties + * @param mixed[] $properties * @param string[] $constants * @phpstan-param array $constants * @phpstan-param-out array $constants From 9fdb6ba5aa4df65a78684db2c8d10fc3d8a9f7b4 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 25 Aug 2023 14:02:49 +0100 Subject: [PATCH 32/48] Mark some new things as internal --- build/generate-pocketmine-yml-property-consts.php | 10 ++++++++++ src/ServerProperties.php | 4 ++++ src/YmlServerProperties.php | 6 ++++++ 3 files changed, 20 insertions(+) diff --git a/build/generate-pocketmine-yml-property-consts.php b/build/generate-pocketmine-yml-property-consts.php index 23d1de04a..90342a75f 100644 --- a/build/generate-pocketmine-yml-property-consts.php +++ b/build/generate-pocketmine-yml-property-consts.php @@ -90,6 +90,16 @@ HEADER fwrite($file, "declare(strict_types=1);\n\n"); fwrite($file, "namespace pocketmine;\n\n"); +fwrite($file, <<<'DOC' +/** + * @internal + * Constants for all properties available in pocketmine.yml. + * This is generated by build/generate-pocketmine-yml-property-consts.php. + * Do not edit this file manually. + */ + +DOC +); fwrite($file, "final class YmlServerProperties{\n"); foreach(Utils::stringifyKeys($constants) as $constName => $propertyName){ fwrite($file, "\tpublic const $constName = '$propertyName';\n"); diff --git a/src/ServerProperties.php b/src/ServerProperties.php index 884ff4f67..aad26d242 100644 --- a/src/ServerProperties.php +++ b/src/ServerProperties.php @@ -23,6 +23,10 @@ declare(strict_types=1); namespace pocketmine; +/** + * @internal + * Constants for all properties available in server.properties. + */ final class ServerProperties{ public const AUTO_SAVE = "auto-save"; diff --git a/src/YmlServerProperties.php b/src/YmlServerProperties.php index 920f0797a..7d088b13c 100644 --- a/src/YmlServerProperties.php +++ b/src/YmlServerProperties.php @@ -23,6 +23,12 @@ declare(strict_types=1); namespace pocketmine; +/** + * @internal + * Constants for all properties available in pocketmine.yml. + * This is generated by build/generate-pocketmine-yml-property-consts.php. + * Do not edit this file manually. + */ final class YmlServerProperties{ public const ALIASES = 'aliases'; public const ANONYMOUS_STATISTICS = 'anonymous-statistics'; From 19e3d339f6c119fb30b49e2a502b69882fee310f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=AD=E3=82=89=E3=81=B2=E3=81=8B=E3=81=A0?= Date: Tue, 29 Aug 2023 19:43:21 +0900 Subject: [PATCH 33/48] InGamePacketHandler: subtract from raw position before rounding it (#6022) This allows better compensation for floating point errors introduced by the subtraction of the 1.62 height offset. For example, if the player is at y=7 exactly, their Y coordinate will be reported as 8.62, which, because of floating point errors, will be something like `8.619999999`. Subtracting `1.62` from this (really something like `1.62000000000005...`) leads to the calculated Y coordinate being slightly below 7. Rounding after subtracting this offset allows this to be rounded to 7 sharp. Similar errors appear in various other coordinates. --- src/network/mcpe/handler/InGamePacketHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index 729b5b51b..30841d806 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -201,7 +201,7 @@ class InGamePacketHandler extends PacketHandler{ } $hasMoved = $this->lastPlayerAuthInputPosition === null || !$this->lastPlayerAuthInputPosition->equals($rawPos); - $newPos = $rawPos->round(4)->subtract(0, 1.62, 0); + $newPos = $rawPos->subtract(0, 1.62, 0)->round(4); if($this->forceMoveSync && $hasMoved){ $curPos = $this->player->getLocation(); From 540f088edaaa24adb604d165ebcfbd7ed2c51f1d Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 1 Sep 2023 20:51:45 +0100 Subject: [PATCH 34/48] tools/generate-bedrock-data-from-packets: make duplicate reporting less spammy --- tools/generate-bedrock-data-from-packets.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tools/generate-bedrock-data-from-packets.php b/tools/generate-bedrock-data-from-packets.php index a8ea6554b..ab8a28ced 100644 --- a/tools/generate-bedrock-data-from-packets.php +++ b/tools/generate-bedrock-data-from-packets.php @@ -440,17 +440,22 @@ class ParserPacketHandler extends PacketHandler{ //how the data is ordered doesn't matter as long as it's reproducible foreach($recipes as $_type => $entries){ $_sortedRecipes = []; + $_seen = []; foreach($entries as $entry){ $entry = self::sort($entry); $_key = json_encode($entry); - while(isset($_sortedRecipes[$_key])){ - echo "warning: duplicated $_type recipe: $_key\n"; - $_key .= "a"; - } - $_sortedRecipes[$_key] = $entry; + $duplicates = $_seen[$_key] ??= 0; + $_seen[$_key]++; + $suffix = chr(ord("a") + $duplicates); + $_sortedRecipes[$_key . $suffix] = $entry; } ksort($_sortedRecipes, SORT_STRING); $recipes[$_type] = array_values($_sortedRecipes); + foreach($_seen as $_key => $_seenCount){ + if($_seenCount > 1){ + fwrite(STDERR, "warning: $_type recipe $_key was seen $_seenCount times\n"); + } + } } ksort($recipes, SORT_STRING); From ce044783952d17f273f003fb9b2a89a23365719e Mon Sep 17 00:00:00 2001 From: Jonathan B <45127993+Crasher508@users.noreply.github.com> Date: Wed, 6 Sep 2023 09:15:27 +0200 Subject: [PATCH 35/48] Fix SmithingTableInventory size (#6035) Since 1.20 SmithingTable has a new Template slot, size is now 3 Fix debug error from InventoryManager --- src/block/inventory/SmithingTableInventory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/block/inventory/SmithingTableInventory.php b/src/block/inventory/SmithingTableInventory.php index a01b80cad..2f67ac9d2 100644 --- a/src/block/inventory/SmithingTableInventory.php +++ b/src/block/inventory/SmithingTableInventory.php @@ -32,6 +32,6 @@ final class SmithingTableInventory extends SimpleInventory implements BlockInven public function __construct(Position $holder){ $this->holder = $holder; - parent::__construct(2); + parent::__construct(3); } } From a91ca999feede9bb05195ee3baf886efceafab42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 08:32:33 +0100 Subject: [PATCH 36/48] Bump actions/checkout from 3 to 4 (#6032) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docker-image.yml | 2 +- .github/workflows/discord-release-notify.yml | 2 +- .github/workflows/draft-release.yml | 2 +- .github/workflows/main.yml | 10 +++++----- .github/workflows/update-updater-api.yml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index c6a5a8ed2..fefc06c0a 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -28,7 +28,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Clone pmmp/PocketMine-Docker repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: pmmp/PocketMine-Docker fetch-depth: 1 diff --git a/.github/workflows/discord-release-notify.yml b/.github/workflows/discord-release-notify.yml index a8282f542..a74922938 100644 --- a/.github/workflows/discord-release-notify.yml +++ b/.github/workflows/discord-release-notify.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup PHP and tools uses: shivammathur/setup-php@2.25.5 diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index 7dc9f08b1..4cf78f57e 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -15,7 +15,7 @@ jobs: php-version: [8.1] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 022e0ab3a..81a0eeb78 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,7 @@ jobs: php: ["8.1", "8.2"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup PHP uses: pmmp/setup-php-action@2.0.0 @@ -52,7 +52,7 @@ jobs: php: ["8.1", "8.2"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup PHP uses: pmmp/setup-php-action@2.0.0 @@ -87,7 +87,7 @@ jobs: php: ["8.1", "8.2"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true @@ -124,7 +124,7 @@ jobs: php: ["8.1", "8.2"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup PHP uses: pmmp/setup-php-action@2.0.0 @@ -170,7 +170,7 @@ jobs: fail-fast: false steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup PHP and tools uses: shivammathur/setup-php@2.25.5 diff --git a/.github/workflows/update-updater-api.yml b/.github/workflows/update-updater-api.yml index 7a695306b..3f42062fd 100644 --- a/.github/workflows/update-updater-api.yml +++ b/.github/workflows/update-updater-api.yml @@ -14,7 +14,7 @@ jobs: - name: Install jq run: sudo apt update && sudo apt install jq -y - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: ${{ github.repository_owner }}/update.pmmp.io ssh-key: ${{ secrets.UPDATE_PMMP_IO_DEPLOY_KEY }} From 0920c76a35952505f67d75e4f12dab7b96da013e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 08:37:05 +0100 Subject: [PATCH 37/48] Bump build/php from `8884039` to `3331f8c` (#6031) Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `8884039` to `3331f8c`. - [Release notes](https://github.com/pmmp/php-build-scripts/releases) - [Commits](https://github.com/pmmp/php-build-scripts/compare/8884039bee1db64acca83edd57ed5e25d69287b9...3331f8c0d50075eee250ac4b3a8517a12186137a) --- updated-dependencies: - dependency-name: build/php dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build/php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/php b/build/php index 8884039be..3331f8c0d 160000 --- a/build/php +++ b/build/php @@ -1 +1 @@ -Subproject commit 8884039bee1db64acca83edd57ed5e25d69287b9 +Subproject commit 3331f8c0d50075eee250ac4b3a8517a12186137a From a7c806d54975c675e971296c79615d642c6e1d06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:24:23 +0100 Subject: [PATCH 38/48] Bump phpunit/phpunit from 10.3.2 to 10.3.3 (#6033) Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.3.2 to 10.3.3. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.3.3/ChangeLog-10.3.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.3.2...10.3.3) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- composer.lock | 75 ++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/composer.lock b/composer.lock index c864786f3..0c348da81 100644 --- a/composer.lock +++ b/composer.lock @@ -1541,16 +1541,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "10.1.3", + "version": "10.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "be1fe461fdc917de2a29a452ccf2657d325b443d" + "reference": "cd59bb34756a16ca8253ce9b2909039c227fff71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/be1fe461fdc917de2a29a452ccf2657d325b443d", - "reference": "be1fe461fdc917de2a29a452ccf2657d325b443d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/cd59bb34756a16ca8253ce9b2909039c227fff71", + "reference": "cd59bb34756a16ca8253ce9b2909039c227fff71", "shasum": "" }, "require": { @@ -1607,7 +1607,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.3" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.4" }, "funding": [ { @@ -1615,20 +1615,20 @@ "type": "github" } ], - "time": "2023-07-26T13:45:28+00:00" + "time": "2023-08-31T14:04:38+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "4.0.2", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "5647d65443818959172645e7ed999217360654b6" + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/5647d65443818959172645e7ed999217360654b6", - "reference": "5647d65443818959172645e7ed999217360654b6", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { @@ -1668,7 +1668,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.2" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" }, "funding": [ { @@ -1676,7 +1676,7 @@ "type": "github" } ], - "time": "2023-05-07T09:13:23+00:00" + "time": "2023-08-31T06:24:48+00:00" }, { "name": "phpunit/php-invoker", @@ -1743,16 +1743,16 @@ }, { "name": "phpunit/php-text-template", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d" + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/9f3d3709577a527025f55bcf0f7ab8052c8bb37d", - "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { @@ -1790,7 +1790,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" }, "funding": [ { @@ -1798,7 +1799,7 @@ "type": "github" } ], - "time": "2023-02-03T06:56:46+00:00" + "time": "2023-08-31T14:07:24+00:00" }, { "name": "phpunit/php-timer", @@ -1861,16 +1862,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.3.2", + "version": "10.3.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1" + "reference": "241ed4dd0db1c096984e62d414c4e1ac8d5dbff4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0dafb1175c366dd274eaa9a625e914451506bcd1", - "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/241ed4dd0db1c096984e62d414c4e1ac8d5dbff4", + "reference": "241ed4dd0db1c096984e62d414c4e1ac8d5dbff4", "shasum": "" }, "require": { @@ -1942,7 +1943,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.2" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.3" }, "funding": [ { @@ -1958,7 +1959,7 @@ "type": "tidelift" } ], - "time": "2023-08-15T05:34:23+00:00" + "time": "2023-09-05T04:34:51+00:00" }, { "name": "sebastian/cli-parser", @@ -2206,16 +2207,16 @@ }, { "name": "sebastian/complexity", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6" + "reference": "c70b73893e10757af9c6a48929fa6a333b56a97a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/e67d240970c9dc7ea7b2123a6d520e334dd61dc6", - "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c70b73893e10757af9c6a48929fa6a333b56a97a", + "reference": "c70b73893e10757af9c6a48929fa6a333b56a97a", "shasum": "" }, "require": { @@ -2251,7 +2252,8 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.1" }, "funding": [ { @@ -2259,7 +2261,7 @@ "type": "github" } ], - "time": "2023-02-03T06:59:47+00:00" + "time": "2023-08-31T09:55:53+00:00" }, { "name": "sebastian/diff", @@ -2533,16 +2535,16 @@ }, { "name": "sebastian/lines-of-code", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130" + "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/17c4d940ecafb3d15d2cf916f4108f664e28b130", - "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d", + "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d", "shasum": "" }, "require": { @@ -2578,7 +2580,8 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.0" + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1" }, "funding": [ { @@ -2586,7 +2589,7 @@ "type": "github" } ], - "time": "2023-02-03T07:08:02+00:00" + "time": "2023-08-31T09:25:50+00:00" }, { "name": "sebastian/object-enumerator", From 67f399b238afa06091f8bd72759f052b728b55e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:24:41 +0100 Subject: [PATCH 39/48] Bump phpstan/phpstan-phpunit from 1.3.13 to 1.3.14 (#6021) Bumps [phpstan/phpstan-phpunit](https://github.com/phpstan/phpstan-phpunit) from 1.3.13 to 1.3.14. - [Release notes](https://github.com/phpstan/phpstan-phpunit/releases) - [Commits](https://github.com/phpstan/phpstan-phpunit/compare/1.3.13...1.3.14) --- updated-dependencies: - dependency-name: phpstan/phpstan-phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- composer.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index 0c348da81..9e3fedec8 100644 --- a/composer.lock +++ b/composer.lock @@ -1440,16 +1440,16 @@ }, { "name": "phpstan/phpstan-phpunit", - "version": "1.3.13", + "version": "1.3.14", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5" + "reference": "614acc10c522e319639bf38b0698a4a566665f04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/d8bdab0218c5eb0964338d24a8511b65e9c94fa5", - "reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/614acc10c522e319639bf38b0698a4a566665f04", + "reference": "614acc10c522e319639bf38b0698a4a566665f04", "shasum": "" }, "require": { @@ -1462,7 +1462,7 @@ "require-dev": { "nikic/php-parser": "^4.13.0", "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-strict-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.5.1", "phpunit/phpunit": "^9.5" }, "type": "phpstan-extension", @@ -1486,9 +1486,9 @@ "description": "PHPUnit extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.13" + "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.14" }, - "time": "2023-05-26T11:05:59+00:00" + "time": "2023-08-25T09:46:39+00:00" }, { "name": "phpstan/phpstan-strict-rules", From a0c7587b68c0dade28834dd824de0408b25a806d Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 6 Sep 2023 11:09:28 +0100 Subject: [PATCH 40/48] Update composer dependencies --- composer.lock | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/composer.lock b/composer.lock index 9e3fedec8..52700d9fd 100644 --- a/composer.lock +++ b/composer.lock @@ -200,16 +200,16 @@ }, { "name": "pocketmine/bedrock-protocol", - "version": "23.0.3+bedrock-1.20.10", + "version": "23.0.4+bedrock-1.20.10", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockProtocol.git", - "reference": "e4157c7af3f91e1b08fe21be171eb73dad7029e9" + "reference": "ae0d8f4d49506674b7ff622f7c81ce241dc49adb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/e4157c7af3f91e1b08fe21be171eb73dad7029e9", - "reference": "e4157c7af3f91e1b08fe21be171eb73dad7029e9", + "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/ae0d8f4d49506674b7ff622f7c81ce241dc49adb", + "reference": "ae0d8f4d49506674b7ff622f7c81ce241dc49adb", "shasum": "" }, "require": { @@ -223,7 +223,7 @@ "ramsey/uuid": "^4.1" }, "require-dev": { - "phpstan/phpstan": "1.10.7", + "phpstan/phpstan": "1.10.33", "phpstan/phpstan-phpunit": "^1.0.0", "phpstan/phpstan-strict-rules": "^1.0.0", "phpunit/phpunit": "^9.5" @@ -241,9 +241,9 @@ "description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP", "support": { "issues": "https://github.com/pmmp/BedrockProtocol/issues", - "source": "https://github.com/pmmp/BedrockProtocol/tree/23.0.3+bedrock-1.20.10" + "source": "https://github.com/pmmp/BedrockProtocol/tree/23.0.4+bedrock-1.20.10" }, - "time": "2023-08-03T15:30:52+00:00" + "time": "2023-09-06T07:36:44+00:00" }, { "name": "pocketmine/binaryutils", @@ -985,16 +985,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", "shasum": "" }, "require": { @@ -1009,7 +1009,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1047,7 +1047,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" }, "funding": [ { @@ -1063,20 +1063,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "42292d99c55abe617799667f454222c54c60e229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", "shasum": "" }, "require": { @@ -1091,7 +1091,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1130,7 +1130,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" }, "funding": [ { @@ -1146,7 +1146,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-07-28T09:04:16+00:00" } ], "packages-dev": [ @@ -2963,5 +2963,5 @@ "platform-overrides": { "php": "8.1.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From 690ee4c574e6d696103780ebef42b30b701c82d5 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 6 Sep 2023 11:24:08 +0100 Subject: [PATCH 41/48] CrashDump: fixed empty elements in lastError trace as shown by #6010 --- src/crash/CrashDump.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crash/CrashDump.php b/src/crash/CrashDump.php index ded1e5d88..741a88ca6 100644 --- a/src/crash/CrashDump.php +++ b/src/crash/CrashDump.php @@ -206,6 +206,7 @@ class CrashDump{ if(isset($lastError)){ $this->data->lastError = $lastError; $this->data->lastError["message"] = mb_scrub($this->data->lastError["message"], 'UTF-8'); + $this->data->lastError["trace"] = array_map(array: $lastError["trace"], callback: fn(ThreadCrashInfoFrame $frame) => $frame->getPrintableFrame()); } $this->data->error = $error; From b160b87e249c05de684e291f609572a1ad3cbee7 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 6 Sep 2023 11:34:03 +0100 Subject: [PATCH 42/48] Server: stop discriminating against crashes caused by folder plugins these are the de facto standard, which means that a lot of crashes aren't getting reported from servers with folder plugins. --- src/Server.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Server.php b/src/Server.php index 148c93b8e..fb8a2bb6e 100644 --- a/src/Server.php +++ b/src/Server.php @@ -80,7 +80,6 @@ use pocketmine\player\PlayerDataProvider; use pocketmine\player\PlayerDataSaveException; use pocketmine\player\PlayerInfo; use pocketmine\plugin\PharPluginLoader; -use pocketmine\plugin\Plugin; use pocketmine\plugin\PluginEnableOrder; use pocketmine\plugin\PluginGraylist; use pocketmine\plugin\PluginManager; @@ -1606,15 +1605,6 @@ class Server{ } @touch($stamp); //update file timestamp - $plugin = $dump->getData()->plugin; - if($plugin !== ""){ - $p = $this->pluginManager->getPlugin($plugin); - if($p instanceof Plugin && !($p->getPluginLoader() instanceof PharPluginLoader)){ - $this->logger->debug("Not sending crashdump due to caused by non-phar plugin"); - $report = false; - } - } - if($dump->getData()->error["type"] === \ParseError::class){ $report = false; } From 6aab07debdb235adeb3df76c6cbca7be96699007 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 6 Sep 2023 11:53:01 +0100 Subject: [PATCH 43/48] Release 5.4.4 --- changelogs/5.4.md | 12 ++++++++++++ src/VersionInfo.php | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/changelogs/5.4.md b/changelogs/5.4.md index 7dd95a657..43f609620 100644 --- a/changelogs/5.4.md +++ b/changelogs/5.4.md @@ -119,3 +119,15 @@ Released 21st August 2023. - Fixed `PotionCauldron::setPotionItem()` not validating the item type. - Fixed chorus fruit not considering teleport destinations below y=0. - Fixed cake dropping itself when mined. + +# 5.4.4 +Released 6th September 2023. + +## General +- Crashdumps caused by non-phar plugins are now submitted to the Crash Archive, the same as other plugins. Previously, non-phar plugin crashes would not be submitted, causing maintainers to potentially miss important issues. + +## Fixes +- Fixed player Y coordinates sometimes being slightly below the top of the block they were standing on (floating point error due to subtracting eye height). +- Fixed template slot of smithing tables not accepting any items. +- `tools/generate-bedrock-data-from-packets.php` is now significantly less spammy when warning about duplicated recipes. +- Fixed empty stack traces in `lastError` data of crashdumps. diff --git a/src/VersionInfo.php b/src/VersionInfo.php index c9109487b..80828048d 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -32,7 +32,7 @@ use function str_repeat; final class VersionInfo{ public const NAME = "PocketMine-MP"; public const BASE_VERSION = "5.4.4"; - public const IS_DEVELOPMENT_BUILD = true; + public const IS_DEVELOPMENT_BUILD = false; public const BUILD_CHANNEL = "stable"; /** From 73a44d50eeac48dbebd913f9c52312f7f7b56439 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 6 Sep 2023 11:53:04 +0100 Subject: [PATCH 44/48] 5.4.5 is next --- src/VersionInfo.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VersionInfo.php b/src/VersionInfo.php index 80828048d..c523d3d95 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -31,8 +31,8 @@ use function str_repeat; final class VersionInfo{ public const NAME = "PocketMine-MP"; - public const BASE_VERSION = "5.4.4"; - public const IS_DEVELOPMENT_BUILD = false; + public const BASE_VERSION = "5.4.5"; + public const IS_DEVELOPMENT_BUILD = true; public const BUILD_CHANNEL = "stable"; /** From ec1cd5967dc0e4eab1a6bcb263b1f798df47fc66 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 6 Sep 2023 12:12:11 +0100 Subject: [PATCH 45/48] Added private constructors for new internal classes --- build/generate-pocketmine-yml-property-consts.php | 9 +++++++++ src/ServerProperties.php | 4 ++++ src/YmlServerProperties.php | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/build/generate-pocketmine-yml-property-consts.php b/build/generate-pocketmine-yml-property-consts.php index 90342a75f..dcc574f8a 100644 --- a/build/generate-pocketmine-yml-property-consts.php +++ b/build/generate-pocketmine-yml-property-consts.php @@ -101,6 +101,15 @@ fwrite($file, <<<'DOC' DOC ); fwrite($file, "final class YmlServerProperties{\n"); +fwrite($file, <<<'CONSTRUCTOR' + + private function __construct(){ + //NOOP + } + + +CONSTRUCTOR +); foreach(Utils::stringifyKeys($constants) as $constName => $propertyName){ fwrite($file, "\tpublic const $constName = '$propertyName';\n"); } diff --git a/src/ServerProperties.php b/src/ServerProperties.php index aad26d242..ddbbd8134 100644 --- a/src/ServerProperties.php +++ b/src/ServerProperties.php @@ -29,6 +29,10 @@ namespace pocketmine; */ final class ServerProperties{ + private function __construct(){ + //NOOP + } + public const AUTO_SAVE = "auto-save"; public const DEFAULT_WORLD_GENERATOR = "level-type"; public const DEFAULT_WORLD_GENERATOR_SETTINGS = "generator-settings"; diff --git a/src/YmlServerProperties.php b/src/YmlServerProperties.php index 7d088b13c..9bd203eef 100644 --- a/src/YmlServerProperties.php +++ b/src/YmlServerProperties.php @@ -30,6 +30,11 @@ namespace pocketmine; * Do not edit this file manually. */ final class YmlServerProperties{ + + private function __construct(){ + //NOOP + } + public const ALIASES = 'aliases'; public const ANONYMOUS_STATISTICS = 'anonymous-statistics'; public const ANONYMOUS_STATISTICS_ENABLED = 'anonymous-statistics.enabled'; From c8d357f4eb360b632df47a0c7ec93ddb1a89a995 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 6 Sep 2023 12:13:26 +0100 Subject: [PATCH 46/48] Release 5.5.0 --- changelogs/5.5.md | 162 ++++++++++++++++++++++++++++++++++++++++++++ src/VersionInfo.php | 6 +- 2 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 changelogs/5.5.md diff --git a/changelogs/5.5.md b/changelogs/5.5.md new file mode 100644 index 000000000..750e21129 --- /dev/null +++ b/changelogs/5.5.md @@ -0,0 +1,162 @@ +# 5.5.0 +Released 6th September 2023. + +**For Minecraft: Bedrock Edition 1.20.10** + +This is a minor feature release, including performance improvements, new API methods, and new gameplay features. + +**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace. +Do not update plugin minimum API versions unless you need new features added in this release. + +**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.** +Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly. + +## Dependencies +- Updated `pocketmine/math` dependency to [`1.0.0`](https://github.com/pmmp/Math/releases/tag/1.0.0). +- Updated `pocketmine/nbt` dependency to [`1.0.0`](https://github.com/pmmp/NBT/releases/tag/1.0.0). + +## Performance +- Some events are now no longer fired if no handlers are registered. + - This improves performance by avoiding unnecessary object allocations and function calls. + - Events such as `DataPacketReceiveEvent`, `DataPacketSendEvent` and `PlayerMoveEvent` are optimized away almost completely by this change, offering some much-needed performance gains. +- Significantly improved performance of small moving entities, such as dropped items. + - This was achieved by a combination of changes, which together improved observed performance with 2000 item entities moving in water by 30-40%. + - The benefit of this will be most noticeable in SkyBlock servers, where large cactus farms can generate thousands of dropped items. +- `World->getCollisionBoxes()` now uses an improved search method, which reduces the work done by the function by almost 90% for small entities. + - This improves performance of collision detection for small entities, such as dropped items. + +## Gameplay +### General +- Implemented enchanting using an enchanting table (yes, finally!) + - Thanks to [@S3v3Nice](https://github.com/S3v3Nice) for investing lots of time and effort into developing this. + - Since this feature is quite complex, it's possible there may be bugs. Please be vigilant and report any issues you find. + +### Blocks +- The following new blocks have been implemented: + - Pink Petals +- Pressure plates are now functional, in the sense that they react when entities stand on them and perform the correct logic. + - Note that since redstone is not yet implemented, pressure plates do not activate any redstone devices, similar to buttons and levers. +- Signs can now be edited by right-clicking them. +- Signs can now be waxed using a honeycomb, which prevents them from being edited. + +### Items +- The following new items have been implemented: + - Enchanted Book + +## API +### `pocketmine\block` +- The following new API methods have been added: + - `public Block->getEnchantmentTags() : list` returns a list of strings indicating which types of enchantment can be applied to the block when in item form + - `public BlockTypeInfo->getEnchantmentTags() : list` + - `protected PressurePlate->getActivationBox() : AxisAlignedBB` - returns the AABB entities must intersect with in order to activate the pressure plate (not the same as the visual shape) + - `protected PressurePlate->hasOutputSignal() : bool` - returns whether the pressure plate has an output signal - this should be implemented by subclasses + - `protected PressurePlate->calculatePlateState() : array{Block, ?bool}` - returns the state the pressure plate will change to if the given list of entities are standing on it, and a bool indicating whether the plate activated or deactivated this tick + - `protected PressurePlate->filterIrrelevantEntities(list $entities) : list` - returns the given list filtered of entities that don't affect the plate's state (e.g. dropped items don't affect stone pressure plates) + - `public BaseSign->isWaxed() : bool` + - `public BaseSign->setWaxed(bool $waxed) : $this` + - `public inventory\EnchantInventory->getInput() : Item` + - `public inventory\EnchantInventory->getLapis() : Item` + - `public inventory\EnchantInventory->getOutput(int $optionId) : ?Item` - returns the item that would be produced if the input item was enchanted with the selected option, or `null` if the option is invalid + - `public inventory\EnchantInventory->getOption(int $optionId) : EnchantOption` - returns the enchanting option at the given index +- The following API methods have signature changes: + - `BlockTypeInfo->__construct()` now accepts an optional `list $enchantmentTags` parameter + - `PressurePlate->__construct()` now accepts an optional `int $deactivationDelayTicks` parameter + - `WeightedPressurePlate->__construct()` now accepts optional `int $deactivationDelayTicks` and `float $signalStrengthFactor` parameters + - `SimplePressurePlate->__construct()` now accepts an optional `int $deactivationDelayTicks` parameter +- The following new classes have been added: + - `PinkPetals` + - `utils\BlockEventHelper` - provides helper methods for calling block-related events +- The following classes have been deprecated: + - `WeightedPressurePlateLight` + - `WeightedPressurePlateHeavy` + +### `pocketmine\entity` +- The following new API methods have been added: + - `public Human->getEnchantmentSeed() : int` - returns the current seed used to randomize options shown on the enchanting table for this human + - `public Human->setEnchantmentSeed(int $seed) : void` + - `public Human->regenerateEnchantmentSeed() : void` - returns a new randomly generated seed which can be set with `setEnchantmentSeed()` + +### `pocketmine\event` +- The following new classes have been added: + - `block\FarmlandHydrationChangeEvent` - called when farmland is hydrated or dehydrated + - `block\PressurePlateUpdateEvent` - called when a pressure plate is activated or changes its power output + - `player\PlayerEnchantingOptionsRequestEvent` - called when a player puts an item to be enchanted into an enchanting table, to allow plugins to modify the enchanting options shown + - `player\PlayerItemEnchantEvent` - called when a player enchants an item in an enchanting table + - `world\WorldDifficultyChangeEvent` - called when a world's difficulty is changed +- The following new API methods have been added: + - `public static Event::hasHandlers() : bool` - returns whether the event class has any registered handlers - used like `SomeEvent::hasHandlers()` + - `public HandlerListManager->getHandlersFor(class-string $event) : list` - returns a list of all registered listeners for the given event class, using cache if available + +### `pocketmine\inventory\transaction` +- The following new classes have been added: + - `EnchantingTransaction` - used when a player enchants an item in an enchanting table + +### `pocketmine\item` +- The following new API methods have been added: + - `public Armor->getMaterial() : ArmorMaterial` - returns an object containing properties shared by all items of the same armor material + - `public ArmorTypeInfo->getMaterial() : ArmorMaterial` + - `public Item->getEnchantability() : int` - returns the enchantability value of the item - higher values increase the chance of more powerful enchantments being offered by an enchanting table + - `public Item->getEnchantmentTags() : list` - returns a list of strings indicating which types of enchantment can be applied to the item + - `public ToolTier->getEnchantability() : int` +- The following API methods have signature changes: + - `Item->__construct()` now accepts an optional `list $enchantmentTags` parameter + - `ArmorTypeInfo->__construct()` now accepts an optional `?ArmorMaterial $material` parameter +- The following new classes have been added: + - `ArmorMaterial` - container for shared armor properties + - `VanillaArmorMaterials` - all vanilla armor materials + - `EnchantedBook` - represents an enchanted book item + +### `pocketmine\item\enchantment` +- The following new classes have been added: + - `AvailableEnchantmentRegistry` - enchantments to be displayed on the enchanting table are selected from here - custom enchantments may be added + - `EnchantingHelper` - static class containing various helper methods for enchanting tables + - `EnchantingOption` - represents an option on the enchanting table menu + - `IncompatibleEnchantmentGroups` - list of constants naming groups of enchantments that are incompatible with each other - custom enchantments may be added using these group names to make them incompatible with existing enchantments in the same group + - `IncompatibleEnchantmentRegistry` - manages which enchantments are considered incompatible with each other - custom enchantments may be added using existing group names to make them incompatible with existing enchantments in the same group, or to entirely new groups + - `ItemEnchantmentTagRegistry` - manages item enchantment compatibility tags and which tags include which other tags + - `ItemEnchantmentTags` - list of constants naming item types for enchantment compatibility checks +- The following classes have been deprecated + - `ItemFlags` +- The following API methods have been added: + - `public Enchantment->isCompatibleWith(Enchantment $other) : bool` + - `public Enchantment->getMinEnchantingPower()` - returns the minimum enchanting power (derived from enchantability and number of bookshelves) needed to allow this enchantment to show on the enchanting table with a given level + - `public Enchantment->getMaxEnchantingPower()` - upper limit of enchanting power for this enchantment to be offered on the enchanting table with a given level +- The following API methods have signature changes: + - `Enchantment->__construct()` now accepts optional `(\Closure(int $level) : int)|null $minEnchantingPower` and `int $enchantingPowerRange` parameters + - `Enchantment->__construct()` parameters `$primaryItemFlags` and `$secondaryItemFlags` are now deprecated and no longer used + - `ProtectionEnchantment->__construct()` has extra parameters to reflect `Enchantment->__construct()` changes +- The following API methods have been deprecated: + - `Enchantment->getPrimaryItemFlags()` - use API methods provided by `AvailableEnchantmentRegistry` instead + - `Enchantment->getSecondaryItemFlags()` - use API methods provided by `AvailableEnchantmentRegistry` instead + - `Enchantment->hasPrimaryItemType()` + - `Enchantment->hasSecondaryItemType()` + +### `pocketmine\plugin` +- The following new API methods have been added: + - `public PluginBase->getResourcePath(string $filename) : string` - returns a URI to an embedded resource file that can be used with `file_get_contents()` and similar functions + - `public PluginBase->getResourceFolder() : string` - returns a URI to the plugin's folder of embedded resources +- The following API methods have been deprecated: + - `PluginBase->getResource()` - prefer using `getResourcePath()` with `file_get_contents()` or other PHP built-in functions instead + +### `pocketmine\resourcepacks` +- The following new API methods have been added: + - `public ResourcePackManager->setResourcePacksRequired(bool $value) : void` - sets whether players must accept resource packs in order to join + +### `pocketmine\world\generator` +- The following new API methods have been added: + - `public GeneratorManager->addAlias(string $name, string $alias) : void` - allows registering a generator alias without copying the generator registration parameters + +### `pocketmine\world\sound` +- The following new classes have been added: +- `PressurePlateActivateSound` +- `PressurePlateDeactivateSound` + +### `pocketmine\utils` +- The following new API methods have been added: + - `public StringToTParser->registerAlias(string $existing, string $alias) : void` - allows registering a string alias without copying registration parameters + +## Internals +- Various `TypeIdMap` classes in the `pocketmine\data\bedrock` package now use the new `IntSaveIdMapTrait` to reduce code duplication. +- Added a new `ServerProperties` class containing constants for all known `server.properties` keys. +- Added a new `YmlServerProperties` class containing generated constants for all known `pocketmine.yml` keys. These keys can be used with `Config->getNested()`. + diff --git a/src/VersionInfo.php b/src/VersionInfo.php index f792fe0a4..2037c5d06 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -31,9 +31,9 @@ use function str_repeat; final class VersionInfo{ public const NAME = "PocketMine-MP"; - public const BASE_VERSION = "5.5.0-BETA2"; - public const IS_DEVELOPMENT_BUILD = true; - public const BUILD_CHANNEL = "beta"; + public const BASE_VERSION = "5.5.0"; + public const IS_DEVELOPMENT_BUILD = false; + public const BUILD_CHANNEL = "stable"; /** * PocketMine-MP-specific version ID for world data. Used to determine what fixes need to be applied to old world From 79acc4fed4930b43bbd6e0ae3d692dc05c1d577e Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 6 Sep 2023 12:13:26 +0100 Subject: [PATCH 47/48] 5.5.1 is next --- src/VersionInfo.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VersionInfo.php b/src/VersionInfo.php index 2037c5d06..18f03233d 100644 --- a/src/VersionInfo.php +++ b/src/VersionInfo.php @@ -31,8 +31,8 @@ use function str_repeat; final class VersionInfo{ public const NAME = "PocketMine-MP"; - public const BASE_VERSION = "5.5.0"; - public const IS_DEVELOPMENT_BUILD = false; + public const BASE_VERSION = "5.5.1"; + public const IS_DEVELOPMENT_BUILD = true; public const BUILD_CHANNEL = "stable"; /** From fe94379a937b8a194b3cdf820cd7d890c213878b Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 6 Sep 2023 12:56:47 +0100 Subject: [PATCH 48/48] Fixed connection requirements for fences, glass, bars and walls these connect to the back faces of stairs and to glass, for example. --- src/block/Fence.php | 2 +- src/block/Thin.php | 2 +- src/block/Wall.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/block/Fence.php b/src/block/Fence.php index 7180b38ea..b57e81ded 100644 --- a/src/block/Fence.php +++ b/src/block/Fence.php @@ -42,7 +42,7 @@ class Fence extends Transparent{ foreach(Facing::HORIZONTAL as $facing){ $block = $this->getSide($facing); - if($block instanceof static || $block instanceof FenceGate || ($block->isSolid() && !$block->isTransparent())){ + if($block instanceof static || $block instanceof FenceGate || $block->getSupportType(Facing::opposite($facing))->equals(SupportType::FULL())){ $this->connections[$facing] = true; }else{ unset($this->connections[$facing]); diff --git a/src/block/Thin.php b/src/block/Thin.php index 8de39f4ea..2b89b4bee 100644 --- a/src/block/Thin.php +++ b/src/block/Thin.php @@ -41,7 +41,7 @@ class Thin extends Transparent{ foreach(Facing::HORIZONTAL as $facing){ $side = $this->getSide($facing); - if($side instanceof Thin || $side instanceof Wall || $side->isFullCube()){ + if($side instanceof Thin || $side instanceof Wall || $side->getSupportType(Facing::opposite($facing))->equals(SupportType::FULL())){ $this->connections[$facing] = true; }else{ unset($this->connections[$facing]); diff --git a/src/block/Wall.php b/src/block/Wall.php index 30584c92b..87ee0b1bd 100644 --- a/src/block/Wall.php +++ b/src/block/Wall.php @@ -101,7 +101,7 @@ class Wall extends Transparent{ foreach(Facing::HORIZONTAL as $facing){ $block = $this->getSide($facing); - if($block instanceof static || $block instanceof FenceGate || $block instanceof Thin || ($block->isSolid() && !$block->isTransparent())){ + if($block instanceof static || $block instanceof FenceGate || $block instanceof Thin || $block->getSupportType(Facing::opposite($facing))->equals(SupportType::FULL())){ if(!isset($this->connections[$facing])){ $this->connections[$facing] = WallConnectionType::SHORT(); $changed++;