PocketMine-MP 5.15.1 git-fb9a74e8799c71ed8292cfa53abe7a4c9204629d
SimpleCommandMap.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\command;
25
73use function array_shift;
74use function count;
75use function implode;
76use function str_contains;
77use function strcasecmp;
78use function strtolower;
79use function trim;
80
82
84 protected array $knownCommands = [];
85
86 public function __construct(private Server $server){
87 $this->setDefaultCommands();
88 }
89
90 private function setDefaultCommands() : void{
91 $this->registerAll("pocketmine", [
92 new BanCommand(),
93 new BanIpCommand(),
94 new BanListCommand(),
95 new ClearCommand(),
97 new DeopCommand(),
100 new EffectCommand(),
101 new EnchantCommand(),
102 new GamemodeCommand(),
104 new GiveCommand(),
105 new HelpCommand(),
106 new KickCommand(),
107 new KillCommand(),
108 new ListCommand(),
109 new MeCommand(),
110 new OpCommand(),
111 new PardonCommand(),
112 new PardonIpCommand(),
113 new ParticleCommand(),
114 new PluginsCommand(),
115 new SaveCommand(),
116 new SaveOffCommand(),
117 new SaveOnCommand(),
118 new SayCommand(),
119 new SeedCommand(),
121 new SpawnpointCommand(),
122 new StatusCommand(),
123 new StopCommand(),
124 new TeleportCommand(),
125 new TellCommand(),
126 new TimeCommand(),
127 new TimingsCommand(),
128 new TitleCommand(),
130 new VersionCommand(),
131 new WhitelistCommand()
132 ]);
133 }
134
135 public function registerAll(string $fallbackPrefix, array $commands) : void{
136 foreach($commands as $command){
137 $this->register($fallbackPrefix, $command);
138 }
139 }
140
141 public function register(string $fallbackPrefix, Command $command, ?string $label = null) : bool{
142 if(count($command->getPermissions()) === 0){
143 throw new \InvalidArgumentException("Commands must have a permission set");
144 }
145
146 if($label === null){
147 $label = $command->getLabel();
148 }
149 $label = trim($label);
150 $fallbackPrefix = strtolower(trim($fallbackPrefix));
151
152 $registered = $this->registerAlias($command, false, $fallbackPrefix, $label);
153
154 $aliases = $command->getAliases();
155 foreach($aliases as $index => $alias){
156 if(!$this->registerAlias($command, true, $fallbackPrefix, $alias)){
157 unset($aliases[$index]);
158 }
159 }
160 $command->setAliases($aliases);
161
162 if(!$registered){
163 $command->setLabel($fallbackPrefix . ":" . $label);
164 }
165
166 $command->register($this);
167
168 return $registered;
169 }
170
171 public function unregister(Command $command) : bool{
172 foreach($this->knownCommands as $lbl => $cmd){
173 if($cmd === $command){
174 unset($this->knownCommands[$lbl]);
175 }
176 }
177
178 $command->unregister($this);
179
180 return true;
181 }
182
183 private function registerAlias(Command $command, bool $isAlias, string $fallbackPrefix, string $label) : bool{
184 $this->knownCommands[$fallbackPrefix . ":" . $label] = $command;
185 if(($command instanceof VanillaCommand || $isAlias) && isset($this->knownCommands[$label])){
186 return false;
187 }
188
189 if(isset($this->knownCommands[$label]) && $this->knownCommands[$label]->getLabel() === $label){
190 return false;
191 }
192
193 if(!$isAlias){
194 $command->setLabel($label);
195 }
196
197 $this->knownCommands[$label] = $command;
198
199 return true;
200 }
201
202 public function dispatch(CommandSender $sender, string $commandLine) : bool{
203 $args = CommandStringHelper::parseQuoteAware($commandLine);
204
205 $sentCommandLabel = array_shift($args);
206 if($sentCommandLabel !== null && ($target = $this->getCommand($sentCommandLabel)) !== null){
207 $timings = Timings::getCommandDispatchTimings($target->getLabel());
208 $timings->startTiming();
209
210 try{
211 if($target->testPermission($sender)){
212 $target->execute($sender, $sentCommandLabel, $args);
213 }
214 }catch(InvalidCommandSyntaxException $e){
215 $sender->sendMessage($sender->getLanguage()->translate(KnownTranslationFactory::commands_generic_usage($target->getUsage())));
216 }finally{
217 $timings->stopTiming();
218 }
219 return true;
220 }
221
222 $sender->sendMessage(KnownTranslationFactory::pocketmine_command_notFound($sentCommandLabel ?? "", "/help")->prefix(TextFormat::RED));
223 return false;
224 }
225
226 public function clearCommands() : void{
227 foreach($this->knownCommands as $command){
228 $command->unregister($this);
229 }
230 $this->knownCommands = [];
231 $this->setDefaultCommands();
232 }
233
234 public function getCommand(string $name) : ?Command{
235 return $this->knownCommands[$name] ?? null;
236 }
237
241 public function getCommands() : array{
242 return $this->knownCommands;
243 }
244
245 public function registerServerAliases() : void{
246 $values = $this->server->getCommandAliases();
247
248 foreach($values as $alias => $commandStrings){
249 if(str_contains($alias, ":")){
250 $this->server->getLogger()->warning($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_command_alias_illegal($alias)));
251 continue;
252 }
253
254 $targets = [];
255 $bad = [];
256 $recursive = [];
257
258 foreach($commandStrings as $commandString){
259 $args = CommandStringHelper::parseQuoteAware($commandString);
260 $commandName = array_shift($args) ?? "";
261 $command = $this->getCommand($commandName);
262
263 if($command === null){
264 $bad[] = $commandString;
265 }elseif(strcasecmp($commandName, $alias) === 0){
266 $recursive[] = $commandString;
267 }else{
268 $targets[] = $commandString;
269 }
270 }
271
272 if(count($recursive) > 0){
273 $this->server->getLogger()->warning($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_command_alias_recursive($alias, implode(", ", $recursive))));
274 continue;
275 }
276
277 if(count($bad) > 0){
278 $this->server->getLogger()->warning($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_command_alias_notFound($alias, implode(", ", $bad))));
279 continue;
280 }
281
282 //These registered commands have absolute priority
283 $lowerAlias = strtolower($alias);
284 if(count($targets) > 0){
285 $this->knownCommands[$lowerAlias] = new FormattedCommandAlias($lowerAlias, $targets);
286 }else{
287 unset($this->knownCommands[$lowerAlias]);
288 }
289
290 }
291 }
292}
registerAll(string $fallbackPrefix, array $commands)