├── .gitignore ├── LICENSE ├── README.md ├── plugin.yml └── src ├── DevTools ├── ConsoleScript.php ├── DevTools.php └── commands │ ├── DevToolsCommand.php │ └── ExtractPluginCommand.php └── FolderPluginLoader ├── FolderPluginLoader.php └── Main.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Development Tools for PocketMine-MP 2 | 3 | ### Warning: This version is for the new PocketMine-MP API 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Lesser General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public License 16 | along with this program. If not, see . 17 | 18 | 19 | ## Installation 20 | - Drop it into the PocketMine's `plugins/` folder. 21 | - Restart the server. The plugin will be loaded 22 | 23 | ## Usage 24 | * _/makeplugin _: Creates a Phar plugin archive for its distribution 25 | * _/makeserver_: Creates a PocketMine-MP Phar archive 26 | * _/checkperm [playerName]_: Checks a permission node 27 | 28 | ## Create .phar from console 29 | Download [DevTools.phar](https://github.com/PocketMine/DevTools/releases) 30 | 31 | php -dphar.readonly=0 DevTools.phar \ 32 | --make="./plugin/" \ 33 | --relative="./plugin/" \ 34 | --out "plugin.phar" 35 | 36 | or [ConsoleScript.php](https://github.com/PocketMine/DevTools/blob/master/src/DevTools/ConsoleScript.php) 37 | 38 | php -dphar.readonly=0 ConsoleScript.php \ 39 | --make="./plugin/" \ 40 | --relative="./plugin/" \ 41 | --out "plugin.phar" 42 | -------------------------------------------------------------------------------- /plugin.yml: -------------------------------------------------------------------------------- 1 | name: DevTools 2 | main: DevTools\DevTools 3 | version: 1.11.0 4 | api: 2.0.0 5 | load: STARTUP 6 | author: PocketMine Team 7 | description: Helps develop and distribute PocketMine-MP plugins 8 | website: https://github.com/PocketMine/DevTools 9 | commands: 10 | makeserver: 11 | description: Creates a PocketMine-MP Phar 12 | usage: "/makeserver" 13 | permission: devtools.command.makeserver 14 | makeplugin: 15 | description: Creates a Phar plugin from one in source code form 16 | usage: "/makeplugin " 17 | permission: devtools.command.makeplugin 18 | checkperm: 19 | description: Checks a permission value for the current sender, or a player 20 | usage: "/checkperm [playerName]" 21 | permission: "devtools.command.checkperm;devtools.command.checkperm.other" 22 | permissions: 23 | devtools: 24 | default: op 25 | description: "Allows using all the DevTools things" 26 | children: 27 | devtools.command: 28 | default: op 29 | description: "Allows using all the DevTools commands" 30 | children: 31 | devtools.command.makeplugin: 32 | default: op 33 | description: "Allows the creation of Phar plugins" 34 | devtools.command.extractplugin: 35 | default: op 36 | description: "Allows the extraction of Phar plugins" 37 | devtools.command.makeserver: 38 | default: op 39 | description: "Allows the creation of a PocketMine-MP Phar" 40 | devtools.command.checkperm: 41 | default: true 42 | description: "Allows checking a permission value" 43 | children: 44 | devtools.command.checkperm.other: 45 | default: op 46 | description: "Allows checking others permission value" 47 | -------------------------------------------------------------------------------- /src/DevTools/ConsoleScript.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | 18 | const VERSION = "1.11.0"; 19 | 20 | $opts = getopt("", ["make:", "relative:", "out:", "entry:", "compress"]); 21 | 22 | if(!isset($opts["make"])){ 23 | echo "== PocketMine-MP DevTools CLI interface ==\n\n"; 24 | echo "Usage: ". PHP_BINARY ." -dphar.readonly=0 ".$argv[0]." --make --relative --entry \"relativeSourcePath.php\" --out \n"; 25 | exit(0); 26 | } 27 | 28 | if(ini_get("phar.readonly") == 1){ 29 | echo "Set phar.readonly to 0 with -dphar.readonly=0\n"; 30 | exit(1); 31 | } 32 | 33 | $folderPath = rtrim(str_replace("\\", "/", realpath($opts["make"])), "/") . "/"; 34 | $relativePath = isset($opts["relative"]) ? rtrim(str_replace("\\", "/", realpath($opts["relative"])), "/") . "/" : $folderPath; 35 | $pharName = isset($opts["out"]) ? $opts["out"] : "output.phar"; 36 | 37 | 38 | 39 | if(!is_dir($folderPath)){ 40 | echo $folderPath ." is not a folder\n"; 41 | exit(1); 42 | } 43 | 44 | echo "\nCreating ".$pharName."...\n"; 45 | $phar = new \Phar($pharName); 46 | if($metadata["name"] === "DevTools"){ 47 | $phar->setStub('setStub('setMetadata([ 56 | "name" => $metadata["name"], 57 | "version" => $metadata["version"], 58 | "main" => $metadata["main"], 59 | "api" => $metadata["api"], 60 | "depend" => (isset($metadata["depend"]) ? $metadata["depend"] : ""), 61 | "description" => (isset($metadata["description"]) ?$metadata["description"] : ""), 62 | "authors" => (isset($metadata["authors"]) ? $metadata["authors"] : ""), 63 | "website" => (isset($metadata["website"]) ? $metadata["website"] : ""), 64 | "creationDate" => time() 65 | ]); 66 | $phar->setStub('getMetadata() as $key => $value){echo ucfirst($key).": ".(is_array($value) ? implode(", ", $value):$value)."\n";}} __HALT_COMPILER();'); 67 | }else{ 68 | echo "Missing entry point or plugin.yml\n"; 69 | exit(1); 70 | } 71 | } 72 | $phar->setSignatureAlgorithm(\Phar::SHA1); 73 | $phar->startBuffering(); 74 | echo "Adding files...\n"; 75 | $maxLen = 0; 76 | $count = 0; 77 | foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($folderPath)) as $file){ 78 | $path = rtrim(str_replace(["\\", $relativePath], ["/", ""], $file), "/"); 79 | if($path{0} === "." or strpos($path, "/.") !== false){ 80 | continue; 81 | } 82 | $phar->addFile($file, $path); 83 | if(strlen($path) > $maxLen){ 84 | $maxLen = strlen($path); 85 | } 86 | echo "\r[".(++$count)."] ".str_pad($path, $maxLen, " "); 87 | } 88 | 89 | $phar->stopBuffering(); 90 | 91 | echo "Done!\n"; 92 | exit(0); -------------------------------------------------------------------------------- /src/DevTools/DevTools.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | 18 | namespace DevTools; 19 | 20 | use DevTools\commands\ExtractPluginCommand; 21 | use FolderPluginLoader\FolderPluginLoader; 22 | use pocketmine\command\Command; 23 | use pocketmine\command\CommandExecutor; 24 | use pocketmine\command\CommandSender; 25 | use pocketmine\network\protocol\Info; 26 | use pocketmine\permission\Permission; 27 | use pocketmine\Player; 28 | use pocketmine\plugin\Plugin; 29 | use pocketmine\plugin\PluginBase; 30 | use pocketmine\plugin\PluginLoadOrder; 31 | use pocketmine\Server; 32 | use pocketmine\utils\TextFormat; 33 | 34 | class DevTools extends PluginBase implements CommandExecutor{ 35 | 36 | public function onLoad(){ 37 | $this->getServer()->getCommandMap()->register("devtools", new ExtractPluginCommand($this)); 38 | } 39 | 40 | public function onEnable(){ 41 | @mkdir($this->getDataFolder()); 42 | 43 | if(!class_exists("FolderPluginLoader\\FolderPluginLoader", false)){ 44 | $this->getServer()->getPluginManager()->registerInterface("FolderPluginLoader\\FolderPluginLoader"); 45 | $this->getServer()->getPluginManager()->loadPlugins($this->getServer()->getPluginPath(), ["FolderPluginLoader\\FolderPluginLoader"]); 46 | $this->getLogger()->info("Registered folder plugin loader"); 47 | $this->getServer()->enablePlugins(PluginLoadOrder::STARTUP); 48 | } 49 | } 50 | 51 | public function onCommand(CommandSender $sender, Command $command, $label, array $args){ 52 | switch($command->getName()){ 53 | case "makeplugin": 54 | if(isset($args[0]) and $args[0] === "FolderPluginLoader"){ 55 | return $this->makePluginLoader($sender, $command, $label, $args); 56 | }else{ 57 | return $this->makePluginCommand($sender, $command, $label, $args); 58 | } 59 | case "makeserver": 60 | return $this->makeServerCommand($sender, $command, $label, $args); 61 | case "checkperm": 62 | return $this->permissionCheckCommand($sender, $command, $label, $args); 63 | default: 64 | return false; 65 | } 66 | } 67 | 68 | private function permissionCheckCommand(CommandSender $sender, Command $command, $label, array $args){ 69 | $target = $sender; 70 | if(!isset($args[0])){ 71 | return false; 72 | } 73 | $node = strtolower($args[0]); 74 | if(isset($args[1])){ 75 | if(($player = $this->getServer()->getPlayer($args[1])) instanceof Player){ 76 | $target = $player; 77 | }else{ 78 | return false; 79 | } 80 | } 81 | 82 | if($target !== $sender and !$sender->hasPermission("devtools.command.checkperm.other")){ 83 | $sender->sendMessage(TextFormat::RED . "You do not have permissions to check other players."); 84 | return true; 85 | }else{ 86 | $sender->sendMessage(TextFormat::GREEN . "---- ".TextFormat::WHITE . "Permission node ".$node.TextFormat::GREEN. " ----"); 87 | $perm = $this->getServer()->getPluginManager()->getPermission($node); 88 | if($perm instanceof Permission){ 89 | $desc = TextFormat::GOLD . "Description: ".TextFormat::WHITE . $perm->getDescription()."\n"; 90 | $desc .= TextFormat::GOLD . "Default: ".TextFormat::WHITE . $perm->getDefault()."\n"; 91 | $children = ""; 92 | foreach($perm->getChildren() as $name => $true){ 93 | $children .= $name . ", "; 94 | } 95 | $desc .= TextFormat::GOLD . "Children: ".TextFormat::WHITE . substr($children, 0, -2)."\n"; 96 | }else{ 97 | $desc = TextFormat::RED . "Permission does not exist\n"; 98 | $desc .= TextFormat::GOLD . "Default: ".TextFormat::WHITE . Permission::$DEFAULT_PERMISSION."\n"; 99 | } 100 | $sender->sendMessage($desc); 101 | $sender->sendMessage(TextFormat::YELLOW . $target->getName() . TextFormat::WHITE . " has it set to ".($target->hasPermission($node) === true ? TextFormat::GREEN . "true" : TextFormat::RED . "false")); 102 | return true; 103 | } 104 | } 105 | 106 | private function makePluginLoader(CommandSender $sender, Command $command, $label, array $args){ 107 | $pharPath = $this->getDataFolder() . DIRECTORY_SEPARATOR . "FolderPluginLoader.phar"; 108 | if(file_exists($pharPath)){ 109 | $sender->sendMessage("Phar plugin already exists, overwriting..."); 110 | @unlink($pharPath); 111 | } 112 | $phar = new \Phar($pharPath); 113 | $phar->setMetadata([ 114 | "name" => "FolderPluginLoader", 115 | "version" => "1.0.0", 116 | "main" => "FolderPluginLoader\\Main", 117 | "api" => ["1.0.0"], 118 | "depend" => [], 119 | "description" => "Loader of folder plugins", 120 | "authors" => ["PocketMine Team"], 121 | "website" => "https://github.com/PocketMine/DevTools", 122 | "creationDate" => time() 123 | ]); 124 | $phar->setStub('setSignatureAlgorithm(\Phar::SHA1); 126 | $phar->startBuffering(); 127 | 128 | $phar->addFromString("plugin.yml", "name: FolderPluginLoader\nversion: 1.0.0\nmain: FolderPluginLoader\\Main\napi: [1.0.0]\nload: STARTUP\n"); 129 | $phar->addFile($this->getFile() . "src/FolderPluginLoader/FolderPluginLoader.php", "src/FolderPluginLoader/FolderPluginLoader.php"); 130 | $phar->addFile($this->getFile() . "src/FolderPluginLoader/Main.php", "src/FolderPluginLoader/Main.php"); 131 | 132 | foreach($phar as $file => $finfo){ 133 | /** @var \PharFileInfo $finfo */ 134 | if($finfo->getSize() > (1024 * 512)){ 135 | $finfo->compress(\Phar::GZ); 136 | } 137 | } 138 | $phar->stopBuffering(); 139 | $sender->sendMessage("Folder plugin loader has been created on ".$pharPath); 140 | return true; 141 | } 142 | 143 | private function makePluginCommand(CommandSender $sender, Command $command, $label, array $args){ 144 | $pluginName = trim(implode(" ", $args)); 145 | if($pluginName === "" or !(($plugin = Server::getInstance()->getPluginManager()->getPlugin($pluginName)) instanceof Plugin)){ 146 | $sender->sendMessage(TextFormat::RED . "Invalid plugin name, check the name case."); 147 | return true; 148 | } 149 | $description = $plugin->getDescription(); 150 | 151 | if(!($plugin->getPluginLoader() instanceof FolderPluginLoader)){ 152 | $sender->sendMessage(TextFormat::RED . "Plugin ".$description->getName()." is not in folder structure."); 153 | return true; 154 | } 155 | 156 | $pharPath = $this->getDataFolder() . DIRECTORY_SEPARATOR . $description->getName()."_v".$description->getVersion().".phar"; 157 | if(file_exists($pharPath)){ 158 | $sender->sendMessage("Phar plugin already exists, overwriting..."); 159 | @unlink($pharPath); 160 | } 161 | $phar = new \Phar($pharPath); 162 | $phar->setMetadata([ 163 | "name" => $description->getName(), 164 | "version" => $description->getVersion(), 165 | "main" => $description->getMain(), 166 | "api" => $description->getCompatibleApis(), 167 | "depend" => $description->getDepend(), 168 | "description" => $description->getDescription(), 169 | "authors" => $description->getAuthors(), 170 | "website" => $description->getWebsite(), 171 | "creationDate" => time() 172 | ]); 173 | if($description->getName() === "DevTools"){ 174 | $phar->setStub('setStub('getName() .' v'.$description->getVersion().'\nThis file has been generated using DevTools v'.$this->getDescription()->getVersion().' at '.date("r").'\n----------------\n";if(extension_loaded("phar")){$phar = new \Phar(__FILE__);foreach($phar->getMetadata() as $key => $value){echo ucfirst($key).": ".(is_array($value) ? implode(", ", $value):$value)."\n";}} __HALT_COMPILER();'); 177 | } 178 | $phar->setSignatureAlgorithm(\Phar::SHA1); 179 | $reflection = new \ReflectionClass("pocketmine\\plugin\\PluginBase"); 180 | $file = $reflection->getProperty("file"); 181 | $file->setAccessible(true); 182 | $filePath = rtrim(str_replace("\\", "/", $file->getValue($plugin)), "/") . "/"; 183 | $phar->startBuffering(); 184 | foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($filePath)) as $file){ 185 | $path = ltrim(str_replace(["\\", $filePath], ["/", ""], $file), "/"); 186 | if($path{0} === "." or strpos($path, "/.") !== false){ 187 | continue; 188 | } 189 | $phar->addFile($file, $path); 190 | $sender->sendMessage("[DevTools] Adding $path"); 191 | } 192 | 193 | foreach($phar as $file => $finfo){ 194 | /** @var \PharFileInfo $finfo */ 195 | if($finfo->getSize() > (1024 * 512)){ 196 | $finfo->compress(\Phar::GZ); 197 | } 198 | } 199 | $phar->stopBuffering(); 200 | $sender->sendMessage("Phar plugin ".$description->getName() ." v".$description->getVersion()." has been created on ".$pharPath); 201 | return true; 202 | } 203 | 204 | private function makeServerCommand(CommandSender $sender, Command $command, $label, array $args){ 205 | $server = $sender->getServer(); 206 | $pharPath = $this->getDataFolder() . DIRECTORY_SEPARATOR . $server->getName()."_".$server->getPocketMineVersion().".phar"; 207 | if(file_exists($pharPath)){ 208 | $sender->sendMessage("Phar file already exists, overwriting..."); 209 | @unlink($pharPath); 210 | } 211 | $phar = new \Phar($pharPath); 212 | $phar->setMetadata([ 213 | "name" => $server->getName(), 214 | "version" => $server->getPocketMineVersion(), 215 | "api" => $server->getApiVersion(), 216 | "minecraft" => $server->getVersion(), 217 | "protocol" => Info::CURRENT_PROTOCOL, 218 | "creationDate" => time() 219 | ]); 220 | $phar->setStub('setSignatureAlgorithm(\Phar::SHA1); 222 | $phar->startBuffering(); 223 | 224 | $filePath = substr(\pocketmine\PATH, 0, 7) === "phar://" ? \pocketmine\PATH : realpath(\pocketmine\PATH) . "/"; 225 | $filePath = rtrim(str_replace("\\", "/", $filePath), "/") . "/"; 226 | foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($filePath . "src")) as $file){ 227 | $path = ltrim(str_replace(["\\", $filePath], ["/", ""], $file), "/"); 228 | if($path{0} === "." or strpos($path, "/.") !== false or substr($path, 0, 4) !== "src/"){ 229 | continue; 230 | } 231 | $phar->addFile($file, $path); 232 | $sender->sendMessage("[DevTools] Adding $path"); 233 | } 234 | foreach($phar as $file => $finfo){ 235 | /** @var \PharFileInfo $finfo */ 236 | if($finfo->getSize() > (1024 * 512)){ 237 | $finfo->compress(\Phar::GZ); 238 | } 239 | } 240 | $phar->stopBuffering(); 241 | 242 | $sender->sendMessage($server->getName() . " " . $server->getPocketMineVersion() . " Phar file has been created on ".$pharPath); 243 | 244 | return true; 245 | } 246 | 247 | } -------------------------------------------------------------------------------- /src/DevTools/commands/DevToolsCommand.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | 18 | namespace DevTools\commands; 19 | 20 | use DevTools\DevTools; 21 | use pocketmine\command\Command; 22 | use pocketmine\command\PluginIdentifiableCommand; 23 | 24 | abstract class DevToolsCommand extends Command implements PluginIdentifiableCommand{ 25 | /** @var \pocketmine\plugin\Plugin */ 26 | private $owningPlugin; 27 | 28 | public function __construct($name, DevTools $plugin){ 29 | parent::__construct($name); 30 | $this->owningPlugin = $plugin; 31 | $this->usageMessage = ""; 32 | } 33 | 34 | public function getPlugin(){ 35 | return $this->owningPlugin; 36 | } 37 | } -------------------------------------------------------------------------------- /src/DevTools/commands/ExtractPluginCommand.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | 18 | namespace DevTools\commands; 19 | 20 | use DevTools\DevTools; 21 | use pocketmine\command\CommandSender; 22 | use pocketmine\plugin\PharPluginLoader; 23 | use pocketmine\plugin\Plugin; 24 | use pocketmine\Server; 25 | use pocketmine\utils\TextFormat; 26 | 27 | class ExtractPluginCommand extends DevToolsCommand{ 28 | 29 | public function __construct(DevTools $plugin){ 30 | parent::__construct("extractplugin", $plugin); 31 | $this->setUsage("/extractplugin "); 32 | $this->setDescription("Extracts the source code from a Phar plugin"); 33 | $this->setPermission("devtools.command.extractplugin"); 34 | } 35 | 36 | public function execute(CommandSender $sender, $commandLabel, array $args){ 37 | if(!$this->getPlugin()->isEnabled()){ 38 | return false; 39 | } 40 | 41 | if(!$this->testPermission($sender)){ 42 | return false; 43 | } 44 | 45 | if(count($args) === 0){ 46 | $sender->sendMessage(TextFormat::RED . "Usage: ".$this->usageMessage); 47 | return true; 48 | } 49 | 50 | $pluginName = trim(implode(" ", $args)); 51 | if($pluginName === "" or !(($plugin = Server::getInstance()->getPluginManager()->getPlugin($pluginName)) instanceof Plugin)){ 52 | $sender->sendMessage(TextFormat::RED . "Invalid plugin name, check the name case."); 53 | return true; 54 | } 55 | $description = $plugin->getDescription(); 56 | 57 | if(!($plugin->getPluginLoader() instanceof PharPluginLoader)){ 58 | $sender->sendMessage(TextFormat::RED . "Plugin ".$description->getName()." is not in Phar structure."); 59 | return true; 60 | } 61 | 62 | $folderPath = $this->getPlugin()->getDataFolder() . DIRECTORY_SEPARATOR . $description->getName()."_v".$description->getVersion()."/"; 63 | if(file_exists($folderPath)){ 64 | $sender->sendMessage("Plugin already exists, overwriting..."); 65 | }else{ 66 | @mkdir($folderPath); 67 | } 68 | 69 | $reflection = new \ReflectionClass("pocketmine\\plugin\\PluginBase"); 70 | $file = $reflection->getProperty("file"); 71 | $file->setAccessible(true); 72 | $pharPath = str_replace("\\", "/", rtrim($file->getValue($plugin), "\\/")); 73 | 74 | foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($pharPath)) as $fInfo){ 75 | $path = $fInfo->getPathname(); 76 | @mkdir(dirname($folderPath . str_replace($pharPath, "", $path)), 0755, true); 77 | file_put_contents($folderPath . str_replace($pharPath, "", $path), file_get_contents($path)); 78 | } 79 | $sender->sendMessage("Source plugin ".$description->getName() ." v".$description->getVersion()." has been created on ".$folderPath); 80 | return true; 81 | } 82 | } -------------------------------------------------------------------------------- /src/FolderPluginLoader/FolderPluginLoader.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | 18 | namespace FolderPluginLoader; 19 | 20 | use pocketmine\event\plugin\PluginDisableEvent; 21 | use pocketmine\event\plugin\PluginEnableEvent; 22 | use pocketmine\plugin\Plugin; 23 | use pocketmine\plugin\PluginBase; 24 | use pocketmine\plugin\PluginDescription; 25 | use pocketmine\plugin\PluginLoader; 26 | use pocketmine\Server; 27 | use pocketmine\utils\MainLogger; 28 | use pocketmine\utils\TextFormat; 29 | 30 | class FolderPluginLoader implements PluginLoader{ 31 | 32 | /** @var Server */ 33 | private $server; 34 | 35 | /** 36 | * @param Server $server 37 | */ 38 | public function __construct(Server $server){ 39 | $this->server = $server; 40 | } 41 | 42 | /** 43 | * Loads the plugin contained in $file 44 | * 45 | * @param string $file 46 | * 47 | * @return Plugin 48 | */ 49 | public function loadPlugin($file){ 50 | if(is_dir($file) and file_exists($file . "/plugin.yml") and file_exists($file . "/src/")){ 51 | if(($description = $this->getPluginDescription($file)) instanceof PluginDescription){ 52 | MainLogger::getLogger()->info(TextFormat::LIGHT_PURPLE."Loading source plugin " . $description->getFullName()); 53 | $dataFolder = dirname($file) . DIRECTORY_SEPARATOR . $description->getName(); 54 | if(file_exists($dataFolder) and !is_dir($dataFolder)){ 55 | trigger_error("Projected dataFolder '" . $dataFolder . "' for " . $description->getName() . " exists and is not a directory", E_USER_WARNING); 56 | 57 | return null; 58 | } 59 | 60 | 61 | $className = $description->getMain(); 62 | $this->server->getLoader()->addPath($file . "/src"); 63 | 64 | if(class_exists($className, true)){ 65 | $plugin = new $className(); 66 | $this->initPlugin($plugin, $description, $dataFolder, $file); 67 | 68 | return $plugin; 69 | }else{ 70 | trigger_error("Couldn't load source plugin " . $description->getName() . ": main class not found", E_USER_WARNING); 71 | 72 | return null; 73 | } 74 | } 75 | } 76 | 77 | return null; 78 | } 79 | 80 | /** 81 | * Gets the PluginDescription from the file 82 | * 83 | * @param string $file 84 | * 85 | * @return PluginDescription 86 | */ 87 | public function getPluginDescription($file){ 88 | if(is_dir($file) and file_exists($file . "/plugin.yml")){ 89 | $yaml = @file_get_contents($file . "/plugin.yml"); 90 | if($yaml != ""){ 91 | return new PluginDescription($yaml); 92 | } 93 | } 94 | 95 | return null; 96 | } 97 | 98 | /** 99 | * Returns the filename patterns that this loader accepts 100 | * 101 | * @return array 102 | */ 103 | public function getPluginFilters(){ 104 | return "/[^\\.]/"; 105 | } 106 | 107 | /** 108 | * @param PluginBase $plugin 109 | * @param PluginDescription $description 110 | * @param string $dataFolder 111 | * @param string $file 112 | */ 113 | private function initPlugin(PluginBase $plugin, PluginDescription $description, $dataFolder, $file){ 114 | $plugin->init($this, $this->server, $description, $dataFolder, $file); 115 | $plugin->onLoad(); 116 | } 117 | 118 | /** 119 | * @param Plugin $plugin 120 | */ 121 | public function enablePlugin(Plugin $plugin){ 122 | if($plugin instanceof PluginBase and !$plugin->isEnabled()){ 123 | MainLogger::getLogger()->info("Enabling " . $plugin->getDescription()->getFullName()); 124 | 125 | $plugin->setEnabled(true); 126 | 127 | Server::getInstance()->getPluginManager()->callEvent(new PluginEnableEvent($plugin)); 128 | } 129 | } 130 | 131 | /** 132 | * @param Plugin $plugin 133 | */ 134 | public function disablePlugin(Plugin $plugin){ 135 | if($plugin instanceof PluginBase and $plugin->isEnabled()){ 136 | MainLogger::getLogger()->info("Disabling " . $plugin->getDescription()->getFullName()); 137 | 138 | Server::getInstance()->getPluginManager()->callEvent(new PluginDisableEvent($plugin)); 139 | 140 | $plugin->setEnabled(false); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/FolderPluginLoader/Main.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | 18 | namespace FolderPluginLoader; 19 | 20 | use pocketmine\plugin\PluginBase; 21 | use pocketmine\plugin\PluginLoadOrder; 22 | 23 | class Main extends PluginBase{ 24 | 25 | public function onLoad(){ 26 | 27 | } 28 | 29 | public function onEnable(){ 30 | $this->getServer()->getPluginManager()->registerInterface("FolderPluginLoader\\FolderPluginLoader"); 31 | $this->getServer()->getPluginManager()->loadPlugins($this->getServer()->getPluginPath(), ["FolderPluginLoader\\FolderPluginLoader"]); 32 | $this->getServer()->enablePlugins(PluginLoadOrder::STARTUP); 33 | } 34 | } 35 | --------------------------------------------------------------------------------