mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-10-16 11:58:00 +00:00
Firebombing of commands for the first time in 10 years
This commit is contained in:
8
composer.lock
generated
8
composer.lock
generated
@@ -349,12 +349,12 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/CallbackValidator.git",
|
||||
"reference": "8e0e3be58e89c2611beac9c6954a036b81b2b6fc"
|
||||
"reference": "431c7aa5685d4d756bc74a78e5cd130a54d6fdf8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/CallbackValidator/zipball/8e0e3be58e89c2611beac9c6954a036b81b2b6fc",
|
||||
"reference": "8e0e3be58e89c2611beac9c6954a036b81b2b6fc",
|
||||
"url": "https://api.github.com/repos/pmmp/CallbackValidator/zipball/431c7aa5685d4d756bc74a78e5cd130a54d6fdf8",
|
||||
"reference": "431c7aa5685d4d756bc74a78e5cd130a54d6fdf8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -391,7 +391,7 @@
|
||||
"issues": "https://github.com/pmmp/CallbackValidator/issues",
|
||||
"source": "https://github.com/pmmp/CallbackValidator/tree/rewrite"
|
||||
},
|
||||
"time": "2025-10-10T21:55:21+00:00"
|
||||
"time": "2025-10-11T15:05:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/color",
|
||||
|
@@ -29,13 +29,14 @@ use pocketmine\utils\Utils;
|
||||
/**
|
||||
* @phpstan-type Execute \Closure(CommandSender $sender, Command $command, string $commandLabel, list<string> $args) : mixed
|
||||
*/
|
||||
final class ClosureCommand extends Command{
|
||||
final class ClosureCommand extends LegacyCommand{
|
||||
/** @phpstan-var Execute */
|
||||
private \Closure $execute;
|
||||
|
||||
/**
|
||||
* @param string[] $permissions
|
||||
* @phpstan-param Execute $execute
|
||||
* @phpstan-param list<string> $permissions
|
||||
*/
|
||||
public function __construct(
|
||||
string $namespace,
|
||||
|
@@ -26,34 +26,40 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace pocketmine\command;
|
||||
|
||||
use pocketmine\command\utils\CommandException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\permission\PermissionManager;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\BroadcastLoggerForwarder;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function explode;
|
||||
use function array_unique;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function str_replace;
|
||||
use function strtolower;
|
||||
use function trim;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
abstract class Command{
|
||||
private readonly string $namespace;
|
||||
private readonly string $name;
|
||||
|
||||
/** @var string[] */
|
||||
private array $permission = [];
|
||||
private Translatable|string|null $permissionMessage = null;
|
||||
|
||||
/**
|
||||
* @param CommandOverload[] $overloads
|
||||
* @phpstan-param list<CommandOverload> $overloads
|
||||
*/
|
||||
public function __construct(
|
||||
string $namespace,
|
||||
string $name,
|
||||
private array $overloads,
|
||||
private Translatable|string $description = "",
|
||||
private Translatable|string|null $usageMessage = null
|
||||
){
|
||||
if(count($this->overloads) === 0){
|
||||
throw new \InvalidArgumentException("At least one overload must be provided (extend LegacyCommand for classic execute())");
|
||||
}
|
||||
if($namespace === ""){
|
||||
throw new \InvalidArgumentException("Command namespace cannot be empty (set it to, for example, your plugin's name)");
|
||||
}
|
||||
@@ -65,14 +71,57 @@ abstract class Command{
|
||||
$this->name = trim($name);
|
||||
}
|
||||
|
||||
final public function executeOverloaded(CommandSender $sender, string $aliasUsed, string $rawArgs) : bool{
|
||||
foreach($this->overloads as $k => $overload){
|
||||
if(!$overload->senderHasAnyPermissions($sender)){
|
||||
continue;
|
||||
}
|
||||
try{
|
||||
$overload->invoke($sender, $aliasUsed, $rawArgs);
|
||||
return true;
|
||||
}catch(InvalidCommandSyntaxException $e){
|
||||
\GlobalLogger::get()->debug("Overload $k of /$aliasUsed rejected: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$usages = $this->getUsages($sender, $aliasUsed);
|
||||
if(count($usages) === 0){
|
||||
$message = $this->permissionMessage ?? KnownTranslationFactory::pocketmine_command_error_permission($aliasUsed);
|
||||
if($message instanceof Translatable){
|
||||
$sender->sendMessage($message->prefix(TextFormat::RED));
|
||||
}elseif($message !== ""){
|
||||
$permissions = [];
|
||||
foreach($this->overloads as $overload){
|
||||
foreach($overload->getPermissions() as $permission){
|
||||
$permissions[] = $permission;
|
||||
}
|
||||
}
|
||||
$permissions = array_unique($permissions);
|
||||
$sender->sendMessage(str_replace("<permission>", implode(";", $permissions), $message));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach($usages as $usageMessage){
|
||||
$sender->sendMessage($sender->getLanguage()->translate(KnownTranslationFactory::commands_generic_usage($usageMessage)));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $args
|
||||
* @phpstan-param list<string> $args
|
||||
*
|
||||
* @return mixed
|
||||
* @throws CommandException
|
||||
* @return Translatable[]
|
||||
* @phpstan-return list<Translatable>
|
||||
*/
|
||||
abstract public function execute(CommandSender $sender, string $commandLabel, array $args);
|
||||
public function getUsages(CommandSender $sender, string $aliasUsed) : array{
|
||||
$usages = [];
|
||||
foreach($this->overloads as $overload){
|
||||
if($overload->senderHasAnyPermissions($sender)){
|
||||
$usages[] = new Translatable("/$aliasUsed {%0}", [$overload->getUsage()]);
|
||||
}
|
||||
}
|
||||
|
||||
return $usages;
|
||||
}
|
||||
|
||||
final public function getNamespace() : string{
|
||||
return $this->namespace;
|
||||
@@ -93,59 +142,17 @@ abstract class Command{
|
||||
return "$this->namespace:$this->name";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPermissions() : array{
|
||||
return $this->permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $permissions
|
||||
* @phpstan-param list<string> $permissions
|
||||
*/
|
||||
public function setPermissions(array $permissions) : void{
|
||||
$permissionManager = PermissionManager::getInstance();
|
||||
foreach($permissions as $perm){
|
||||
if($permissionManager->getPermission($perm) === null){
|
||||
throw new \InvalidArgumentException("Cannot use non-existing permission \"$perm\"");
|
||||
}
|
||||
}
|
||||
$this->permission = $permissions;
|
||||
}
|
||||
|
||||
public function setPermission(?string $permission) : void{
|
||||
$this->setPermissions($permission === null ? [] : explode(";", $permission, limit: PHP_INT_MAX));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $context usually the command name, but may include extra args if useful (e.g. for subcommands)
|
||||
* @param CommandSender $target the target to check the permission for
|
||||
* @param string|null $permission the permission to check, if null, will check if the target has any of the command's permissions
|
||||
*/
|
||||
public function testPermission(string $context, CommandSender $target, ?string $permission = null) : bool{
|
||||
if($this->testPermissionSilent($target, $permission)){
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function sendBadPermissionMessage(string $context, CommandSender $sender, array $permissions) : void{
|
||||
$message = $this->permissionMessage ?? KnownTranslationFactory::pocketmine_command_error_permission($context);
|
||||
if($message instanceof Translatable){
|
||||
$target->sendMessage($message->prefix(TextFormat::RED));
|
||||
$sender->sendMessage($message->prefix(TextFormat::RED));
|
||||
}elseif($message !== ""){
|
||||
$target->sendMessage(str_replace("<permission>", $permission ?? implode(";", $this->permission), $message));
|
||||
$sender->sendMessage(str_replace("<permission>", implode(";", $permissions), $message));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function testPermissionSilent(CommandSender $target, ?string $permission = null) : bool{
|
||||
$list = $permission !== null ? [$permission] : $this->permission;
|
||||
foreach($list as $p){
|
||||
if($target->hasPermission($p)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPermissionMessage() : Translatable|string|null{
|
||||
@@ -156,10 +163,6 @@ abstract class Command{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function getUsage() : Translatable|string|null{
|
||||
return $this->usageMessage;
|
||||
}
|
||||
|
||||
public function setDescription(Translatable|string $description) : void{
|
||||
$this->description = $description;
|
||||
}
|
||||
@@ -168,10 +171,6 @@ abstract class Command{
|
||||
$this->permissionMessage = $permissionMessage;
|
||||
}
|
||||
|
||||
public function setUsage(Translatable|string|null $usage) : void{
|
||||
$this->usageMessage = $usage;
|
||||
}
|
||||
|
||||
public static function broadcastCommandMessage(CommandSender $source, Translatable|string $message, bool $sendToSource = true) : void{
|
||||
$users = $source->getServer()->getBroadcastChannelSubscribers(Server::BROADCAST_CHANNEL_ADMINISTRATIVE);
|
||||
$result = KnownTranslationFactory::chat_type_admin($source->getName(), $message);
|
||||
@@ -189,4 +188,31 @@ abstract class Command{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static function fetchPermittedPlayerTarget(
|
||||
CommandSender $sender,
|
||||
?string $target,
|
||||
string $selfPermission,
|
||||
string $otherPermission
|
||||
) : ?Player{
|
||||
if($target !== null){
|
||||
$player = $sender->getServer()->getPlayerByPrefix($target);
|
||||
}elseif($sender instanceof Player){
|
||||
$player = $sender;
|
||||
}else{
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
if($player === null){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_generic_player_notFound()->prefix(TextFormat::RED));
|
||||
return null;
|
||||
}
|
||||
|
||||
$permission = $player === $sender ? $selfPermission : $otherPermission;
|
||||
if(!$sender->hasPermission($permission)){
|
||||
$sender->sendMessage(TextFormat::RED . "You don't have permission to use this command on others");
|
||||
return null;
|
||||
}
|
||||
return $player;
|
||||
}
|
||||
}
|
||||
|
@@ -24,20 +24,18 @@ declare(strict_types=1);
|
||||
namespace pocketmine\command;
|
||||
|
||||
use pocketmine\command\utils\CommandStringHelper;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_shift;
|
||||
use function addcslashes;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function preg_match;
|
||||
use function str_contains;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
|
||||
class FormattedCommandAlias extends Command{
|
||||
class FormattedCommandAlias extends LegacyCommand{
|
||||
/**
|
||||
* - matches a $
|
||||
* - captures an optional second $ to indicate required/optional
|
||||
@@ -77,7 +75,7 @@ class FormattedCommandAlias extends Command{
|
||||
$processedArgs[] = $processedArg;
|
||||
}
|
||||
}
|
||||
$commands[] = $processedArgs;
|
||||
$commands[] = implode(" ", $processedArgs);
|
||||
}catch(\InvalidArgumentException $e){
|
||||
$sender->sendMessage(TextFormat::RED . $e->getMessage());
|
||||
return false;
|
||||
@@ -85,38 +83,13 @@ class FormattedCommandAlias extends Command{
|
||||
}
|
||||
|
||||
$commandMap = $sender->getServer()->getCommandMap();
|
||||
foreach($commands as $commandArgs){
|
||||
//this approximately duplicates the logic found in SimpleCommandMap::dispatch()
|
||||
//this is to allow directly invoking the commands without having to rebuild a command string and parse it
|
||||
//again for no reason
|
||||
//TODO: a method on CommandMap to invoke a command with pre-parsed arguments would probably be a good idea
|
||||
//for a future major version
|
||||
$commandLabel = array_shift($commandArgs);
|
||||
if($commandLabel === null){
|
||||
throw new AssumptionFailedError("This should have been checked before construction");
|
||||
}
|
||||
|
||||
//formatted command aliases don't use user-specific aliases since they are globally defined in pocketmine.yml
|
||||
//using user-specific aliases might break the behaviour
|
||||
if(($target = $commandMap->getCommand($commandLabel)) instanceof Command){
|
||||
|
||||
$timings = Timings::getCommandDispatchTimings($target->getId());
|
||||
$timings->startTiming();
|
||||
|
||||
try{
|
||||
$target->execute($sender, $commandLabel, $commandArgs);
|
||||
}catch(InvalidCommandSyntaxException $e){
|
||||
$sender->sendMessage($sender->getLanguage()->translate(KnownTranslationFactory::commands_generic_usage($target->getUsage() ?? "/$commandLabel")));
|
||||
}finally{
|
||||
$timings->stopTiming();
|
||||
}
|
||||
}else{
|
||||
//TODO: this seems suspicious - why do we continue alias execution if one of the commands is borked?
|
||||
$sender->sendMessage($sender->getLanguage()->translate(KnownTranslationFactory::pocketmine_command_notFound($commandLabel, "/help")->prefix(TextFormat::RED)));
|
||||
|
||||
foreach($commands as $commandLine){
|
||||
$sender->getServer()->getLogger()->debug("Dispatching formatted command: $commandLine");
|
||||
if(!$commandMap->dispatch($sender, $commandLine)){
|
||||
//to match the behaviour of SimpleCommandMap::dispatch()
|
||||
//this shouldn't normally happen, but might happen if the command was unregistered or modified after
|
||||
//the alias was installed
|
||||
//TODO: maybe we should abort command processing if there was an error???
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
@@ -160,6 +133,11 @@ class FormattedCommandAlias extends Command{
|
||||
$index = $start + strlen($replacement);
|
||||
}
|
||||
|
||||
//we need to assemble a command string to call the target commands, so this needs to be properly quoted
|
||||
if(str_contains($formatString, " ")){
|
||||
return '"' . addcslashes($formatString, '"') . '"';
|
||||
}
|
||||
|
||||
return $formatString;
|
||||
}
|
||||
|
||||
|
140
src/command/LegacyCommand.php
Normal file
140
src/command/LegacyCommand.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command;
|
||||
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\RawParameter;
|
||||
use pocketmine\command\utils\CommandException;
|
||||
use pocketmine\command\utils\CommandStringHelper;
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\permission\PermissionManager;
|
||||
use function explode;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
/**
|
||||
* Offers a quick & dirty upgrade path for old code that can't be quickly migrated to the new overload system in PM6.
|
||||
* @deprecated
|
||||
*/
|
||||
abstract class LegacyCommand extends Command{
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
private array $permission = [];
|
||||
|
||||
public function __construct(
|
||||
string $namespace,
|
||||
string $name,
|
||||
Translatable|string $description = "",
|
||||
private Translatable|string|null $usageMessage = null,
|
||||
){
|
||||
parent::__construct($namespace, $name, [new CommandOverload(
|
||||
[new RawParameter("args", "args")],
|
||||
DefaultPermissionNames::GROUP_USER,
|
||||
$this->handler(...),
|
||||
acceptsAliasUsed: true
|
||||
)], $description);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
public function getPermissions() : array{
|
||||
return $this->permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $permissions
|
||||
* @phpstan-param list<string> $permissions
|
||||
*/
|
||||
public function setPermissions(array $permissions) : void{
|
||||
$permissionManager = PermissionManager::getInstance();
|
||||
foreach($permissions as $perm){
|
||||
if($permissionManager->getPermission($perm) === null){
|
||||
throw new \InvalidArgumentException("Cannot use non-existing permission \"$perm\"");
|
||||
}
|
||||
}
|
||||
$this->permission = $permissions;
|
||||
}
|
||||
|
||||
public function setPermission(?string $permission) : void{
|
||||
$this->setPermissions($permission === null ? [] : explode(";", $permission, limit: PHP_INT_MAX));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $context usually the command name, but may include extra args if useful (e.g. for subcommands)
|
||||
* @param CommandSender $target the target to check the permission for
|
||||
* @param string|null $permission the permission to check, if null, will check if the target has any of the command's permissions
|
||||
*/
|
||||
public function testPermission(string $context, CommandSender $target, ?string $permission = null) : bool{
|
||||
if($this->testPermissionSilent($target, $permission)){
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->sendBadPermissionMessage($context, $target, $permission !== null ? [$permission] : $this->permission);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function testPermissionSilent(CommandSender $target, ?string $permission = null) : bool{
|
||||
$list = $permission !== null ? [$permission] : $this->permission;
|
||||
foreach($list as $p){
|
||||
if($target->hasPermission($p)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getUsages(CommandSender $sender, string $aliasUsed) : array{
|
||||
if($this->testPermissionSilent($sender)){
|
||||
return $this->usageMessage instanceof Translatable ?
|
||||
[$this->usageMessage] :
|
||||
[new Translatable("{%0}", [$this->usageMessage ?? "/$aliasUsed"])];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
private function handler(CommandSender $sender, string $aliasUsed, string $rawArgs = "") : void{
|
||||
if(!$this->testPermission($aliasUsed, $sender)){
|
||||
return;
|
||||
}
|
||||
$args = CommandStringHelper::parseQuoteAware($rawArgs);
|
||||
$this->execute($sender, $aliasUsed, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $args
|
||||
* @phpstan-param list<string> $args
|
||||
*
|
||||
* @return mixed
|
||||
* @throws CommandException
|
||||
*/
|
||||
abstract protected function execute(CommandSender $sender, string $commandLabel, array $args);
|
||||
}
|
@@ -28,7 +28,7 @@ use pocketmine\lang\Translatable;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use pocketmine\plugin\PluginOwned;
|
||||
|
||||
final class PluginCommand extends Command implements PluginOwned{
|
||||
final class PluginCommand extends LegacyCommand implements PluginOwned{
|
||||
public function __construct(
|
||||
string $namespace,
|
||||
string $name,
|
||||
|
@@ -66,7 +66,6 @@ use pocketmine\command\defaults\VersionCommand;
|
||||
use pocketmine\command\defaults\WhitelistCommand;
|
||||
use pocketmine\command\defaults\XpCommand;
|
||||
use pocketmine\command\utils\CommandStringHelper;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\timings\Timings;
|
||||
@@ -76,9 +75,11 @@ use function array_filter;
|
||||
use function array_map;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function is_array;
|
||||
use function is_string;
|
||||
use function ltrim;
|
||||
use function str_contains;
|
||||
use function strcasecmp;
|
||||
use function strtolower;
|
||||
@@ -146,7 +147,7 @@ class SimpleCommandMap implements CommandMap{
|
||||
}
|
||||
|
||||
public function register(Command $command, array $otherAliases = []) : void{
|
||||
if(count($command->getPermissions()) === 0){
|
||||
if($command instanceof LegacyCommand && count($command->getPermissions()) === 0){
|
||||
throw new \InvalidArgumentException("Commands must have a permission set");
|
||||
}
|
||||
|
||||
@@ -172,10 +173,10 @@ class SimpleCommandMap implements CommandMap{
|
||||
}
|
||||
|
||||
public function dispatch(CommandSender $sender, string $commandLine) : bool{
|
||||
$args = CommandStringHelper::parseQuoteAware($commandLine);
|
||||
$parts = explode(" ", ltrim($commandLine), limit: 2);
|
||||
[$sentCommandLabel, $rawArgs] = count($parts) === 2 ? $parts : [$parts[0], ""];
|
||||
|
||||
$sentCommandLabel = array_shift($args);
|
||||
if($sentCommandLabel !== null && ($target = $this->getCommand($sentCommandLabel, $sender->getCommandAliasMap())) !== null){
|
||||
if(($target = $this->getCommand($sentCommandLabel, $sender->getCommandAliasMap())) !== null){
|
||||
if(is_array($target)){
|
||||
self::handleConflicted($sender, $sentCommandLabel, $target, $this->aliasMap);
|
||||
return true;
|
||||
@@ -184,12 +185,7 @@ class SimpleCommandMap implements CommandMap{
|
||||
$timings->startTiming();
|
||||
|
||||
try{
|
||||
if($target->testPermission($sentCommandLabel, $sender)){
|
||||
$target->execute($sender, $sentCommandLabel, $args);
|
||||
}
|
||||
}catch(InvalidCommandSyntaxException $e){
|
||||
//TODO: localised command message should use user-provided alias, it shouldn't be hard-baked into the language strings
|
||||
$sender->sendMessage($sender->getLanguage()->translate(KnownTranslationFactory::commands_generic_usage($target->getUsage() ?? "/$sentCommandLabel")));
|
||||
$target->executeOverloaded($sender, $sentCommandLabel, $rawArgs);
|
||||
}finally{
|
||||
$timings->stopTiming();
|
||||
}
|
||||
@@ -198,7 +194,7 @@ class SimpleCommandMap implements CommandMap{
|
||||
|
||||
//Don't love hardcoding the command ID here, but it seems like the only way for now
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_notFound(
|
||||
$sentCommandLabel ?? "",
|
||||
$sentCommandLabel,
|
||||
"/" . $sender->getCommandAliasMap()->getPreferredAlias("pocketmine:help", $this->aliasMap)
|
||||
)->prefix(TextFormat::RED));
|
||||
return false;
|
||||
@@ -214,7 +210,7 @@ class SimpleCommandMap implements CommandMap{
|
||||
$candidates = [];
|
||||
$userAliasMap = $sender->getCommandAliasMap();
|
||||
foreach($conflictedEntries as $c){
|
||||
if($c->testPermissionSilent($sender)){
|
||||
if(count($c->getUsages($sender, $alias)) > 0){
|
||||
$candidates[] = "/" . $c->getId();
|
||||
}
|
||||
}
|
||||
|
@@ -25,42 +25,38 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\RawParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class BanCommand extends VanillaCommand{
|
||||
class BanCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload(
|
||||
[
|
||||
new StringParameter("playerName", "player name"),
|
||||
new RawParameter("reason", "reason")
|
||||
],
|
||||
DefaultPermissionNames::COMMAND_BAN_PLAYER,
|
||||
self::execute(...)
|
||||
)],
|
||||
KnownTranslationFactory::pocketmine_command_ban_player_description(),
|
||||
KnownTranslationFactory::commands_ban_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_BAN_PLAYER);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
private static function execute(CommandSender $sender, string $playerName, string $reason) : void{
|
||||
$sender->getServer()->getNameBans()->addBan($playerName, $reason, null, $sender->getName());
|
||||
|
||||
$name = array_shift($args);
|
||||
$reason = implode(" ", $args);
|
||||
|
||||
$sender->getServer()->getNameBans()->addBan($name, $reason, null, $sender->getName());
|
||||
|
||||
if(($player = $sender->getServer()->getPlayerExact($name)) instanceof Player){
|
||||
if(($player = $sender->getServer()->getPlayerExact($playerName)) instanceof Player){
|
||||
$player->kick($reason !== "" ? KnownTranslationFactory::pocketmine_disconnect_ban($reason) : KnownTranslationFactory::pocketmine_disconnect_ban_noReason());
|
||||
}
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_ban_success($player !== null ? $player->getName() : $name));
|
||||
|
||||
return true;
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_ban_success($player !== null ? $player->getName() : $playerName));
|
||||
}
|
||||
}
|
||||
|
@@ -25,56 +25,51 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\RawParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function inet_pton;
|
||||
|
||||
class BanIpCommand extends VanillaCommand{
|
||||
class BanIpCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload(
|
||||
[
|
||||
//TODO: maybe split this into two overloads?
|
||||
new StringParameter("target", "name or IP address"),
|
||||
new RawParameter("reason", "reason")
|
||||
],
|
||||
DefaultPermissionNames::COMMAND_BAN_IP,
|
||||
self::execute(...)
|
||||
)],
|
||||
KnownTranslationFactory::pocketmine_command_ban_ip_description(),
|
||||
KnownTranslationFactory::commands_banip_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_BAN_IP);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
private static function execute(CommandSender $sender, string $target, string $reason) : void{
|
||||
if(inet_pton($target) !== false){
|
||||
self::processIPBan($target, $sender, $reason);
|
||||
|
||||
$value = array_shift($args);
|
||||
$reason = implode(" ", $args);
|
||||
|
||||
if(inet_pton($value) !== false){
|
||||
$this->processIPBan($value, $sender, $reason);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_banip_success($value));
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_banip_success($target));
|
||||
}else{
|
||||
if(($player = $sender->getServer()->getPlayerByPrefix($value)) instanceof Player){
|
||||
if(($player = $sender->getServer()->getPlayerByPrefix($target)) instanceof Player){
|
||||
$ip = $player->getNetworkSession()->getIp();
|
||||
$this->processIPBan($ip, $sender, $reason);
|
||||
self::processIPBan($ip, $sender, $reason);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_banip_success_players($ip, $player->getName()));
|
||||
}else{
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_banip_invalid());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function processIPBan(string $ip, CommandSender $sender, string $reason) : void{
|
||||
private static function processIPBan(string $ip, CommandSender $sender, string $reason) : void{
|
||||
$sender->getServer()->getIPBans()->addBan($ip, $reason, null, $sender->getName());
|
||||
|
||||
foreach($sender->getServer()->getOnlinePlayers() as $player){
|
||||
|
@@ -23,59 +23,50 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\BanEntry;
|
||||
use pocketmine\permission\BanList;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use function array_map;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function sort;
|
||||
use function strtolower;
|
||||
use const SORT_STRING;
|
||||
|
||||
class BanListCommand extends VanillaCommand{
|
||||
class BanListCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[
|
||||
new CommandOverload(["ips"], DefaultPermissionNames::COMMAND_BAN_LIST, self::listIPBans(...)),
|
||||
new CommandOverload(["players"], DefaultPermissionNames::COMMAND_BAN_LIST, self::listNameBans(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_banlist_description(),
|
||||
KnownTranslationFactory::commands_banlist_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_BAN_LIST);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(isset($args[0])){
|
||||
$args[0] = strtolower($args[0]);
|
||||
if($args[0] === "ips"){
|
||||
$list = $sender->getServer()->getIPBans();
|
||||
}elseif($args[0] === "players"){
|
||||
$list = $sender->getServer()->getNameBans();
|
||||
}else{
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
}else{
|
||||
$list = $sender->getServer()->getNameBans();
|
||||
$args[0] = "players";
|
||||
}
|
||||
|
||||
private static function printList(BanList $list) : string{
|
||||
$list = array_map(function(BanEntry $entry) : string{
|
||||
return $entry->getName();
|
||||
}, $list->getEntries());
|
||||
sort($list, SORT_STRING);
|
||||
$message = implode(", ", $list);
|
||||
|
||||
if($args[0] === "ips"){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_banlist_ips((string) count($list)));
|
||||
}else{
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_banlist_players((string) count($list)));
|
||||
return implode(", ", $list);
|
||||
}
|
||||
|
||||
$sender->sendMessage($message);
|
||||
private static function listIPBans(CommandSender $sender) : void{
|
||||
$list = $sender->getServer()->getIPBans();
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_banlist_ips((string) count($list->getEntries())));
|
||||
$sender->sendMessage(self::printList($list));
|
||||
}
|
||||
|
||||
return true;
|
||||
private static function listNameBans(CommandSender $sender) : void{
|
||||
$list = $sender->getServer()->getNameBans();
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_banlist_players((string) count($list->getEntries())));
|
||||
$sender->sendMessage(self::printList($list));
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,11 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\IntRangeParameter;
|
||||
use pocketmine\command\overload\MappedParameter;
|
||||
use pocketmine\command\overload\ParameterParseException;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\LegacyStringToItemParser;
|
||||
@@ -37,42 +41,36 @@ use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function min;
|
||||
|
||||
class ClearCommand extends VanillaCommand{
|
||||
class ClearCommand extends Command{
|
||||
|
||||
private const SELF_PERM = DefaultPermissionNames::COMMAND_CLEAR_SELF;
|
||||
private const OTHER_PERM = DefaultPermissionNames::COMMAND_CLEAR_OTHER;
|
||||
|
||||
private const OVERLOAD_PERMS = [self::SELF_PERM, self::OTHER_PERM];
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_clear_description(),
|
||||
KnownTranslationFactory::pocketmine_command_clear_usage()
|
||||
);
|
||||
$this->setPermissions([DefaultPermissionNames::COMMAND_CLEAR_SELF, DefaultPermissionNames::COMMAND_CLEAR_OTHER]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) > 3){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$target = $this->fetchPermittedPlayerTarget($commandLabel, $sender, $args[0] ?? null, DefaultPermissionNames::COMMAND_CLEAR_SELF, DefaultPermissionNames::COMMAND_CLEAR_OTHER);
|
||||
if($target === null){
|
||||
return true;
|
||||
}
|
||||
|
||||
$targetItem = null;
|
||||
$maxCount = -1;
|
||||
if(isset($args[1])){
|
||||
[new CommandOverload([
|
||||
new StringParameter("playerName", "player name"),
|
||||
new MappedParameter("targetItem", "item name", static function(string $v) : Item{
|
||||
try{
|
||||
$targetItem = StringToItemParser::getInstance()->parse($args[1]) ?? LegacyStringToItemParser::getInstance()->parse($args[1]);
|
||||
|
||||
if(isset($args[2])){
|
||||
$targetItem->setCount($maxCount = $this->getInteger($sender, $args[2], -1));
|
||||
}
|
||||
return StringToItemParser::getInstance()->parse($v) ?? LegacyStringToItemParser::getInstance()->parse($v);
|
||||
}catch(LegacyStringToItemParserException $e){
|
||||
//vanilla checks this at argument parsing layer, can't come up with a better alternative
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_give_item_notFound($args[1])->prefix(TextFormat::RED));
|
||||
return true;
|
||||
throw new ParameterParseException("Invalid item name: $v");
|
||||
}
|
||||
}),
|
||||
new IntRangeParameter("maxCount", "max count", -1, 32767)
|
||||
], self::OVERLOAD_PERMS, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_clear_description()
|
||||
);
|
||||
}
|
||||
|
||||
private static function execute(CommandSender $sender, ?string $playerName = null, ?Item $targetItem = null, int $maxCount = -1) : void{
|
||||
$target = self::fetchPermittedPlayerTarget($sender, $playerName, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($target === null){
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,27 +85,27 @@ class ClearCommand extends VanillaCommand{
|
||||
|
||||
// Checking player's inventory for all the items matching the criteria
|
||||
if($targetItem !== null && $maxCount === 0){
|
||||
$count = $this->countItems($inventories, $targetItem);
|
||||
$count = self::countItems($inventories, $targetItem);
|
||||
if($count > 0){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_clear_testing($target->getName(), (string) $count));
|
||||
}else{
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_clear_failure_no_items($target->getName())->prefix(TextFormat::RED));
|
||||
}
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
$clearedCount = 0;
|
||||
if($targetItem === null){
|
||||
// Clear all items from the inventories
|
||||
$clearedCount += $this->countItems($inventories, null);
|
||||
$clearedCount += self::countItems($inventories, null);
|
||||
foreach($inventories as $inventory){
|
||||
$inventory->clearAll();
|
||||
}
|
||||
}else{
|
||||
// Clear the item from target's inventory irrelevant of the count
|
||||
if($maxCount === -1){
|
||||
$clearedCount += $this->countItems($inventories, $targetItem);
|
||||
$clearedCount += self::countItems($inventories, $targetItem);
|
||||
foreach($inventories as $inventory){
|
||||
$inventory->remove($targetItem);
|
||||
}
|
||||
@@ -135,14 +133,12 @@ class ClearCommand extends VanillaCommand{
|
||||
}else{
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_clear_failure_no_items($target->getName())->prefix(TextFormat::RED));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Inventory[] $inventories
|
||||
*/
|
||||
protected function countItems(array $inventories, ?Item $target) : int{
|
||||
protected static function countItems(array $inventories, ?Item $target) : int{
|
||||
$count = 0;
|
||||
foreach($inventories as $inventory){
|
||||
$contents = $target !== null ? $inventory->all($target) : $inventory->getContents();
|
||||
|
@@ -25,14 +25,14 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\Utils;
|
||||
use function array_map;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function is_array;
|
||||
@@ -44,57 +44,64 @@ final class CommandAliasCommand extends Command{
|
||||
private const LIST_PERM = DefaultPermissionNames::COMMAND_CMDALIAS_LIST;
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
$overloads = [];
|
||||
foreach([false, true] as $global){
|
||||
$prefix = $global ? ["global"] : [];
|
||||
$editPerm = $global ? self::GLOBAL_PERM : self::SELF_PERM;
|
||||
$overloads[] = new CommandOverload(
|
||||
[...$prefix, ...[
|
||||
"create",
|
||||
new StringParameter("alias", "alias"),
|
||||
new StringParameter("target", "target")
|
||||
]],
|
||||
$editPerm,
|
||||
fn(CommandSender $sender, string $alias, string $target) => $this->createAlias($sender, $alias, $target, $global)
|
||||
);
|
||||
$overloads[] = new CommandOverload(
|
||||
[...$prefix, ...[
|
||||
"delete",
|
||||
new StringParameter("alias", "alias")
|
||||
]],
|
||||
$editPerm,
|
||||
fn(CommandSender $sender, string $alias) => $this->deleteAlias($sender, $alias, $global)
|
||||
);
|
||||
$overloads[] = new CommandOverload(
|
||||
[...$prefix, "list"],
|
||||
self::LIST_PERM,
|
||||
fn(CommandSender $sender) => $this->listAliases($sender, $global)
|
||||
);
|
||||
}
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
$overloads,
|
||||
KnownTranslationFactory::pocketmine_command_cmdalias_description(),
|
||||
"/cmdalias [global] create <alias> <target> OR /cmdalias [global] delete <alias>"
|
||||
);
|
||||
$this->setPermissions([self::GLOBAL_PERM, self::SELF_PERM, self::LIST_PERM]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
$parsedArgs = $args;
|
||||
private function createAlias(CommandSender $sender, string $alias, string $target, bool $global) : void{
|
||||
$commandMap = $sender->getServer()->getCommandMap();
|
||||
if($parsedArgs[0] === "global"){
|
||||
$editPermission = self::GLOBAL_PERM;
|
||||
$permissionCtx = $commandLabel . " global";
|
||||
array_shift($parsedArgs);
|
||||
if($global){
|
||||
$aliasMap = $commandMap->getAliasMap();
|
||||
$messageScope = fn(Translatable $t) => KnownTranslationFactory::pocketmine_command_cmdalias_template($t, KnownTranslationFactory::pocketmine_command_cmdalias_scope_global());
|
||||
$auditLog = true;
|
||||
}else{
|
||||
$editPermission = self::SELF_PERM;
|
||||
$permissionCtx = $commandLabel;
|
||||
$aliasMap = $sender->getCommandAliasMap();
|
||||
$messageScope = fn(Translatable $t) => KnownTranslationFactory::pocketmine_command_cmdalias_template($t, KnownTranslationFactory::pocketmine_command_cmdalias_scope_userSpecific());
|
||||
$auditLog = false;
|
||||
}
|
||||
$operation = array_shift($parsedArgs);
|
||||
|
||||
if($operation === "create"){
|
||||
if(count($parsedArgs) !== 2){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
if(!$this->testPermission($permissionCtx, $sender, $editPermission)){
|
||||
return true;
|
||||
}
|
||||
|
||||
[$alias, $target] = $parsedArgs;
|
||||
$command = $commandMap->getCommand($target, $sender->getCommandAliasMap());
|
||||
if($command === null){
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_notFound(
|
||||
"/$target",
|
||||
"/" . $sender->getCommandAliasMap()->getPreferredAlias("pocketmine:help", $sender->getServer()->getCommandMap()->getAliasMap())
|
||||
)->prefix(TextFormat::RED));
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if(is_array($command)){
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_error_aliasConflict("/$target", implode(", ", array_map(fn(Command $c) => "/" . $c->getId(), $command)))->prefix(TextFormat::RED));
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
$aliasMap->bindAlias($command->getId(), $alias, override: true);
|
||||
$message = $messageScope(KnownTranslationFactory::pocketmine_command_cmdalias_create_success("/$alias", "/" . $command->getId()));
|
||||
@@ -103,18 +110,19 @@ final class CommandAliasCommand extends Command{
|
||||
}else{
|
||||
$sender->sendMessage($message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if($operation === "delete"){
|
||||
if(count($parsedArgs) !== 1){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
if(!$this->testPermission($permissionCtx, $sender, $editPermission)){
|
||||
return true;
|
||||
}
|
||||
|
||||
$alias = $parsedArgs[0];
|
||||
|
||||
private function deleteAlias(CommandSender $sender, string $alias, bool $global) : void{
|
||||
$commandMap = $sender->getServer()->getCommandMap();
|
||||
if($global){
|
||||
$aliasMap = $commandMap->getAliasMap();
|
||||
$messageScope = fn(Translatable $t) => KnownTranslationFactory::pocketmine_command_cmdalias_template($t, KnownTranslationFactory::pocketmine_command_cmdalias_scope_global());
|
||||
$auditLog = true;
|
||||
}else{
|
||||
$aliasMap = $sender->getCommandAliasMap();
|
||||
$messageScope = fn(Translatable $t) => KnownTranslationFactory::pocketmine_command_cmdalias_template($t, KnownTranslationFactory::pocketmine_command_cmdalias_scope_userSpecific());
|
||||
$auditLog = false;
|
||||
}
|
||||
if($aliasMap->unbindAlias($alias)){
|
||||
$message = $messageScope(KnownTranslationFactory::pocketmine_command_cmdalias_delete_success("/$alias"));
|
||||
if($auditLog){
|
||||
@@ -125,19 +133,20 @@ final class CommandAliasCommand extends Command{
|
||||
}else{
|
||||
$sender->sendMessage($messageScope(KnownTranslationFactory::pocketmine_command_cmdalias_delete_notFound("/$alias"))->prefix(TextFormat::RED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if($operation === "list"){
|
||||
if(count($parsedArgs) !== 0){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
if(!$this->testPermission($permissionCtx, $sender, self::LIST_PERM)){
|
||||
return true;
|
||||
|
||||
private function listAliases(CommandSender $sender, bool $global) : void{
|
||||
if($global){
|
||||
$aliasMap = $sender->getServer()->getCommandMap()->getAliasMap();
|
||||
$messageScope = fn(Translatable $t) => KnownTranslationFactory::pocketmine_command_cmdalias_template($t, KnownTranslationFactory::pocketmine_command_cmdalias_scope_global());
|
||||
}else{
|
||||
$aliasMap = $sender->getCommandAliasMap();
|
||||
$messageScope = fn(Translatable $t) => KnownTranslationFactory::pocketmine_command_cmdalias_template($t, KnownTranslationFactory::pocketmine_command_cmdalias_scope_userSpecific());
|
||||
}
|
||||
$allAliases = $aliasMap->getAllAliases();
|
||||
if(count($allAliases) === 0){
|
||||
$sender->sendMessage($messageScope(KnownTranslationFactory::pocketmine_command_cmdalias_list_noneSet())->prefix(TextFormat::RED));
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
ksort($allAliases);
|
||||
foreach(Utils::promoteKeys($allAliases) as $alias => $commandIds){
|
||||
@@ -153,9 +162,5 @@ final class CommandAliasCommand extends Command{
|
||||
));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
}
|
||||
|
@@ -23,40 +23,35 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\MappedParameter;
|
||||
use pocketmine\command\overload\ParameterParseException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\GameMode;
|
||||
use pocketmine\ServerProperties;
|
||||
use function count;
|
||||
|
||||
class DefaultGamemodeCommand extends VanillaCommand{
|
||||
class DefaultGamemodeCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([
|
||||
new MappedParameter(
|
||||
"gameMode",
|
||||
"game mode",
|
||||
static fn(string $v) : GameMode => GameMode::fromString($v) ?? throw new ParameterParseException("Illegal gamemode value")
|
||||
)
|
||||
], DefaultPermissionNames::COMMAND_DEFAULTGAMEMODE, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_defaultgamemode_description(),
|
||||
KnownTranslationFactory::commands_defaultgamemode_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_DEFAULTGAMEMODE);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$gameMode = GameMode::fromString($args[0]);
|
||||
if($gameMode === null){
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gamemode_unknown($args[0]));
|
||||
return true;
|
||||
}
|
||||
|
||||
//TODO: this probably shouldn't use the enum name directly
|
||||
public function execute(CommandSender $sender, GameMode $gameMode) : void{
|
||||
$sender->getServer()->getConfigGroup()->setConfigString(ServerProperties::GAME_MODE, $gameMode->name);
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_defaultgamemode_success($gameMode->getTranslatableName()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,42 +25,32 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
|
||||
class DeopCommand extends VanillaCommand{
|
||||
class DeopCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload(
|
||||
[new StringParameter("playerName", "player name")],
|
||||
DefaultPermissionNames::COMMAND_OP_TAKE,
|
||||
self::execute(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_deop_description(),
|
||||
KnownTranslationFactory::commands_deop_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_OP_TAKE);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$name = array_shift($args);
|
||||
if(!Player::isValidUserName($name)){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$sender->getServer()->removeOp($name);
|
||||
if(($player = $sender->getServer()->getPlayerExact($name)) !== null){
|
||||
private static function execute(CommandSender $sender, string $playerName) : void{
|
||||
$sender->getServer()->removeOp($playerName);
|
||||
if(($player = $sender->getServer()->getPlayerExact($playerName)) !== null){
|
||||
$player->sendMessage(KnownTranslationFactory::commands_deop_message()->prefix(TextFormat::GRAY));
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_deop_success($name));
|
||||
|
||||
return true;
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_deop_success($playerName));
|
||||
}
|
||||
}
|
||||
|
@@ -25,37 +25,44 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\MappedParameter;
|
||||
use pocketmine\command\overload\ParameterParseException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\ServerProperties;
|
||||
use pocketmine\world\World;
|
||||
use function count;
|
||||
|
||||
class DifficultyCommand extends VanillaCommand{
|
||||
class DifficultyCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload(
|
||||
[new MappedParameter(
|
||||
"difficulty",
|
||||
"difficulty",
|
||||
static function(string $v) : int{
|
||||
$difficulty = World::getDifficultyFromString($v);
|
||||
if($difficulty === -1){
|
||||
throw new ParameterParseException("Invalid difficulty value");
|
||||
}
|
||||
return $difficulty;
|
||||
}
|
||||
)],
|
||||
DefaultPermissionNames::COMMAND_DIFFICULTY,
|
||||
self::execute(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_difficulty_description(),
|
||||
KnownTranslationFactory::commands_difficulty_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_DIFFICULTY);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) !== 1){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$difficulty = World::getDifficultyFromString($args[0]);
|
||||
|
||||
private static function execute(CommandSender $sender, int $difficulty) : void{
|
||||
if($sender->getServer()->isHardcore()){
|
||||
$difficulty = World::DIFFICULTY_HARD;
|
||||
}
|
||||
|
||||
if($difficulty !== -1){
|
||||
$sender->getServer()->getConfigGroup()->setConfigInt(ServerProperties::DIFFICULTY, $difficulty);
|
||||
|
||||
//TODO: add per-world support
|
||||
@@ -64,10 +71,5 @@ class DifficultyCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_difficulty_success((string) $difficulty));
|
||||
}else{
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -23,26 +23,31 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\RawParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function date;
|
||||
|
||||
class DumpMemoryCommand extends VanillaCommand{
|
||||
class DumpMemoryCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload(
|
||||
[new RawParameter("path", "path")],
|
||||
DefaultPermissionNames::COMMAND_DUMPMEMORY,
|
||||
self::execute(...)
|
||||
)],
|
||||
KnownTranslationFactory::pocketmine_command_dumpmemory_description(),
|
||||
"/dumpmemory [path]"
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_DUMPMEMORY);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
$sender->getServer()->getMemoryManager()->dumpServerMemory($args[0] ?? (Path::join($sender->getServer()->getDataPath(), "memory_dumps", date("D_M_j-H.i.s-T_Y"))), 48, 80);
|
||||
return true;
|
||||
private static function execute(CommandSender $sender, string $path = "") : void{
|
||||
$sender->getServer()->getMemoryManager()->dumpServerMemory($path !== "" ? $path : (Path::join($sender->getServer()->getDataPath(), "memory_dumps", date("D_M_j-H.i.s-T_Y"))), 48, 80);
|
||||
}
|
||||
}
|
||||
|
@@ -23,81 +23,84 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\BoolParameter;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\IntRangeParameter;
|
||||
use pocketmine\command\overload\MappedParameter;
|
||||
use pocketmine\command\overload\ParameterParseException;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\entity\effect\Effect;
|
||||
use pocketmine\entity\effect\EffectInstance;
|
||||
use pocketmine\entity\effect\StringToEffectParser;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\Limits;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function strtolower;
|
||||
|
||||
class EffectCommand extends VanillaCommand{
|
||||
class EffectCommand extends Command{
|
||||
|
||||
private const SELF_PERM = DefaultPermissionNames::COMMAND_EFFECT_OTHER;
|
||||
private const OTHER_PERM = DefaultPermissionNames::COMMAND_EFFECT_OTHER;
|
||||
|
||||
private const OVERLOAD_PERMS = [self::SELF_PERM, self::OTHER_PERM];
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[
|
||||
new CommandOverload([
|
||||
//TODO: this should be a target param in the future
|
||||
new StringParameter("target", "target"),
|
||||
"clear"
|
||||
|
||||
//TODO: our permission system isn't granular enough for this right now - the permission required
|
||||
//differs not by the usage, but by the target selected
|
||||
], self::OVERLOAD_PERMS, self::removeEffect(...)),
|
||||
new CommandOverload([
|
||||
new StringParameter("target", "target"),
|
||||
new MappedParameter("effect", "effect name", static fn(string $v) : Effect =>
|
||||
StringToEffectParser::getInstance()->parse($v) ??
|
||||
throw new ParameterParseException("Invalid effect name")
|
||||
),
|
||||
new IntRangeParameter("duration", "duration", 0, (int) (Limits::INT32_MAX / 20)),
|
||||
new IntRangeParameter("amplifier", "amplifier", 0, 255),
|
||||
new BoolParameter("bubbles", "bubbles")
|
||||
|
||||
//TODO: our permission system isn't granular enough for this right now - the permission required
|
||||
//differs not by the usage, but by the target selected
|
||||
], self::OVERLOAD_PERMS, self::modifyEffect(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_effect_description(),
|
||||
KnownTranslationFactory::commands_effect_usage()
|
||||
);
|
||||
$this->setPermissions([
|
||||
DefaultPermissionNames::COMMAND_EFFECT_SELF,
|
||||
DefaultPermissionNames::COMMAND_EFFECT_OTHER
|
||||
]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) < 2){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player = $this->fetchPermittedPlayerTarget($commandLabel, $sender, $args[0], DefaultPermissionNames::COMMAND_EFFECT_SELF, DefaultPermissionNames::COMMAND_EFFECT_OTHER);
|
||||
private static function removeEffect(CommandSender $sender, string $target) : void{
|
||||
$player = self::fetchPermittedPlayerTarget($sender, $target, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($player === null){
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
$effectManager = $player->getEffects();
|
||||
|
||||
if(strtolower($args[1]) === "clear"){
|
||||
$effectManager->clear();
|
||||
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_effect_success_removed_all($player->getDisplayName()));
|
||||
return true;
|
||||
}
|
||||
|
||||
$effect = StringToEffectParser::getInstance()->parse($args[1]);
|
||||
if($effect === null){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_effect_notFound($args[1])->prefix(TextFormat::RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
$amplification = 0;
|
||||
|
||||
if(count($args) >= 3){
|
||||
if(($d = $this->getBoundedInt($sender, $args[2], 0, (int) (Limits::INT32_MAX / 20))) === null){
|
||||
return false;
|
||||
}
|
||||
$duration = $d * 20; //ticks
|
||||
}else{
|
||||
$duration = null;
|
||||
}
|
||||
|
||||
if(count($args) >= 4){
|
||||
$amplification = $this->getBoundedInt($sender, $args[3], 0, 255);
|
||||
if($amplification === null){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$visible = true;
|
||||
if(count($args) >= 5){
|
||||
$v = strtolower($args[4]);
|
||||
if($v === "on" || $v === "true" || $v === "t" || $v === "1"){
|
||||
$visible = false;
|
||||
}
|
||||
private function modifyEffect(
|
||||
CommandSender $sender,
|
||||
string $target,
|
||||
Effect $effect,
|
||||
?int $duration = null,
|
||||
int $amplifier = 0,
|
||||
bool $bubbles = true
|
||||
) : void{
|
||||
$player = self::fetchPermittedPlayerTarget($sender, $target, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($player === null){
|
||||
return;
|
||||
}
|
||||
$effectManager = $player->getEffects();
|
||||
|
||||
if($duration === 0){
|
||||
if(!$effectManager->has($effect)){
|
||||
@@ -106,17 +109,15 @@ class EffectCommand extends VanillaCommand{
|
||||
}else{
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_effect_failure_notActive($effect->getName(), $player->getDisplayName()));
|
||||
}
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
$effectManager->remove($effect);
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_effect_success_removed($effect->getName(), $player->getDisplayName()));
|
||||
}else{
|
||||
$instance = new EffectInstance($effect, $duration, $amplification, $visible);
|
||||
$instance = new EffectInstance($effect, $duration !== null ? $duration * 20 : null, $amplifier, $bubbles);
|
||||
$effectManager->add($instance);
|
||||
self::broadcastCommandMessage($sender, KnownTranslationFactory::commands_effect_success($effect->getName(), (string) $instance->getAmplifier(), $player->getDisplayName(), (string) ($instance->getDuration() / 20)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -23,59 +23,61 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\IntRangeParameter;
|
||||
use pocketmine\command\overload\MappedParameter;
|
||||
use pocketmine\command\overload\ParameterParseException;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\item\enchantment\EnchantingHelper;
|
||||
use pocketmine\item\enchantment\Enchantment;
|
||||
use pocketmine\item\enchantment\EnchantmentInstance;
|
||||
use pocketmine\item\enchantment\StringToEnchantmentParser;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use function count;
|
||||
use pocketmine\utils\TextFormat;
|
||||
|
||||
class EnchantCommand extends VanillaCommand{
|
||||
class EnchantCommand extends Command{
|
||||
|
||||
private const string SELF_PERM = DefaultPermissionNames::COMMAND_ENCHANT_SELF;
|
||||
private const string OTHER_PERM = DefaultPermissionNames::COMMAND_ENCHANT_OTHER;
|
||||
|
||||
private const OVERLOAD_PERMS = [self::SELF_PERM, self::OTHER_PERM];
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_enchant_description(),
|
||||
KnownTranslationFactory::commands_enchant_usage()
|
||||
[new CommandOverload([
|
||||
new StringParameter("target", "target"),
|
||||
new MappedParameter("enchantment", "enchantment", static fn(string $v) : Enchantment => StringToEnchantmentParser::getInstance()->parse($v) ??
|
||||
throw new ParameterParseException("Invalid enchantment name")
|
||||
),
|
||||
//sad, this one depends on previous parameters :(
|
||||
new IntRangeParameter("level", "level", 1, 10)
|
||||
], self::OVERLOAD_PERMS, self::enchant(...))],
|
||||
KnownTranslationFactory::pocketmine_command_enchant_description()
|
||||
);
|
||||
$this->setPermissions([
|
||||
DefaultPermissionNames::COMMAND_ENCHANT_SELF,
|
||||
DefaultPermissionNames::COMMAND_ENCHANT_OTHER
|
||||
]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) < 2){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player = $this->fetchPermittedPlayerTarget($commandLabel, $sender, $args[0], DefaultPermissionNames::COMMAND_ENCHANT_SELF, DefaultPermissionNames::COMMAND_ENCHANT_OTHER);
|
||||
private function enchant(CommandSender $sender, string $target, Enchantment $enchantment, int $level = 1) : void{
|
||||
$player = self::fetchPermittedPlayerTarget($sender, $target, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($player === null){
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
$item = $player->getMainHandItem();
|
||||
|
||||
if($item->isNull()){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_enchant_noItem());
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
$enchantment = StringToEnchantmentParser::getInstance()->parse($args[1]);
|
||||
if($enchantment === null){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_enchant_notFound($args[1]));
|
||||
return true;
|
||||
}
|
||||
|
||||
$level = 1;
|
||||
if(isset($args[2])){
|
||||
$level = $this->getBoundedInt($sender, $args[2], 1, $enchantment->getMaxLevel());
|
||||
if($level === null){
|
||||
return false;
|
||||
}
|
||||
$max = $enchantment->getMaxLevel();
|
||||
if($level > $max){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_generic_num_tooBig("$level", "$max")->prefix(TextFormat::RED));
|
||||
return;
|
||||
}
|
||||
|
||||
//this is necessary to deal with enchanted books, which are a different item type than regular books
|
||||
@@ -83,6 +85,5 @@ class EnchantCommand extends VanillaCommand{
|
||||
$player->setMainHandItem($enchantedItem);
|
||||
|
||||
self::broadcastCommandMessage($sender, KnownTranslationFactory::commands_enchant_success($player->getName()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,46 +25,44 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\MappedParameter;
|
||||
use pocketmine\command\overload\ParameterParseException;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\GameMode;
|
||||
use function count;
|
||||
|
||||
class GamemodeCommand extends VanillaCommand{
|
||||
class GamemodeCommand extends Command{
|
||||
|
||||
private const string SELF_PERM = DefaultPermissionNames::COMMAND_GAMEMODE_SELF;
|
||||
private const string OTHER_PERM = DefaultPermissionNames::COMMAND_GAMEMODE_OTHER;
|
||||
|
||||
private const OVERLOAD_PERMS = [self::SELF_PERM, self::OTHER_PERM];
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([
|
||||
new MappedParameter("gameMode", "game mode", static fn(string $v) : GameMode =>
|
||||
GameMode::fromString($v) ?? throw new ParameterParseException("Invalid game mode: $v")
|
||||
),
|
||||
new StringParameter("target", "target")
|
||||
], self::OVERLOAD_PERMS, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_gamemode_description(),
|
||||
KnownTranslationFactory::commands_gamemode_usage()
|
||||
);
|
||||
$this->setPermissions([
|
||||
DefaultPermissionNames::COMMAND_GAMEMODE_SELF,
|
||||
DefaultPermissionNames::COMMAND_GAMEMODE_OTHER
|
||||
]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$gameMode = GameMode::fromString($args[0]);
|
||||
if($gameMode === null){
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gamemode_unknown($args[0]));
|
||||
return true;
|
||||
}
|
||||
|
||||
$target = $this->fetchPermittedPlayerTarget($commandLabel, $sender, $args[1] ?? null, DefaultPermissionNames::COMMAND_GAMEMODE_SELF, DefaultPermissionNames::COMMAND_GAMEMODE_OTHER);
|
||||
private static function execute(CommandSender $sender, GameMode $gameMode, ?string $target = null) : void{
|
||||
$target = self::fetchPermittedPlayerTarget($sender, $target, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($target === null){
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if($target->getGamemode() === $gameMode){
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gamemode_failure($target->getName()));
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
$target->setGamemode($gameMode);
|
||||
@@ -78,7 +76,5 @@ class GamemodeCommand extends VanillaCommand{
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_gamemode_success_other($gameMode->getTranslatableName(), $target->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@@ -32,18 +34,18 @@ use function memory_get_usage;
|
||||
use function number_format;
|
||||
use function round;
|
||||
|
||||
class GarbageCollectorCommand extends VanillaCommand{
|
||||
class GarbageCollectorCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([], DefaultPermissionNames::COMMAND_GC, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_gc_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_GC);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
private static function execute(CommandSender $sender) : void{
|
||||
$chunksCollected = 0;
|
||||
$entitiesCollected = 0;
|
||||
|
||||
@@ -66,6 +68,5 @@ class GarbageCollectorCommand extends VanillaCommand{
|
||||
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gc_cycles(TextFormat::RED . number_format($cyclesCollected))->prefix(TextFormat::GOLD));
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gc_memoryFreed(TextFormat::RED . number_format(round((($memory - memory_get_usage()) / 1024) / 1024, 2), 2))->prefix(TextFormat::GOLD));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,11 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\IntRangeParameter;
|
||||
use pocketmine\command\overload\ParameterParseException;
|
||||
use pocketmine\command\overload\RawParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\item\LegacyStringToItemParser;
|
||||
use pocketmine\item\LegacyStringToItemParserException;
|
||||
use pocketmine\item\StringToItemParser;
|
||||
@@ -34,67 +38,54 @@ use pocketmine\nbt\JsonNbtParser;
|
||||
use pocketmine\nbt\NbtDataException;
|
||||
use pocketmine\nbt\NbtException;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_slice;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class GiveCommand extends VanillaCommand{
|
||||
class GiveCommand extends Command{
|
||||
|
||||
private const string SELF_PERM = DefaultPermissionNames::COMMAND_GIVE_SELF;
|
||||
private const string OTHER_PERM = DefaultPermissionNames::COMMAND_GIVE_OTHER;
|
||||
|
||||
private const OVERLOAD_PERMS = [self::SELF_PERM, self::OTHER_PERM];
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([
|
||||
new StringParameter("target", "target"),
|
||||
new StringParameter("itemName", "item"),
|
||||
new IntRangeParameter("count", "count", 1, 32767),
|
||||
new RawParameter("nbt", "nbt")
|
||||
], self::OVERLOAD_PERMS, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_give_description(),
|
||||
KnownTranslationFactory::pocketmine_command_give_usage()
|
||||
);
|
||||
$this->setPermissions([
|
||||
DefaultPermissionNames::COMMAND_GIVE_SELF,
|
||||
DefaultPermissionNames::COMMAND_GIVE_OTHER
|
||||
]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) < 2){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player = $this->fetchPermittedPlayerTarget($commandLabel, $sender, $args[0], DefaultPermissionNames::COMMAND_GIVE_SELF, DefaultPermissionNames::COMMAND_GIVE_OTHER);
|
||||
private static function execute(CommandSender $sender, string $target, string $itemName, ?int $count = null, ?string $nbt = null) : void{
|
||||
$player = self::fetchPermittedPlayerTarget($sender, $target, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($player === null){
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
$item = StringToItemParser::getInstance()->parse($args[1]) ?? LegacyStringToItemParser::getInstance()->parse($args[1]);
|
||||
}catch(LegacyStringToItemParserException $e){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_give_item_notFound($args[1])->prefix(TextFormat::RED));
|
||||
return true;
|
||||
$item = StringToItemParser::getInstance()->parse($itemName) ?? LegacyStringToItemParser::getInstance()->parse($itemName);
|
||||
}catch(LegacyStringToItemParserException){
|
||||
throw new ParameterParseException("Invalid item name $itemName");
|
||||
}
|
||||
$item->setCount($count ?? $item->getMaxStackSize());
|
||||
|
||||
if(!isset($args[2])){
|
||||
$item->setCount($item->getMaxStackSize());
|
||||
}else{
|
||||
$count = $this->getBoundedInt($sender, $args[2], 1, 32767);
|
||||
if($count === null){
|
||||
return true;
|
||||
}
|
||||
$item->setCount($count);
|
||||
}
|
||||
|
||||
if(isset($args[3])){
|
||||
$data = implode(" ", array_slice($args, 3));
|
||||
if($nbt !== null){
|
||||
try{
|
||||
$tags = JsonNbtParser::parseJson($data);
|
||||
$tags = JsonNbtParser::parseJson($nbt);
|
||||
}catch(NbtDataException $e){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_give_tagError($e->getMessage()));
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
$item->setNamedTag($tags);
|
||||
}catch(NbtException $e){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_give_tagError($e->getMessage()));
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,10 +93,9 @@ class GiveCommand extends VanillaCommand{
|
||||
$player->getInventory()->addItem($item);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_give_success(
|
||||
$item->getName() . " (" . $args[1] . ")",
|
||||
$item->getName() . " ($itemName)",
|
||||
(string) $item->getCount(),
|
||||
$player->getName()
|
||||
));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,9 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\IntRangeParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\command\SimpleCommandMap;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\Translatable;
|
||||
@@ -34,12 +37,10 @@ use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\Utils;
|
||||
use function array_chunk;
|
||||
use function array_key_first;
|
||||
use function array_pop;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function is_array;
|
||||
use function is_numeric;
|
||||
use function ksort;
|
||||
use function min;
|
||||
use function sort;
|
||||
@@ -48,42 +49,33 @@ use const PHP_INT_MAX;
|
||||
use const SORT_FLAG_CASE;
|
||||
use const SORT_NATURAL;
|
||||
|
||||
class HelpCommand extends VanillaCommand{
|
||||
class HelpCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[
|
||||
new CommandOverload([
|
||||
new IntRangeParameter("pageNumber", "page", 1, PHP_INT_MAX)
|
||||
], DefaultPermissionNames::COMMAND_HELP, self::commandListPage(...)),
|
||||
new CommandOverload([
|
||||
new StringParameter("commandName", "command name")
|
||||
], DefaultPermissionNames::COMMAND_HELP, self::commandSpecificInfo(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_help_description(),
|
||||
KnownTranslationFactory::commands_help_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_HELP);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
$commandName = "";
|
||||
$pageNumber = 1;
|
||||
}elseif(is_numeric($args[count($args) - 1])){
|
||||
$pageNumber = (int) array_pop($args);
|
||||
if($pageNumber <= 0){
|
||||
$pageNumber = 1;
|
||||
}
|
||||
$commandName = implode(" ", $args);
|
||||
}else{
|
||||
$commandName = implode(" ", $args);
|
||||
$pageNumber = 1;
|
||||
}
|
||||
|
||||
private static function commandListPage(CommandSender $sender, int $pageNumber = 1) : void{
|
||||
$pageHeight = $sender->getScreenLineHeight();
|
||||
|
||||
//TODO: maybe inject this in the constructor instead of assuming the server's command map?
|
||||
$commandMap = $sender->getServer()->getCommandMap();
|
||||
$userAliasMap = $sender->getCommandAliasMap();
|
||||
if($commandName === ""){
|
||||
$commands = [];
|
||||
foreach($commandMap->getUniqueCommands() as $command){
|
||||
if($command->testPermissionSilent($sender)){
|
||||
if(count($command->getUsages($sender, "")) > 0){
|
||||
$userAliases = $userAliasMap->getMergedAliases($command->getId(), $commandMap->getAliasMap());
|
||||
$preferredAlias = $userAliases[array_key_first($userAliases)];
|
||||
if(isset($commands[$preferredAlias])){
|
||||
@@ -107,16 +99,22 @@ class HelpCommand extends VanillaCommand{
|
||||
$sender->sendMessage(TextFormat::DARK_GREEN . "/$preferredAlias: " . TextFormat::RESET . $descriptionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}else{
|
||||
private static function commandSpecificInfo(CommandSender $sender, string $commandName) : void{
|
||||
//TODO: maybe inject this in the constructor instead of assuming the server's command map?
|
||||
$commandMap = $sender->getServer()->getCommandMap();
|
||||
$userAliasMap = $sender->getCommandAliasMap();
|
||||
if(($command = $commandMap->getCommand(strtolower($commandName), $userAliasMap)) !== null){
|
||||
if(is_array($command)){
|
||||
SimpleCommandMap::handleConflicted($sender, $commandName, $command, $commandMap->getAliasMap());
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if($command->testPermissionSilent($sender)){
|
||||
|
||||
$lang = $sender->getLanguage();
|
||||
$usages = $command->getUsages($sender, $commandName);
|
||||
|
||||
if(count($usages) > 0){ //only permitted usages are shown
|
||||
$description = $command->getDescription();
|
||||
$descriptionString = $description instanceof Translatable ? $lang->translate($description) : $description;
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_help_specificCommand_header($commandName)
|
||||
@@ -124,22 +122,20 @@ class HelpCommand extends VanillaCommand{
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_help_specificCommand_description(TextFormat::RESET . $descriptionString)
|
||||
->prefix(TextFormat::GOLD));
|
||||
|
||||
$usage = $command->getUsage() ?? "/$commandName";
|
||||
$usageString = $usage instanceof Translatable ? $lang->translate($usage) : $usage;
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_help_specificCommand_usage(TextFormat::RESET . implode("\n" . TextFormat::RESET, explode("\n", $usageString, limit: PHP_INT_MAX)))
|
||||
->prefix(TextFormat::GOLD));
|
||||
|
||||
$aliases = $userAliasMap->getMergedAliases($command->getId(), $commandMap->getAliasMap());
|
||||
sort($aliases, SORT_NATURAL);
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_help_specificCommand_aliases(TextFormat::RESET . implode(", ", $aliases))
|
||||
->prefix(TextFormat::GOLD));
|
||||
|
||||
return true;
|
||||
foreach($usages as $usage){
|
||||
$usageString = $lang->translate($usage);
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_help_specificCommand_usage(TextFormat::RESET . implode("\n" . TextFormat::RESET, explode("\n", $usageString, limit: PHP_INT_MAX)))
|
||||
->prefix(TextFormat::GOLD));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_notFound($commandName, "/" . $userAliasMap->getPreferredAlias("pocketmine:help", $commandMap->getAliasMap()))->prefix(TextFormat::RED));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,37 +25,30 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\RawParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function trim;
|
||||
|
||||
class KickCommand extends VanillaCommand{
|
||||
class KickCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([
|
||||
new StringParameter("playerName", "player name"),
|
||||
new RawParameter("reason", "reason")
|
||||
], DefaultPermissionNames::COMMAND_KICK, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_kick_description(),
|
||||
KnownTranslationFactory::commands_kick_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_KICK);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$name = array_shift($args);
|
||||
$reason = trim(implode(" ", $args));
|
||||
|
||||
if(($player = $sender->getServer()->getPlayerByPrefix($name)) instanceof Player){
|
||||
private static function execute(CommandSender $sender, string $playerName, string $reason = "") : void{
|
||||
if(($player = $sender->getServer()->getPlayerByPrefix($playerName)) instanceof Player){
|
||||
$player->kick($reason !== "" ? KnownTranslationFactory::pocketmine_disconnect_kick($reason) : KnownTranslationFactory::pocketmine_disconnect_kick_noReason());
|
||||
if($reason !== ""){
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_kick_success_reason($player->getName(), $reason));
|
||||
@@ -65,7 +58,5 @@ class KickCommand extends VanillaCommand{
|
||||
}else{
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_generic_player_notFound()->prefix(TextFormat::RED));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,32 +25,34 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use function count;
|
||||
|
||||
class KillCommand extends VanillaCommand{
|
||||
class KillCommand extends Command{
|
||||
|
||||
private const string SELF_PERM = DefaultPermissionNames::COMMAND_KILL_SELF;
|
||||
private const string OTHER_PERM = DefaultPermissionNames::COMMAND_KILL_OTHER;
|
||||
|
||||
private const OVERLOAD_PERMS = [self::SELF_PERM, self::OTHER_PERM];
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_kill_description(),
|
||||
KnownTranslationFactory::pocketmine_command_kill_usage()
|
||||
[new CommandOverload([
|
||||
new StringParameter("target", "target")
|
||||
], self::OVERLOAD_PERMS, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_kill_description()
|
||||
);
|
||||
$this->setPermissions([DefaultPermissionNames::COMMAND_KILL_SELF, DefaultPermissionNames::COMMAND_KILL_OTHER]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) >= 2){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player = $this->fetchPermittedPlayerTarget($commandLabel, $sender, $args[0] ?? null, DefaultPermissionNames::COMMAND_KILL_SELF, DefaultPermissionNames::COMMAND_KILL_OTHER);
|
||||
private static function execute(CommandSender $sender, ?string $target = null) : void{
|
||||
$player = self::fetchPermittedPlayerTarget($sender, $target, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($player === null){
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
$player->attack(new EntityDamageEvent($player, EntityDamageEvent::CAUSE_SUICIDE, $player->getHealth()));
|
||||
@@ -59,7 +61,5 @@ class KillCommand extends VanillaCommand{
|
||||
}else{
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_kill_successful($player->getName()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
@@ -34,18 +36,18 @@ use function implode;
|
||||
use function sort;
|
||||
use const SORT_STRING;
|
||||
|
||||
class ListCommand extends VanillaCommand{
|
||||
class ListCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([], DefaultPermissionNames::COMMAND_LIST, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_list_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_LIST);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
private static function execute(CommandSender $sender) : void{
|
||||
$playerNames = array_map(function(Player $player) : string{
|
||||
return $player->getName();
|
||||
}, array_filter($sender->getServer()->getOnlinePlayers(), function(Player $player) use ($sender) : bool{
|
||||
@@ -55,7 +57,5 @@ class ListCommand extends VanillaCommand{
|
||||
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_players_list((string) count($playerNames), (string) $sender->getServer()->getMaxPlayers()));
|
||||
$sender->sendMessage(implode(", ", $playerNames));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -23,34 +23,34 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\RawParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class MeCommand extends VanillaCommand{
|
||||
class MeCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload(
|
||||
[new RawParameter("message", "message")],
|
||||
DefaultPermissionNames::COMMAND_ME,
|
||||
self::execute(...)
|
||||
)],
|
||||
KnownTranslationFactory::pocketmine_command_me_description(),
|
||||
KnownTranslationFactory::commands_me_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_ME);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$sender->getServer()->broadcastMessage(KnownTranslationFactory::chat_type_emote($sender instanceof Player ? $sender->getDisplayName() : $sender->getName(), TextFormat::RESET . implode(" ", $args)));
|
||||
|
||||
return true;
|
||||
private static function execute(CommandSender $sender, string $message) : void{
|
||||
$sender->getServer()->broadcastMessage(KnownTranslationFactory::chat_type_emote(
|
||||
$sender instanceof Player ? $sender->getDisplayName() : $sender->getName(),
|
||||
TextFormat::RESET . $message
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@@ -25,41 +25,38 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
|
||||
class OpCommand extends VanillaCommand{
|
||||
class OpCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload(
|
||||
[new StringParameter("playerName", "player name")],
|
||||
DefaultPermissionNames::COMMAND_OP_GIVE,
|
||||
self::execute(...)
|
||||
)],
|
||||
KnownTranslationFactory::pocketmine_command_op_description(),
|
||||
KnownTranslationFactory::commands_op_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_OP_GIVE);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
private static function execute(CommandSender $sender, string $playerName) : void{
|
||||
if(!Player::isValidUserName($playerName)){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$name = array_shift($args);
|
||||
if(!Player::isValidUserName($name)){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$sender->getServer()->addOp($name);
|
||||
if(($player = $sender->getServer()->getPlayerExact($name)) !== null){
|
||||
$sender->getServer()->addOp($playerName);
|
||||
if(($player = $sender->getServer()->getPlayerExact($playerName)) !== null){
|
||||
$player->sendMessage(KnownTranslationFactory::commands_op_message()->prefix(TextFormat::GRAY));
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_op_success($name));
|
||||
return true;
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_op_success($playerName));
|
||||
}
|
||||
}
|
||||
|
@@ -25,32 +25,29 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use function count;
|
||||
|
||||
class PardonCommand extends VanillaCommand{
|
||||
class PardonCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload(
|
||||
[new StringParameter("playerName", "player name")],
|
||||
DefaultPermissionNames::COMMAND_UNBAN_PLAYER,
|
||||
self::execute(...)
|
||||
)],
|
||||
KnownTranslationFactory::pocketmine_command_unban_player_description(),
|
||||
KnownTranslationFactory::commands_unban_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_UNBAN_PLAYER);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) !== 1){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
private static function execute(CommandSender $sender, string $playerName) : void{
|
||||
$sender->getServer()->getNameBans()->remove($playerName);
|
||||
|
||||
$sender->getServer()->getNameBans()->remove($args[0]);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_unban_success($args[0]));
|
||||
|
||||
return true;
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_unban_success($playerName));
|
||||
}
|
||||
}
|
||||
|
@@ -25,37 +25,34 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use function count;
|
||||
use function inet_pton;
|
||||
|
||||
class PardonIpCommand extends VanillaCommand{
|
||||
class PardonIpCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_unban_ip_description(),
|
||||
KnownTranslationFactory::commands_unbanip_usage()
|
||||
[new CommandOverload(
|
||||
[new StringParameter("ip", "IP address")],
|
||||
DefaultPermissionNames::COMMAND_UNBAN_IP,
|
||||
self::execute(...)
|
||||
)],
|
||||
KnownTranslationFactory::pocketmine_command_unban_ip_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_UNBAN_IP);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) !== 1){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
if(inet_pton($args[0]) !== false){
|
||||
$sender->getServer()->getIPBans()->remove($args[0]);
|
||||
$sender->getServer()->getNetwork()->unblockAddress($args[0]);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_unbanip_success($args[0]));
|
||||
private static function execute(CommandSender $sender, string $ip) : void{
|
||||
if(inet_pton($ip) !== false){
|
||||
$sender->getServer()->getIPBans()->remove($ip);
|
||||
$sender->getServer()->getNetwork()->unblockAddress($ip);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_unbanip_success($ip));
|
||||
}else{
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_unbanip_invalid());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,14 +25,21 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\block\BlockTypeIds;
|
||||
use pocketmine\color\Color;
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\FloatRangeParameter;
|
||||
use pocketmine\command\overload\IntRangeParameter;
|
||||
use pocketmine\command\overload\RelativeFloat;
|
||||
use pocketmine\command\overload\RelativeFloatParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\item\StringToItemParser;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\Limits;
|
||||
use pocketmine\utils\Random;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\world\particle\AngryVillagerParticle;
|
||||
@@ -67,59 +74,71 @@ use pocketmine\world\particle\WaterParticle;
|
||||
use pocketmine\world\World;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function max;
|
||||
use function microtime;
|
||||
use function mt_rand;
|
||||
use function strtolower;
|
||||
|
||||
class ParticleCommand extends VanillaCommand{
|
||||
class ParticleCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_particle_description(),
|
||||
KnownTranslationFactory::pocketmine_command_particle_usage()
|
||||
[new CommandOverload(
|
||||
[
|
||||
new StringParameter("particleName", "particle name"),
|
||||
new RelativeFloatParameter("x", "x"),
|
||||
new RelativeFloatParameter("y", "y"),
|
||||
new RelativeFloatParameter("z", "z"),
|
||||
new FloatRangeParameter("xd", "xd", -1000, 1000),
|
||||
new FloatRangeParameter("yd", "yd", -1000, 1000),
|
||||
new FloatRangeParameter("zd", "zd", -1000, 1000),
|
||||
new IntRangeParameter("count", "count", 1, 100000),
|
||||
new StringParameter("data", "data")
|
||||
],
|
||||
DefaultPermissionNames::COMMAND_PARTICLE,
|
||||
self::execute(...)
|
||||
)],
|
||||
KnownTranslationFactory::pocketmine_command_particle_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_PARTICLE);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) < 7){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
private static function execute(
|
||||
CommandSender $sender,
|
||||
string $particleName,
|
||||
RelativeFloat $x,
|
||||
RelativeFloat $y,
|
||||
RelativeFloat $z,
|
||||
float $xd = 0.0,
|
||||
float $yd = 0.0,
|
||||
float $zd = 0.0,
|
||||
int $count = 1,
|
||||
string $data = ""
|
||||
) : void{
|
||||
|
||||
if($sender instanceof Player){
|
||||
$senderPos = $sender->getPosition();
|
||||
$world = $senderPos->getWorld();
|
||||
$pos = new Vector3(
|
||||
$this->getRelativeDouble($senderPos->getX(), $sender, $args[1]),
|
||||
$this->getRelativeDouble($senderPos->getY(), $sender, $args[2], World::Y_MIN, World::Y_MAX),
|
||||
$this->getRelativeDouble($senderPos->getZ(), $sender, $args[3])
|
||||
);
|
||||
[$senderX, $senderY, $senderZ] = [$senderPos->getX(), $senderPos->getY(), $senderPos->getZ()];
|
||||
}else{
|
||||
$world = $sender->getServer()->getWorldManager()->getDefaultWorld();
|
||||
$pos = new Vector3((float) $args[1], (float) $args[2], (float) $args[3]);
|
||||
[$senderX, $senderY, $senderZ] = [0, 0, 0];
|
||||
}
|
||||
|
||||
$name = strtolower($args[0]);
|
||||
$pos = new Vector3(
|
||||
$x->resolve($senderX, Limits::INT32_MIN, Limits::INT32_MAX),
|
||||
$y->resolve($senderY, World::Y_MIN, World::Y_MAX),
|
||||
$z->resolve($senderZ, Limits::INT32_MIN, Limits::INT32_MAX)
|
||||
);
|
||||
|
||||
$xd = (float) $args[4];
|
||||
$yd = (float) $args[5];
|
||||
$zd = (float) $args[6];
|
||||
|
||||
$count = isset($args[7]) ? max(1, (int) $args[7]) : 1;
|
||||
|
||||
$data = $args[8] ?? null;
|
||||
|
||||
$particle = $this->getParticle($name, $data);
|
||||
$particle = self::getParticle(strtolower($particleName), $data);
|
||||
|
||||
if($particle === null){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_particle_notFound($name)->prefix(TextFormat::RED));
|
||||
return true;
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_particle_notFound($particleName)->prefix(TextFormat::RED));
|
||||
return;
|
||||
}
|
||||
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_particle_success($name, (string) $count));
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_particle_success($particleName, (string) $count));
|
||||
|
||||
$random = new Random((int) (microtime(true) * 1000) + mt_rand());
|
||||
|
||||
@@ -130,11 +149,9 @@ class ParticleCommand extends VanillaCommand{
|
||||
$random->nextSignedFloat() * $zd
|
||||
), $particle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getParticle(string $name, ?string $data = null) : ?Particle{
|
||||
private static function getParticle(string $name, ?string $data = null) : ?Particle{
|
||||
switch($name){
|
||||
case "explode":
|
||||
return new ExplodeParticle();
|
||||
|
@@ -23,7 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\plugin\Plugin;
|
||||
@@ -34,25 +36,23 @@ use function implode;
|
||||
use function sort;
|
||||
use const SORT_STRING;
|
||||
|
||||
class PluginsCommand extends VanillaCommand{
|
||||
class PluginsCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([], DefaultPermissionNames::COMMAND_PLUGINS, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_plugins_description(),
|
||||
null
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_PLUGINS);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
private static function execute(CommandSender $sender) : void{
|
||||
$list = array_map(function(Plugin $plugin) : string{
|
||||
return ($plugin->isEnabled() ? TextFormat::GREEN : TextFormat::RED) . $plugin->getDescription()->getFullName();
|
||||
}, $sender->getServer()->getPluginManager()->getPlugins());
|
||||
sort($list, SORT_STRING);
|
||||
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_plugins_success((string) count($list), implode(TextFormat::RESET . ", ", $list)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,23 +25,24 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use function microtime;
|
||||
use function round;
|
||||
|
||||
class SaveCommand extends VanillaCommand{
|
||||
class SaveCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([], DefaultPermissionNames::COMMAND_SAVE_PERFORM, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_save_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SAVE_PERFORM);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
private static function execute(CommandSender $sender) : void{
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_save_start());
|
||||
$start = microtime(true);
|
||||
|
||||
@@ -54,7 +55,5 @@ class SaveCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_save_success((string) round(microtime(true) - $start, 3)));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,25 +25,24 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
|
||||
class SaveOffCommand extends VanillaCommand{
|
||||
class SaveOffCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([], DefaultPermissionNames::COMMAND_SAVE_DISABLE, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_saveoff_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SAVE_DISABLE);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
private static function execute(CommandSender $sender) : void{
|
||||
$sender->getServer()->getWorldManager()->setAutoSave(false);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_save_disabled());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,25 +25,24 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
|
||||
class SaveOnCommand extends VanillaCommand{
|
||||
class SaveOnCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([], DefaultPermissionNames::COMMAND_SAVE_ENABLE, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_saveon_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SAVE_ENABLE);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
private static function execute(CommandSender $sender) : void{
|
||||
$sender->getServer()->getWorldManager()->setAutoSave(true);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_save_enabled());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -23,37 +23,33 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\RawParameter;
|
||||
use pocketmine\console\ConsoleCommandSender;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class SayCommand extends VanillaCommand{
|
||||
class SayCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([
|
||||
new RawParameter("message", "message")
|
||||
], DefaultPermissionNames::COMMAND_SAY, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_say_description(),
|
||||
KnownTranslationFactory::commands_say_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SAY);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
private static function execute(CommandSender $sender, string $message) : void{
|
||||
$sender->getServer()->broadcastMessage(KnownTranslationFactory::chat_type_announcement(
|
||||
$sender instanceof Player ? $sender->getDisplayName() : ($sender instanceof ConsoleCommandSender ? "Server" : $sender->getName()),
|
||||
implode(" ", $args)
|
||||
$message
|
||||
)->prefix(TextFormat::LIGHT_PURPLE));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -23,30 +23,30 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
|
||||
class SeedCommand extends VanillaCommand{
|
||||
class SeedCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([], DefaultPermissionNames::COMMAND_SEED, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_seed_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SEED);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
private static function execute(CommandSender $sender) : void{
|
||||
if($sender instanceof Player){
|
||||
$seed = $sender->getPosition()->getWorld()->getSeed();
|
||||
}else{
|
||||
$seed = $sender->getServer()->getWorldManager()->getDefaultWorld()->getSeed();
|
||||
}
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_seed_success((string) $seed));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,39 +25,50 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\RelativeFloat;
|
||||
use pocketmine\command\overload\RelativeFloatParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\Limits;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\world\World;
|
||||
use function count;
|
||||
|
||||
class SetWorldSpawnCommand extends VanillaCommand{
|
||||
class SetWorldSpawnCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_setworldspawn_description(),
|
||||
KnownTranslationFactory::commands_setworldspawn_usage()
|
||||
[
|
||||
new CommandOverload([], DefaultPermissionNames::COMMAND_SETWORLDSPAWN, self::setSpawnHere(...)),
|
||||
new CommandOverload([
|
||||
new RelativeFloatParameter("x", "x"),
|
||||
new RelativeFloatParameter("y", "y"),
|
||||
new RelativeFloatParameter("z", "z")
|
||||
], DefaultPermissionNames::COMMAND_SETWORLDSPAWN, self::setSpawnCoordinates(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_setworldspawn_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SETWORLDSPAWN);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
if($sender instanceof Player){
|
||||
private static function setSpawnHere(CommandSender $sender) : void{
|
||||
if(!$sender instanceof Player){
|
||||
$sender->sendMessage(TextFormat::RED . "You can only perform this command as a player");
|
||||
return;
|
||||
}
|
||||
$location = $sender->getPosition();
|
||||
$world = $location->getWorld();
|
||||
$pos = $location->asVector3()->floor();
|
||||
}else{
|
||||
$sender->sendMessage(TextFormat::RED . "You can only perform this command as a player");
|
||||
|
||||
return true;
|
||||
$world->setSpawnLocation($pos);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_setworldspawn_success((string) $pos->x, (string) $pos->y, (string) $pos->z));
|
||||
}
|
||||
}elseif(count($args) === 3){
|
||||
|
||||
private static function setSpawnCoordinates(CommandSender $sender, RelativeFloat $x, RelativeFloat $y, RelativeFloat $z) : void{
|
||||
if($sender instanceof Player){
|
||||
$base = $sender->getPosition();
|
||||
$world = $base->getWorld();
|
||||
@@ -66,18 +77,13 @@ class SetWorldSpawnCommand extends VanillaCommand{
|
||||
$world = $sender->getServer()->getWorldManager()->getDefaultWorld();
|
||||
}
|
||||
$pos = (new Vector3(
|
||||
$this->getRelativeDouble($base->x, $sender, $args[0]),
|
||||
$this->getRelativeDouble($base->y, $sender, $args[1], World::Y_MIN, World::Y_MAX),
|
||||
$this->getRelativeDouble($base->z, $sender, $args[2]),
|
||||
$x->resolve($base->x, Limits::INT32_MIN, Limits::INT32_MAX),
|
||||
$y->resolve($base->y, World::Y_MIN, World::Y_MAX),
|
||||
$z->resolve($base->z, Limits::INT32_MIN, Limits::INT32_MAX)
|
||||
))->floor();
|
||||
}else{
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$world->setSpawnLocation($pos);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_setworldspawn_success((string) $pos->x, (string) $pos->y, (string) $pos->z));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,56 +25,71 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\RelativeFloat;
|
||||
use pocketmine\command\overload\RelativeFloatParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\Limits;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\World;
|
||||
use function count;
|
||||
use function round;
|
||||
|
||||
class SpawnpointCommand extends VanillaCommand{
|
||||
class SpawnpointCommand extends Command{
|
||||
|
||||
private const string SELF_PERM = DefaultPermissionNames::COMMAND_SPAWNPOINT_SELF;
|
||||
private const string OTHER_PERM = DefaultPermissionNames::COMMAND_SPAWNPOINT_OTHER;
|
||||
|
||||
private const OVERLOAD_PERMS = [self::SELF_PERM, self::OTHER_PERM];
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_spawnpoint_description(),
|
||||
KnownTranslationFactory::commands_spawnpoint_usage()
|
||||
[
|
||||
new CommandOverload([
|
||||
new StringParameter("target", "target")
|
||||
], self::OVERLOAD_PERMS, self::setSpawnHere(...)),
|
||||
new CommandOverload([
|
||||
new StringParameter("target", "target"),
|
||||
new RelativeFloatParameter("x", "x"),
|
||||
new RelativeFloatParameter("y", "y"),
|
||||
new RelativeFloatParameter("z", "z")
|
||||
], self::OVERLOAD_PERMS, self::setSpawnCoords(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_spawnpoint_description()
|
||||
);
|
||||
$this->setPermissions([
|
||||
DefaultPermissionNames::COMMAND_SPAWNPOINT_SELF,
|
||||
DefaultPermissionNames::COMMAND_SPAWNPOINT_OTHER
|
||||
]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
$target = $this->fetchPermittedPlayerTarget($commandLabel, $sender, $args[0] ?? null, DefaultPermissionNames::COMMAND_SPAWNPOINT_SELF, DefaultPermissionNames::COMMAND_SPAWNPOINT_OTHER);
|
||||
private static function setSpawnHere(CommandSender $sender, ?string $target = null) : void{
|
||||
$target = self::fetchPermittedPlayerTarget($sender, $target, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($target === null){
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if(count($args) === 4){
|
||||
$world = $target->getWorld();
|
||||
$pos = $sender instanceof Player ? $sender->getPosition() : $world->getSpawnLocation();
|
||||
$x = $this->getRelativeDouble($pos->x, $sender, $args[1]);
|
||||
$y = $this->getRelativeDouble($pos->y, $sender, $args[2], World::Y_MIN, World::Y_MAX);
|
||||
$z = $this->getRelativeDouble($pos->z, $sender, $args[3]);
|
||||
$target->setSpawn(new Position($x, $y, $z, $world));
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_spawnpoint_success($target->getName(), (string) round($x, 2), (string) round($y, 2), (string) round($z, 2)));
|
||||
|
||||
return true;
|
||||
}elseif(count($args) <= 1 && $sender instanceof Player){
|
||||
$cpos = $sender->getPosition();
|
||||
$cpos = $target->getPosition();
|
||||
$pos = Position::fromObject($cpos->floor(), $cpos->getWorld());
|
||||
$target->setSpawn($pos);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_spawnpoint_success($target->getName(), (string) round($pos->x, 2), (string) round($pos->y, 2), (string) round($pos->z, 2)));
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new InvalidCommandSyntaxException();
|
||||
private static function setSpawnCoords(CommandSender $sender, string $target, RelativeFloat $x, RelativeFloat $y, RelativeFloat $z) : void{
|
||||
$target = self::fetchPermittedPlayerTarget($sender, $target, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($target === null){
|
||||
return;
|
||||
}
|
||||
|
||||
$world = $target->getWorld();
|
||||
$pos = $sender instanceof Player ? $sender->getPosition() : $world->getSpawnLocation();
|
||||
$x = $x->resolve($pos->x, Limits::INT32_MIN, Limits::INT32_MAX);
|
||||
$y = $y->resolve($pos->y, World::Y_MIN, World::Y_MAX);
|
||||
$z = $z->resolve($pos->z, Limits::INT32_MIN, Limits::INT32_MAX);
|
||||
$target->setSpawn(new Position($x, $y, $z, $world));
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_spawnpoint_success($target->getName(), (string) round($x, 2), (string) round($y, 2), (string) round($z, 2)));
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\Process;
|
||||
@@ -34,18 +36,18 @@ use function microtime;
|
||||
use function number_format;
|
||||
use function round;
|
||||
|
||||
class StatusCommand extends VanillaCommand{
|
||||
class StatusCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([], DefaultPermissionNames::COMMAND_STATUS, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_status_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_STATUS);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
private static function execute(CommandSender $sender) : void{
|
||||
$mUsage = Process::getAdvancedMemoryUsage();
|
||||
|
||||
$server = $sender->getServer();
|
||||
@@ -113,7 +115,5 @@ class StatusCommand extends VanillaCommand{
|
||||
"Time $timeColor" . round($world->getTickRateTime(), 2) . "ms"
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,25 +25,24 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
|
||||
class StopCommand extends VanillaCommand{
|
||||
class StopCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([], DefaultPermissionNames::COMMAND_STOP, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_stop_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_STOP);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
private static function execute(CommandSender $sender) : void{
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_stop_start());
|
||||
|
||||
$sender->getServer()->shutdown();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,88 +25,69 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\FloatRangeParameter;
|
||||
use pocketmine\command\overload\RelativeFloat;
|
||||
use pocketmine\command\overload\RelativeFloatParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\entity\Location;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Limits;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\world\World;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function round;
|
||||
|
||||
class TeleportCommand extends VanillaCommand{
|
||||
class TeleportCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_tp_description(),
|
||||
KnownTranslationFactory::commands_tp_usage()
|
||||
[
|
||||
new CommandOverload([
|
||||
new RelativeFloatParameter("xIn", "x"),
|
||||
new RelativeFloatParameter("yIn", "y"),
|
||||
new RelativeFloatParameter("zIn", "z"),
|
||||
new FloatRangeParameter("yaw", "yaw", 0, 360),
|
||||
new FloatRangeParameter("pitch", "pitch", -90, 90)
|
||||
], DefaultPermissionNames::COMMAND_TELEPORT_SELF, self::tpSelfCoords(...)),
|
||||
new CommandOverload([
|
||||
new StringParameter("teleportedPlayerName", "player to teleport"),
|
||||
new RelativeFloatParameter("xIn", "x"),
|
||||
new RelativeFloatParameter("yIn", "y"),
|
||||
new RelativeFloatParameter("zIn", "z"),
|
||||
new FloatRangeParameter("yaw", "yaw", 0, 360),
|
||||
new FloatRangeParameter("pitch", "pitch", -90, 90)
|
||||
], DefaultPermissionNames::COMMAND_TELEPORT_OTHER, self::tpOtherCoords(...)),
|
||||
new CommandOverload([
|
||||
new StringParameter("destinationPlayerName", "destination player")
|
||||
], DefaultPermissionNames::COMMAND_TELEPORT_SELF, self::tpSelfToPlayer(...)),
|
||||
new CommandOverload([
|
||||
new StringParameter("teleportedPlayerName", "player to teleport"),
|
||||
new StringParameter("destinationPlayerName", "destination player")
|
||||
], DefaultPermissionNames::COMMAND_TELEPORT_OTHER, self::tpOtherToPlayer(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_tp_description()
|
||||
);
|
||||
$this->setPermissions([
|
||||
DefaultPermissionNames::COMMAND_TELEPORT_SELF,
|
||||
DefaultPermissionNames::COMMAND_TELEPORT_OTHER
|
||||
]);
|
||||
}
|
||||
|
||||
private function findPlayer(CommandSender $sender, string $playerName) : ?Player{
|
||||
$subject = $sender->getServer()->getPlayerByPrefix($playerName);
|
||||
if($subject === null){
|
||||
$sender->sendMessage(TextFormat::RED . "Can't find player " . $playerName);
|
||||
return null;
|
||||
}
|
||||
return $subject;
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
switch(count($args)){
|
||||
case 1: // /tp targetPlayer
|
||||
case 3: // /tp x y z
|
||||
case 5: // /tp x y z yaw pitch - TODO: 5 args could be target x y z yaw :(
|
||||
$subjectName = null; //self
|
||||
break;
|
||||
case 2: // /tp player1 player2
|
||||
case 4: // /tp player1 x y z - TODO: 4 args could be x y z yaw :(
|
||||
case 6: // /tp player1 x y z yaw pitch
|
||||
$subjectName = array_shift($args);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$subject = $this->fetchPermittedPlayerTarget($commandLabel, $sender, $subjectName, DefaultPermissionNames::COMMAND_TELEPORT_SELF, DefaultPermissionNames::COMMAND_TELEPORT_OTHER);
|
||||
if($subject === null){
|
||||
return true;
|
||||
}
|
||||
|
||||
switch(count($args)){
|
||||
case 1:
|
||||
$targetPlayer = $this->findPlayer($sender, $args[0]);
|
||||
if($targetPlayer === null){
|
||||
return true;
|
||||
}
|
||||
|
||||
$subject->teleport($targetPlayer->getLocation());
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_tp_success($subject->getName(), $targetPlayer->getName()));
|
||||
|
||||
return true;
|
||||
case 3:
|
||||
case 5:
|
||||
private static function tpCoords(
|
||||
CommandSender $sender,
|
||||
Player $subject,
|
||||
RelativeFloat $xIn,
|
||||
RelativeFloat $yIn,
|
||||
RelativeFloat $zIn,
|
||||
float $yaw,
|
||||
float $pitch
|
||||
) : void{
|
||||
$base = $subject->getLocation();
|
||||
if(count($args) === 5){
|
||||
$yaw = (float) $args[3];
|
||||
$pitch = (float) $args[4];
|
||||
}else{
|
||||
$yaw = $base->yaw;
|
||||
$pitch = $base->pitch;
|
||||
}
|
||||
|
||||
$x = $this->getRelativeDouble($base->x, $sender, $args[0]);
|
||||
$y = $this->getRelativeDouble($base->y, $sender, $args[1], World::Y_MIN, World::Y_MAX);
|
||||
$z = $this->getRelativeDouble($base->z, $sender, $args[2]);
|
||||
$x = $xIn->resolve($base->x, Limits::INT32_MIN, Limits::INT32_MAX);
|
||||
$y = $yIn->resolve($base->y, World::Y_MIN, World::Y_MAX);
|
||||
$z = $zIn->resolve($base->z, Limits::INT32_MIN, Limits::INT32_MAX);
|
||||
$targetLocation = new Location($x, $y, $z, $base->getWorld(), $yaw, $pitch);
|
||||
|
||||
$subject->teleport($targetLocation);
|
||||
@@ -116,9 +97,66 @@ class TeleportCommand extends VanillaCommand{
|
||||
(string) round($targetLocation->y, 2),
|
||||
(string) round($targetLocation->z, 2)
|
||||
));
|
||||
return true;
|
||||
default:
|
||||
throw new AssumptionFailedError("This branch should be unreachable (for now)");
|
||||
}
|
||||
}
|
||||
|
||||
private static function tpSelfCoords(
|
||||
CommandSender $sender,
|
||||
RelativeFloat $xIn,
|
||||
RelativeFloat $yIn,
|
||||
RelativeFloat $zIn,
|
||||
float $yaw = 0.0,
|
||||
float $pitch = 0.0
|
||||
) : void{
|
||||
if(!$sender instanceof Player){
|
||||
throw new InvalidCommandSyntaxException("This syntax can only be used as a player");
|
||||
}
|
||||
|
||||
self::tpCoords($sender, $sender, $xIn, $yIn, $zIn, $yaw, $pitch);
|
||||
}
|
||||
|
||||
private static function tpOtherCoords(
|
||||
CommandSender $sender,
|
||||
string $teleportedPlayerName,
|
||||
RelativeFloat $xIn,
|
||||
RelativeFloat $yIn,
|
||||
RelativeFloat $zIn,
|
||||
float $yaw = 0.0,
|
||||
float $pitch = 0.0
|
||||
) : void{
|
||||
$subject = self::fetchPermittedPlayerTarget($sender, $teleportedPlayerName, DefaultPermissionNames::COMMAND_TELEPORT_SELF, DefaultPermissionNames::COMMAND_TELEPORT_OTHER);
|
||||
if($subject === null){
|
||||
return;
|
||||
}
|
||||
|
||||
self::tpCoords($sender, $subject, $xIn, $yIn, $zIn, $yaw, $pitch);
|
||||
}
|
||||
|
||||
private static function tpToPlayer(CommandSender $sender, Player $teleportedPlayer, string $destinationPlayerName) : void{
|
||||
$destination = $sender->getServer()->getPlayerByPrefix($destinationPlayerName);
|
||||
if($destination === null){
|
||||
//TODO: this isn't really a syntax error, but we don't have strings for it currently
|
||||
$sender->sendMessage(TextFormat::RED . "Cannot find destination player: $destinationPlayerName");
|
||||
return;
|
||||
}
|
||||
|
||||
$teleportedPlayer->teleport($destination->getLocation());
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_tp_success($teleportedPlayer->getName(), $destination->getName()));
|
||||
}
|
||||
|
||||
private static function tpSelfToPlayer(CommandSender $sender, string $destinationPlayer) : void{
|
||||
if(!$sender instanceof Player){
|
||||
throw new InvalidCommandSyntaxException("This syntax can only be used as a player");
|
||||
}
|
||||
|
||||
self::tpToPlayer($sender, $sender, $destinationPlayer);
|
||||
}
|
||||
|
||||
private static function tpOtherToPlayer(CommandSender $sender, string $teleportedPlayerName, string $destinationPlayerName) : void{
|
||||
$subject = self::fetchPermittedPlayerTarget($sender, $teleportedPlayerName, DefaultPermissionNames::COMMAND_TELEPORT_SELF, DefaultPermissionNames::COMMAND_TELEPORT_OTHER);
|
||||
if($subject === null){
|
||||
return;
|
||||
}
|
||||
|
||||
self::tpToPlayer($sender, $subject, $destinationPlayerName);
|
||||
}
|
||||
}
|
||||
|
@@ -25,41 +25,37 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\RawParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class TellCommand extends VanillaCommand{
|
||||
class TellCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[new CommandOverload([
|
||||
new StringParameter("recipientName", "recipient player"),
|
||||
new RawParameter("message", "message")
|
||||
], DefaultPermissionNames::COMMAND_TELL, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_tell_description(),
|
||||
KnownTranslationFactory::commands_message_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_TELL);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) < 2){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player = $sender->getServer()->getPlayerByPrefix(array_shift($args));
|
||||
private static function execute(CommandSender $sender, string $recipientName, string $message) : void{
|
||||
$player = $sender->getServer()->getPlayerByPrefix($recipientName);
|
||||
|
||||
if($player === $sender){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_message_sameTarget()->prefix(TextFormat::RED));
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if($player instanceof Player){
|
||||
$message = implode(" ", $args);
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_message_display_outgoing($player->getDisplayName(), $message)->prefix(TextFormat::GRAY . TextFormat::ITALIC));
|
||||
$name = $sender instanceof Player ? $sender->getDisplayName() : $sender->getName();
|
||||
$player->sendMessage(KnownTranslationFactory::commands_message_display_incoming($name, $message)->prefix(TextFormat::GRAY . TextFormat::ITALIC));
|
||||
@@ -67,7 +63,5 @@ class TellCommand extends VanillaCommand{
|
||||
}else{
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_generic_player_notFound());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,119 +25,87 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\IntRangeParameter;
|
||||
use pocketmine\command\overload\MappedParameter;
|
||||
use pocketmine\command\overload\ParameterParseException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\Limits;
|
||||
use pocketmine\world\World;
|
||||
use function count;
|
||||
|
||||
class TimeCommand extends VanillaCommand{
|
||||
class TimeCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_time_description(),
|
||||
KnownTranslationFactory::pocketmine_command_time_usage()
|
||||
[
|
||||
new CommandOverload(["start"], DefaultPermissionNames::COMMAND_TIME_START, self::startTime(...)),
|
||||
new CommandOverload(["stop"], DefaultPermissionNames::COMMAND_TIME_STOP, self::stopTime(...)),
|
||||
new CommandOverload(["query"], DefaultPermissionNames::COMMAND_TIME_QUERY, self::queryTime(...)),
|
||||
new CommandOverload([
|
||||
"set",
|
||||
new MappedParameter("time", "time name", static fn(string $v) : int => match($v){
|
||||
"day" => World::TIME_DAY,
|
||||
"noon" => World::TIME_NOON,
|
||||
"sunset" => World::TIME_SUNSET,
|
||||
"night" => World::TIME_NIGHT,
|
||||
"midnight" => World::TIME_MIDNIGHT,
|
||||
"sunrise" => World::TIME_SUNRISE,
|
||||
//numeric times are handled in a separate overload, for clarity's sake
|
||||
default => throw new ParameterParseException("Invalid time name: $v")
|
||||
})
|
||||
], DefaultPermissionNames::COMMAND_TIME_SET, self::setTime(...)),
|
||||
new CommandOverload([
|
||||
"set",
|
||||
new IntRangeParameter("time", "timestamp", 0, Limits::INT32_MAX)
|
||||
], DefaultPermissionNames::COMMAND_TIME_SET, self::setTime(...)),
|
||||
new CommandOverload([
|
||||
"add",
|
||||
new IntRangeParameter("ticks", "ticks", 0, Limits::INT32_MAX),
|
||||
], DefaultPermissionNames::COMMAND_TIME_ADD, self::addTime(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_time_description()
|
||||
);
|
||||
$this->setPermissions([
|
||||
DefaultPermissionNames::COMMAND_TIME_ADD,
|
||||
DefaultPermissionNames::COMMAND_TIME_SET,
|
||||
DefaultPermissionNames::COMMAND_TIME_START,
|
||||
DefaultPermissionNames::COMMAND_TIME_STOP,
|
||||
DefaultPermissionNames::COMMAND_TIME_QUERY
|
||||
]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) < 1){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
$testPermissionCtx = $commandLabel . " " . $args[0];
|
||||
|
||||
if($args[0] === "start"){
|
||||
if(!$this->testPermission($testPermissionCtx, $sender, DefaultPermissionNames::COMMAND_TIME_START)){
|
||||
return true;
|
||||
}
|
||||
private static function startTime(CommandSender $sender) : void{
|
||||
foreach($sender->getServer()->getWorldManager()->getWorlds() as $world){
|
||||
$world->startTime();
|
||||
}
|
||||
//TODO: l10n
|
||||
Command::broadcastCommandMessage($sender, "Restarted the time");
|
||||
return true;
|
||||
}elseif($args[0] === "stop"){
|
||||
if(!$this->testPermission($testPermissionCtx, $sender, DefaultPermissionNames::COMMAND_TIME_STOP)){
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function stopTime(CommandSender $sender) : void{
|
||||
foreach($sender->getServer()->getWorldManager()->getWorlds() as $world){
|
||||
$world->stopTime();
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, "Stopped the time");
|
||||
return true;
|
||||
}elseif($args[0] === "query"){
|
||||
if(!$this->testPermission($testPermissionCtx, $sender, DefaultPermissionNames::COMMAND_TIME_QUERY)){
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function queryTime(CommandSender $sender) : void{
|
||||
if($sender instanceof Player){
|
||||
$world = $sender->getWorld();
|
||||
}else{
|
||||
$world = $sender->getServer()->getWorldManager()->getDefaultWorld();
|
||||
}
|
||||
$sender->sendMessage($sender->getLanguage()->translate(KnownTranslationFactory::commands_time_query((string) $world->getTime())));
|
||||
return true;
|
||||
}
|
||||
|
||||
if(count($args) < 2){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
if($args[0] === "set"){
|
||||
if(!$this->testPermission($testPermissionCtx, $sender, DefaultPermissionNames::COMMAND_TIME_SET)){
|
||||
return true;
|
||||
}
|
||||
|
||||
switch($args[1]){
|
||||
case "day":
|
||||
$value = World::TIME_DAY;
|
||||
break;
|
||||
case "noon":
|
||||
$value = World::TIME_NOON;
|
||||
break;
|
||||
case "sunset":
|
||||
$value = World::TIME_SUNSET;
|
||||
break;
|
||||
case "night":
|
||||
$value = World::TIME_NIGHT;
|
||||
break;
|
||||
case "midnight":
|
||||
$value = World::TIME_MIDNIGHT;
|
||||
break;
|
||||
case "sunrise":
|
||||
$value = World::TIME_SUNRISE;
|
||||
break;
|
||||
default:
|
||||
$value = $this->getInteger($sender, $args[1], 0);
|
||||
break;
|
||||
}
|
||||
|
||||
private static function setTime(CommandSender $sender, int $time) : void{
|
||||
foreach($sender->getServer()->getWorldManager()->getWorlds() as $world){
|
||||
$world->setTime($value);
|
||||
$world->setTime($time);
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_time_set((string) $value));
|
||||
}elseif($args[0] === "add"){
|
||||
if(!$this->testPermission($testPermissionCtx, $sender, DefaultPermissionNames::COMMAND_TIME_ADD)){
|
||||
return true;
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_time_set((string) $time));
|
||||
}
|
||||
|
||||
$value = $this->getInteger($sender, $args[1], 0);
|
||||
private static function addTime(CommandSender $sender, int $ticks) : void{
|
||||
foreach($sender->getServer()->getWorldManager()->getWorlds() as $world){
|
||||
$world->setTime($world->getTime() + $value);
|
||||
$world->setTime($world->getTime() + $ticks);
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_time_added((string) $value));
|
||||
}else{
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
return true;
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_time_added((string) $ticks));
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
@@ -38,7 +38,6 @@ use pocketmine\utils\InternetException;
|
||||
use pocketmine\utils\InternetRequestResult;
|
||||
use pocketmine\YmlServerProperties;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function count;
|
||||
use function fclose;
|
||||
use function file_exists;
|
||||
use function fopen;
|
||||
@@ -50,7 +49,6 @@ use function is_int;
|
||||
use function is_string;
|
||||
use function json_decode;
|
||||
use function mkdir;
|
||||
use function strtolower;
|
||||
use const CURLOPT_AUTOREFERER;
|
||||
use const CURLOPT_FOLLOWLOCATION;
|
||||
use const CURLOPT_HTTPHEADER;
|
||||
@@ -58,95 +56,79 @@ use const CURLOPT_POST;
|
||||
use const CURLOPT_POSTFIELDS;
|
||||
use const PHP_EOL;
|
||||
|
||||
class TimingsCommand extends VanillaCommand{
|
||||
class TimingsCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[
|
||||
new CommandOverload(["on"], DefaultPermissionNames::COMMAND_TIMINGS, self::enableTimings(...)),
|
||||
new CommandOverload(["off"], DefaultPermissionNames::COMMAND_TIMINGS, self::disableTimings(...)),
|
||||
new CommandOverload(["reset"], DefaultPermissionNames::COMMAND_TIMINGS, self::resetTimings(...)),
|
||||
new CommandOverload(["paste"], DefaultPermissionNames::COMMAND_TIMINGS, self::requestTimingsUpload(...)),
|
||||
new CommandOverload(["report"], DefaultPermissionNames::COMMAND_TIMINGS, self::requestTimingsFile(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_timings_description(),
|
||||
KnownTranslationFactory::pocketmine_command_timings_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_TIMINGS);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) !== 1){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$mode = strtolower($args[0]);
|
||||
|
||||
if($mode === "on"){
|
||||
private static function enableTimings(CommandSender $sender) : void{
|
||||
if(TimingsHandler::isEnabled()){
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_alreadyEnabled());
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
TimingsHandler::setEnabled();
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_enable());
|
||||
}
|
||||
|
||||
return true;
|
||||
}elseif($mode === "off"){
|
||||
private static function disableTimings(CommandSender $sender) : void{
|
||||
TimingsHandler::setEnabled(false);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_disable());
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function resetTimings(CommandSender $sender) : void{
|
||||
if(!TimingsHandler::isEnabled()){
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_timingsDisabled());
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
$paste = $mode === "paste";
|
||||
|
||||
if($mode === "reset"){
|
||||
TimingsHandler::reload();
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_reset());
|
||||
}elseif($mode === "merged" || $mode === "report" || $paste){
|
||||
}
|
||||
|
||||
private static function requestTimingsUpload(CommandSender $sender) : void{
|
||||
if(!TimingsHandler::isEnabled()){
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_timingsDisabled());
|
||||
return;
|
||||
}
|
||||
|
||||
$timingsPromise = TimingsHandler::requestPrintTimings();
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_collect());
|
||||
$timingsPromise->onCompletion(
|
||||
fn(array $lines) => $paste ? $this->uploadReport($lines, $sender) : $this->createReportFile($lines, $sender),
|
||||
fn(array $lines) => self::uploadReport($lines, $sender),
|
||||
fn() => throw new AssumptionFailedError("This promise is not expected to be rejected")
|
||||
);
|
||||
}else{
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
return true;
|
||||
private static function requestTimingsFile(CommandSender $sender) : void{
|
||||
if(!TimingsHandler::isEnabled()){
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_timingsDisabled());
|
||||
return;
|
||||
}
|
||||
$timingsPromise = TimingsHandler::requestPrintTimings();
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_collect());
|
||||
$timingsPromise->onCompletion(
|
||||
fn(array $lines) => self::createReportFile($lines, $sender),
|
||||
fn() => throw new AssumptionFailedError("This promise is not expected to be rejected")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $lines
|
||||
* @phpstan-param list<string> $lines
|
||||
*/
|
||||
private function createReportFile(array $lines, CommandSender $sender) : void{
|
||||
$index = 0;
|
||||
$timingFolder = Path::join($sender->getServer()->getDataPath(), "timings");
|
||||
|
||||
if(!file_exists($timingFolder)){
|
||||
mkdir($timingFolder, 0777);
|
||||
}
|
||||
$timings = Path::join($timingFolder, "timings.txt");
|
||||
while(file_exists($timings)){
|
||||
$timings = Path::join($timingFolder, "timings" . (++$index) . ".txt");
|
||||
}
|
||||
|
||||
$fileTimings = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen($timings, "a+b"));
|
||||
foreach($lines as $line){
|
||||
fwrite($fileTimings, $line . PHP_EOL);
|
||||
}
|
||||
fclose($fileTimings);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsWrite($timings));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $lines
|
||||
* @phpstan-param list<string> $lines
|
||||
*/
|
||||
private function uploadReport(array $lines, CommandSender $sender) : void{
|
||||
private static function uploadReport(array $lines, CommandSender $sender) : void{
|
||||
$data = [
|
||||
"browser" => $agent = $sender->getServer()->getName() . " " . $sender->getServer()->getPocketMineVersion(),
|
||||
"data" => implode("\n", $lines),
|
||||
@@ -197,4 +179,29 @@ class TimingsCommand extends VanillaCommand{
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $lines
|
||||
* @phpstan-param list<string> $lines
|
||||
*/
|
||||
private static function createReportFile(array $lines, CommandSender $sender) : void{
|
||||
$index = 0;
|
||||
$timingFolder = Path::join($sender->getServer()->getDataPath(), "timings");
|
||||
|
||||
if(!file_exists($timingFolder)){
|
||||
mkdir($timingFolder, 0777);
|
||||
}
|
||||
$timings = Path::join($timingFolder, "timings.txt");
|
||||
while(file_exists($timings)){
|
||||
$timings = Path::join($timingFolder, "timings" . (++$index) . ".txt");
|
||||
}
|
||||
|
||||
$fileTimings = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen($timings, "a+b"));
|
||||
foreach($lines as $line){
|
||||
fwrite($fileTimings, $line . PHP_EOL);
|
||||
}
|
||||
fclose($fileTimings);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsWrite($timings));
|
||||
}
|
||||
}
|
||||
|
@@ -23,80 +23,82 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\IntRangeParameter;
|
||||
use pocketmine\command\overload\RawParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use function array_slice;
|
||||
use function count;
|
||||
use function implode;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\Limits;
|
||||
|
||||
class TitleCommand extends VanillaCommand{
|
||||
class TitleCommand extends Command{
|
||||
|
||||
private const string SELF_PERM = DefaultPermissionNames::COMMAND_TITLE_SELF;
|
||||
private const string OTHER_PERM = DefaultPermissionNames::COMMAND_TITLE_OTHER;
|
||||
|
||||
private const OVERLOAD_PERMS = [self::SELF_PERM, self::OTHER_PERM];
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
$playerParameter = new StringParameter("playerName", "player name");
|
||||
$textParameter = new RawParameter("text", "text");
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
[
|
||||
new CommandOverload([$playerParameter, "clear"], self::OVERLOAD_PERMS, self::clearTitles(...)),
|
||||
new CommandOverload([$playerParameter, "reset"], self::OVERLOAD_PERMS, self::resetTitles(...)),
|
||||
new CommandOverload([$playerParameter, "title", $textParameter], self::OVERLOAD_PERMS, self::sendTitle(...)),
|
||||
new CommandOverload([$playerParameter, "subtitle", $textParameter], self::OVERLOAD_PERMS, self::sendSubTitle(...)),
|
||||
new CommandOverload([$playerParameter, "actionbar", $textParameter], self::OVERLOAD_PERMS, self::sendActionBar(...)),
|
||||
new CommandOverload([
|
||||
$playerParameter,
|
||||
"times",
|
||||
new IntRangeParameter("fadeInTicks", "fade-in ticks", 0, Limits::INT32_MAX),
|
||||
new IntRangeParameter("stayTicks", "stay ticks", 0, Limits::INT32_MAX),
|
||||
new IntRangeParameter("fadeOutTicks", "fade-out ticks", 0, Limits::INT32_MAX)
|
||||
], self::OVERLOAD_PERMS, self::setTitleDuration(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_title_description(),
|
||||
KnownTranslationFactory::commands_title_usage()
|
||||
);
|
||||
$this->setPermissions([
|
||||
DefaultPermissionNames::COMMAND_TITLE_SELF,
|
||||
DefaultPermissionNames::COMMAND_TITLE_OTHER
|
||||
]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) < 2){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player = $this->fetchPermittedPlayerTarget($commandLabel, $sender, $args[0], DefaultPermissionNames::COMMAND_TITLE_SELF, DefaultPermissionNames::COMMAND_TITLE_OTHER);
|
||||
/**
|
||||
* @phpstan-param \Closure(Player) : void $action
|
||||
*/
|
||||
private static function doTitleAction(CommandSender $sender, string $playerName, \Closure $action) : void{
|
||||
$player = self::fetchPermittedPlayerTarget($sender, $playerName, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($player === null){
|
||||
return true;
|
||||
}
|
||||
|
||||
switch($args[1]){
|
||||
case "clear":
|
||||
$player->removeTitles();
|
||||
break;
|
||||
case "reset":
|
||||
$player->resetTitles();
|
||||
break;
|
||||
case "title":
|
||||
if(count($args) < 3){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player->sendTitle(implode(" ", array_slice($args, 2)));
|
||||
break;
|
||||
case "subtitle":
|
||||
if(count($args) < 3){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player->sendSubTitle(implode(" ", array_slice($args, 2)));
|
||||
break;
|
||||
case "actionbar":
|
||||
if(count($args) < 3){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player->sendActionBarMessage(implode(" ", array_slice($args, 2)));
|
||||
break;
|
||||
case "times":
|
||||
if(count($args) < 5){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player->setTitleDuration($this->getInteger($sender, $args[2]), $this->getInteger($sender, $args[3]), $this->getInteger($sender, $args[4]));
|
||||
break;
|
||||
default:
|
||||
throw new InvalidCommandSyntaxException();
|
||||
return;
|
||||
}
|
||||
$action($player);
|
||||
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_title_success());
|
||||
}
|
||||
|
||||
return true;
|
||||
private static function clearTitles(CommandSender $sender, string $playerName) : void{
|
||||
self::doTitleAction($sender, $playerName, static fn(Player $p) => $p->removeTitles());
|
||||
}
|
||||
|
||||
private static function resetTitles(CommandSender $sender, string $playerName) : void{
|
||||
self::doTitleAction($sender, $playerName, static fn(Player $p) => $p->resetTitles());
|
||||
}
|
||||
|
||||
private static function sendTitle(CommandSender $sender, string $playerName, string $text) : void{
|
||||
self::doTitleAction($sender, $playerName, static fn(Player $p) => $p->sendTitle($text));
|
||||
}
|
||||
|
||||
private static function sendSubTitle(CommandSender $sender, string $playerName, string $text) : void{
|
||||
self::doTitleAction($sender, $playerName, static fn(Player $p) => $p->sendSubTitle($text));
|
||||
}
|
||||
|
||||
private static function sendActionBar(CommandSender $sender, string $playerName, string $text) : void{
|
||||
self::doTitleAction($sender, $playerName, static fn(Player $p) => $p->sendActionBarMessage($text));
|
||||
}
|
||||
|
||||
private static function setTitleDuration(CommandSender $sender, string $playerName, int $fadeInTicks, int $stayTicks, int $fadeOutTicks) : void{
|
||||
self::doTitleAction($sender, $playerName, static fn(Player $p) => $p->setTitleDuration($fadeInTicks, $stayTicks, $fadeOutTicks));
|
||||
}
|
||||
}
|
||||
|
@@ -23,36 +23,37 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\IntRangeParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use function count;
|
||||
use pocketmine\utils\TextFormat;
|
||||
|
||||
class TransferServerCommand extends VanillaCommand{
|
||||
class TransferServerCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_transferserver_description(),
|
||||
KnownTranslationFactory::pocketmine_command_transferserver_usage()
|
||||
[new CommandOverload([
|
||||
new StringParameter("serverAddress", "server address"),
|
||||
new IntRangeParameter("serverPort", "server port", 1, 65535)
|
||||
], DefaultPermissionNames::COMMAND_TRANSFERSERVER, self::execute(...))],
|
||||
KnownTranslationFactory::pocketmine_command_transferserver_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_TRANSFERSERVER);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) < 1){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}elseif(!($sender instanceof Player)){
|
||||
$sender->sendMessage("This command must be executed as a player");
|
||||
private static function execute(CommandSender $sender, string $serverAddress, int $serverPort = 19132) : void{
|
||||
if(!($sender instanceof Player)){
|
||||
$sender->sendMessage(TextFormat::RED . "This command must be executed as a player");
|
||||
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
$sender->transfer($args[0], (int) ($args[1] ?? 19132));
|
||||
|
||||
return true;
|
||||
$sender->transfer($serverAddress, $serverPort);
|
||||
}
|
||||
}
|
||||
|
@@ -1,121 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function is_numeric;
|
||||
use function substr;
|
||||
|
||||
abstract class VanillaCommand extends Command{
|
||||
public const MAX_COORD = 30000000;
|
||||
public const MIN_COORD = -30000000;
|
||||
|
||||
protected function fetchPermittedPlayerTarget(
|
||||
string $testPermissionContext,
|
||||
CommandSender $sender,
|
||||
?string $target,
|
||||
string $selfPermission,
|
||||
string $otherPermission
|
||||
) : ?Player{
|
||||
if($target !== null){
|
||||
$player = $sender->getServer()->getPlayerByPrefix($target);
|
||||
}elseif($sender instanceof Player){
|
||||
$player = $sender;
|
||||
}else{
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
if($player === null){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_generic_player_notFound()->prefix(TextFormat::RED));
|
||||
return null;
|
||||
}
|
||||
//TODO: using loud testPermission here will generate misleading messages
|
||||
//e.g. if the sender has self permission and tries to use the command on another player, it will give them a
|
||||
//generic message saying that they don't have permission to use the command, which is not correct
|
||||
if(
|
||||
($player === $sender && $this->testPermission($testPermissionContext, $sender, $selfPermission)) ||
|
||||
($player !== $sender && $this->testPermission($testPermissionContext, $sender, $otherPermission))
|
||||
){
|
||||
return $player;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function getInteger(CommandSender $sender, string $value, int $min = self::MIN_COORD, int $max = self::MAX_COORD) : int{
|
||||
$i = (int) $value;
|
||||
|
||||
if($i < $min){
|
||||
$i = $min;
|
||||
}elseif($i > $max){
|
||||
$i = $max;
|
||||
}
|
||||
|
||||
return $i;
|
||||
}
|
||||
|
||||
protected function getRelativeDouble(float $original, CommandSender $sender, string $input, float $min = self::MIN_COORD, float $max = self::MAX_COORD) : float{
|
||||
if($input[0] === "~"){
|
||||
$value = $this->getDouble($sender, substr($input, 1));
|
||||
|
||||
return $original + $value;
|
||||
}
|
||||
|
||||
return $this->getDouble($sender, $input, $min, $max);
|
||||
}
|
||||
|
||||
protected function getDouble(CommandSender $sender, string $value, float $min = self::MIN_COORD, float $max = self::MAX_COORD) : float{
|
||||
$i = (double) $value;
|
||||
|
||||
if($i < $min){
|
||||
$i = $min;
|
||||
}elseif($i > $max){
|
||||
$i = $max;
|
||||
}
|
||||
|
||||
return $i;
|
||||
}
|
||||
|
||||
protected function getBoundedInt(CommandSender $sender, string $input, int $min, int $max) : ?int{
|
||||
if(!is_numeric($input)){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$v = (int) $input;
|
||||
if($v > $max){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_generic_num_tooBig($input, (string) $max)->prefix(TextFormat::RED));
|
||||
return null;
|
||||
}
|
||||
if($v < $min){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_generic_num_tooSmall($input, (string) $min)->prefix(TextFormat::RED));
|
||||
return null;
|
||||
}
|
||||
|
||||
return $v;
|
||||
}
|
||||
}
|
@@ -23,7 +23,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
@@ -38,20 +41,25 @@ use function stripos;
|
||||
use function strtolower;
|
||||
use const PHP_VERSION;
|
||||
|
||||
class VersionCommand extends VanillaCommand{
|
||||
class VersionCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_version_description(),
|
||||
KnownTranslationFactory::pocketmine_command_version_usage()
|
||||
[
|
||||
//technically this could be one overload, but two lets us do two separate handlers
|
||||
new CommandOverload([], DefaultPermissionNames::COMMAND_VERSION, self::showServerVersion(...)),
|
||||
|
||||
new CommandOverload([
|
||||
new StringParameter("pluginName", "plugin name")
|
||||
], DefaultPermissionNames::COMMAND_VERSION, self::showPluginVersion(...)),
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_version_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_VERSION);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
private static function showServerVersion(CommandSender $sender) : void{
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_version_serverSoftwareName(
|
||||
TextFormat::GREEN . VersionInfo::NAME . TextFormat::RESET
|
||||
));
|
||||
@@ -78,21 +86,22 @@ class VersionCommand extends VanillaCommand{
|
||||
}
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_version_phpJitStatus($jitStatus->format(TextFormat::GREEN, TextFormat::RESET)));
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_version_operatingSystem(TextFormat::GREEN . Utils::getOS() . TextFormat::RESET));
|
||||
}else{
|
||||
$pluginName = implode(" ", $args);
|
||||
}
|
||||
|
||||
private static function showPluginVersion(CommandSender $sender, string $pluginName) : void{
|
||||
$exactPlugin = $sender->getServer()->getPluginManager()->getPlugin($pluginName);
|
||||
|
||||
if($exactPlugin instanceof Plugin){
|
||||
$this->describeToSender($exactPlugin, $sender);
|
||||
self::describeToSender($exactPlugin, $sender);
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
$found = false;
|
||||
$pluginName = strtolower($pluginName);
|
||||
foreach($sender->getServer()->getPluginManager()->getPlugins() as $plugin){
|
||||
if(stripos($plugin->getName(), $pluginName) !== false){
|
||||
$this->describeToSender($plugin, $sender);
|
||||
self::describeToSender($plugin, $sender);
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
@@ -102,10 +111,7 @@ class VersionCommand extends VanillaCommand{
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function describeToSender(Plugin $plugin, CommandSender $sender) : void{
|
||||
private static function describeToSender(Plugin $plugin, CommandSender $sender) : void{
|
||||
$desc = $plugin->getDescription();
|
||||
$sender->sendMessage(TextFormat::DARK_GREEN . $desc->getName() . TextFormat::RESET . " version " . TextFormat::DARK_GREEN . $desc->getVersion());
|
||||
|
||||
|
@@ -25,6 +25,8 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
@@ -34,64 +36,54 @@ use pocketmine\ServerProperties;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function sort;
|
||||
use function strtolower;
|
||||
use const SORT_STRING;
|
||||
|
||||
class WhitelistCommand extends VanillaCommand{
|
||||
class WhitelistCommand extends Command{
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_whitelist_description(),
|
||||
KnownTranslationFactory::commands_whitelist_usage()
|
||||
[
|
||||
new CommandOverload(["reload"], DefaultPermissionNames::COMMAND_WHITELIST_RELOAD, self::reloadWhitelist(...)),
|
||||
new CommandOverload(["enable"], DefaultPermissionNames::COMMAND_WHITELIST_ENABLE, self::enableWhitelist(...)),
|
||||
new CommandOverload(["disable"], DefaultPermissionNames::COMMAND_WHITELIST_DISABLE, self::disableWhitelist(...)),
|
||||
new CommandOverload(["list"], DefaultPermissionNames::COMMAND_WHITELIST_LIST, self::listWhitelist(...)),
|
||||
new CommandOverload([
|
||||
"add",
|
||||
new StringParameter("playerName", "player name")
|
||||
], DefaultPermissionNames::COMMAND_WHITELIST_ADD, self::addWhitelistedPlayer(...)),
|
||||
new CommandOverload([
|
||||
"remove",
|
||||
new StringParameter("playerName", "player name"),
|
||||
], DefaultPermissionNames::COMMAND_WHITELIST_REMOVE, self::removeWhitelistedPlayer(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_whitelist_description()
|
||||
);
|
||||
$this->setPermissions([
|
||||
DefaultPermissionNames::COMMAND_WHITELIST_RELOAD,
|
||||
DefaultPermissionNames::COMMAND_WHITELIST_ENABLE,
|
||||
DefaultPermissionNames::COMMAND_WHITELIST_DISABLE,
|
||||
DefaultPermissionNames::COMMAND_WHITELIST_LIST,
|
||||
DefaultPermissionNames::COMMAND_WHITELIST_ADD,
|
||||
DefaultPermissionNames::COMMAND_WHITELIST_REMOVE
|
||||
]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) === 0){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
$testPermissionCtx = $commandLabel . " " . $args[0];
|
||||
if(count($args) === 1){
|
||||
switch(strtolower($args[0])){
|
||||
case "reload":
|
||||
if($this->testPermission($testPermissionCtx, $sender, DefaultPermissionNames::COMMAND_WHITELIST_RELOAD)){
|
||||
private static function reloadWhitelist(CommandSender $sender) : void{
|
||||
$server = $sender->getServer();
|
||||
$server->getWhitelisted()->reload();
|
||||
if($server->hasWhitelist()){
|
||||
$this->kickNonWhitelistedPlayers($server);
|
||||
self::kickNonWhitelistedPlayers($server);
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_whitelist_reloaded());
|
||||
}
|
||||
|
||||
return true;
|
||||
case "on":
|
||||
if($this->testPermission($testPermissionCtx, $sender, DefaultPermissionNames::COMMAND_WHITELIST_ENABLE)){
|
||||
private static function enableWhitelist(CommandSender $sender) : void{
|
||||
$server = $sender->getServer();
|
||||
$server->getConfigGroup()->setConfigBool(ServerProperties::WHITELIST, true);
|
||||
$this->kickNonWhitelistedPlayers($server);
|
||||
self::kickNonWhitelistedPlayers($server);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_whitelist_enabled());
|
||||
}
|
||||
|
||||
return true;
|
||||
case "off":
|
||||
if($this->testPermission($testPermissionCtx, $sender, DefaultPermissionNames::COMMAND_WHITELIST_DISABLE)){
|
||||
private static function disableWhitelist(CommandSender $sender) : void{
|
||||
$sender->getServer()->getConfigGroup()->setConfigBool(ServerProperties::WHITELIST, false);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_whitelist_disabled());
|
||||
}
|
||||
|
||||
return true;
|
||||
case "list":
|
||||
if($this->testPermission($testPermissionCtx, $sender, DefaultPermissionNames::COMMAND_WHITELIST_LIST)){
|
||||
private static function listWhitelist(CommandSender $sender) : void{
|
||||
$entries = $sender->getServer()->getWhitelisted()->getAll(true);
|
||||
sort($entries, SORT_STRING);
|
||||
$result = implode(", ", $entries);
|
||||
@@ -101,46 +93,27 @@ class WhitelistCommand extends VanillaCommand{
|
||||
$sender->sendMessage($result);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
case "add":
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_generic_usage(KnownTranslationFactory::commands_whitelist_add_usage()));
|
||||
return true;
|
||||
|
||||
case "remove":
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_generic_usage(KnownTranslationFactory::commands_whitelist_remove_usage()));
|
||||
return true;
|
||||
}
|
||||
}elseif(count($args) === 2){
|
||||
if(!Player::isValidUserName($args[1])){
|
||||
private static function addWhitelistedPlayer(CommandSender $sender, string $playerName) : void{
|
||||
if(!Player::isValidUserName($playerName)){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
switch(strtolower($args[0])){
|
||||
case "add":
|
||||
if($this->testPermission($testPermissionCtx, $sender, DefaultPermissionNames::COMMAND_WHITELIST_ADD)){
|
||||
$sender->getServer()->addWhitelist($args[1]);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_whitelist_add_success($args[1]));
|
||||
$sender->getServer()->addWhitelist($playerName);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_whitelist_add_success($playerName));
|
||||
}
|
||||
|
||||
return true;
|
||||
case "remove":
|
||||
if($this->testPermission($testPermissionCtx, $sender, DefaultPermissionNames::COMMAND_WHITELIST_REMOVE)){
|
||||
private static function removeWhitelistedPlayer(CommandSender $sender, string $playerName) : void{
|
||||
if(!Player::isValidUserName($playerName)){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
$server = $sender->getServer();
|
||||
$server->removeWhitelist($args[1]);
|
||||
if(!$server->isWhitelisted($args[1])){
|
||||
$server->getPlayerExact($args[1])?->kick(KnownTranslationFactory::pocketmine_disconnect_kick(KnownTranslationFactory::pocketmine_disconnect_whitelisted()));
|
||||
$server->removeWhitelist($playerName);
|
||||
if(!$server->isWhitelisted($playerName)){
|
||||
$server->getPlayerExact($playerName)?->kick(KnownTranslationFactory::pocketmine_disconnect_kick(KnownTranslationFactory::pocketmine_disconnect_whitelisted()));
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_whitelist_remove_success($args[1]));
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_whitelist_remove_success($playerName));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
private function kickNonWhitelistedPlayers(Server $server) : void{
|
||||
private static function kickNonWhitelistedPlayers(Server $server) : void{
|
||||
$message = KnownTranslationFactory::pocketmine_disconnect_kick(KnownTranslationFactory::pocketmine_disconnect_whitelisted());
|
||||
foreach($server->getOnlinePlayers() as $player){
|
||||
if(!$server->isWhitelisted($player->getName())){
|
||||
|
@@ -23,8 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\command\overload\CommandOverload;
|
||||
use pocketmine\command\overload\IntRangeParameter;
|
||||
use pocketmine\command\overload\StringParameter;
|
||||
use pocketmine\entity\Attribute;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
@@ -32,41 +35,59 @@ use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Limits;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function abs;
|
||||
use function count;
|
||||
use function str_ends_with;
|
||||
use function substr;
|
||||
use function max;
|
||||
use function min;
|
||||
|
||||
class XpCommand extends VanillaCommand{
|
||||
class XpCommand extends Command{
|
||||
|
||||
private const SELF_PERM = DefaultPermissionNames::COMMAND_XP_SELF;
|
||||
private const OTHER_PERM = DefaultPermissionNames::COMMAND_XP_OTHER;
|
||||
|
||||
private const OVERLOAD_PERMS = [self::SELF_PERM, self::OTHER_PERM];
|
||||
|
||||
public function __construct(string $namespace, string $name){
|
||||
parent::__construct(
|
||||
$namespace,
|
||||
$name,
|
||||
KnownTranslationFactory::pocketmine_command_xp_description(),
|
||||
KnownTranslationFactory::pocketmine_command_xp_usage()
|
||||
[
|
||||
new CommandOverload([
|
||||
new IntRangeParameter("xp", "xp", 0, Limits::INT32_MAX),
|
||||
new StringParameter("playerName", "player name"),
|
||||
], self::OVERLOAD_PERMS, self::addXp(...)),
|
||||
new CommandOverload([
|
||||
new IntRangeParameter("xpLevels", "xp levels", Limits::INT32_MIN, Limits::INT32_MAX, "L"),
|
||||
new StringParameter("playerName", "player name"),
|
||||
], self::OVERLOAD_PERMS, self::addXpLevels(...))
|
||||
],
|
||||
KnownTranslationFactory::pocketmine_command_xp_description()
|
||||
);
|
||||
$this->setPermissions([
|
||||
DefaultPermissionNames::COMMAND_XP_SELF,
|
||||
DefaultPermissionNames::COMMAND_XP_OTHER
|
||||
]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) < 1){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player = $this->fetchPermittedPlayerTarget($commandLabel, $sender, $args[1] ?? null, DefaultPermissionNames::COMMAND_XP_SELF, DefaultPermissionNames::COMMAND_XP_OTHER);
|
||||
private static function addXp(CommandSender $sender, int $xp, ?string $playerName = null) : void{
|
||||
$player = self::fetchPermittedPlayerTarget($sender, $playerName, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($player === null){
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if($xp < 0){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_xp_failure_widthdrawXp()->prefix(TextFormat::RED));
|
||||
}else{
|
||||
$player->getXpManager()->addXp($xp, false);
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_xp_success((string) $xp, $player->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
private static function addXpLevels(CommandSender $sender, int $xpLevels, ?string $playerName = null) : void{
|
||||
$player = self::fetchPermittedPlayerTarget($sender, $playerName, self::SELF_PERM, self::OTHER_PERM);
|
||||
if($player === null){
|
||||
return;
|
||||
}
|
||||
|
||||
$xpManager = $player->getXpManager();
|
||||
if(str_ends_with($args[0], "L")){
|
||||
$xpLevelAttr = $player->getAttributeMap()->get(Attribute::EXPERIENCE_LEVEL) ?? throw new AssumptionFailedError();
|
||||
$maxXpLevel = (int) $xpLevelAttr->getMaxValue();
|
||||
$currentXpLevel = $xpManager->getXpLevel();
|
||||
$xpLevels = $this->getInteger($sender, substr($args[0], 0, -1), -$currentXpLevel, $maxXpLevel - $currentXpLevel);
|
||||
$xpLevels = max(-$currentXpLevel, min($maxXpLevel - $currentXpLevel, $xpLevels));
|
||||
if($xpLevels >= 0){
|
||||
$xpManager->addXpLevels($xpLevels, false);
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_xp_success_levels((string) $xpLevels, $player->getName()));
|
||||
@@ -75,16 +96,5 @@ class XpCommand extends VanillaCommand{
|
||||
$xpManager->subtractXpLevels($xpLevels);
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_xp_success_negative_levels((string) $xpLevels, $player->getName()));
|
||||
}
|
||||
}else{
|
||||
$xp = $this->getInteger($sender, $args[0], max: Limits::INT32_MAX);
|
||||
if($xp < 0){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_xp_failure_widthdrawXp()->prefix(TextFormat::RED));
|
||||
}else{
|
||||
$xpManager->addXp($xp, false);
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_xp_success((string) $xp, $player->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
48
src/command/overload/BoolParameter.php
Normal file
48
src/command/overload/BoolParameter.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\overload;
|
||||
|
||||
use DaveRandom\CallbackValidator\Type\BuiltInType;
|
||||
use DaveRandom\CallbackValidator\Type\NamedType;
|
||||
use pocketmine\command\utils\CommandStringHelper;
|
||||
use pocketmine\lang\Translatable;
|
||||
|
||||
/**
|
||||
* @phpstan-extends Parameter<bool>
|
||||
*/
|
||||
final class BoolParameter extends Parameter{
|
||||
|
||||
public function __construct(string $codeName, Translatable|string $printableName){
|
||||
parent::__construct($codeName, $printableName, new NamedType(BuiltInType::BOOL));
|
||||
}
|
||||
|
||||
public function parse(string $buffer, int &$offset) : bool{
|
||||
$token = CommandStringHelper::parseQuoteAwareSingle($buffer, $offset);
|
||||
return match($token){
|
||||
"on", "true", "1" => true,
|
||||
"off", "false", "0" => false,
|
||||
default => throw new ParameterParseException("Invalid value for bool parameter: $token")
|
||||
};
|
||||
}
|
||||
}
|
226
src/command/overload/CommandOverload.php
Normal file
226
src/command/overload/CommandOverload.php
Normal file
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\overload;
|
||||
|
||||
use DaveRandom\CallbackValidator\ParameterInfo;
|
||||
use DaveRandom\CallbackValidator\Prototype;
|
||||
use DaveRandom\CallbackValidator\ReturnInfo;
|
||||
use DaveRandom\CallbackValidator\Type\BuiltInType;
|
||||
use DaveRandom\CallbackValidator\Type\NamedType;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\permission\PermissionManager;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Utils;
|
||||
use function array_filter;
|
||||
use function array_map;
|
||||
use function count;
|
||||
use function get_class;
|
||||
use function implode;
|
||||
use function is_string;
|
||||
use function preg_match;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
use function var_dump;
|
||||
|
||||
final class CommandOverload{
|
||||
|
||||
private int $requiredInputCount;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
private array $permissions;
|
||||
|
||||
/**
|
||||
* @param Parameter[]|string[] $parameters
|
||||
* @param string|string[] $permission
|
||||
* @phpstan-param list<Parameter<*>|string> $parameters
|
||||
* @phpstan-param string|list<string> $permission
|
||||
* @phpstan-param anyClosure $handler
|
||||
*/
|
||||
public function __construct(
|
||||
private array $parameters,
|
||||
string|array $permission,
|
||||
private \Closure $handler,
|
||||
private bool $acceptsAliasUsed = false
|
||||
){
|
||||
$permissions = is_string($permission) ? [$permission] : $permission;
|
||||
if(count($permissions) === 0){
|
||||
throw new \InvalidArgumentException("At least one permission must be provided");
|
||||
}
|
||||
$permissionManager = PermissionManager::getInstance();
|
||||
foreach($permissions as $perm){
|
||||
if($permissionManager->getPermission($perm) === null){
|
||||
throw new \InvalidArgumentException("Cannot use non-existing permission \"$perm\"");
|
||||
}
|
||||
}
|
||||
$this->permissions = $permissions;
|
||||
|
||||
//TODO: auto infer parameter infos if they aren't provided?
|
||||
//TODO: allow the type of CommandSender to be constrained - this can be useful for player-only commands etc
|
||||
$alwaysPresentArgs = self::alwaysPresentArgs($this->acceptsAliasUsed);
|
||||
|
||||
$passableParameters = array_filter($this->parameters, is_object(...));
|
||||
$expectedPrototype = new Prototype(
|
||||
new ReturnInfo(new NamedType(BuiltInType::VOID), byReference: false),
|
||||
...$alwaysPresentArgs,
|
||||
...array_map(fn(Parameter $p) => new ParameterInfo(
|
||||
$p->getCodeName(),
|
||||
$p->getCodeType(),
|
||||
byReference: false,
|
||||
isOptional: false,
|
||||
isVariadic: false,
|
||||
), $passableParameters)
|
||||
);
|
||||
$actualPrototype = Prototype::fromClosure($this->handler);
|
||||
Utils::validateCallableSignature($expectedPrototype, $actualPrototype);
|
||||
|
||||
$this->requiredInputCount = $actualPrototype->getRequiredParameterCount() - count($alwaysPresentArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ParameterInfo[]
|
||||
*/
|
||||
private static function alwaysPresentArgs(bool $acceptsAliasUsed) : array{
|
||||
$result = [new ParameterInfo("sender", new NamedType(CommandSender::class), byReference: false, isOptional: false, isVariadic: false)];
|
||||
if($acceptsAliasUsed){
|
||||
$result[] = new ParameterInfo("aliasUsed", new NamedType(BuiltInType::STRING), byReference: false, isOptional: false, isVariadic: false);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
public function getPermissions() : array{ return $this->permissions; }
|
||||
|
||||
public function senderHasAnyPermissions(CommandSender $sender) : bool{
|
||||
foreach($this->permissions as $permission){
|
||||
if($sender->hasPermission($permission)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getUsage() : Translatable{
|
||||
$templates = [];
|
||||
$args = [];
|
||||
$pos = 0;
|
||||
foreach($this->parameters as $parameter){
|
||||
if(is_string($parameter)){
|
||||
//literal token
|
||||
$templates[] = $parameter;
|
||||
continue;
|
||||
}
|
||||
//TODO: printable type info would be nice
|
||||
if($pos < $this->requiredInputCount){
|
||||
$template = "<{%$pos}>";
|
||||
}else{
|
||||
$template = "[{%$pos}]";
|
||||
}
|
||||
$suffix = $parameter->getSuffix();
|
||||
$template .= $suffix;
|
||||
$templates[] = $template;
|
||||
|
||||
$args[] = $parameter->getPrintableName();
|
||||
$pos++;
|
||||
}
|
||||
|
||||
return new Translatable(implode(" ", $templates), $args);
|
||||
}
|
||||
|
||||
private static function skipWhitespace(string $commandLine, int &$offset) : int{
|
||||
if(preg_match('/\G\s+/', $commandLine, $matches, offset: $offset) > 0){
|
||||
$offset += strlen($matches[0]);
|
||||
return strlen($matches[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidCommandSyntaxException
|
||||
*/
|
||||
public function invoke(CommandSender $sender, string $aliasUsed, string $commandLine) : void{
|
||||
$offset = 0;
|
||||
$args = [];
|
||||
//skip preceding whitespace
|
||||
|
||||
self::skipWhitespace($commandLine, $offset);
|
||||
if($offset < strlen($commandLine)){
|
||||
foreach($this->parameters as $parameter){
|
||||
if(is_string($parameter)){
|
||||
if(strpos($commandLine, $parameter, $offset) === $offset){
|
||||
$offset += strlen($parameter);
|
||||
}else{
|
||||
throw new ParameterParseException("Literal \"$parameter\" expected");
|
||||
}
|
||||
}else{
|
||||
try{
|
||||
$args[] = $parameter->parse($commandLine, $offset);
|
||||
}catch(ParameterParseException $e){
|
||||
throw new ParameterParseException(
|
||||
"Failed parsing argument \$" . $parameter->getCodeName() . ": " . $e->getMessage(),
|
||||
previous: $e
|
||||
);
|
||||
}
|
||||
}
|
||||
if(self::skipWhitespace($commandLine, $offset) === 0){
|
||||
if($offset === strlen($commandLine)){
|
||||
//no more tokens, rest of the parameters must be optional
|
||||
break;
|
||||
}else{
|
||||
if(is_string($parameter)){
|
||||
throw new AssumptionFailedError();
|
||||
}
|
||||
var_dump(substr($commandLine, $offset));
|
||||
throw new ParameterParseException("Parameter " . get_class($parameter) . " for \$" . $parameter->getCodeName() . " didn't stop on a whitespace character");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($offset !== strlen($commandLine)){
|
||||
throw new InvalidCommandSyntaxException("Too many arguments provided for overload");
|
||||
}
|
||||
if(count($args) < $this->requiredInputCount){
|
||||
throw new InvalidCommandSyntaxException("Not enough arguments provided for overload");
|
||||
}
|
||||
//Reflection magic here :)
|
||||
//TODO: maybe we don't want to invoke this directly, but hand the args back to the caller?
|
||||
//this would allow resolving by more than just overload order
|
||||
if($this->acceptsAliasUsed){
|
||||
// @phpstan-ignore-next-line
|
||||
($this->handler)($sender, $aliasUsed, ...$args);
|
||||
}else{
|
||||
// @phpstan-ignore-next-line
|
||||
($this->handler)($sender, ...$args);
|
||||
}
|
||||
}
|
||||
}
|
61
src/command/overload/FloatRangeParameter.php
Normal file
61
src/command/overload/FloatRangeParameter.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\overload;
|
||||
|
||||
use DaveRandom\CallbackValidator\Type\BuiltInType;
|
||||
use DaveRandom\CallbackValidator\Type\NamedType;
|
||||
use pocketmine\lang\Translatable;
|
||||
use function preg_match;
|
||||
use function strlen;
|
||||
|
||||
/**
|
||||
* @phpstan-extends Parameter<float>
|
||||
*/
|
||||
final class FloatRangeParameter extends Parameter{
|
||||
|
||||
public function __construct(
|
||||
string $codeName,
|
||||
Translatable|string $printableName,
|
||||
private float $min,
|
||||
private float $max
|
||||
){
|
||||
parent::__construct($codeName, $printableName, new NamedType(BuiltInType::FLOAT));
|
||||
}
|
||||
|
||||
public function parse(string $buffer, int &$offset) : float{
|
||||
if(preg_match('/\G(-?\d+\.?\d*)/', $buffer, $matches, offset: $offset) > 0){
|
||||
$offset += strlen($matches[0]);
|
||||
$value = (float) $matches[0];
|
||||
if($value < $this->min || $value > $this->max){
|
||||
//TODO: we should probably use localised messages for this, but they probably won't be seen by the user
|
||||
//anyway since we'll try all the overloads before giving up
|
||||
throw new ParameterParseException("Value must be in the range $this->min ... $this->max");
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
throw new ParameterParseException("Expected a float in the range $this->min ... $this->max");
|
||||
}
|
||||
}
|
67
src/command/overload/IntRangeParameter.php
Normal file
67
src/command/overload/IntRangeParameter.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\overload;
|
||||
|
||||
use DaveRandom\CallbackValidator\Type\BuiltInType;
|
||||
use DaveRandom\CallbackValidator\Type\NamedType;
|
||||
use pocketmine\lang\Translatable;
|
||||
use function preg_match;
|
||||
use function preg_quote;
|
||||
use function strlen;
|
||||
|
||||
/**
|
||||
* @phpstan-extends Parameter<int>
|
||||
*/
|
||||
final class IntRangeParameter extends Parameter{
|
||||
|
||||
public function __construct(
|
||||
string $codeName,
|
||||
Translatable|string $printableName,
|
||||
private int $min,
|
||||
private int $max,
|
||||
private string $suffix = ""
|
||||
){
|
||||
parent::__construct($codeName, $printableName, new NamedType(BuiltInType::INT));
|
||||
}
|
||||
|
||||
public function parse(string $buffer, int &$offset) : int{
|
||||
if(preg_match('/\G-?\d+' . preg_quote($this->suffix, '/') . '/', $buffer, $matches, offset: $offset) > 0){
|
||||
$offset += strlen($matches[0]);
|
||||
$int = (int) $matches[0];
|
||||
if($int < $this->min || $int > $this->max){
|
||||
//TODO: we should probably use localised messages for this, but they probably won't be seen by the user
|
||||
//anyway since we'll try all the overloads before giving up
|
||||
throw new ParameterParseException("Value must be in the range $this->min ... $this->max");
|
||||
}
|
||||
|
||||
return $int;
|
||||
}
|
||||
|
||||
throw new ParameterParseException("Expected an integer in the range $this->min ... $this->max");
|
||||
}
|
||||
|
||||
public function getSuffix() : string{
|
||||
return $this->suffix;
|
||||
}
|
||||
}
|
75
src/command/overload/MappedParameter.php
Normal file
75
src/command/overload/MappedParameter.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\overload;
|
||||
|
||||
use DaveRandom\CallbackValidator\ParameterInfo;
|
||||
use DaveRandom\CallbackValidator\Prototype;
|
||||
use DaveRandom\CallbackValidator\ReturnInfo;
|
||||
use DaveRandom\CallbackValidator\Type\BuiltInType;
|
||||
use DaveRandom\CallbackValidator\Type\NamedType;
|
||||
use pocketmine\command\utils\CommandStringHelper;
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\utils\Utils;
|
||||
|
||||
/**
|
||||
* Looks up a string and converts it to some type of value.
|
||||
* The associated argument type will be inferred from the return type of the provided mapper function.
|
||||
*
|
||||
* @phpstan-template TValue
|
||||
* @phpstan-extends Parameter<TValue>
|
||||
*/
|
||||
final class MappedParameter extends Parameter{
|
||||
|
||||
/**
|
||||
* @phpstan-param \Closure(string): TValue $mapper
|
||||
*/
|
||||
public function __construct(
|
||||
string $codeName,
|
||||
Translatable|string $printableName,
|
||||
private \Closure $mapper
|
||||
){
|
||||
$givenPrototype = Prototype::fromClosure($this->mapper);
|
||||
$type = $givenPrototype->getReturnInfo()->type;
|
||||
if($type === null){
|
||||
throw new \InvalidArgumentException("Mapper callback must have a return type set");
|
||||
}
|
||||
$expectedPrototype = new Prototype(
|
||||
new ReturnInfo($type, byReference: false),
|
||||
new ParameterInfo("value", new NamedType(BuiltInType::STRING), byReference: false, isOptional: false, isVariadic: false)
|
||||
);
|
||||
Utils::validateCallableSignature($expectedPrototype, $givenPrototype);
|
||||
|
||||
parent::__construct(
|
||||
$codeName,
|
||||
$printableName,
|
||||
$type
|
||||
);
|
||||
}
|
||||
|
||||
public function parse(string $buffer, int &$offset) : mixed{
|
||||
$lookupKey = CommandStringHelper::parseQuoteAwareSingle($buffer, $offset) ?? throw new ParameterParseException("Unable to parse an argument from the buffer");
|
||||
|
||||
return ($this->mapper)($lookupKey);
|
||||
}
|
||||
}
|
70
src/command/overload/Parameter.php
Normal file
70
src/command/overload/Parameter.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\overload;
|
||||
|
||||
use DaveRandom\CallbackValidator\Type\BaseType;
|
||||
use pocketmine\lang\Translatable;
|
||||
|
||||
/**
|
||||
* @phpstan-template TValue
|
||||
*/
|
||||
abstract class Parameter{
|
||||
|
||||
public function __construct(
|
||||
private string $codeName,
|
||||
private Translatable|string $printableName,
|
||||
private BaseType $codeType,
|
||||
){}
|
||||
|
||||
public function getCodeName() : string{
|
||||
return $this->codeName;
|
||||
}
|
||||
|
||||
public function getPrintableName() : Translatable|string{
|
||||
return $this->printableName;
|
||||
}
|
||||
|
||||
public function getCodeType() : BaseType{
|
||||
return $this->codeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this command will consume all remaining inputs.
|
||||
*/
|
||||
public function consumesAllRemainingInputs() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The given string will be stripped of whitespace at the start
|
||||
*
|
||||
* @phpstan-return TValue
|
||||
* @throws ParameterParseException
|
||||
*/
|
||||
abstract public function parse(string $buffer, int &$offset) : mixed;
|
||||
|
||||
public function getSuffix() : string{
|
||||
return "";
|
||||
}
|
||||
}
|
30
src/command/overload/ParameterParseException.php
Normal file
30
src/command/overload/ParameterParseException.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\overload;
|
||||
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
|
||||
final class ParameterParseException extends InvalidCommandSyntaxException{
|
||||
|
||||
}
|
54
src/command/overload/RawParameter.php
Normal file
54
src/command/overload/RawParameter.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\overload;
|
||||
|
||||
use DaveRandom\CallbackValidator\Type\BuiltInType;
|
||||
use DaveRandom\CallbackValidator\Type\NamedType;
|
||||
use pocketmine\lang\Translatable;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* @phpstan-extends Parameter<string>
|
||||
*/
|
||||
final class RawParameter extends Parameter{
|
||||
|
||||
public function __construct(string $codeName, Translatable|string $printableName){
|
||||
parent::__construct(
|
||||
$codeName,
|
||||
$printableName,
|
||||
new NamedType(BuiltInType::STRING)
|
||||
);
|
||||
}
|
||||
|
||||
public function consumesAllRemainingInputs() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function parse(string $buffer, int &$offset) : string{
|
||||
$value = substr($buffer, $offset);
|
||||
$offset += strlen($value);
|
||||
return $value;
|
||||
}
|
||||
}
|
44
src/command/overload/RelativeFloat.php
Normal file
44
src/command/overload/RelativeFloat.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\overload;
|
||||
|
||||
use function max;
|
||||
use function min;
|
||||
|
||||
final class RelativeFloat{
|
||||
|
||||
public function __construct(
|
||||
private float $value,
|
||||
private bool $relative
|
||||
){}
|
||||
|
||||
public function getValue() : float{ return $this->value; }
|
||||
|
||||
public function isRelative() : bool{ return $this->relative; }
|
||||
|
||||
public function resolve(float $base, float $min, float $max) : float{
|
||||
//TODO: this should probably bail on out of bounds values
|
||||
return min($max, max($min, $this->relative ? $base + $this->value : $this->value));
|
||||
}
|
||||
}
|
54
src/command/overload/RelativeFloatParameter.php
Normal file
54
src/command/overload/RelativeFloatParameter.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\overload;
|
||||
|
||||
use DaveRandom\CallbackValidator\Type\NamedType;
|
||||
use pocketmine\lang\Translatable;
|
||||
use function preg_match;
|
||||
use function strlen;
|
||||
|
||||
/**
|
||||
* @phpstan-extends Parameter<RelativeFloat>
|
||||
*/
|
||||
final class RelativeFloatParameter extends Parameter{
|
||||
|
||||
public function __construct(string $codeName, Translatable|string $printableName){
|
||||
parent::__construct($codeName, $printableName, new NamedType(RelativeFloat::class));
|
||||
}
|
||||
|
||||
public function parse(string $buffer, int &$offset) : RelativeFloat{
|
||||
if(preg_match('/\G(~)?(-?\d+\.?\d*)?/', $buffer, $matches, offset: $offset) > 0){
|
||||
$relativeRaw = $matches[1] ?? "";
|
||||
$valueRaw = $matches[2] ?? "";
|
||||
if($valueRaw !== "" || $relativeRaw !== ""){
|
||||
$offset += strlen($matches[0]);
|
||||
$relative = $relativeRaw === "~";
|
||||
$value = (float) $valueRaw;
|
||||
return new RelativeFloat($value, $relative);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ParameterParseException("Expected a float, possibly preceded by a ~ symbol");
|
||||
}
|
||||
}
|
50
src/command/overload/StringParameter.php
Normal file
50
src/command/overload/StringParameter.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command\overload;
|
||||
|
||||
use DaveRandom\CallbackValidator\Type\BuiltInType;
|
||||
use DaveRandom\CallbackValidator\Type\NamedType;
|
||||
use pocketmine\command\utils\CommandStringHelper;
|
||||
use pocketmine\lang\Translatable;
|
||||
|
||||
/**
|
||||
* @phpstan-extends Parameter<string>
|
||||
*/
|
||||
final class StringParameter extends Parameter{
|
||||
|
||||
public function __construct(
|
||||
string $codeName,
|
||||
Translatable|string $printableName,
|
||||
){
|
||||
parent::__construct(
|
||||
$codeName,
|
||||
$printableName,
|
||||
new NamedType(BuiltInType::STRING)
|
||||
);
|
||||
}
|
||||
|
||||
public function parse(string $buffer, int &$offset) : string{
|
||||
return CommandStringHelper::parseQuoteAwareSingle($buffer, $offset) ?? throw new ParameterParseException();
|
||||
}
|
||||
}
|
@@ -25,8 +25,10 @@ namespace pocketmine\command\utils;
|
||||
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use function preg_last_error_msg;
|
||||
use function preg_match;
|
||||
use function preg_match_all;
|
||||
use function preg_replace;
|
||||
use function strlen;
|
||||
|
||||
final class CommandStringHelper{
|
||||
|
||||
@@ -60,4 +62,30 @@ final class CommandStringHelper{
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits by the same logic as {@link self::parseQuoteAware()}, but doesn't strip quotes from the parts or remove
|
||||
* escapes. Useful if you need to join the parts back into a new command string.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function splitQuoteAware(string $commandLine) : array{
|
||||
preg_match_all('/"((?:\\\\.|[^\\\\"])*)"|(\S+)/u', $commandLine, $matches);
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
public static function parseQuoteAwareSingle(string $commandLine, int &$offset = 0) : ?string{
|
||||
//quoted or bare string, like the old CommandStringHelper
|
||||
if(preg_match('/\G(?:"((?:\\\\.|[^\\\\"])*)"|(\S+))/u', $commandLine, $matches, offset: $offset) > 0){
|
||||
$offset += strlen($matches[0]);
|
||||
for($i = 1; $i <= 2; ++$i){
|
||||
if($matches[$i] !== ""){
|
||||
$match = $matches[$i];
|
||||
return preg_replace('/\\\\([\\\\"])/u', '$1', $match) ?? throw new AssumptionFailedError(preg_last_error_msg());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -1099,7 +1099,8 @@ class NetworkSession{
|
||||
$globalAliasMap = $this->server->getCommandMap()->getAliasMap();
|
||||
$userAliasMap = $this->player->getCommandAliasMap();
|
||||
foreach($this->server->getCommandMap()->getUniqueCommands() as $command){
|
||||
if(!$command->testPermissionSilent($this->player)){
|
||||
if(count($command->getUsages($this->player, "")) === 0){
|
||||
//no permitted overloads
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@@ -559,9 +559,9 @@ final class Utils{
|
||||
* @phpstan-param anyClosure $signature
|
||||
* @phpstan-param anyClosure $subject
|
||||
*/
|
||||
public static function validateCallableSignature(Prototype|\Closure $signature, \Closure $subject) : void{
|
||||
public static function validateCallableSignature(Prototype|\Closure $signature, Prototype|\Closure $subject) : void{
|
||||
$signaturePrototype = $signature instanceof Prototype ? $signature : Prototype::fromClosure($signature);
|
||||
$subjectPrototype = Prototype::fromClosure($subject);
|
||||
$subjectPrototype = $subject instanceof Prototype ? $subject : Prototype::fromClosure($subject);
|
||||
if(!$signaturePrototype->isSatisfiedBy($subjectPrototype)){
|
||||
throw new \TypeError("Declaration of callable `$subjectPrototype` must be compatible with `$signaturePrototype`");
|
||||
}
|
||||
|
@@ -781,7 +781,7 @@ parameters:
|
||||
path: ../../../src/network/mcpe/NetworkSession.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#1 \$target of method pocketmine\\command\\Command\:\:testPermissionSilent\(\) expects pocketmine\\command\\CommandSender, pocketmine\\player\\Player\|null given\.$#'
|
||||
message: '#^Parameter \#1 \$sender of method pocketmine\\command\\Command\:\:getUsages\(\) expects pocketmine\\command\\CommandSender, pocketmine\\player\\Player\|null given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: ../../../src/network/mcpe/NetworkSession.php
|
||||
|
@@ -156,12 +156,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/block/VanillaBlocks.php
|
||||
|
||||
-
|
||||
message: '#^Strict comparison using \=\=\= between \*NEVER\* and 5 will always evaluate to false\.$#'
|
||||
identifier: identical.alwaysFalse
|
||||
count: 1
|
||||
path: ../../../src/command/defaults/TeleportCommand.php
|
||||
|
||||
-
|
||||
message: '#^Method pocketmine\\crafting\\ShapedRecipe\:\:getIngredientMap\(\) should return list\<list\<pocketmine\\crafting\\RecipeIngredient\|null\>\> but returns array\<int\<0, max\>, non\-empty\-array\<int\<0, max\>, pocketmine\\crafting\\RecipeIngredient\|null\>\>\.$#'
|
||||
identifier: return.type
|
||||
|
Reference in New Issue
Block a user