From ba630f9bd1b2444632679df710c504e3d024eae1 Mon Sep 17 00:00:00 2001 From: PEMapModder Date: Wed, 25 Jun 2014 19:03:52 +0800 Subject: [PATCH] WorldEditArt: added permission nodes; added /wea wand --- WorldEditArt/Description.md | 10 +- WorldEditArt/plugin.yml | 35 ++++++ WorldEditArt/resources/config.yml | 6 + WorldEditArt/resources/player.yml | 4 + .../src/pemapmodder/worldeditart/Main.php | 106 ++++++++++++++---- .../worldeditart/utils/subcommand/Macro.php | 7 ++ .../utils/subcommand/Subcommand.php | 11 +- .../utils/subcommand/SubcommandMap.php | 8 +- .../worldeditart/utils/subcommand/Wand.php | 89 +++++++++++++++ 9 files changed, 237 insertions(+), 39 deletions(-) create mode 100644 WorldEditArt/resources/config.yml create mode 100644 WorldEditArt/resources/player.yml create mode 100644 WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/Macro.php create mode 100644 WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/Wand.php diff --git a/WorldEditArt/Description.md b/WorldEditArt/Description.md index 1e35eba..ecb325b 100644 --- a/WorldEditArt/Description.md +++ b/WorldEditArt/Description.md @@ -3,16 +3,16 @@ WorldEditArt WorldEditArt is a professional world editor that is very convenient for building. It includes the following features: ## Convenient coordinate selection -You can define your own wand using `/wea wand ` or check it via `/wea wand`. If you touch a block with a wand, your selected position will be the touched block. You can also select your current standing/flying position by `/wea sel here`. +You can define your own wand using `/wea wand `, set to the current held item using `/wea wand hand` or check it via `/wea wand`. If you touch a block with a wand, your selected position will be the touched block. You can also select your current standing/flying position by `/wea sel here`. ##Cuboid/Cylinder/Sphere selection, replacing, editing and copying -A cuboid can be selected by two selected points. Select the first point, run `/wea sel1`, select the second point, run `/wea sel2`, then you have the cuboid block selected. You can change any of the points by selecting it again. You can select the second point first; it doesn't matter. It can also be selected by a command. First, select the starting point of the cuboid. Then run the command `/wea cubsel `. A line will grow for blocks towards the direction you are looking at, and the smallest right cuboid that can fit the line will be selected. +A cuboid can be selected by two selected points. Select the first point, run `/wea sel 1`, select the second point, run `/wea sel 2`, then you have the cuboid block selected. You can change any of the points by selecting it again. You can select the second point first; it doesn't matter. It can also be selected by a command. First, select the starting point of the cuboid. Then run the command `/wea sel cub `. A line will grow for blocks towards the direction you are looking at, and the smallest right cuboid that can fit the line will be selected. -A cylinder needs to be selected by a command. First, select the base of the cylinder. Then, run `/wea cylsel ` to select it. The cylinder will grow for blocks towards the linear direction you are looking at (west, east, north, south, directly downwards and directly upwards) with a base radius of blocks. +A cylinder needs to be selected by a command. First, select the base of the cylinder. Then, run `/wea sel cyl ` to select it. The cylinder will grow for blocks towards the linear direction you are looking at (west, east, north, south, directly downwards and directly upwards) with a base radius of blocks. -A sphere also needs to be selected by a command. First, select the centre point of the sphere. Then, run `/wea sphsel ` to select it. A sphere centered at your selected point with blocks of radius will be selected. +A sphere also needs to be selected by a command. First, select the centre point of the sphere. Then, run `/wea sel sph ` to select it. A sphere centered at your selected point with blocks of radius will be selected. -If you want to test how your selection is, use `/wea seltest ` +If you want to test how your selection is, use `/wea sel test ` ## Macros If you have not heard of macros, here it is. diff --git a/WorldEditArt/plugin.yml b/WorldEditArt/plugin.yml index b9c2bba..04609f5 100644 --- a/WorldEditArt/plugin.yml +++ b/WorldEditArt/plugin.yml @@ -4,3 +4,38 @@ version: 1.0 api: [1.0.0] load: POSTWORLD main: pemapmodder\worldeditart +permissions: + wea: + description: Allow using all WorldEditArt functions + children: + wea.cmd: + description: Allow using command /wea + wea.sel: + description: Allow making selections + children: + wea.sel.pt: + description: Allow making point selections + children: + wea.sel.pt.here: + description: Allow selecting a point by the player's self location + wea.sel.pt.cmd: + description: Allow using subcommand /wea wand plus selecting points using wands + wea.wand: + description: Allow using everything of /wea wand + children: + wea.wand.check: + description: Allow checking own wand + wea.wand.set: + description: Allow setting own wand + children: + wea.wand.set.hand: + description: Allow using subcommand /wea wand hand + wea.wand.set.named: + description: Allow using subcommand /wea wand + wea.macro: + description: Allow using all features of macros + children: + wea.macro.record: + description: Allow recording macros + wea.macro.run: + description: Allow running macros \ No newline at end of file diff --git a/WorldEditArt/resources/config.yml b/WorldEditArt/resources/config.yml new file mode 100644 index 0000000..00e9cd2 --- /dev/null +++ b/WorldEditArt/resources/config.yml @@ -0,0 +1,6 @@ +--- +## Wands +# The default wand item ID +wand-id: 292 +# leave true for any damage values +wand-damage: true diff --git a/WorldEditArt/resources/player.yml b/WorldEditArt/resources/player.yml new file mode 100644 index 0000000..8e93d17 --- /dev/null +++ b/WorldEditArt/resources/player.yml @@ -0,0 +1,4 @@ +--- +wand-id: false +wand-damage: false # false for default, true for any +... diff --git a/WorldEditArt/src/pemapmodder/worldeditart/Main.php b/WorldEditArt/src/pemapmodder/worldeditart/Main.php index d063b51..8a9a33f 100644 --- a/WorldEditArt/src/pemapmodder/worldeditart/Main.php +++ b/WorldEditArt/src/pemapmodder/worldeditart/Main.php @@ -2,52 +2,55 @@ namespace pemapmodder\worldeditart; +use pemapmodder\worldeditart\utils\subcommand\Macro; use pemapmodder\worldeditart\utils\subcommand\SubcommandMap; +use pemapmodder\worldeditart\utils\subcommand\Wand; use pocketmine\event\Listener; use pocketmine\event\player\PlayerInteractEvent; use pocketmine\event\player\PlayerJoinEvent; use pocketmine\event\player\PlayerQuitEvent; +use pocketmine\item\Item; use pocketmine\level\Position; use pocketmine\Player; use pocketmine\plugin\PluginBase; class Main extends PluginBase implements Listener{ - // block touch sessions - const BTS_NOTHING = 0; - /** @var int[] */ - private $blockTouchSessions = []; - - // macros - /** @var Position[] */ - private $anchors = []; - - private $recordingMacros = []; - + const W_NOTHING = 0; + /** @var int[] $wandSessions */ + private $wandSessions = []; + /** @var Position[] $selectedPoints */ + private $selectedPoints = []; + /** @var utils\spaces\Space[] */ + private $selections = []; public function onEnable(){ - // config file + @mkdir($this->getDataFolder()); + @mkdir($this->getDataFolder()."players/"); $this->saveDefaultConfig(); $this->getConfig(); // just to load it - // events $this->getServer()->getPluginManager()->registerEvents($this, $this); - // commands $this->registerCommands(); } private function registerCommands(){ - $wea = new SubcommandMap("worldeditart", $this, "WorldEditArt main command", "wea.cmd", ["wea"]); + $wea = new SubcommandMap("worldeditart", $this, "WorldEditArt main command", "wea.cmd", ["wea", "we", "w"]); // I expect them to use fallback prefix if they use /w + $wea->registerAll([ + new Macro($this), + new Wand($this), + ]); + $this->getServer()->getCommandMap()->register("wea", $wea); } public function onJoin(PlayerJoinEvent $event){ - $this->blockTouchSessions[$event->getPlayer()->getID()] = self::BTS_NOTHING; + $this->wandSessions[$event->getPlayer()->getID()] = self::W_NOTHING; } public function onQuit(PlayerQuitEvent $event){ - if(isset($this->blockTouchSessions[$k = $event->getPlayer()->getID()])){ - unset($this->blockTouchSessions[$k]); + if(isset($this->wandSessions[$k = $event->getPlayer()->getID()])){ + unset($this->wandSessions[$k]); } } public function onInteract(PlayerInteractEvent $event){ $p = $event->getPlayer(); - switch($this->blockTouchSessions[$p->getID()]){ - case "": - break; + switch($this->wandSessions[$p->getID()]){ + case self::W_NOTHING: + return; } } /** @@ -55,6 +58,67 @@ public function onInteract(PlayerInteractEvent $event){ * @return Position|bool */ public function getSelectedPoint(Player $player){ + if(isset($this->selectedPoints[$player->getID()])){ + return $this->selectedPoints[$player->getID()]; + } return false; // TODO } + public function setSelectedPoint(Player $player, Position $pos){ + $this->selectedPoints[$player->getID()] = $pos; + } + public function getPlayerWand(Player $player, &$isDamageLimited){ + $id = false; + $damage = false; + if(is_file($path = $this->getPlayerFile($player))){ + $data = yaml_parse_file($path); + $id = $data["wand-id"]; + $damage = $data["wand-damage"]; + } + if($id === false){ + $id = $this->getConfig()->get("wand-id"); + } + if($damage === false){ + $damage = $this->getConfig()->get("wand-damage"); + } + $isDamageLimited = is_int($damage); + if($damage === true){ + $damage = 0; + } + return Item::get($id, $damage); + } + public function setWand(Player $player, $id, $damage = true){ + if(!is_file($path = $this->getPlayerFile($player))){ + stream_copy_to_stream($this->getResource("player.yml"), fopen($path, "wb")); + } + $yaml = yaml_parse_file($path); + $yaml["wand-id"] = $id; + $yaml["wand-damage"] = $damage; + yaml_emit_file($path, $yaml, YAML_UTF8_ENCODING); + } + public function getPlayerFile(Player $player){ + return $this->getDataFolder()."players/".strtolower($player->getName()); + } + public function isWand(Player $player, Item $item){ + $path = $this->getPlayerFile($player); + $id = false; + $damage = false; + if(is_file($path)){ + $data = yaml_parse_file($path); + $id = $data["wand-id"]; + $damage = $data["wand-damage"]; + } + if($id === false){ + $id = $this->getConfig()->get("wand-id"); + } + if($damage === false){ + $damage = $this->getConfig()->get("wand-damage"); + } + if($id !== $item->getID()){ + return false; + } + if($damage === true or $damage === $item->getDamage()){ + return true; + } + return false; + } } diff --git a/WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/Macro.php b/WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/Macro.php new file mode 100644 index 0000000..b6f3859 --- /dev/null +++ b/WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/Macro.php @@ -0,0 +1,7 @@ +main = $main; - $this->name = $name; $rc = new \ReflectionClass($this); $this->callable = $callable; $this->permCheck = $permCheck; @@ -95,9 +92,7 @@ public final function run(array $args, CommandSender $sender){ } return; } // I made these functions final to avoid accidental override - public final function getName(){ - return $this->name; - } + public abstract function getName(); public final function getMain(){ return $this->main; } diff --git a/WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/SubcommandMap.php b/WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/SubcommandMap.php index c5723f7..5b2b6e6 100644 --- a/WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/SubcommandMap.php +++ b/WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/SubcommandMap.php @@ -37,9 +37,10 @@ public function execute(CommandSender $issuer, $lbl, array $args){ } $cmd = array_shift($args); if(isset($this->subcmds[$cmd = strtolower(trim($cmd))]) and $cmd !== "help"){ - if($this->subcmds[$cmd]->hasPermission($issuer) and $issuer->hasPermission($this->getPermission() . "." . strtolower($this->subcmds[$cmd]->getName()))){ + if($this->subcmds[$cmd]->hasPermission($issuer)){ $this->subcmds[$cmd]->run($args, $issuer); - }else{ + } + else{ $issuer->sendMessage("You don't have permission to do this!"); } }else{ @@ -68,9 +69,6 @@ public function getFullHelp(CommandSender $sender){ if(!$cmd->hasPermission($sender)){ continue; } - if(!$sender->hasPermission($this->getPermission().".".strtolower($cmd->getName()))){ - continue; - } $output = ""; $output .= "/{$this->getName()} "; $output .= TextFormat::LIGHT_PURPLE . $cmd->getName() . " "; diff --git a/WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/Wand.php b/WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/Wand.php new file mode 100644 index 0000000..238e4bc --- /dev/null +++ b/WorldEditArt/src/pemapmodder/worldeditart/utils/subcommand/Wand.php @@ -0,0 +1,89 @@ +hasPermission("wea.wand.check")){ + return self::NO_PERM; + } + $damageSpecified = 0; + $item = $this->getMain()->getPlayerWand($player, $damageSpecified); + $name = strtolower($item->getName()." with item damage ".($damageSpecified ? "specified as {$item->getDamage()}.":"not specified.")); + return "Your wand item is $name"; + } + if($args[0] === "hand"){ + if(!$player->hasPermission("wea.wand.set.hand")){ + return self::NO_PERM; + } + $item = $player->getInventory()->getItemInHand(); + $damage = true; + if(isset($args[1]) and $args[1] === "-d"){ + $damage = $item->getDamage(); + } + $this->getMain()->setWand($player, $item->getID(), $damage); + $name = strtolower($item->getName()." with item damage ".($damage !== true ? "specified as {$item->getDamage()}.":"not specified.")); + return "Your wand item is now $name"; + } + if(!$player->hasPermission("wea.wand.set.named")){ + return self::NO_PERM; + } + $name = implode("_", $args); + if(is_numeric(str_replace(":", "", $name))){ + $tokens = explode(":", $name); + $damage = true; + if(isset($tokens[1])){ + $damage = (int) $tokens[1]; + } + $id = (int) $tokens[0]; + $this->getMain()->setWand($player, $id, $damage); + $item = Item::get($id, $damage === true ? 0:$damage); + $name = strtolower($item->getName()." with item damage ".($damage !== true ? "specified as {$item->getDamage()}.":"not specified.")); + return "Your wand item is now $name"; + } + $damage = 0; + $tokens = explode(":", $name); + if(isset($tokens[1])){ + $name = $tokens[0]; + $damage = (int) $name; + } + $class = "pocketmine\\item\\".str_replace("_", "", $name); + if(class_exists($class) and is_subclass_of($class, "pocketmine\\item\\Item")){ + /** @var Item $instance */ + $instance = new $class($damage); + if(!isset($tokens[1])){ + $damage = true; + } + $this->getMain()->setWand($player, $instance->getID(), $damage); + } + elseif(defined("pocketmine\\item\\Item::$name")){ + $id = constant("pocketmine\\item\\Item::$name"); + if(!isset($tokens[1])){ + $damage = true; + } + $this->getMain()->setWand($player, $id, $damage); + $instance = Item::get($id, $damage); + } + else{ + return self::WRONG_USE; + } + $name = strtolower($instance->getName()." with item damage ".($damage !== true ? "specified as {$instance->getDamage()}.":"not specified.")); + return "Your wand item is now $name"; + } + public function checkPermission(Player $player){ + return $player->hasPermission("wea.wand.check") or $player->hasPermission("wea.wand.set.hand") or $player->hasPermission("wea.wand.set.named"); + } +}