From f9bcc8e8628be68f16bb301ff0af2f17c441f31a Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 7 Jan 2023 16:19:02 +0000 Subject: [PATCH 01/31] NetworkSession: added a rate-limit for incoming batches --- src/network/mcpe/NetworkSession.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 188b2fcae..47e63c37c 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -132,6 +132,7 @@ use function get_class; use function in_array; use function json_encode; use function ksort; +use function min; use function strcasecmp; use function strlen; use function strtolower; @@ -142,6 +143,19 @@ use const JSON_THROW_ON_ERROR; use const SORT_NUMERIC; class NetworkSession{ + private const INCOMING_PACKET_BATCH_PER_TICK = 2; //we should normally see only 1 per tick - 2 allows recovery of the budget after a lag spike + private const INCOMING_PACKET_BATCH_MAX_BUDGET = 100; //enough to account for a 5-second lag spike + + /** + * At most this many more packets can be received. If this reaches zero, any additional packets received will cause + * the player to be kicked from the server. + * This number is increased every tick up to a maximum limit. + * + * @see self::INCOMING_PACKET_BATCH_PER_TICK + * @see self::INCOMING_PACKET_BATCH_MAX_BUDGET + */ + private int $incomingPacketBatchBudget = self::INCOMING_PACKET_BATCH_MAX_BUDGET; + private \PrefixedLogger $logger; private ?Player $player = null; private ?PlayerInfo $info = null; @@ -339,6 +353,11 @@ class NetworkSession{ return; } + if($this->incomingPacketBatchBudget <= 0){ + throw new PacketHandlingException("Receiving packets too fast"); + } + $this->incomingPacketBatchBudget--; + if($this->cipher !== null){ Timings::$playerNetworkReceiveDecrypt->startTiming(); try{ @@ -1129,5 +1148,6 @@ class NetworkSession{ } $this->flushSendBuffer(); + $this->incomingPacketBatchBudget = min($this->incomingPacketBatchBudget + self::INCOMING_PACKET_BATCH_PER_TICK, self::INCOMING_PACKET_BATCH_MAX_BUDGET); } } From eb06535ed1d9c70cb295e26ba5c6912b08c7ce38 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 7 Jan 2023 16:22:01 +0000 Subject: [PATCH 02/31] Release 4.12.6 --- changelogs/4.12.md | 6 ++++++ src/VersionInfo.php | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/changelogs/4.12.md b/changelogs/4.12.md index 16e23dc6a..065c9c5dc 100644 --- a/changelogs/4.12.md +++ b/changelogs/4.12.md @@ -50,3 +50,9 @@ Released 6th January 2023. ## Fixes - Removed a workaround for an old client bug in custom form responses. The code contained a denial-of-service vulnerability. + +# 4.12.6 +Released 7th January 2023. + +## Changes +- Added a new security measure to `NetworkSession` to detect and ban players who flood the server with packets. \ No newline at end of file diff --git a/src/VersionInfo.php b/src/VersionInfo.php index 384a63ae7..88adf1a38 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.12.6"; - public const IS_DEVELOPMENT_BUILD = true; + public const IS_DEVELOPMENT_BUILD = false; public const BUILD_CHANNEL = "stable"; private function __construct(){ From 653178c1fde0f69ade544c3b47afdb447ab1dddb Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 7 Jan 2023 16:22:01 +0000 Subject: [PATCH 03/31] 4.12.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 88adf1a38..317f0b5e6 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.12.6"; - public const IS_DEVELOPMENT_BUILD = false; + public const BASE_VERSION = "4.12.7"; + public const IS_DEVELOPMENT_BUILD = true; public const BUILD_CHANNEL = "stable"; private function __construct(){ From 91e38d1f9729b67f030450795bec79d20ebd3b9f Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 7 Jan 2023 21:33:34 +0000 Subject: [PATCH 04/31] NetworkSession: compensate for server lag in batch budgeting --- src/network/mcpe/NetworkSession.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 47e63c37c..cbeab346a 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -193,6 +193,8 @@ class NetworkSession{ */ private ObjectSet $disposeHooks; + private int $lastUpdateTimeNs; + public function __construct( private Server $server, private NetworkSessionManager $manager, @@ -213,6 +215,7 @@ class NetworkSession{ $this->disposeHooks = new ObjectSet(); $this->connectTime = time(); + $this->lastUpdateTimeNs = hrtime(true); $this->setHandler(new SessionStartPacketHandler( $this->server, @@ -1127,6 +1130,10 @@ class NetworkSession{ } public function tick() : void{ + $nowNs = hrtime(true); + $timeSinceLastUpdateNs = $nowNs - $this->lastUpdateTimeNs; + $this->lastUpdateTimeNs = $nowNs; + if($this->info === null){ if(time() >= $this->connectTime + 10){ $this->disconnect("Login timeout"); @@ -1148,6 +1155,15 @@ class NetworkSession{ } $this->flushSendBuffer(); - $this->incomingPacketBatchBudget = min($this->incomingPacketBatchBudget + self::INCOMING_PACKET_BATCH_PER_TICK, self::INCOMING_PACKET_BATCH_MAX_BUDGET); + $ticksSinceLastUpdate = intdiv($timeSinceLastUpdateNs, 50_000_000); + if($ticksSinceLastUpdate > 0){ + if($ticksSinceLastUpdate > 1){ + $this->logger->debug("Adding packet budget for $ticksSinceLastUpdate ticks (current budget is $this->incomingPacketBatchBudget)"); + } + $this->incomingPacketBatchBudget = min( + $this->incomingPacketBatchBudget + (self::INCOMING_PACKET_BATCH_PER_TICK * $ticksSinceLastUpdate), + self::INCOMING_PACKET_BATCH_MAX_BUDGET + ); + } } } From 6cecd690b22997ee1573beff907f137081d5adcc Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 7 Jan 2023 21:33:53 +0000 Subject: [PATCH 05/31] CS --- src/network/mcpe/NetworkSession.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index cbeab346a..9682b1f02 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -129,7 +129,9 @@ use function base64_encode; use function bin2hex; use function count; use function get_class; +use function hrtime; use function in_array; +use function intdiv; use function json_encode; use function ksort; use function min; From 1c96e7936c2049bb91257b0a93b8e88a65607708 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 8 Jan 2023 16:20:05 +0000 Subject: [PATCH 06/31] Remove dead translation code we don't translate raw string parameters anywhere else these days, so there's no reason to do so here either. The parameters array is already reduced to string[] by this point anyway. --- src/network/mcpe/NetworkSession.php | 3 --- src/network/mcpe/handler/DeathPacketHandler.php | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 0962e607f..f064731b2 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -937,9 +937,6 @@ class NetworkSession{ $language = $this->player->getLanguage(); $parameters = array_map(fn(string|Translatable $p) => $p instanceof Translatable ? $language->translate($p) : $p, $message->getParameters()); if(!$this->server->isLanguageForced()){ - foreach($parameters as $i => $p){ - $parameters[$i] = $language->translateString($p, [], "pocketmine."); - } $this->sendDataPacket(TextPacket::translation($language->translateString($message->getText(), $parameters, "pocketmine."), $parameters)); }else{ $this->sendDataPacket(TextPacket::raw($language->translateString($message->getText(), $parameters))); diff --git a/src/network/mcpe/handler/DeathPacketHandler.php b/src/network/mcpe/handler/DeathPacketHandler.php index 43deec463..dd8e78af8 100644 --- a/src/network/mcpe/handler/DeathPacketHandler.php +++ b/src/network/mcpe/handler/DeathPacketHandler.php @@ -56,9 +56,6 @@ class DeathPacketHandler extends PacketHandler{ $language = $this->player->getLanguage(); $parameters = array_map(fn(string|Translatable $p) => $p instanceof Translatable ? $language->translate($p) : $p, $this->deathMessage->getParameters()); if(!$this->player->getServer()->isLanguageForced()){ - foreach($parameters as $i => $p){ - $parameters[$i] = $language->translateString($p, [], "pocketmine."); - } $message = $language->translateString($this->deathMessage->getText(), $parameters, "pocketmine."); }else{ $message = $language->translateString($this->deathMessage->getText(), $parameters); From 4a3d9f8f83e971b5b19d6caa3b68b6cac91c32a9 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 8 Jan 2023 16:45:57 +0000 Subject: [PATCH 07/31] Make client-aware translation handling more coherent I have no clear idea why this was still using translateString(), since it's entirely unnecessary when we aren't selectively translating. --- src/network/mcpe/NetworkSession.php | 4 ++-- src/network/mcpe/handler/DeathPacketHandler.php | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index f064731b2..ca4ad258a 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -935,11 +935,11 @@ class NetworkSession{ if($message instanceof Translatable){ //we can't send nested translations to the client, so make sure they are always pre-translated by the server $language = $this->player->getLanguage(); - $parameters = array_map(fn(string|Translatable $p) => $p instanceof Translatable ? $language->translate($p) : $p, $message->getParameters()); if(!$this->server->isLanguageForced()){ + $parameters = array_map(fn(string|Translatable $p) => $p instanceof Translatable ? $language->translate($p) : $p, $message->getParameters()); $this->sendDataPacket(TextPacket::translation($language->translateString($message->getText(), $parameters, "pocketmine."), $parameters)); }else{ - $this->sendDataPacket(TextPacket::raw($language->translateString($message->getText(), $parameters))); + $this->sendDataPacket(TextPacket::raw($language->translate($message))); } }else{ $this->sendDataPacket(TextPacket::raw($message)); diff --git a/src/network/mcpe/handler/DeathPacketHandler.php b/src/network/mcpe/handler/DeathPacketHandler.php index dd8e78af8..f1d887100 100644 --- a/src/network/mcpe/handler/DeathPacketHandler.php +++ b/src/network/mcpe/handler/DeathPacketHandler.php @@ -54,12 +54,11 @@ class DeathPacketHandler extends PacketHandler{ if($this->deathMessage instanceof Translatable){ //we can't send nested translations to the client, so make sure they are always pre-translated by the server $language = $this->player->getLanguage(); - $parameters = array_map(fn(string|Translatable $p) => $p instanceof Translatable ? $language->translate($p) : $p, $this->deathMessage->getParameters()); if(!$this->player->getServer()->isLanguageForced()){ + $parameters = array_map(fn(string|Translatable $p) => $p instanceof Translatable ? $language->translate($p) : $p, $this->deathMessage->getParameters()); $message = $language->translateString($this->deathMessage->getText(), $parameters, "pocketmine."); }else{ - $message = $language->translateString($this->deathMessage->getText(), $parameters); - $parameters = []; + $message = $language->translate($this->deathMessage); } }else{ $message = $this->deathMessage; From d4b8c47a65958cc047aa248847961dbf959ef18b Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 8 Jan 2023 16:46:25 +0000 Subject: [PATCH 08/31] Language: document poorly-named function parseTranslation() --- src/lang/Language.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/lang/Language.php b/src/lang/Language.php index 3cfb5d566..301376364 100644 --- a/src/lang/Language.php +++ b/src/lang/Language.php @@ -183,6 +183,19 @@ class Language{ return $this->lang; } + /** + * Replaces translation keys embedded inside a string with their raw values. + * Embedded translation keys must be prefixed by a "%" character. + * + * This is used to allow the "text" field of a Translatable to contain formatting (e.g. colour codes) and + * multiple embedded translation keys. + * + * Normal translations whose "text" is just a single translation key don't need to use this method, and can be + * processed via get() directly. + * + * @param string|null $onlyPrefix If non-null, only translation keys with this prefix will be replaced. This is + * used to allow a client to do its own translating of vanilla strings. + */ protected function parseTranslation(string $text, ?string $onlyPrefix = null) : string{ $newString = ""; From 267032cff996971d78e3a594903f103b849a2daa Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 8 Jan 2023 19:31:39 +0000 Subject: [PATCH 09/31] NetworkSession: do not rate limit packets if a debugging session is active --- src/network/mcpe/NetworkSession.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 9682b1f02..97528c819 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -358,10 +358,12 @@ class NetworkSession{ return; } - if($this->incomingPacketBatchBudget <= 0){ - throw new PacketHandlingException("Receiving packets too fast"); + if(!function_exists('xdebug_is_debugger_active') || !xdebug_is_debugger_active()){ + if($this->incomingPacketBatchBudget <= 0){ + throw new PacketHandlingException("Receiving packets too fast"); + } + $this->incomingPacketBatchBudget--; } - $this->incomingPacketBatchBudget--; if($this->cipher !== null){ Timings::$playerNetworkReceiveDecrypt->startTiming(); From dd355c58d860a398d877bf96f476eb7db0db1a36 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 8 Jan 2023 19:35:43 +0000 Subject: [PATCH 10/31] NetworkSession: fix CS --- src/network/mcpe/NetworkSession.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 97528c819..3faf24720 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -128,6 +128,7 @@ use function array_values; use function base64_encode; use function bin2hex; use function count; +use function function_exists; use function get_class; use function hrtime; use function in_array; @@ -141,6 +142,7 @@ use function strtolower; use function substr; use function time; use function ucfirst; +use function xdebug_is_debugger_active; use const JSON_THROW_ON_ERROR; use const SORT_NUMERIC; From 0233e74f4fddaceb47036cc8d7e232d6f3b3a773 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 8 Jan 2023 19:45:14 +0000 Subject: [PATCH 11/31] NetworkSession: micro optimisation - do not check if a debugger is active unless the packet limit is exceeded --- src/network/mcpe/NetworkSession.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 3faf24720..ee95d6122 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -360,12 +360,16 @@ class NetworkSession{ return; } - if(!function_exists('xdebug_is_debugger_active') || !xdebug_is_debugger_active()){ - if($this->incomingPacketBatchBudget <= 0){ + if($this->incomingPacketBatchBudget <= 0){ + if(!function_exists('xdebug_is_debugger_active') || !xdebug_is_debugger_active()){ throw new PacketHandlingException("Receiving packets too fast"); + }else{ + //when a debugging session is active, the server may halt at any point for an indefinite length of time, + //in which time the client will continue to send packets + $this->incomingPacketBatchBudget = self::INCOMING_PACKET_BATCH_MAX_BUDGET; } - $this->incomingPacketBatchBudget--; } + $this->incomingPacketBatchBudget--; if($this->cipher !== null){ Timings::$playerNetworkReceiveDecrypt->startTiming(); From 52b6f1a492de260556852763c33d7bb5812fa793 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 8 Jan 2023 20:23:15 +0000 Subject: [PATCH 12/31] Release 4.12.7 --- changelogs/4.12.md | 9 ++++++++- src/VersionInfo.php | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/4.12.md b/changelogs/4.12.md index 065c9c5dc..77f30f554 100644 --- a/changelogs/4.12.md +++ b/changelogs/4.12.md @@ -55,4 +55,11 @@ Released 6th January 2023. Released 7th January 2023. ## Changes -- Added a new security measure to `NetworkSession` to detect and ban players who flood the server with packets. \ No newline at end of file +- Added a new security measure to `NetworkSession` to detect and ban players who flood the server with packets. + +# 4.12.7 +Released 8th January 2023. + +## Fixes +- Fixed players getting kicked when the server lags for too long. +- Fixed players getting kicked when a debugging session is active and a breakpoint is hit. \ No newline at end of file diff --git a/src/VersionInfo.php b/src/VersionInfo.php index 317f0b5e6..65b86da3b 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.12.7"; - public const IS_DEVELOPMENT_BUILD = true; + public const IS_DEVELOPMENT_BUILD = false; public const BUILD_CHANNEL = "stable"; private function __construct(){ From fc77b14760b3abcf58a02ce2cafa74d57558fd98 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 8 Jan 2023 20:23:18 +0000 Subject: [PATCH 13/31] 4.12.8 is next --- src/VersionInfo.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VersionInfo.php b/src/VersionInfo.php index 65b86da3b..94294157a 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.12.7"; - public const IS_DEVELOPMENT_BUILD = false; + public const BASE_VERSION = "4.12.8"; + public const IS_DEVELOPMENT_BUILD = true; public const BUILD_CHANNEL = "stable"; private function __construct(){ From 81ca0c8fbf2e9ef6f52976f586b6a77bbfc64be0 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 8 Jan 2023 20:56:12 +0000 Subject: [PATCH 14/31] Language: do not parse translations if the text was a plain key this unintentionally allowed translations to reference other translations 1 level deep, which is not desired behaviour. This also improves performance for the cases where formatting isn't used. --- src/lang/Language.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/lang/Language.php b/src/lang/Language.php index 301376364..d6e2b2214 100644 --- a/src/lang/Language.php +++ b/src/lang/Language.php @@ -144,8 +144,10 @@ class Language{ * @param (float|int|string|Translatable)[] $params */ public function translateString(string $str, array $params = [], ?string $onlyPrefix = null) : string{ - $baseText = $this->get($str); - $baseText = $this->parseTranslation(($onlyPrefix === null || str_starts_with($str, $onlyPrefix)) ? $baseText : $str, $onlyPrefix); + $baseText = ($onlyPrefix === null || str_starts_with($str, $onlyPrefix)) ? $this->internalGet($str) : null; + if($baseText === null){ //key not found, embedded inside format string, or doesn't match prefix + $baseText = $this->parseTranslation($str, $onlyPrefix); + } foreach($params as $i => $p){ $replacement = $p instanceof Translatable ? $this->translate($p) : (string) $p; @@ -157,7 +159,9 @@ class Language{ public function translate(Translatable $c) : string{ $baseText = $this->internalGet($c->getText()); - $baseText = $this->parseTranslation($baseText ?? $c->getText()); + if($baseText === null){ //key not found or embedded inside format string + $baseText = $this->parseTranslation($c->getText()); + } foreach($c->getParameters() as $i => $p){ $replacement = $p instanceof Translatable ? $this->translate($p) : $p; From d2eddf9d3346bb30bbd4ff1c1c7b15f165c84b32 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 8 Jan 2023 20:56:51 +0000 Subject: [PATCH 15/31] relocate comments --- src/network/mcpe/NetworkSession.php | 2 +- src/network/mcpe/handler/DeathPacketHandler.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index ca4ad258a..7d5c4cbd3 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -933,9 +933,9 @@ class NetworkSession{ public function onChatMessage(Translatable|string $message) : void{ if($message instanceof Translatable){ - //we can't send nested translations to the client, so make sure they are always pre-translated by the server $language = $this->player->getLanguage(); if(!$this->server->isLanguageForced()){ + //we can't send nested translations to the client, so make sure they are always pre-translated by the server $parameters = array_map(fn(string|Translatable $p) => $p instanceof Translatable ? $language->translate($p) : $p, $message->getParameters()); $this->sendDataPacket(TextPacket::translation($language->translateString($message->getText(), $parameters, "pocketmine."), $parameters)); }else{ diff --git a/src/network/mcpe/handler/DeathPacketHandler.php b/src/network/mcpe/handler/DeathPacketHandler.php index f1d887100..6347d8f65 100644 --- a/src/network/mcpe/handler/DeathPacketHandler.php +++ b/src/network/mcpe/handler/DeathPacketHandler.php @@ -52,9 +52,9 @@ class DeathPacketHandler extends PacketHandler{ /** @var string[] $parameters */ $parameters = []; if($this->deathMessage instanceof Translatable){ - //we can't send nested translations to the client, so make sure they are always pre-translated by the server $language = $this->player->getLanguage(); if(!$this->player->getServer()->isLanguageForced()){ + //we can't send nested translations to the client, so make sure they are always pre-translated by the server $parameters = array_map(fn(string|Translatable $p) => $p instanceof Translatable ? $language->translate($p) : $p, $this->deathMessage->getParameters()); $message = $language->translateString($this->deathMessage->getText(), $parameters, "pocketmine."); }else{ From bb3f87f862781bdb55b946b99476521e14294eb6 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 9 Jan 2023 00:00:39 +0000 Subject: [PATCH 16/31] NetworkSession: allow 2 batches per tick apparently InventoryTransactionPacket may arrive outside of the normal update cycle, since it's prioritized to reduce latency. --- src/network/mcpe/NetworkSession.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index ee95d6122..7e8ca2dd8 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -147,7 +147,7 @@ use const JSON_THROW_ON_ERROR; use const SORT_NUMERIC; class NetworkSession{ - private const INCOMING_PACKET_BATCH_PER_TICK = 2; //we should normally see only 1 per tick - 2 allows recovery of the budget after a lag spike + private const INCOMING_PACKET_BATCH_PER_TICK = 2; //usually max 1 per tick, but transactions may arrive separately private const INCOMING_PACKET_BATCH_MAX_BUDGET = 100; //enough to account for a 5-second lag spike /** @@ -1171,7 +1171,7 @@ class NetworkSession{ $this->logger->debug("Adding packet budget for $ticksSinceLastUpdate ticks (current budget is $this->incomingPacketBatchBudget)"); } $this->incomingPacketBatchBudget = min( - $this->incomingPacketBatchBudget + (self::INCOMING_PACKET_BATCH_PER_TICK * $ticksSinceLastUpdate), + $this->incomingPacketBatchBudget + (self::INCOMING_PACKET_BATCH_PER_TICK * 2 * $ticksSinceLastUpdate), self::INCOMING_PACKET_BATCH_MAX_BUDGET ); } From 992cb06da61ca76f4b3958a210a421c61ed047d8 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 9 Jan 2023 00:01:56 +0000 Subject: [PATCH 17/31] NetworkSession: fixed rate limit not being increased correctly on Windows due to the 15ms scheduler interval, the server will often sleep 45ms instead of 50ms, which causes the budget not to get updated. --- src/network/mcpe/NetworkSession.php | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 7e8ca2dd8..be2158f55 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -159,6 +159,7 @@ class NetworkSession{ * @see self::INCOMING_PACKET_BATCH_MAX_BUDGET */ private int $incomingPacketBatchBudget = self::INCOMING_PACKET_BATCH_MAX_BUDGET; + private int $lastPacketBudgetUpdateTimeNs; private \PrefixedLogger $logger; private ?Player $player = null; @@ -197,8 +198,6 @@ class NetworkSession{ */ private ObjectSet $disposeHooks; - private int $lastUpdateTimeNs; - public function __construct( private Server $server, private NetworkSessionManager $manager, @@ -219,7 +218,7 @@ class NetworkSession{ $this->disposeHooks = new ObjectSet(); $this->connectTime = time(); - $this->lastUpdateTimeNs = hrtime(true); + $this->lastPacketBudgetUpdateTimeNs = hrtime(true); $this->setHandler(new SessionStartPacketHandler( $this->server, @@ -1140,10 +1139,6 @@ class NetworkSession{ } public function tick() : void{ - $nowNs = hrtime(true); - $timeSinceLastUpdateNs = $nowNs - $this->lastUpdateTimeNs; - $this->lastUpdateTimeNs = $nowNs; - if($this->info === null){ if(time() >= $this->connectTime + 10){ $this->disconnect("Login timeout"); @@ -1165,15 +1160,16 @@ class NetworkSession{ } $this->flushSendBuffer(); - $ticksSinceLastUpdate = intdiv($timeSinceLastUpdateNs, 50_000_000); - if($ticksSinceLastUpdate > 0){ - if($ticksSinceLastUpdate > 1){ - $this->logger->debug("Adding packet budget for $ticksSinceLastUpdate ticks (current budget is $this->incomingPacketBatchBudget)"); - } + + $nowNs = hrtime(true); + $timeSinceLastUpdateNs = $nowNs - $this->lastPacketBudgetUpdateTimeNs; + if($timeSinceLastUpdateNs > 50_000_000){ + $ticksSinceLastUpdate = intdiv($timeSinceLastUpdateNs, 50_000_000); $this->incomingPacketBatchBudget = min( $this->incomingPacketBatchBudget + (self::INCOMING_PACKET_BATCH_PER_TICK * 2 * $ticksSinceLastUpdate), self::INCOMING_PACKET_BATCH_MAX_BUDGET ); + $this->lastPacketBudgetUpdateTimeNs = $nowNs; } } } From bb7df60a4d6a26bffefa9fc5547a10b68bde0750 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 9 Jan 2023 00:04:40 +0000 Subject: [PATCH 18/31] Release 4.12.8 --- changelogs/4.12.md | 9 ++++++++- src/VersionInfo.php | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/4.12.md b/changelogs/4.12.md index 77f30f554..ab233e6ca 100644 --- a/changelogs/4.12.md +++ b/changelogs/4.12.md @@ -62,4 +62,11 @@ Released 8th January 2023. ## Fixes - Fixed players getting kicked when the server lags for too long. -- Fixed players getting kicked when a debugging session is active and a breakpoint is hit. \ No newline at end of file +- Fixed players getting kicked when a debugging session is active and a breakpoint is hit. + +# 4.12.8 +Released 9th January 2023. + +## Fixes +- Fixed players getting kicked during PvP. +- Fixed players randomly getting kicked on Windows (improper rate limit handling wrt. 15ms timer resolution). \ No newline at end of file diff --git a/src/VersionInfo.php b/src/VersionInfo.php index 94294157a..a7346a476 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.12.8"; - public const IS_DEVELOPMENT_BUILD = true; + public const IS_DEVELOPMENT_BUILD = false; public const BUILD_CHANNEL = "stable"; private function __construct(){ From f7930a3a0b742120f6fa7d1464ce05618cf1aa15 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 9 Jan 2023 00:04:40 +0000 Subject: [PATCH 19/31] 4.12.9 is next --- src/VersionInfo.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VersionInfo.php b/src/VersionInfo.php index a7346a476..90e4b50d0 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.12.8"; - public const IS_DEVELOPMENT_BUILD = false; + public const BASE_VERSION = "4.12.9"; + public const IS_DEVELOPMENT_BUILD = true; public const BUILD_CHANNEL = "stable"; private function __construct(){ From 5021096bdd3cd99f824bfe701a320363b7e35e60 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 9 Jan 2023 20:46:57 +0000 Subject: [PATCH 20/31] Fixed walls and thin blocks not connecting to each other closes #5498 --- src/block/Thin.php | 2 +- src/block/Wall.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/block/Thin.php b/src/block/Thin.php index f6e41d43a..d480d43bb 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->isFullCube()){ + if($side instanceof Thin || $side instanceof Wall || $side->isFullCube()){ $this->connections[$facing] = true; }else{ unset($this->connections[$facing]); diff --git a/src/block/Wall.php b/src/block/Wall.php index 6860337b9..8a31d4816 100644 --- a/src/block/Wall.php +++ b/src/block/Wall.php @@ -39,7 +39,7 @@ class Wall 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 instanceof Thin || ($block->isSolid() && !$block->isTransparent())){ $this->connections[$facing] = $facing; }else{ unset($this->connections[$facing]); From a47aa50477e6a60c4eeaec7f185c1bffdaae103b Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 12 Jan 2023 18:59:18 +0000 Subject: [PATCH 21/31] Update composer dependencies --- composer.json | 2 +- composer.lock | 127 +++++++++++++++++++++++++++----------------------- 2 files changed, 70 insertions(+), 59 deletions(-) diff --git a/composer.json b/composer.json index 68a22e7f1..0e1db9747 100644 --- a/composer.json +++ b/composer.json @@ -54,7 +54,7 @@ "webmozart/path-util": "^2.3" }, "require-dev": { - "phpstan/phpstan": "1.9.7", + "phpstan/phpstan": "1.9.10", "phpstan/phpstan-phpunit": "^1.1.0", "phpstan/phpstan-strict-rules": "^1.2.0", "phpunit/phpunit": "^9.2" diff --git a/composer.lock b/composer.lock index a2f6c207e..025337ad8 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": "76c6b5521d8f88d9070e8dec1c0ae144", + "content-hash": "14f22331e4a45935b2b2134031eaa47e", "packages": [ { "name": "adhocore/json-comment", @@ -852,42 +852,53 @@ }, { "name": "ramsey/collection", - "version": "1.2.2", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a" + "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/cccc74ee5e328031b15640b51056ee8d3bb66c0a", - "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a", + "url": "https://api.github.com/repos/ramsey/collection/zipball/ad7475d1c9e70b190ecffc58f2d989416af339b4", + "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4", "shasum": "" }, "require": { - "php": "^7.3 || ^8", + "php": "^7.4 || ^8.0", "symfony/polyfill-php81": "^1.23" }, "require-dev": { - "captainhook/captainhook": "^5.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "ergebnis/composer-normalize": "^2.6", - "fakerphp/faker": "^1.5", - "hamcrest/hamcrest-php": "^2", - "jangregor/phpstan-prophecy": "^0.8", - "mockery/mockery": "^1.3", + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.28.3", + "fakerphp/faker": "^1.21", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^1.0", + "mockery/mockery": "^1.5", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcsstandards/phpcsutils": "^1.0.0-rc1", "phpspec/prophecy-phpunit": "^2.0", - "phpstan/extension-installer": "^1", - "phpstan/phpstan": "^0.12.32", - "phpstan/phpstan-mockery": "^0.12.5", - "phpstan/phpstan-phpunit": "^0.12.11", - "phpunit/phpunit": "^8.5 || ^9", - "psy/psysh": "^0.10.4", - "slevomat/coding-standard": "^6.3", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.4" + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18.4", + "ramsey/coding-standard": "^2.0.3", + "ramsey/conventional-commits": "^1.3", + "vimeo/psalm": "^5.4" }, "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, "autoload": { "psr-4": { "Ramsey\\Collection\\": "src/" @@ -915,7 +926,7 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/1.2.2" + "source": "https://github.com/ramsey/collection/tree/1.3.0" }, "funding": [ { @@ -927,27 +938,27 @@ "type": "tidelift" } ], - "time": "2021-10-10T03:01:02+00:00" + "time": "2022-12-27T19:12:24+00:00" }, { "name": "ramsey/uuid", - "version": "4.6.0", + "version": "4.7.3", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "ad63bc700e7d021039e30ce464eba384c4a1d40f" + "reference": "433b2014e3979047db08a17a205f410ba3869cf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/ad63bc700e7d021039e30ce464eba384c4a1d40f", - "reference": "ad63bc700e7d021039e30ce464eba384c4a1d40f", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/433b2014e3979047db08a17a205f410ba3869cf2", + "reference": "433b2014e3979047db08a17a205f410ba3869cf2", "shasum": "" }, "require": { "brick/math": "^0.8.8 || ^0.9 || ^0.10", "ext-json": "*", "php": "^8.0", - "ramsey/collection": "^1.0" + "ramsey/collection": "^1.2 || ^2.0" }, "replace": { "rhumsaa/uuid": "self.version" @@ -1007,7 +1018,7 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.6.0" + "source": "https://github.com/ramsey/uuid/tree/4.7.3" }, "funding": [ { @@ -1019,7 +1030,7 @@ "type": "tidelift" } ], - "time": "2022-11-05T23:03:38+00:00" + "time": "2023-01-12T18:13:24+00:00" }, { "name": "symfony/filesystem", @@ -1525,30 +1536,30 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.4.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9", + "doctrine/coding-standard": "^9 || ^11", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^0.16 || ^1", "phpstan/phpstan": "^1.4", "phpstan/phpstan-phpunit": "^1", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" + "vimeo/psalm": "^4.30 || ^5.4" }, "type": "library", "autoload": { @@ -1575,7 +1586,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" }, "funding": [ { @@ -1591,7 +1602,7 @@ "type": "tidelift" } ], - "time": "2022-03-03T08:28:38+00:00" + "time": "2022-12-30T00:15:36+00:00" }, { "name": "myclabs/deep-copy", @@ -1821,16 +1832,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.9.7", + "version": "1.9.10", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "0501435cd342eac7664bd62155b1ef907fc60b6f" + "reference": "5d4fe21376ba8ad66ce147fbc89e4fb4b7728de4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0501435cd342eac7664bd62155b1ef907fc60b6f", - "reference": "0501435cd342eac7664bd62155b1ef907fc60b6f", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/5d4fe21376ba8ad66ce147fbc89e4fb4b7728de4", + "reference": "5d4fe21376ba8ad66ce147fbc89e4fb4b7728de4", "shasum": "" }, "require": { @@ -1860,7 +1871,7 @@ ], "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.9.7" + "source": "https://github.com/phpstan/phpstan/tree/1.9.10" }, "funding": [ { @@ -1876,7 +1887,7 @@ "type": "tidelift" } ], - "time": "2023-01-04T21:59:57+00:00" + "time": "2023-01-12T12:57:25+00:00" }, { "name": "phpstan/phpstan-phpunit", @@ -1932,21 +1943,21 @@ }, { "name": "phpstan/phpstan-strict-rules", - "version": "1.4.4", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6" + "reference": "361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", - "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d", + "reference": "361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.8.6" + "phpstan/phpstan": "^1.9.7" }, "require-dev": { "nikic/php-parser": "^4.13.0", @@ -1974,22 +1985,22 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.4" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.5" }, - "time": "2022-09-21T11:38:17+00:00" + "time": "2023-01-11T14:16:29+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.22", + "version": "9.2.23", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "e4bf60d2220b4baaa0572986b5d69870226b06df" + "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e4bf60d2220b4baaa0572986b5d69870226b06df", - "reference": "e4bf60d2220b4baaa0572986b5d69870226b06df", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c", + "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c", "shasum": "" }, "require": { @@ -2045,7 +2056,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.22" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23" }, "funding": [ { @@ -2053,7 +2064,7 @@ "type": "github" } ], - "time": "2022-12-18T16:40:55+00:00" + "time": "2022-12-28T12:41:10+00:00" }, { "name": "phpunit/php-file-iterator", From c5056e0a4368d150d398157962f257c1aa98f70b Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 12 Jan 2023 19:01:57 +0000 Subject: [PATCH 22/31] phpstan 1.9.11 --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 0e1db9747..1b2679e71 100644 --- a/composer.json +++ b/composer.json @@ -54,7 +54,7 @@ "webmozart/path-util": "^2.3" }, "require-dev": { - "phpstan/phpstan": "1.9.10", + "phpstan/phpstan": "1.9.11", "phpstan/phpstan-phpunit": "^1.1.0", "phpstan/phpstan-strict-rules": "^1.2.0", "phpunit/phpunit": "^9.2" diff --git a/composer.lock b/composer.lock index 025337ad8..64e8d1cea 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": "14f22331e4a45935b2b2134031eaa47e", + "content-hash": "d5ea4a4f41bf80636b678e6d3d06eac0", "packages": [ { "name": "adhocore/json-comment", @@ -1832,16 +1832,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.9.10", + "version": "1.9.11", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "5d4fe21376ba8ad66ce147fbc89e4fb4b7728de4" + "reference": "60f3d68481eef216199eae7a2603cd5fe124d464" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/5d4fe21376ba8ad66ce147fbc89e4fb4b7728de4", - "reference": "5d4fe21376ba8ad66ce147fbc89e4fb4b7728de4", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/60f3d68481eef216199eae7a2603cd5fe124d464", + "reference": "60f3d68481eef216199eae7a2603cd5fe124d464", "shasum": "" }, "require": { @@ -1871,7 +1871,7 @@ ], "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.9.10" + "source": "https://github.com/phpstan/phpstan/tree/1.9.11" }, "funding": [ { @@ -1887,7 +1887,7 @@ "type": "tidelift" } ], - "time": "2023-01-12T12:57:25+00:00" + "time": "2023-01-12T14:04:13+00:00" }, { "name": "phpstan/phpstan-phpunit", From 4df1f7f5025d265d23946f0d1277a147a90f0ae7 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 12 Jan 2023 19:03:55 +0000 Subject: [PATCH 23/31] Updated composer dependencies (next-minor) --- composer.json | 6 +- composer.lock | 48 ++-- src/lang/KnownTranslationFactory.php | 345 +++++++++++++++++++++++++++ src/lang/KnownTranslationKeys.php | 83 +++++++ 4 files changed, 455 insertions(+), 27 deletions(-) diff --git a/composer.json b/composer.json index 1b2679e71..0bee48852 100644 --- a/composer.json +++ b/composer.json @@ -35,13 +35,13 @@ "fgrosse/phpasn1": "^2.3", "netresearch/jsonmapper": "^4.0", "pocketmine/bedrock-data": "~1.13.0+bedrock-1.19.50", - "pocketmine/bedrock-protocol": "~17.1.0+bedrock-1.19.50", + "pocketmine/bedrock-protocol": "~18.0.0+bedrock-1.19.50", "pocketmine/binaryutils": "^0.2.1", "pocketmine/callback-validator": "^1.0.2", "pocketmine/classloader": "^0.2.0", - "pocketmine/color": "^0.2.0", + "pocketmine/color": "^0.3.0", "pocketmine/errorhandler": "^0.6.0", - "pocketmine/locale-data": "~2.11.0", + "pocketmine/locale-data": "~2.16.0", "pocketmine/log": "^0.4.0", "pocketmine/log-pthreads": "^0.4.0", "pocketmine/math": "^0.4.0", diff --git a/composer.lock b/composer.lock index 64e8d1cea..8345acd3a 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": "d5ea4a4f41bf80636b678e6d3d06eac0", + "content-hash": "ed6e310514b168db7eef4ae5d84c8baf", "packages": [ { "name": "adhocore/json-comment", @@ -276,16 +276,16 @@ }, { "name": "pocketmine/bedrock-protocol", - "version": "17.1.0+bedrock-1.19.50", + "version": "18.0.0+bedrock-1.19.50", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockProtocol.git", - "reference": "c572706cf5e3202718dd35a35dd30fe08cd671de" + "reference": "b558ec883bd967dd3339f513cba62d2fbcd63349" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/c572706cf5e3202718dd35a35dd30fe08cd671de", - "reference": "c572706cf5e3202718dd35a35dd30fe08cd671de", + "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/b558ec883bd967dd3339f513cba62d2fbcd63349", + "reference": "b558ec883bd967dd3339f513cba62d2fbcd63349", "shasum": "" }, "require": { @@ -293,13 +293,13 @@ "netresearch/jsonmapper": "^4.0", "php": "^8.0", "pocketmine/binaryutils": "^0.2.0", - "pocketmine/color": "^0.2.0", + "pocketmine/color": "^0.2.0 || ^0.3.0", "pocketmine/math": "^0.3.0 || ^0.4.0", "pocketmine/nbt": "^0.3.0", "ramsey/uuid": "^4.1" }, "require-dev": { - "phpstan/phpstan": "1.9.3", + "phpstan/phpstan": "1.9.4", "phpstan/phpstan-phpunit": "^1.0.0", "phpstan/phpstan-strict-rules": "^1.0.0", "phpunit/phpunit": "^9.5" @@ -317,9 +317,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/17.1.0+bedrock-1.19.50" + "source": "https://github.com/pmmp/BedrockProtocol/tree/18.0.0+bedrock-1.19.50" }, - "time": "2022-12-15T20:34:49+00:00" + "time": "2023-01-06T21:47:35+00:00" }, { "name": "pocketmine/binaryutils", @@ -460,24 +460,24 @@ }, { "name": "pocketmine/color", - "version": "0.2.0", + "version": "0.3.0", "source": { "type": "git", "url": "https://github.com/pmmp/Color.git", - "reference": "09be6ea6d76f2e33d6813c39d29c22c46c17e1d2" + "reference": "8cb346d0a21ad3287cc8d7175e4b643416607249" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/Color/zipball/09be6ea6d76f2e33d6813c39d29c22c46c17e1d2", - "reference": "09be6ea6d76f2e33d6813c39d29c22c46c17e1d2", + "url": "https://api.github.com/repos/pmmp/Color/zipball/8cb346d0a21ad3287cc8d7175e4b643416607249", + "reference": "8cb346d0a21ad3287cc8d7175e4b643416607249", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^8.0" }, "require-dev": { - "phpstan/phpstan": "0.12.59", - "phpstan/phpstan-strict-rules": "^0.12.2" + "phpstan/phpstan": "1.9.4", + "phpstan/phpstan-strict-rules": "^1.2.0" }, "type": "library", "autoload": { @@ -492,9 +492,9 @@ "description": "Color handling library used by PocketMine-MP and related projects", "support": { "issues": "https://github.com/pmmp/Color/issues", - "source": "https://github.com/pmmp/Color/tree/0.2.0" + "source": "https://github.com/pmmp/Color/tree/0.3.0" }, - "time": "2020-12-11T01:24:32+00:00" + "time": "2022-12-18T19:49:21+00:00" }, { "name": "pocketmine/errorhandler", @@ -537,16 +537,16 @@ }, { "name": "pocketmine/locale-data", - "version": "2.11.0", + "version": "2.16.0", "source": { "type": "git", "url": "https://github.com/pmmp/Language.git", - "reference": "4b33d8fa53eda53d9662a7478806ebae2e4a5c53" + "reference": "b3bf9029c112414fdb7cd9de778df191565d3038" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/Language/zipball/4b33d8fa53eda53d9662a7478806ebae2e4a5c53", - "reference": "4b33d8fa53eda53d9662a7478806ebae2e4a5c53", + "url": "https://api.github.com/repos/pmmp/Language/zipball/b3bf9029c112414fdb7cd9de778df191565d3038", + "reference": "b3bf9029c112414fdb7cd9de778df191565d3038", "shasum": "" }, "type": "library", @@ -554,9 +554,9 @@ "description": "Language resources used by PocketMine-MP", "support": { "issues": "https://github.com/pmmp/Language/issues", - "source": "https://github.com/pmmp/Language/tree/2.11.0" + "source": "https://github.com/pmmp/Language/tree/2.16.0" }, - "time": "2022-11-25T14:24:34+00:00" + "time": "2023-01-04T20:27:52+00:00" }, { "name": "pocketmine/log", diff --git a/src/lang/KnownTranslationFactory.php b/src/lang/KnownTranslationFactory.php index f1db1c6d1..0a690236a 100644 --- a/src/lang/KnownTranslationFactory.php +++ b/src/lang/KnownTranslationFactory.php @@ -661,6 +661,12 @@ final class KnownTranslationFactory{ ]); } + public static function death_attack_fireworks(Translatable|string $param0) : Translatable{ + return new Translatable(KnownTranslationKeys::DEATH_ATTACK_FIREWORKS, [ + 0 => $param0, + ]); + } + public static function death_attack_generic(Translatable|string $param0) : Translatable{ return new Translatable(KnownTranslationKeys::DEATH_ATTACK_GENERIC, [ 0 => $param0, @@ -760,6 +766,10 @@ final class KnownTranslationFactory{ return new Translatable(KnownTranslationKeys::DISCONNECTIONSCREEN_INVALIDSKIN, []); } + public static function disconnectionScreen_loggedinOtherLocation() : Translatable{ + return new Translatable(KnownTranslationKeys::DISCONNECTIONSCREEN_LOGGEDINOTHERLOCATION, []); + } + public static function disconnectionScreen_noReason() : Translatable{ return new Translatable(KnownTranslationKeys::DISCONNECTIONSCREEN_NOREASON, []); } @@ -1166,6 +1176,10 @@ final class KnownTranslationFactory{ return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_DIFFICULTY_DESCRIPTION, []); } + public static function pocketmine_command_dumpmemory_description() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_DUMPMEMORY_DESCRIPTION, []); + } + public static function pocketmine_command_effect_description() : Translatable{ return new Translatable(KnownTranslationKeys::POCKETMINE_COMMAND_EFFECT_DESCRIPTION, []); } @@ -1574,6 +1588,47 @@ final class KnownTranslationFactory{ return new Translatable(KnownTranslationKeys::POCKETMINE_DEBUG_ENABLE, []); } + public static function pocketmine_disconnect_ban(Translatable|string $reason) : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_BAN, [ + "reason" => $reason, + ]); + } + + public static function pocketmine_disconnect_ban_hardcore() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_BAN_HARDCORE, []); + } + + public static function pocketmine_disconnect_ban_ip() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_BAN_IP, []); + } + + public static function pocketmine_disconnect_ban_noReason() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_BAN_NOREASON, []); + } + + public static function pocketmine_disconnect_error(Translatable|string $error, Translatable|string $errorId) : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_ERROR, [ + "error" => $error, + "errorId" => $errorId, + ]); + } + + public static function pocketmine_disconnect_error_authentication() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_ERROR_AUTHENTICATION, []); + } + + public static function pocketmine_disconnect_error_badPacket() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_ERROR_BADPACKET, []); + } + + public static function pocketmine_disconnect_error_internal() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_ERROR_INTERNAL, []); + } + + public static function pocketmine_disconnect_error_loginTimeout() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_ERROR_LOGINTIMEOUT, []); + } + public static function pocketmine_disconnect_incompatibleProtocol(Translatable|string $param0) : Translatable{ return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_INCOMPATIBLEPROTOCOL, [ 0 => $param0, @@ -1602,6 +1657,28 @@ final class KnownTranslationFactory{ return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_INVALIDSESSION_TOOLATE, []); } + public static function pocketmine_disconnect_kick(Translatable|string $reason) : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_KICK, [ + "reason" => $reason, + ]); + } + + public static function pocketmine_disconnect_kick_noReason() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_KICK_NOREASON, []); + } + + public static function pocketmine_disconnect_transfer() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_TRANSFER, []); + } + + public static function pocketmine_disconnect_whitelisted() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_WHITELISTED, []); + } + + public static function pocketmine_disconnect_xblImpersonation() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_DISCONNECT_XBLIMPERSONATION, []); + } + public static function pocketmine_level_ambiguousFormat(Translatable|string $param0) : Translatable{ return new Translatable(KnownTranslationKeys::POCKETMINE_LEVEL_AMBIGUOUSFORMAT, [ 0 => $param0, @@ -1707,6 +1784,274 @@ final class KnownTranslationFactory{ ]); } + public static function pocketmine_network_session_close(Translatable|string $reason) : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_NETWORK_SESSION_CLOSE, [ + "reason" => $reason, + ]); + } + + public static function pocketmine_network_session_open() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_NETWORK_SESSION_OPEN, []); + } + + public static function pocketmine_network_session_playerName(Translatable|string $playerName) : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_NETWORK_SESSION_PLAYERNAME, [ + "playerName" => $playerName, + ]); + } + + public static function pocketmine_permission_broadcast_admin() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_BROADCAST_ADMIN, []); + } + + public static function pocketmine_permission_broadcast_user() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_BROADCAST_USER, []); + } + + public static function pocketmine_permission_command_ban_ip() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_BAN_IP, []); + } + + public static function pocketmine_permission_command_ban_list() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_BAN_LIST, []); + } + + public static function pocketmine_permission_command_ban_player() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_BAN_PLAYER, []); + } + + public static function pocketmine_permission_command_clear_other() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_CLEAR_OTHER, []); + } + + public static function pocketmine_permission_command_clear_self() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_CLEAR_SELF, []); + } + + public static function pocketmine_permission_command_defaultgamemode() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_DEFAULTGAMEMODE, []); + } + + public static function pocketmine_permission_command_difficulty() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_DIFFICULTY, []); + } + + public static function pocketmine_permission_command_dumpmemory() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_DUMPMEMORY, []); + } + + public static function pocketmine_permission_command_effect_other() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_EFFECT_OTHER, []); + } + + public static function pocketmine_permission_command_effect_self() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_EFFECT_SELF, []); + } + + public static function pocketmine_permission_command_enchant_other() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_ENCHANT_OTHER, []); + } + + public static function pocketmine_permission_command_enchant_self() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_ENCHANT_SELF, []); + } + + public static function pocketmine_permission_command_gamemode_other() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_GAMEMODE_OTHER, []); + } + + public static function pocketmine_permission_command_gamemode_self() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_GAMEMODE_SELF, []); + } + + public static function pocketmine_permission_command_gc() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_GC, []); + } + + public static function pocketmine_permission_command_give_other() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_GIVE_OTHER, []); + } + + public static function pocketmine_permission_command_give_self() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_GIVE_SELF, []); + } + + public static function pocketmine_permission_command_help() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_HELP, []); + } + + public static function pocketmine_permission_command_kick() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_KICK, []); + } + + public static function pocketmine_permission_command_kill_other() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_KILL_OTHER, []); + } + + public static function pocketmine_permission_command_kill_self() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_KILL_SELF, []); + } + + public static function pocketmine_permission_command_list() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_LIST, []); + } + + public static function pocketmine_permission_command_me() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_ME, []); + } + + public static function pocketmine_permission_command_op_give() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_OP_GIVE, []); + } + + public static function pocketmine_permission_command_op_take() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_OP_TAKE, []); + } + + public static function pocketmine_permission_command_particle() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_PARTICLE, []); + } + + public static function pocketmine_permission_command_plugins() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_PLUGINS, []); + } + + public static function pocketmine_permission_command_save_disable() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_SAVE_DISABLE, []); + } + + public static function pocketmine_permission_command_save_enable() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_SAVE_ENABLE, []); + } + + public static function pocketmine_permission_command_save_perform() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_SAVE_PERFORM, []); + } + + public static function pocketmine_permission_command_say() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_SAY, []); + } + + public static function pocketmine_permission_command_seed() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_SEED, []); + } + + public static function pocketmine_permission_command_setworldspawn() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_SETWORLDSPAWN, []); + } + + public static function pocketmine_permission_command_spawnpoint_other() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_SPAWNPOINT_OTHER, []); + } + + public static function pocketmine_permission_command_spawnpoint_self() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_SPAWNPOINT_SELF, []); + } + + public static function pocketmine_permission_command_status() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_STATUS, []); + } + + public static function pocketmine_permission_command_stop() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_STOP, []); + } + + public static function pocketmine_permission_command_teleport_other() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TELEPORT_OTHER, []); + } + + public static function pocketmine_permission_command_teleport_self() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TELEPORT_SELF, []); + } + + public static function pocketmine_permission_command_tell() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TELL, []); + } + + public static function pocketmine_permission_command_time_add() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TIME_ADD, []); + } + + public static function pocketmine_permission_command_time_query() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TIME_QUERY, []); + } + + public static function pocketmine_permission_command_time_set() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TIME_SET, []); + } + + public static function pocketmine_permission_command_time_start() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TIME_START, []); + } + + public static function pocketmine_permission_command_time_stop() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TIME_STOP, []); + } + + public static function pocketmine_permission_command_timings() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TIMINGS, []); + } + + public static function pocketmine_permission_command_title_other() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TITLE_OTHER, []); + } + + public static function pocketmine_permission_command_title_self() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TITLE_SELF, []); + } + + public static function pocketmine_permission_command_transferserver() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_TRANSFERSERVER, []); + } + + public static function pocketmine_permission_command_unban_ip() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_UNBAN_IP, []); + } + + public static function pocketmine_permission_command_unban_player() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_UNBAN_PLAYER, []); + } + + public static function pocketmine_permission_command_version() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_VERSION, []); + } + + public static function pocketmine_permission_command_whitelist_add() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_WHITELIST_ADD, []); + } + + public static function pocketmine_permission_command_whitelist_disable() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_WHITELIST_DISABLE, []); + } + + public static function pocketmine_permission_command_whitelist_enable() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_WHITELIST_ENABLE, []); + } + + public static function pocketmine_permission_command_whitelist_list() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_WHITELIST_LIST, []); + } + + public static function pocketmine_permission_command_whitelist_reload() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_WHITELIST_RELOAD, []); + } + + public static function pocketmine_permission_command_whitelist_remove() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_COMMAND_WHITELIST_REMOVE, []); + } + + public static function pocketmine_permission_group_console() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_GROUP_CONSOLE, []); + } + + public static function pocketmine_permission_group_operator() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_GROUP_OPERATOR, []); + } + + public static function pocketmine_permission_group_user() : Translatable{ + return new Translatable(KnownTranslationKeys::POCKETMINE_PERMISSION_GROUP_USER, []); + } + public static function pocketmine_player_invalidEntity(Translatable|string $param0) : Translatable{ return new Translatable(KnownTranslationKeys::POCKETMINE_PLAYER_INVALIDENTITY, [ 0 => $param0, diff --git a/src/lang/KnownTranslationKeys.php b/src/lang/KnownTranslationKeys.php index bd98496cb..d826a5a10 100644 --- a/src/lang/KnownTranslationKeys.php +++ b/src/lang/KnownTranslationKeys.php @@ -146,6 +146,7 @@ final class KnownTranslationKeys{ public const DEATH_ATTACK_EXPLOSION_PLAYER = "death.attack.explosion.player"; public const DEATH_ATTACK_FALL = "death.attack.fall"; public const DEATH_ATTACK_FALLINGBLOCK = "death.attack.fallingBlock"; + public const DEATH_ATTACK_FIREWORKS = "death.attack.fireworks"; public const DEATH_ATTACK_GENERIC = "death.attack.generic"; public const DEATH_ATTACK_INFIRE = "death.attack.inFire"; public const DEATH_ATTACK_INWALL = "death.attack.inWall"; @@ -163,6 +164,7 @@ final class KnownTranslationKeys{ public const DEFAULT_VALUES_INFO = "default_values_info"; public const DISCONNECTIONSCREEN_INVALIDNAME = "disconnectionScreen.invalidName"; public const DISCONNECTIONSCREEN_INVALIDSKIN = "disconnectionScreen.invalidSkin"; + public const DISCONNECTIONSCREEN_LOGGEDINOTHERLOCATION = "disconnectionScreen.loggedinOtherLocation"; public const DISCONNECTIONSCREEN_NOREASON = "disconnectionScreen.noReason"; public const DISCONNECTIONSCREEN_NOTAUTHENTICATED = "disconnectionScreen.notAuthenticated"; public const DISCONNECTIONSCREEN_OUTDATEDCLIENT = "disconnectionScreen.outdatedClient"; @@ -258,6 +260,7 @@ final class KnownTranslationKeys{ public const POCKETMINE_COMMAND_DEFAULTGAMEMODE_DESCRIPTION = "pocketmine.command.defaultgamemode.description"; public const POCKETMINE_COMMAND_DEOP_DESCRIPTION = "pocketmine.command.deop.description"; public const POCKETMINE_COMMAND_DIFFICULTY_DESCRIPTION = "pocketmine.command.difficulty.description"; + public const POCKETMINE_COMMAND_DUMPMEMORY_DESCRIPTION = "pocketmine.command.dumpmemory.description"; public const POCKETMINE_COMMAND_EFFECT_DESCRIPTION = "pocketmine.command.effect.description"; public const POCKETMINE_COMMAND_ENCHANT_DESCRIPTION = "pocketmine.command.enchant.description"; public const POCKETMINE_COMMAND_ERROR_PERMISSION = "pocketmine.command.error.permission"; @@ -342,12 +345,26 @@ final class KnownTranslationKeys{ public const POCKETMINE_DATA_PLAYEROLD = "pocketmine.data.playerOld"; public const POCKETMINE_DATA_SAVEERROR = "pocketmine.data.saveError"; public const POCKETMINE_DEBUG_ENABLE = "pocketmine.debug.enable"; + public const POCKETMINE_DISCONNECT_BAN = "pocketmine.disconnect.ban"; + public const POCKETMINE_DISCONNECT_BAN_HARDCORE = "pocketmine.disconnect.ban.hardcore"; + public const POCKETMINE_DISCONNECT_BAN_IP = "pocketmine.disconnect.ban.ip"; + public const POCKETMINE_DISCONNECT_BAN_NOREASON = "pocketmine.disconnect.ban.noReason"; + public const POCKETMINE_DISCONNECT_ERROR = "pocketmine.disconnect.error"; + public const POCKETMINE_DISCONNECT_ERROR_AUTHENTICATION = "pocketmine.disconnect.error.authentication"; + public const POCKETMINE_DISCONNECT_ERROR_BADPACKET = "pocketmine.disconnect.error.badPacket"; + public const POCKETMINE_DISCONNECT_ERROR_INTERNAL = "pocketmine.disconnect.error.internal"; + public const POCKETMINE_DISCONNECT_ERROR_LOGINTIMEOUT = "pocketmine.disconnect.error.loginTimeout"; public const POCKETMINE_DISCONNECT_INCOMPATIBLEPROTOCOL = "pocketmine.disconnect.incompatibleProtocol"; public const POCKETMINE_DISCONNECT_INVALIDSESSION = "pocketmine.disconnect.invalidSession"; public const POCKETMINE_DISCONNECT_INVALIDSESSION_BADSIGNATURE = "pocketmine.disconnect.invalidSession.badSignature"; public const POCKETMINE_DISCONNECT_INVALIDSESSION_MISSINGKEY = "pocketmine.disconnect.invalidSession.missingKey"; public const POCKETMINE_DISCONNECT_INVALIDSESSION_TOOEARLY = "pocketmine.disconnect.invalidSession.tooEarly"; public const POCKETMINE_DISCONNECT_INVALIDSESSION_TOOLATE = "pocketmine.disconnect.invalidSession.tooLate"; + public const POCKETMINE_DISCONNECT_KICK = "pocketmine.disconnect.kick"; + public const POCKETMINE_DISCONNECT_KICK_NOREASON = "pocketmine.disconnect.kick.noReason"; + public const POCKETMINE_DISCONNECT_TRANSFER = "pocketmine.disconnect.transfer"; + public const POCKETMINE_DISCONNECT_WHITELISTED = "pocketmine.disconnect.whitelisted"; + public const POCKETMINE_DISCONNECT_XBLIMPERSONATION = "pocketmine.disconnect.xblImpersonation"; public const POCKETMINE_LEVEL_AMBIGUOUSFORMAT = "pocketmine.level.ambiguousFormat"; public const POCKETMINE_LEVEL_BACKGROUNDGENERATION = "pocketmine.level.backgroundGeneration"; public const POCKETMINE_LEVEL_BADDEFAULTFORMAT = "pocketmine.level.badDefaultFormat"; @@ -365,6 +382,72 @@ final class KnownTranslationKeys{ public const POCKETMINE_LEVEL_UNKNOWNGENERATOR = "pocketmine.level.unknownGenerator"; public const POCKETMINE_LEVEL_UNLOADING = "pocketmine.level.unloading"; public const POCKETMINE_LEVEL_UNSUPPORTEDFORMAT = "pocketmine.level.unsupportedFormat"; + public const POCKETMINE_NETWORK_SESSION_CLOSE = "pocketmine.network.session.close"; + public const POCKETMINE_NETWORK_SESSION_OPEN = "pocketmine.network.session.open"; + public const POCKETMINE_NETWORK_SESSION_PLAYERNAME = "pocketmine.network.session.playerName"; + public const POCKETMINE_PERMISSION_BROADCAST_ADMIN = "pocketmine.permission.broadcast.admin"; + public const POCKETMINE_PERMISSION_BROADCAST_USER = "pocketmine.permission.broadcast.user"; + public const POCKETMINE_PERMISSION_COMMAND_BAN_IP = "pocketmine.permission.command.ban.ip"; + public const POCKETMINE_PERMISSION_COMMAND_BAN_LIST = "pocketmine.permission.command.ban.list"; + public const POCKETMINE_PERMISSION_COMMAND_BAN_PLAYER = "pocketmine.permission.command.ban.player"; + public const POCKETMINE_PERMISSION_COMMAND_CLEAR_OTHER = "pocketmine.permission.command.clear.other"; + public const POCKETMINE_PERMISSION_COMMAND_CLEAR_SELF = "pocketmine.permission.command.clear.self"; + public const POCKETMINE_PERMISSION_COMMAND_DEFAULTGAMEMODE = "pocketmine.permission.command.defaultgamemode"; + public const POCKETMINE_PERMISSION_COMMAND_DIFFICULTY = "pocketmine.permission.command.difficulty"; + public const POCKETMINE_PERMISSION_COMMAND_DUMPMEMORY = "pocketmine.permission.command.dumpmemory"; + public const POCKETMINE_PERMISSION_COMMAND_EFFECT_OTHER = "pocketmine.permission.command.effect.other"; + public const POCKETMINE_PERMISSION_COMMAND_EFFECT_SELF = "pocketmine.permission.command.effect.self"; + public const POCKETMINE_PERMISSION_COMMAND_ENCHANT_OTHER = "pocketmine.permission.command.enchant.other"; + public const POCKETMINE_PERMISSION_COMMAND_ENCHANT_SELF = "pocketmine.permission.command.enchant.self"; + public const POCKETMINE_PERMISSION_COMMAND_GAMEMODE_OTHER = "pocketmine.permission.command.gamemode.other"; + public const POCKETMINE_PERMISSION_COMMAND_GAMEMODE_SELF = "pocketmine.permission.command.gamemode.self"; + public const POCKETMINE_PERMISSION_COMMAND_GC = "pocketmine.permission.command.gc"; + public const POCKETMINE_PERMISSION_COMMAND_GIVE_OTHER = "pocketmine.permission.command.give.other"; + public const POCKETMINE_PERMISSION_COMMAND_GIVE_SELF = "pocketmine.permission.command.give.self"; + public const POCKETMINE_PERMISSION_COMMAND_HELP = "pocketmine.permission.command.help"; + public const POCKETMINE_PERMISSION_COMMAND_KICK = "pocketmine.permission.command.kick"; + public const POCKETMINE_PERMISSION_COMMAND_KILL_OTHER = "pocketmine.permission.command.kill.other"; + public const POCKETMINE_PERMISSION_COMMAND_KILL_SELF = "pocketmine.permission.command.kill.self"; + public const POCKETMINE_PERMISSION_COMMAND_LIST = "pocketmine.permission.command.list"; + public const POCKETMINE_PERMISSION_COMMAND_ME = "pocketmine.permission.command.me"; + public const POCKETMINE_PERMISSION_COMMAND_OP_GIVE = "pocketmine.permission.command.op.give"; + public const POCKETMINE_PERMISSION_COMMAND_OP_TAKE = "pocketmine.permission.command.op.take"; + public const POCKETMINE_PERMISSION_COMMAND_PARTICLE = "pocketmine.permission.command.particle"; + public const POCKETMINE_PERMISSION_COMMAND_PLUGINS = "pocketmine.permission.command.plugins"; + public const POCKETMINE_PERMISSION_COMMAND_SAVE_DISABLE = "pocketmine.permission.command.save.disable"; + public const POCKETMINE_PERMISSION_COMMAND_SAVE_ENABLE = "pocketmine.permission.command.save.enable"; + public const POCKETMINE_PERMISSION_COMMAND_SAVE_PERFORM = "pocketmine.permission.command.save.perform"; + public const POCKETMINE_PERMISSION_COMMAND_SAY = "pocketmine.permission.command.say"; + public const POCKETMINE_PERMISSION_COMMAND_SEED = "pocketmine.permission.command.seed"; + public const POCKETMINE_PERMISSION_COMMAND_SETWORLDSPAWN = "pocketmine.permission.command.setworldspawn"; + public const POCKETMINE_PERMISSION_COMMAND_SPAWNPOINT_OTHER = "pocketmine.permission.command.spawnpoint.other"; + public const POCKETMINE_PERMISSION_COMMAND_SPAWNPOINT_SELF = "pocketmine.permission.command.spawnpoint.self"; + public const POCKETMINE_PERMISSION_COMMAND_STATUS = "pocketmine.permission.command.status"; + public const POCKETMINE_PERMISSION_COMMAND_STOP = "pocketmine.permission.command.stop"; + public const POCKETMINE_PERMISSION_COMMAND_TELEPORT_OTHER = "pocketmine.permission.command.teleport.other"; + public const POCKETMINE_PERMISSION_COMMAND_TELEPORT_SELF = "pocketmine.permission.command.teleport.self"; + public const POCKETMINE_PERMISSION_COMMAND_TELL = "pocketmine.permission.command.tell"; + public const POCKETMINE_PERMISSION_COMMAND_TIME_ADD = "pocketmine.permission.command.time.add"; + public const POCKETMINE_PERMISSION_COMMAND_TIME_QUERY = "pocketmine.permission.command.time.query"; + public const POCKETMINE_PERMISSION_COMMAND_TIME_SET = "pocketmine.permission.command.time.set"; + public const POCKETMINE_PERMISSION_COMMAND_TIME_START = "pocketmine.permission.command.time.start"; + public const POCKETMINE_PERMISSION_COMMAND_TIME_STOP = "pocketmine.permission.command.time.stop"; + public const POCKETMINE_PERMISSION_COMMAND_TIMINGS = "pocketmine.permission.command.timings"; + public const POCKETMINE_PERMISSION_COMMAND_TITLE_OTHER = "pocketmine.permission.command.title.other"; + public const POCKETMINE_PERMISSION_COMMAND_TITLE_SELF = "pocketmine.permission.command.title.self"; + public const POCKETMINE_PERMISSION_COMMAND_TRANSFERSERVER = "pocketmine.permission.command.transferserver"; + public const POCKETMINE_PERMISSION_COMMAND_UNBAN_IP = "pocketmine.permission.command.unban.ip"; + public const POCKETMINE_PERMISSION_COMMAND_UNBAN_PLAYER = "pocketmine.permission.command.unban.player"; + public const POCKETMINE_PERMISSION_COMMAND_VERSION = "pocketmine.permission.command.version"; + public const POCKETMINE_PERMISSION_COMMAND_WHITELIST_ADD = "pocketmine.permission.command.whitelist.add"; + public const POCKETMINE_PERMISSION_COMMAND_WHITELIST_DISABLE = "pocketmine.permission.command.whitelist.disable"; + public const POCKETMINE_PERMISSION_COMMAND_WHITELIST_ENABLE = "pocketmine.permission.command.whitelist.enable"; + public const POCKETMINE_PERMISSION_COMMAND_WHITELIST_LIST = "pocketmine.permission.command.whitelist.list"; + public const POCKETMINE_PERMISSION_COMMAND_WHITELIST_RELOAD = "pocketmine.permission.command.whitelist.reload"; + public const POCKETMINE_PERMISSION_COMMAND_WHITELIST_REMOVE = "pocketmine.permission.command.whitelist.remove"; + public const POCKETMINE_PERMISSION_GROUP_CONSOLE = "pocketmine.permission.group.console"; + public const POCKETMINE_PERMISSION_GROUP_OPERATOR = "pocketmine.permission.group.operator"; + public const POCKETMINE_PERMISSION_GROUP_USER = "pocketmine.permission.group.user"; public const POCKETMINE_PLAYER_INVALIDENTITY = "pocketmine.player.invalidEntity"; public const POCKETMINE_PLAYER_INVALIDMOVE = "pocketmine.player.invalidMove"; public const POCKETMINE_PLAYER_LOGIN = "pocketmine.player.logIn"; From 2f3fcef97c4596765873c21bb4e7d2f5c3c47f79 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 12 Jan 2023 19:36:23 +0000 Subject: [PATCH 24/31] Fixed blocks incorrectly using blockClicked for support checks this caused some interesting bugs, such as being able to place floating pressure plates by clicking on the side of a solid block halfway up a wall. --- src/block/ItemFrame.php | 2 +- src/block/PressurePlate.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/block/ItemFrame.php b/src/block/ItemFrame.php index 8df62c72f..7a224c47b 100644 --- a/src/block/ItemFrame.php +++ b/src/block/ItemFrame.php @@ -175,7 +175,7 @@ class ItemFrame extends Flowable{ } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ - if($face === Facing::DOWN || $face === Facing::UP || !$blockClicked->isSolid()){ + if($face === Facing::DOWN || $face === Facing::UP || !$blockReplace->getSide(Facing::opposite($face))->isSolid()){ return false; } diff --git a/src/block/PressurePlate.php b/src/block/PressurePlate.php index 5610b4e1a..5ad0e7873 100644 --- a/src/block/PressurePlate.php +++ b/src/block/PressurePlate.php @@ -45,7 +45,7 @@ abstract class PressurePlate extends Transparent{ } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ - if($this->canBeSupportedBy($blockClicked)){ + if($this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){ return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); } return false; From d295e1be54557c41f2629403f25ebb944d8dd830 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 12 Jan 2023 19:36:47 +0000 Subject: [PATCH 25/31] PressurePlate: destroy self when no support is present --- src/block/PressurePlate.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/block/PressurePlate.php b/src/block/PressurePlate.php index 5ad0e7873..7f9403b74 100644 --- a/src/block/PressurePlate.php +++ b/src/block/PressurePlate.php @@ -55,5 +55,11 @@ abstract class PressurePlate extends Transparent{ return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE()); } + public function onNearbyBlockChange() : void{ + if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){ + $this->position->getWorld()->useBreakOn($this->position); + } + } + //TODO } From 4e9c3e101d69fa979915ee820592d8020e0c52fa Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 12 Jan 2023 19:42:33 +0000 Subject: [PATCH 26/31] Bell: fixed blocks not being able to be placed when not ringing the bell --- src/block/Bell.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/block/Bell.php b/src/block/Bell.php index 70c78d027..4af738d59 100644 --- a/src/block/Bell.php +++ b/src/block/Bell.php @@ -161,21 +161,20 @@ final class Bell extends Transparent{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ if($player !== null){ $faceHit = Facing::opposite($player->getHorizontalFacing()); - if($this->attachmentType->equals(BellAttachmentType::CEILING())){ - $this->ring($faceHit); - } - if($this->attachmentType->equals(BellAttachmentType::FLOOR()) && Facing::axis($faceHit) === Facing::axis($this->facing)){ - $this->ring($faceHit); - } if( - ($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) || $this->attachmentType->equals(BellAttachmentType::TWO_WALLS())) && - ($faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true)) + $this->attachmentType->equals(BellAttachmentType::CEILING()) || + ($this->attachmentType->equals(BellAttachmentType::FLOOR()) && Facing::axis($faceHit) === Facing::axis($this->facing)) || + ( + ($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) || $this->attachmentType->equals(BellAttachmentType::TWO_WALLS())) && + ($faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true)) + ) ){ $this->ring($faceHit); + return true; } } - return true; + return false; } public function ring(int $faceHit) : void{ From e26c8b9e9fa3bf902be54d5511d8d9672c77d67b Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 12 Jan 2023 20:35:26 +0000 Subject: [PATCH 27/31] block: eliminate suspicious usages of $blockClicked in place() --- src/block/Button.php | 2 +- src/block/Ladder.php | 2 +- src/block/Lever.php | 2 +- src/block/Torch.php | 2 +- src/block/Vine.php | 2 +- src/block/WallCoralFan.php | 2 +- src/block/WaterLily.php | 14 ++------------ 7 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/block/Button.php b/src/block/Button.php index c447ddb8d..f86d8a579 100644 --- a/src/block/Button.php +++ b/src/block/Button.php @@ -61,7 +61,7 @@ abstract class Button extends Flowable{ } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ - if($this->canBeSupportedBy($blockClicked, $face)){ + if($this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){ $this->facing = $face; return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); } diff --git a/src/block/Ladder.php b/src/block/Ladder.php index fcf2be061..ccedb33bd 100644 --- a/src/block/Ladder.php +++ b/src/block/Ladder.php @@ -70,7 +70,7 @@ class Ladder extends Transparent{ } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ - if($this->canBeSupportedBy($blockClicked, $face) && Facing::axis($face) !== Axis::Y){ + if($this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face) && Facing::axis($face) !== Axis::Y){ $this->facing = $face; return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); } diff --git a/src/block/Lever.php b/src/block/Lever.php index beec393b7..01512007b 100644 --- a/src/block/Lever.php +++ b/src/block/Lever.php @@ -95,7 +95,7 @@ class Lever extends Flowable{ } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ - if(!$this->canBeSupportedBy($blockClicked, $face)){ + if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){ return false; } diff --git a/src/block/Torch.php b/src/block/Torch.php index ded081bcc..99975d4f6 100644 --- a/src/block/Torch.php +++ b/src/block/Torch.php @@ -77,7 +77,7 @@ class Torch extends Flowable{ if($blockClicked->canBeReplaced() && $this->canBeSupportedBy($blockClicked->getSide(Facing::DOWN), Facing::UP)){ $this->facing = Facing::UP; return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); - }elseif($face !== Facing::DOWN && $this->canBeSupportedBy($blockClicked, $face)){ + }elseif($face !== Facing::DOWN && $this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){ $this->facing = $face; return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); }else{ diff --git a/src/block/Vine.php b/src/block/Vine.php index 9159315da..80943dc7c 100644 --- a/src/block/Vine.php +++ b/src/block/Vine.php @@ -116,7 +116,7 @@ class Vine extends Flowable{ } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ - if(!$blockClicked->isFullCube() || Facing::axis($face) === Axis::Y){ + if(!$blockReplace->getSide(Facing::opposite($face))->isFullCube() || Facing::axis($face) === Axis::Y){ return false; } diff --git a/src/block/WallCoralFan.php b/src/block/WallCoralFan.php index ee0dcc35a..fe8dc40a8 100644 --- a/src/block/WallCoralFan.php +++ b/src/block/WallCoralFan.php @@ -113,7 +113,7 @@ final class WallCoralFan extends BaseCoral{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ $axis = Facing::axis($face); - if(($axis !== Axis::X && $axis !== Axis::Z) || !$this->canBeSupportedBy($blockClicked, $face)){ + if(($axis !== Axis::X && $axis !== Axis::Z) || !$this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){ return false; } $this->facing = $face; diff --git a/src/block/WaterLily.php b/src/block/WaterLily.php index 39b3c8cee..25af0a8b0 100644 --- a/src/block/WaterLily.php +++ b/src/block/WaterLily.php @@ -23,12 +23,9 @@ declare(strict_types=1); namespace pocketmine\block; -use pocketmine\item\Item; use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use pocketmine\math\Vector3; -use pocketmine\player\Player; -use pocketmine\world\BlockTransaction; class WaterLily extends Flowable{ @@ -39,15 +36,8 @@ class WaterLily extends Flowable{ return [AxisAlignedBB::one()->contract(1 / 16, 0, 1 / 16)->trim(Facing::UP, 63 / 64)]; } - public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ - if($blockClicked instanceof Water){ - $up = $blockClicked->getSide(Facing::UP); - if($up->canBeReplaced()){ - return parent::place($tx, $item, $up, $blockClicked, $face, $clickVector, $player); - } - } - - return false; + public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{ + return !$blockReplace instanceof Water && parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock); } public function onNearbyBlockChange() : void{ From a79be994de43610a0404d239ca474a828c214f9d Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 12 Jan 2023 21:11:48 +0000 Subject: [PATCH 28/31] World: fixed block placement when clicking on replaceable blocks in vanilla, it appears to behave as if the player always clicked on the up face if a block was replaced. In PM, we were still using the original face, which caused bugs when, for example, placing a button next to a wall by clicking on the side of tallgrass. The button would replace the tallgrass, but stick to the wall, instead of placing itself on the ground like vanilla expects. This may appear unusual to anyone who also happens to implement canBePlacedAt(), since the facing behaviour will be different. However, this behaviour appears to match vanilla, and even slabs (which I feared might break because of this change) work perfectly. In the future, it may be desirable to pass some other value here, such as null, to indicate that the clicked block is being replaced. However, that's a BC break and therefore outside of the scope of a stable bug fix. --- src/block/Torch.php | 5 +---- src/world/World.php | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/block/Torch.php b/src/block/Torch.php index 99975d4f6..77046867a 100644 --- a/src/block/Torch.php +++ b/src/block/Torch.php @@ -74,10 +74,7 @@ class Torch extends Flowable{ } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ - if($blockClicked->canBeReplaced() && $this->canBeSupportedBy($blockClicked->getSide(Facing::DOWN), Facing::UP)){ - $this->facing = Facing::UP; - return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); - }elseif($face !== Facing::DOWN && $this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){ + if($face !== Facing::DOWN && $this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){ $this->facing = $face; return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); }else{ diff --git a/src/world/World.php b/src/world/World.php index 09795fd2f..c9521d11d 100644 --- a/src/world/World.php +++ b/src/world/World.php @@ -58,6 +58,7 @@ use pocketmine\item\StringToItemParser; use pocketmine\item\VanillaItems; use pocketmine\lang\KnownTranslationFactory; use pocketmine\math\AxisAlignedBB; +use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\StringTag; @@ -1955,6 +1956,10 @@ class World implements ChunkManager{ if($hand->canBePlacedAt($blockClicked, $clickVector, $face, true)){ $blockReplace = $blockClicked; + //TODO: while this mimics the vanilla behaviour with replaceable blocks, we should really pass some other + //value like NULL and let place() deal with it. This will look like a bug to anyone who doesn't know about + //the vanilla behaviour. + $face = Facing::UP; $hand->position($this, $blockReplace->getPosition()->x, $blockReplace->getPosition()->y, $blockReplace->getPosition()->z); }elseif(!$hand->canBePlacedAt($blockReplace, $clickVector, $face, false)){ return false; From b25e8e26f0cf5cf16897215e7dbb654f537f561a Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 12 Jan 2023 21:31:50 +0000 Subject: [PATCH 29/31] BaseBanner: fixed incorrect support requirements --- src/block/BaseBanner.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/block/BaseBanner.php b/src/block/BaseBanner.php index 5b3f9acce..400b8a78e 100644 --- a/src/block/BaseBanner.php +++ b/src/block/BaseBanner.php @@ -112,7 +112,14 @@ abstract class BaseBanner extends Transparent{ return SupportType::NONE(); } + private function canBeSupportedBy(Block $block) : bool{ + return $block->isSolid(); + } + public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ + if(!$this->canBeSupportedBy($blockReplace->getSide($this->getSupportingFace()))){ + return false; + } if($item instanceof ItemBanner){ $this->color = $item->getColor(); $this->setPatterns($item->getPatterns()); @@ -124,7 +131,7 @@ abstract class BaseBanner extends Transparent{ abstract protected function getSupportingFace() : int; public function onNearbyBlockChange() : void{ - if($this->getSide($this->getSupportingFace())->getId() === BlockLegacyIds::AIR){ + if(!$this->canBeSupportedBy($this->getSide($this->getSupportingFace()))){ $this->position->getWorld()->useBreakOn($this->position); } } From cbeae906e1ae0f593c495c43e8d0584cfea7439c Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 12 Jan 2023 21:34:44 +0000 Subject: [PATCH 30/31] Torch: remove unused variable --- src/block/Torch.php | 1 - src/block/WaterLily.php | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/block/Torch.php b/src/block/Torch.php index 77046867a..768c21223 100644 --- a/src/block/Torch.php +++ b/src/block/Torch.php @@ -65,7 +65,6 @@ class Torch extends Flowable{ } public function onNearbyBlockChange() : void{ - $below = $this->getSide(Facing::DOWN); $face = Facing::opposite($this->facing); if(!$this->canBeSupportedBy($this->getSide($face), $this->facing)){ diff --git a/src/block/WaterLily.php b/src/block/WaterLily.php index 25af0a8b0..8263330f6 100644 --- a/src/block/WaterLily.php +++ b/src/block/WaterLily.php @@ -23,9 +23,12 @@ declare(strict_types=1); namespace pocketmine\block; +use pocketmine\item\Item; use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use pocketmine\math\Vector3; +use pocketmine\player\Player; +use pocketmine\world\BlockTransaction; class WaterLily extends Flowable{ @@ -40,8 +43,19 @@ class WaterLily extends Flowable{ return !$blockReplace instanceof Water && parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock); } + private function canBeSupportedBy(Block $block) : bool{ + return $block instanceof Water; + } + + public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ + if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){ + return false; + } + return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); + } + public function onNearbyBlockChange() : void{ - if(!($this->getSide(Facing::DOWN) instanceof Water)){ + if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){ $this->position->getWorld()->useBreakOn($this->position); } } From f4a1d690752466f22f8f4187a45054476471ebd6 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 12 Jan 2023 21:45:25 +0000 Subject: [PATCH 31/31] Bell: fixed support requirements this somehow got overlooked in the support types refactor. --- src/block/Bell.php | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/block/Bell.php b/src/block/Bell.php index 4af738d59..00a53a9be 100644 --- a/src/block/Bell.php +++ b/src/block/Bell.php @@ -114,14 +114,13 @@ final class Bell extends Transparent{ return $this; } - private function canBeSupportedBy(Block $block) : bool{ - //TODO: this isn't the actual logic, but it's the closest approximation we can support for now - return $block->isSolid(); + private function canBeSupportedBy(Block $block, int $face) : bool{ + return !$block->getSupportType($face)->equals(SupportType::NONE()); } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ if($face === Facing::UP){ - if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->down()))){ + if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->down()), Facing::UP)){ return false; } if($player !== null){ @@ -129,18 +128,18 @@ final class Bell extends Transparent{ } $this->setAttachmentType(BellAttachmentType::FLOOR()); }elseif($face === Facing::DOWN){ - if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->up()))){ + if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->up()), Facing::DOWN)){ return false; } $this->setAttachmentType(BellAttachmentType::CEILING()); }else{ $this->setFacing($face); - if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide(Facing::opposite($face))))){ + if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide(Facing::opposite($face))), $face)){ $this->setAttachmentType(BellAttachmentType::ONE_WALL()); }else{ return false; } - if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide($face)))){ + if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide($face)), Facing::opposite($face))){ $this->setAttachmentType(BellAttachmentType::TWO_WALLS()); } } @@ -149,10 +148,10 @@ final class Bell extends Transparent{ public function onNearbyBlockChange() : void{ if( - ($this->attachmentType->equals(BellAttachmentType::CEILING()) && !$this->canBeSupportedBy($this->getSide(Facing::UP))) || - ($this->attachmentType->equals(BellAttachmentType::FLOOR()) && !$this->canBeSupportedBy($this->getSide(Facing::DOWN))) || - ($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) && !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)))) || - ($this->attachmentType->equals(BellAttachmentType::TWO_WALLS()) && (!$this->canBeSupportedBy($this->getSide($this->facing)) || !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing))))) + ($this->attachmentType->equals(BellAttachmentType::CEILING()) && !$this->canBeSupportedBy($this->getSide(Facing::UP), Facing::DOWN)) || + ($this->attachmentType->equals(BellAttachmentType::FLOOR()) && !$this->canBeSupportedBy($this->getSide(Facing::DOWN), Facing::UP)) || + ($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) && !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)) || + ($this->attachmentType->equals(BellAttachmentType::TWO_WALLS()) && (!$this->canBeSupportedBy($this->getSide($this->facing), Facing::opposite($this->facing)) || !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing))) ){ $this->position->getWorld()->useBreakOn($this->position); }