From 1572b31b8d1f0cb9596c4f2c550c7be3ee94fea6 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 2 Nov 2022 15:01:55 +0000 Subject: [PATCH 1/2] FormattedCommandAlias: do not fill empty strings for missing placeholder arguments this is pretty much always going to cause unexpected behaviour, as most execute() implementations don't expect empty strings, and it can also pad the args with dummy entries, breaking argument count requirements (e.g. aliasing say and using the alias with no arguments will confuse the target command). Instead: - Drop arguments that cannot be resolved (leave them unspecified) - If they are at the end of the argument sequence, this is OK - it will behave the same as if some optional arguments weren't specified. - If they are in the middle of the argument sequence, this will generate an error - this is preferable to having the target invoked with an empty string, which might cause unexpected behaviour. fixes #5379 --- src/command/FormattedCommandAlias.php | 32 +++++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/command/FormattedCommandAlias.php b/src/command/FormattedCommandAlias.php index 21d2c0e70..6ec7b129a 100644 --- a/src/command/FormattedCommandAlias.php +++ b/src/command/FormattedCommandAlias.php @@ -28,9 +28,9 @@ use pocketmine\command\utils\InvalidCommandSyntaxException; use pocketmine\lang\KnownTranslationFactory; use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\TextFormat; -use function array_map; use function array_shift; use function count; +use function implode; use function preg_match; use function strlen; use function strpos; @@ -62,7 +62,20 @@ class FormattedCommandAlias extends Command{ foreach($this->formatStrings as $formatString){ try{ $formatArgs = CommandStringHelper::parseQuoteAware($formatString); - $commands[] = array_map(fn(string $formatArg) => $this->buildCommand($formatArg, $args), $formatArgs); + $unresolved = []; + $processedArgs = []; + foreach($formatArgs as $formatArg){ + $processedArg = $this->buildCommand($formatArg, $args); + if($processedArg === null){ + $unresolved[] = $formatArg; + }elseif(count($unresolved) !== 0){ + //unresolved args are OK only if they are at the end of the string - we can't have holes in the args list + throw new \InvalidArgumentException("Unable to resolve format arguments (" . implode(", ", $unresolved) . ") in command string \"$formatString\" due to missing arguments"); + }else{ + $processedArgs[] = $processedArg; + } + } + $commands[] = $processedArgs; }catch(\InvalidArgumentException $e){ $sender->sendMessage(TextFormat::RED . $e->getMessage()); return false; @@ -107,7 +120,7 @@ class FormattedCommandAlias extends Command{ /** * @param string[] $args */ - private function buildCommand(string $formatString, array $args) : string{ + private function buildCommand(string $formatString, array $args) : ?string{ $index = 0; while(($index = strpos($formatString, '$', $index)) !== false){ $start = $index; @@ -129,6 +142,9 @@ class FormattedCommandAlias extends Command{ } $replacement = self::buildReplacement($args, $position, $rest); + if($replacement === null){ + return null; + } $end = $index + strlen($fullPlaceholder); $formatString = substr($formatString, 0, $start) . $replacement . substr($formatString, $end); @@ -143,9 +159,9 @@ class FormattedCommandAlias extends Command{ * @param string[] $args * @phpstan-param list $args */ - private static function buildReplacement(array $args, int $position, bool $rest) : string{ - $replacement = ""; + private static function buildReplacement(array $args, int $position, bool $rest) : ?string{ if($rest && $position < count($args)){ + $replacement = ""; for($i = $position, $c = count($args); $i < $c; ++$i){ if($i !== $position){ $replacement .= " "; @@ -153,11 +169,13 @@ class FormattedCommandAlias extends Command{ $replacement .= $args[$i]; } + + return $replacement; }elseif($position < count($args)){ - $replacement .= $args[$position]; + return $args[$position]; } - return $replacement; + return null; } /** From fe982c697bec3265c4222b73fe5ed17c9ef3b1ce Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 2 Nov 2022 15:42:44 +0000 Subject: [PATCH 2/2] Durable: reset durability when overstacked items are broken this is not really defined behaviour, but it makes more sense than the current behaviour, which makes the tool unbreakable unintentionally. fixes #5378 --- src/item/Durable.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/item/Durable.php b/src/item/Durable.php index 3b04ef381..f9420503c 100644 --- a/src/item/Durable.php +++ b/src/item/Durable.php @@ -109,6 +109,7 @@ abstract class Durable extends Item{ */ protected function onBroken() : void{ $this->pop(); + $this->setDamage(0); //the stack size may be greater than 1 if overstacked by a plugin } /**