diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 9186fff93..06898f0d7 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -1260,6 +1260,28 @@ class Server{ $this->whitelist->reload(); } + /** + * @return string[] + */ + public function getCommandAliases(){ + $section = $this->getProperty("aliases"); + $result = []; + if(is_array($section)){ + foreach($section as $key => $value){ + $commands = []; + if(is_array($value)){ + $commands = $value; + }else{ + $commands[] = $value; + } + + $result[$key] = $commands; + } + } + + return $result; + } + /** * @return Server */ @@ -1435,11 +1457,12 @@ class Server{ $this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doAutoSave")), $this->getProperty("ticks-per.autosave", 6000), $this->getProperty("ticks-per.autosave", 6000)); } - $this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doLevelGC")), $this->getProperty("chunk-gc.period-in-ticks", 600), $this->getProperty("chunk-gc.period-in-ticks", 600)); + if($this->getProperty("chunk-gc.period-in-ticks", 600) > 0){ + $this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doLevelGC")), $this->getProperty("chunk-gc.period-in-ticks", 600), $this->getProperty("chunk-gc.period-in-ticks", 600)); + } $this->enablePlugins(PluginLoadOrder::POSTWORLD); - } /** @@ -1494,14 +1517,10 @@ class Server{ if($type === PluginLoadOrder::POSTWORLD){ $this->commandMap->registerServerAliases(); - $this->loadCustomPermissions(); + DefaultPermissions::registerCorePermissions(); } } - private function loadCustomPermissions(){ - DefaultPermissions::registerCorePermissions(); - } - /** * @param Plugin $plugin */ diff --git a/src/pocketmine/command/FormattedCommandAlias.php b/src/pocketmine/command/FormattedCommandAlias.php new file mode 100644 index 000000000..e70874047 --- /dev/null +++ b/src/pocketmine/command/FormattedCommandAlias.php @@ -0,0 +1,155 @@ +formatStrings = $formatStrings; + } + + public function execute(CommandSender $sender, $commandLabel, array $args){ + + $commands = []; + $result = false; + + foreach($this->formatStrings as $formatString){ + try{ + $commands[] = $this->buildCommand($formatString, $args); + }catch(\Exception $e){ + if($e instanceof \InvalidArgumentException){ + $sender->sendMessage(TextFormat::RED . $e->getMessage()); + }else{ + $sender->sendMessage(TextFormat::RED . "An internal error occurred while attempting to perform this command"); + } + return false; + } + } + + foreach($commands as $command){ + $result |= Server::getInstance()->dispatchCommand($sender, $command); + } + + return (bool) $result; + } + + /** + * @param string $formatString + * @param array $args + * + * @return string + * @throws \InvalidArgumentException + */ + private function buildCommand($formatString, array $args){ + $index = strpos($formatString, '$'); + while($index !== false){ + $start = $index; + if($index > 0 and $formatString{$start - 1} === "\\"){ + $formatString = substr($formatString, 0, $start - 1) . substr($formatString, $start); + $index = strpos($formatString, '$', $index); + continue; + } + + $required = false; + if($formatString{$index + 1} == '$'){ + $required = true; + + ++$index; + } + + ++$index; + + $argStart = $index; + + while($index < strlen($formatString) and self::inRange($formatString{$index} - 48, 0, 9)){ + ++$index; + } + + if($argStart === $index){ + throw new \InvalidArgumentException("Invalid replacement token"); + } + + $position = intval(substr($formatString, $argStart, $index)); + + if($position === 0){ + throw new \InvalidArgumentException("Invalid replacement token"); + } + + --$position; + + $rest = false; + + if($index < strlen($formatString) and $formatString{$index} === "-"){ + $rest = true; + ++$index; + } + + $end = $index; + + if($required and $position >= count($args)){ + throw new \InvalidArgumentException("Missing required argument " . ($position + 1)); + } + + $replacement = ""; + if($rest and $position < count($args)){ + for($i = $position; $i < count($args); ++$i){ + if($i !== $position){ + $replacement .= " "; + } + + $replacement .= $args[$i]; + } + }elseif($position < count($args)){ + $replacement .= $args[$position]; + } + + $formatString = substr($formatString, 0, $start) . $replacement . substr($formatString, $end); + + $index = $start + strlen($replacement); + + $index = strpos($formatString, '$', $index); + } + + return $formatString; + } + + /** + * @param int $i + * @param int $j + * @param int $k + * + * @return bool + */ + private static function inRange($i, $j, $k){ + return $i >= $j and $i <= $k; + } + +} \ No newline at end of file diff --git a/src/pocketmine/command/SimpleCommandMap.php b/src/pocketmine/command/SimpleCommandMap.php index 798b9056c..a1eb9e38b 100644 --- a/src/pocketmine/command/SimpleCommandMap.php +++ b/src/pocketmine/command/SimpleCommandMap.php @@ -207,7 +207,44 @@ class SimpleCommandMap implements CommandMap{ * @return void */ public function registerServerAliases(){ - //TODO + $values = $this->server->getCommandAliases(); + + foreach($values as $alias => $commandStrings){ + if(strpos($alias, ":") !== false or strpos($alias, " ") !== false){ + $this->server->getLogger()->warning("Could not register alias ". $alias ." because it contains illegal characters"); + continue; + } + + $targets = []; + + $bad = ""; + foreach($commandStrings as $commandString){ + $args = explode(" ", $commandString); + $command = $this->getCommand($args[0]); + + if($command === null){ + if(strlen($bad) > 0){ + $bad .= ", "; + } + $bad .= $commandString; + }else{ + $targets[] = $commandString; + } + } + + if(strlen($bad) > 0){ + $this->server->getLogger()->warning("Could not register alias ". $alias ." because it contains commands that do not exist: ". $bad); + continue; + } + + //These registered commands have absolute priority + if(count($targets) > 0){ + $this->knownCommands[strtolower($alias)] = new FormattedCommandAlias(strtolower($alias), $targets); + }else{ + unset($this->knownCommands[strtolower($alias)]); + } + + } }