90    protected array $knownCommands = [];
 
   92    public function __construct(
private Server $server){
 
   93        $this->setDefaultCommands();
 
   96    private function setDefaultCommands() : 
void{
 
  142    public function registerAll(
string $fallbackPrefix, array $commands) : void{
 
  143        foreach($commands as $command){
 
  144            $this->
register($fallbackPrefix, $command);
 
 
  148    public function register(
string $fallbackPrefix, 
Command $command, ?
string $label = 
null) : 
bool{
 
  149        if(count($command->getPermissions()) === 0){
 
  150            throw new \InvalidArgumentException(
"Commands must have a permission set");
 
  154            $label = $command->getLabel();
 
  156        $label = trim($label);
 
  157        $fallbackPrefix = strtolower(trim($fallbackPrefix));
 
  159        $registered = $this->registerAlias($command, 
false, $fallbackPrefix, $label);
 
  161        $aliases = $command->getAliases();
 
  162        foreach($aliases as $index => $alias){
 
  163            if(!$this->registerAlias($command, 
true, $fallbackPrefix, $alias)){
 
  164                unset($aliases[$index]);
 
  167        $command->setAliases(array_values($aliases));
 
  170            $command->setLabel($fallbackPrefix . 
":" . $label);
 
  173        $command->register($this);
 
  178    public function unregister(Command $command) : bool{
 
  179        foreach(Utils::promoteKeys($this->knownCommands) as $lbl => $cmd){
 
  180            if($cmd === $command){
 
  181                unset($this->knownCommands[$lbl]);
 
  185        $command->unregister($this);
 
  190    private function registerAlias(Command $command, 
bool $isAlias, 
string $fallbackPrefix, 
string $label) : bool{
 
  191        $this->knownCommands[$fallbackPrefix . 
":" . $label] = $command;
 
  192        if(($command instanceof VanillaCommand || $isAlias) && isset($this->knownCommands[$label])){
 
  196        if(isset($this->knownCommands[$label]) && $this->knownCommands[$label]->getLabel() === $label){
 
  201            $command->setLabel($label);
 
  204        $this->knownCommands[$label] = $command;
 
  209    public function dispatch(CommandSender $sender, 
string $commandLine) : bool{
 
  210        $args = CommandStringHelper::parseQuoteAware($commandLine);
 
  212        $sentCommandLabel = array_shift($args);
 
  213        if($sentCommandLabel !== 
null && ($target = $this->getCommand($sentCommandLabel)) !== 
null){
 
  214            $timings = Timings::getCommandDispatchTimings($target->getLabel());
 
  215            $timings->startTiming();
 
  218                if($target->testPermission($sender)){
 
  219                    $target->execute($sender, $sentCommandLabel, $args);
 
  221            }
catch(InvalidCommandSyntaxException $e){
 
  222                $sender->sendMessage($sender->getLanguage()->translate(KnownTranslationFactory::commands_generic_usage($target->getUsage())));
 
  224                $timings->stopTiming();
 
  229        $sender->sendMessage(KnownTranslationFactory::pocketmine_command_notFound($sentCommandLabel ?? 
"", 
"/help")->prefix(TextFormat::RED));
 
  233    public function clearCommands() : void{
 
  234        foreach($this->knownCommands as $command){
 
  235            $command->unregister($this);
 
  237        $this->knownCommands = [];
 
  238        $this->setDefaultCommands();
 
  241    public function getCommand(
string $name) : ?Command{
 
  242        return $this->knownCommands[$name] ?? null;
 
  250        return $this->knownCommands;
 
 
  253    public function registerServerAliases() : void{
 
  254        $values = $this->
server->getCommandAliases();
 
  256        foreach(Utils::stringifyKeys($values) as $alias => $commandStrings){
 
  257            if(str_contains($alias, 
":")){
 
  258                $this->
server->getLogger()->warning($this->
server->getLanguage()->translate(KnownTranslationFactory::pocketmine_command_alias_illegal($alias)));
 
  266            foreach($commandStrings as $commandString){
 
  267                $args = CommandStringHelper::parseQuoteAware($commandString);
 
  268                $commandName = array_shift($args) ?? 
"";
 
  269                $command = $this->getCommand($commandName);
 
  271                if($command === 
null){
 
  272                    $bad[] = $commandString;
 
  273                }elseif(strcasecmp($commandName, $alias) === 0){
 
  274                    $recursive[] = $commandString;
 
  276                    $targets[] = $commandString;
 
  280            if(count($recursive) > 0){
 
  281                $this->
server->getLogger()->warning($this->
server->getLanguage()->translate(KnownTranslationFactory::pocketmine_command_alias_recursive($alias, implode(
", ", $recursive))));
 
  286                $this->
server->getLogger()->warning($this->
server->getLanguage()->translate(KnownTranslationFactory::pocketmine_command_alias_notFound($alias, implode(
", ", $bad))));
 
  291            $lowerAlias = strtolower($alias);
 
  292            if(count($targets) > 0){
 
  293                $this->knownCommands[$lowerAlias] = 
new FormattedCommandAlias($lowerAlias, $targets);
 
  295                unset($this->knownCommands[$lowerAlias]);