From e475423aacdeeefb5bf62a67397e037f5f98b6d9 Mon Sep 17 00:00:00 2001 From: Alejandro Liu Date: Sat, 2 Jul 2016 09:22:44 +0200 Subject: [PATCH] 2.0.0 --- README.md | 197 +++--- plugin.yml | 55 +- resources/messages/messages.ini | 109 +++ resources/messages/spa.ini | 107 +++ src/aliuly/manyworlds/Main.php | 658 ++----------------- src/aliuly/manyworlds/MwCreate.php | 63 ++ src/aliuly/manyworlds/MwDefault.php | 54 ++ src/aliuly/manyworlds/MwGenLst.php | 44 ++ src/aliuly/manyworlds/MwLoader.php | 144 ++++ src/aliuly/manyworlds/MwLs.php | 132 ++++ src/aliuly/manyworlds/MwLvDat.php | 147 +++++ src/aliuly/manyworlds/MwTp.php | 77 +++ src/aliuly/manyworlds/TeleportManager.php | 4 +- src/aliuly/manyworlds/common/BasicCli.php | 109 +++ src/aliuly/manyworlds/common/BasicHelp.php | 64 ++ src/aliuly/manyworlds/common/BasicPlugin.php | 151 +++++ src/aliuly/manyworlds/common/MPMU.php | 99 +++ src/aliuly/manyworlds/common/mc.php | 67 ++ 18 files changed, 1582 insertions(+), 699 deletions(-) create mode 100644 resources/messages/messages.ini create mode 100644 resources/messages/spa.ini create mode 100644 src/aliuly/manyworlds/MwCreate.php create mode 100644 src/aliuly/manyworlds/MwDefault.php create mode 100644 src/aliuly/manyworlds/MwGenLst.php create mode 100644 src/aliuly/manyworlds/MwLoader.php create mode 100644 src/aliuly/manyworlds/MwLs.php create mode 100644 src/aliuly/manyworlds/MwLvDat.php create mode 100644 src/aliuly/manyworlds/MwTp.php create mode 100644 src/aliuly/manyworlds/common/BasicCli.php create mode 100644 src/aliuly/manyworlds/common/BasicHelp.php create mode 100644 src/aliuly/manyworlds/common/BasicPlugin.php create mode 100644 src/aliuly/manyworlds/common/MPMU.php create mode 100644 src/aliuly/manyworlds/common/mc.php diff --git a/README.md b/README.md index 5d9ef8e..9e214a6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -ManyWorlds -========== + -* Summary: Basic commands for MultiWorld functionality +# ManyWorlds + +* Summary: Full Suite for MultiWorld functionality * Dependency Plugins: n/a * PocketMine-MP version: 1.4 - API 1.10.0 * OptionalPlugins: n/a @@ -9,10 +10,20 @@ ManyWorlds * Plugin Access: Commands, Manages Worlds * WebSite: [github](https://github.com/alejandroliu/pocketmine-plugins/tree/master/ManyWorlds) -Overview ---------- +## Overview + +**DO NOT POST QUESTION/BUG-REPORTS/REQUESTS IN THE REVIEWS** -A very basic plugin implementing MultiWorld functionality +It is difficult to carry a conversation in the reviews. If you have a +question/bug-report/request please use the +[Thread](http://forums.pocketmine.net/threads/manyworlds.7277/) for +that. You are more likely to get a response and help that way. + +Please go to +[github](https://github.com/alejandroliu/pocketmine-plugins/tree/master/ManyWorlds) +for the most up-to-date documentation. + +Full feature set of commands to manage multiple worlds. Features: @@ -20,62 +31,101 @@ Features: * load/unload * create * world info +* edit level.dat -Basic Usage: +### Basic Usage -* /mw tp *level* [player] -* /mw create *level* [seed [flat|normal [preset]]] -* /mw load *level* -* /mw unload [-f] *level* -* /mw ls [level] -* /mw lvdat [level] [attr=value] -* /mw fixname [level] +* create : Creates a new world +* default : Sets the default world +* fixname : fixes name mismatches +* generators : List available world generators +* load : Loads a world +* ls : Provide world information +* lvdat : Show/Modify level.dat variables +* tp : Teleport to another world +* unload : Unloads world -Documentation -------------- +## Documentation This plugin is a world manager that allows you to generate and load worlds as well as teleport between worlds. -The teleport itself has a number of workarounds to deal with -Client-Server glitches. Essentially, it works for me. +### Command Reference + +The following commands are available: -### Commands: +* /mw **create** _<world>_ _[seed]_ _[generator]_ _[preset]_ + Creates a new world -Teleporting: + Creates a world named _world_. You can optionally specify a _seed_ + as number, the generator (_flat_ or _normal_) and a _preset_ string. -* mw tp *level* [player] - Teleports `player` to `level`. If no `player` is specified, it - teleports the current user. -* mw ls [level] - If `level` is not specified, it will list all available worlds. If - `level` is specified, it will provide details on that `level`. +* /mw **default** _<world>_ + Sets the default world -World management: + Teleports you to another world. If _player_ is specified, that + player will be teleported. +* /mw **fixname** _<world>_ + fixes name mismatches -* mw create *level* [seed] [flat|normal] [preset] - Creates a world named `level`. You can optionally specify a `seed` - as number, the generator (`flat` or `normal`) and a `preset` string. -* mw load *level* - Loads `level` directly. If you use `--all` for the `level` name, it - will load all worlds. -* mw unload *level* - Unloads `level`. + Fixes a world's **level.dat** file so that the name matches the + folder name. +* /mw **generators** + List available world generators -Format hacking: + List registered world generators. +* /mw **load** _<world>_ + Loads a world -* mw fixname *level* - Fixes `level.dat` files so that the name matches the folder name. -* mw lvdat *attr=value* *attr=value* - Change directly some `level.dat` values/attributes. Supported + Loads _world_ directly. Use _--all_ to load **all** worlds. + +* /mw **ls** _[world]_ + Provide world information + + If _world_ is not specified, it will list available worlds. + Otherwise, details for _world_ will be provided. +* /mw **lvdat** _<world>_ _[attr=value]_ + Show/Modify level.dat variables + + Change directly some **level.dat** values/attributes. Supported attributes: - * spawn=x,y,z : Sets spawn point - * seed=randomseed : seed used for terrain generation - * name=string : Level name - * generator=flat|normal : Terrain generator - * preset=string : Presets string. + - spawn=x,y,z : Sets spawn point + - seed=randomseed : seed used for terrain generation + - name=string : Level name + - generator=flat|normal : Terrain generator + - preset=string : Presets string. + +* /mw **tp** _[player]_ _<world>_ + Teleport to another world + + Teleports you to another world. If _player_ is specified, that + player will be teleported. +* /mw **unload** _[-f]_ _<world>_ + Unloads world + + Unloads _world_. Use _-f_ to force unloads. -### Examples: + +### Permission Nodes + +* mw.cmds : Allow all the ManyWorlds functionality +* mw.cmd.tp : Allows users to travel to other worlds + (Defaults to Op) +* mw.cmd.tp.others : Allows users to make others travel to other worlds + (Defaults to Op) +* mw.cmd.ls : Allows users to list worlds + (Defaults to Op) +* mw.cmd.world.create : Allows users to create worlds + (Defaults to Op) +* mw.cmd.world.load : Allows users to load worlds + (Defaults to Op) +* mw.cmd.lvdat : Manipulate level.dat + (Defaults to Op) +* mw.cmd.default : Changes default world + (Defaults to Op) + + +## Examples Create a new normal world: @@ -91,39 +141,26 @@ Teleport to this newly created world: Teleport a player to another world: - /mw tp flatland joshua - -### Configuration - -In the plugin's config.yml file you can have: + /mw tp joshua flatland - settings: - broadcast-tp: true +## Translations -* `broadcast-tp`: Controls broadcast message that somebody teleported. +This plugin will follow the server language configuration. The +languages currently available are: -### API +* English +* Spanish -To use the teleport provided by ManyWorlds, you can use this code: +You can provide your own message file by creating a file called +`messages.ini` in the pluginc config directory. Check +[github](https://github.com/alejandroliu/pocketmine-plugins/tree/master/ManyWorlds/resources/messages/) +for sample files. - if (($mw = $this->getServer()->getPluginManager()->getPlugin("ManyWorlds")) != null) { - $mw->mwtp($player,$pos); - } else { - $player->teleport($pos); - } +## Issues -You need to do this in order for WorldProtect limits to work. +* New world names can not contain spaces. -### Permission Nodes: - -* mw.cmd.tp - Allows users to travel to other worlds -* mw.cmd.tp.others - Allows users to make others travel to other worlds -* mw.cmd.world.create - Allows users to create worlds -* mw.cmd.world.load - Allows users to load worlds -* mw.cmd.lvdat - Manipulate level data - -FAQ ---- +## FAQ * Q: How do I create a `FLAT` world? * A: You must be using PocketMine-MP v1.4.1. Set the `generator` to @@ -133,14 +170,15 @@ FAQ In the `pocketmine.yml` file there is a `worlds` section where you can define which worlds to load on start-up. -Issues ------- - -* World names can not contain spaces. - -Changes -------- +# Changes +* 2.0.0: Modularization + * Re-written for modularity + * teleport manager API deprecated + * Added `default` command to change the default level. + * New `genlist` for list of generators + * tp command changed to more natural English. + * Translation: Spanish * 1.3.4: Updates for PM1.5 * Removed CallbackTask deprecation warnings * 1.3.3: Updates for PM1.5 @@ -199,3 +237,4 @@ Copyright You should have received a copy of the GNU General Public License along with this program. If not, see . + diff --git a/plugin.yml b/plugin.yml index b442ce0..c9cf3ba 100644 --- a/plugin.yml +++ b/plugin.yml @@ -4,34 +4,37 @@ load: POSTWORLD name: ManyWorlds description: Manage Multiple Worlds -version: 1.3.4 +version: 2.0.0 author: aliuly commands: - mw: - description: Manage worlds - usage: "/mw [options]" - permission: mw.cmds + mw: + description: Manage worlds + usage: "/mw [options]" + permission: mw.cmds permissions: - mw.cmds: - default: true - description: "Allow all the ManyWorlds functionality" - mw.cmd.tp: - default: op - description: "Allows users to travel to other worlds" - mw.cmd.tp.others: - default: op - description: "Allows users to make others travel to other worlds" - mw.cmd.ls: - default: op - description: "Allows users to list worlds" - mw.cmd.world.create: - default: op - description: "Allows users to create worlds" - mw.cmd.world.load: - default: op - description: "Allows users to load worlds" - mw.cmd.lvdat: - default: op - description: "Manipulate level.dat" + mw.cmds: + default: true + description: "Allow all the ManyWorlds functionality" + mw.cmd.tp: + default: op + description: "Allows users to travel to other worlds" + mw.cmd.tp.others: + default: op + description: "Allows users to make others travel to other worlds" + mw.cmd.ls: + default: op + description: "Allows users to list worlds" + mw.cmd.world.create: + default: op + description: "Allows users to create worlds" + mw.cmd.world.load: + default: op + description: "Allows users to load worlds" + mw.cmd.lvdat: + default: op + description: "Manipulate level.dat" + mw.cmd.default: + default: op + description: "Changes default world" diff --git a/resources/messages/messages.ini b/resources/messages/messages.ini new file mode 100644 index 0000000..45c2595 --- /dev/null +++ b/resources/messages/messages.ini @@ -0,0 +1,109 @@ +; messages.ini +"%1%-mode"="" +"%1% is already in %2%"="" +"- /mw unload --enable"="" +""="" +" [attr=value]"="" +" [seed] [generator] [preset]"="" +""="" +"> /mw fixname %1%"="" +"Adventure"="" +"Attempt to unload worlds"="" +"Available sub-commands for %1%"="" +"CHANGES WILL NOT TAKE EFFECT UNTIL UNLOAD"="" +"Change failed!"="" +"Change level.dat values"="" +"Changes default world"="" +"Creates a new world"="" +"Creative"="" +"Default world changed to %1%"="" +"Description: "="" +"Enable %1% features"="" +"Enabled one feature"="" +"Error GetLevelByName %1%"="" +"Error getting %1%"="" +"Fixes world name"="" +"Folder Name and Level.Dat names do NOT match"="" +"Generator: "="" +"Generator Presets: "="" +"Generator unchanged"="" +"Help: "="" +"Info for %1%"="" +"Invalid element: %1%, ignored"="" +"Invalid spawn location: %1%"="" +"List world generators"="" +"List world information"="" +"Load worlds"="" +"NO features enabled"="" +"Name: "="" +"Name unchanged"="" +"No change"="" +"No help for %1%"="" +"No sub-command specified"="" +"Nothing happens"="" +"Path: "="" +"Players(%1%):"="" +"Preset unchanged"="" +"Provider: "="" +"Running /mw lvdat %1% name=%1%"="" +"Seed: "="" +"Seed unchanged"="" +"Spawn: "="" +"Spawn location is unchanged"="" +"Spectator"="" +"Survival"="" +"Teleport across worlds"="" +"Teleport failed"="" +"Teleporting to %1%"="" +"Teleporting you to %1% by %2%"="" +"This can cause intermitent problems"="" +"Unknown feature \"%1%\" ignored."="" +"Unknown key %1%, ignored"="" +"Unknown sub-command %2% (try /%1% help)"="" +"Updating level.dat for %1%"="" +"Usage: "="" +"Use: "="" +"Worlds: %1%"="" +"You are already in %1%"="" +"You are not allowed to do this"="" +"You can only do this in-game"="" +"You do not have permission to do that."="" +"[-f] "="" +"[MW] %1% already loaded"="" +"[MW] %1% does not exists"="" +"[MW] %1% is not loaded!"="" +"[MW] %1% is not loaded."="" +"[MW] %1% unloaded."="" +"[MW] A world named %1% already exists"="" +"[MW] Creating level %1%... (Expect Lag)"="" +"[MW] Loading ALL %1% levels"="" +"[MW] Loading one level"="" +"[MW] Missing path %1%"="" +"[MW] No levels to load"="" +"[MW] No world with the name %1% exists!"="" +"[MW] Plugin provided world generators\n are not included in\n this list."="" +"[MW] To activate use:"="" +"[MW] To disable use: /mw unload --disable"="" +"[MW] To enable use: /mw unload --enable"="" +"[MW] Unable to get %1%"="" +"[MW] Unable to load %1%"="" +"[MW] Unable to unload %1%"="" +"[MW] Unable to unload %1%. Try -f"="" +"[MW] Unexpected error"="" +"[MW] Unknown generator %1%"="" +"[MW] Unload sub-command disabled"="" +"[MW] Unload sub-command enabled"="" +"[MW] Unload sub-command is disabled by default"="" +"[MW] Using %1%"="" +"[MW] server to CRASH!"="" +"[MW] this is because that it usually causes the"="" +"[player] "="" +"[world]"="" +"auto"="" +"default"="" +"loaded"="" +"players:%1%"="" +"to fix this issue"="" +"# [player]"="" +"#List world ifnormation"="" +"#Restart server for changes to take effect!"="" diff --git a/resources/messages/spa.ini b/resources/messages/spa.ini new file mode 100644 index 0000000..542e030 --- /dev/null +++ b/resources/messages/spa.ini @@ -0,0 +1,107 @@ +; spa.ini +"%1%-mode"="modo-%1%" +"%1% is already in %2%"="%1% ya está en %2%" +"- /mw unload --enable"="" +""="" +" [attr=value]"=" [attr=valor]" +" [seed] [generator] [preset]"=" [semilla] [generador] [preset]" +""="" +"> /mw fixname %1%"="" +"Adventure"="Aventura" +"Attempt to unload worlds"="Intentando descargar mundos" +"Available sub-commands for %1%"="Sub-commandos disponibles para %1%" +"CHANGES WILL NOT TAKE EFFECT UNTIL UNLOAD"="CAMBIOS NO TENDRAN EFECTO HASTA UNA DESCARGA" +"Change failed!"="Cambio no resultó" +"Change level.dat values"="Cambiando valores de level.dat" +"Changes default world"="Cambia el mundo inicial" +"Creates a new world"="Crea un nuevo mundo" +"Creative"="Creativo" +"Default world changed to %1%"="Mundo inicial es ahora %1% " +"Description: "="Descripción" +"Enable %1% features"="Activando %1% módulos" +"Enabled one feature"="Activando un módulo" +"Error GetLevelByName %1%"="Error de GetLevelByName %1%" +"Error getting %1%"="Error obteniendo %1%" +"Fixes world name"="Corrige el nombre de un mundo" +"Folder Name and Level.Dat names do NOT match"="Nombre de Carpeta y nombre de Level.Dat no concuerdan" +"Generator: "="Generador: " +"Generator Presets: "="Presets: " +"Generator unchanged"="Generador no ha cambiado" +"Help: "="Ayuda: " +"Info for %1%"="Detalles de %1%" +"Invalid element: %1%, ignored"="Elemento invalido: %1%, ignorando" +"Invalid spawn location: %1%"="Lugar de aparción incorrecto: %1%" +"List world generators"="Lista de generadores" +"List world information"="Lista información de mundos" +"Load worlds"="Carga mundos" +"NO features enabled"="Ningún módulo activado" +"Name: "="Nombre: " +"Name unchanged"="Nombre no ha cambiado" +"No change"="No hay cambios" +"No help for %1%"="No hay ayuda para %1%" +"No sub-command specified"="No sub-comando especificado" +"Nothing happens"="No pasa nada" +"Path: "="Ruta: " +"Players(%1%):"="Jugadores(%1%):" +"Preset unchanged"="Preset no ha cambiado" +"Provider: "="Proevedor: " +"Running /mw lvdat %1% name=%1%"="Corriendo /mwdat lvdat %1% name=%1%" +"Seed: "="Semilla: " +"Seed unchanged"="Semilla no ha cambiado" +"Spawn: "="Punto de Aparición: " +"Spawn location is unchanged"="Punto de Aparición no ha cambiado" +"Spectator"="Espectador" +"Survival"="Supervivencia" +"Teleport across worlds"="Teletransporta através de mundos" +"Teleport failed"="Teletransporte falló" +"Teleporting to %1%"="Teletransportando a %1%" +"Teleporting you to %1% by %2%"="Eres teletransportado a %1% por %2%" +"This can cause intermitent problems"="Esto causa problemas intermitentes" +"Unknown feature \"%1%\" ignored."="Modulo %1% desconocido, ignorando" +"Unknown key %1%, ignored"="Clave %1% desconocida, ignorando" +"Unknown sub-command %2% (try /%1% help)"="Comando %2% desconocido (Intente /try /%1% help)" +"Updating level.dat for %1%"="Actualizando level.dat para %1%" +"Usage: "="Uso: " +"Use: "="Use: " +"Worlds: %1%"="Mundos: %1%" +"You are already in %1%"="Usted ya está en %1%" +"You are not allowed to do this"="Usted no está permitido para hacer esto" +"You can only do this in-game"="Solo se puede hacer eso dentro del juego" +"You do not have permission to do that."="Usted no está permitido para hacer esto" +"[-f] "="[-f] " +"[MW] %1% already loaded"="[MW] %1% ya está cargado" +"[MW] %1% does not exists"="[MW] %1% no existe" +"[MW] %1% is not loaded!"="[MW] %1% no está cargado!" +"[MW] %1% is not loaded."="[MW] %1% no está cargado." +"[MW] %1% unloaded."="[MW] %1% descargado" +"[MW] A world named %1% already exists"="[MW] Un mundo con nombre %1% ya existe" +"[MW] Creating level %1%... (Expect Lag)"="[MW] Creando mundo %1%..." +"[MW] Loading ALL %1% levels"="[MW] Cargando %1% niveles" +"[MW] Loading one level"="[MW] Cargando un nivel" +"[MW] Missing path %1%"="[MW] Ruta no disponible %1%" +"[MW] No levels to load"="[MW] No hay mundos por cargar" +"[MW] No world with the name %1% exists!"="[MW] %1% no existe!" +"[MW] Plugin provided world generators\n are not included in\n this list."="[MW] Generadores cargados por Plugin no son encontrados en esta lista." +"[MW] To activate use:"="[MW] para activar use:" +"[MW] To disable use: /mw unload --disable"="Para des-activar use: /mw unload --disable" +"[MW] To enable use: /mw unload --enable"="Para activar use: /mw unload --enable" +"[MW] Unable to get %1%"="[MW] No se puede obtener %1%" +"[MW] Unable to load %1%"="[MW] No se puede cargar %1%" +"[MW] Unable to unload %1%"="[MW] No se puede descargar %1%" +"[MW] Unable to unload %1%. Try -f"="[MW] No se puede descargar %1%. Intente con -f" +"[MW] Unexpected error"="[MW] Error inesperado" +"[MW] Unknown generator %1%"="[MW] Generador %1% desconosido" +"[MW] Unload sub-command disabled"="[MW] Sub-comando Unload deshabilitado" +"[MW] Unload sub-command enabled"="[MW] Sub-comando Unload habilitado" +"[MW] Unload sub-command is disabled by default"="[MW] Sub-comando Unload no está disponibile por defecto" +"[MW] Using %1%"="[MW] Usando %1%" +"[MW] server to CRASH!"="[MW] que el servidor se caiga." +"[MW] this is because that it usually causes the"="[MW] por que usualmente esto causa" +"[player] "="[jugador] " +"[world]"="[mundo]" +"auto"="automatico" +"default"="inicial" +"loaded"="cargado" +"players:%1%"="jugadores:%1%" +"to fix this issue"="para corrregir este problema" +"#Restart server for changes to take effect!"="Re-inicia el servidor para que los cambios se apliquen" diff --git a/src/aliuly/manyworlds/Main.php b/src/aliuly/manyworlds/Main.php index 152170a..a097172 100644 --- a/src/aliuly/manyworlds/Main.php +++ b/src/aliuly/manyworlds/Main.php @@ -1,606 +1,86 @@ "ls", - "load" => "ld", - ]; +class Main extends BasicPlugin implements CommandExecutor { + public $canUnload = false; + private $tpMgr = null; - // Access and other permission related checks - private function access(CommandSender $sender, $permission) { - if($sender->hasPermission($permission)) return true; - $sender->sendMessage("You do not have permission to do that."); - return false; - } - private function inGame(CommandSender $sender,$msg = true) { - if ($sender instanceof Player) return true; - if ($msg) $sender->sendMessage("You can only use this command in-game"); - return false; - } + public function onEnable() { + // We don't really need this... + //if (!is_dir($this->getDataFolder())) mkdir($this->getDataFolder()); + mc::plugin_init($this,$this->getFile()); - // Paginate output - private function getPageNumber(array &$args) { - $pageNumber = 1; - if (count($args) && is_numeric($args[count($args)-1])) { - $pageNumber = (int)array_pop($args); - if($pageNumber <= 0) $pageNumber = 1; - } - return $pageNumber; - } - private function paginateText(CommandSender $sender,$pageNumber,array $txt) { - $hdr = array_shift($txt); - if($sender instanceof ConsoleCommandSender){ - $sender->sendMessage( TextFormat::GREEN.$hdr.TextFormat::RESET); - foreach ($txt as $ln) $sender->sendMessage($ln); - return true; - } - $pageHeight = 5; - $hdr = TextFormat::GREEN.$hdr. TextFormat::RESET; - if (($pageNumber-1) * $pageHeight >= count($txt)) { - $sender->sendMessage($hdr); - $sender->sendMessage("Only ".intval(count($txt)/$pageHeight+1)." pages available"); - return true; - } - $hdr .= TextFormat::RED." ($pageNumber of ".intval(count($txt)/$pageHeight+1).")".TextFormat::RESET; - $sender->sendMessage($hdr); - for ($ln = ($pageNumber-1)*$pageHeight;$ln < count($txt) && $pageHeight--;++$ln) { - $sender->sendMessage($txt[$ln]); - } - return true; - } - private function paginateTable(CommandSender $sender,$pageNumber,array $tab) { - $cols = []; - for($i=0;$i < count($tab[0]);$i++) $cols[$i] = strlen($tab[0][$i]); - foreach ($tab as $row) { - for($i=0;$i < count($row);$i++) { - if (($l=strlen($row[$i])) > $cols[$i]) $cols[$i] = $l; - } - } - $txt = []; - foreach ($tab as $row) { - $txt[] = sprintf("%-$cols[0]s %-$cols[1]s %-$cols[2]s %-$cols[3]s", - $row[0],$row[1],$row[2],$row[3]); - } - return $this->paginateText($sender,$pageNumber,$txt); - } - // Standard call-backs - public function onEnable(){ - // Depending on the API, we allow unload by default... - $api = explode(".",$this->getServer()->getApiVersion()); - if (intval($api[1]) < 12) { - $this->canUnload = false; - $this->is15 = false; - } else { - $this->getLogger()->info("Runniong on PocketMine-MP v1.5 or better"); - $this->getLogger()->info(TextFormat::RED. - "This version is still under development"); - $this->getLogger()->info(TextFormat::RED. - "and it may not be fully stable"); + if (MPMU::apiVersion("1.12.0")) { $this->canUnload = true; - $this->is15 = true; - } - - $this->tpManager = new TeleportManager($this); - if (!is_dir($this->getDataFolder())) mkdir($this->getDataFolder()); - $defaults = [ - "settings" => [ - "broadcast-tp" => true, - ], - ]; - $this->cfg = (new Config($this->getDataFolder()."config.yml", - Config::YAML,$defaults))->getAll(); - $this->maxplayers = [$this,"maxPlayers1st"]; - } - - public function onCommand(CommandSender $sender, Command $cmd, $label, array $args) { - switch($cmd->getName()) { - case "worldprotect": // Allow WP to call us... - case "mw": - if(isset($args[0])) { - $scmd = strtolower(array_shift($args)); - if (isset(self::$aliases[$scmd])) $scmd = self::$aliases[$scmd]; - switch ($scmd) { - case "tp": - if (!$this->access($sender,"mw.cmd.tp")) return false; - return $this->mwTpCmd($sender,$args); - break; - case "ls": - if (!$this->access($sender,"mw.cmd.ls")) return false; - return $this->mwLsCmd($sender,$args); - case "create": - if (!$this->access($sender,"mw.cmd.world.create")) return false; - return $this->mwWorldCreateCmd($sender,$args); - break; - case "fixname": - if (!$this->access($sender,"mw.cmd.lvdat")) return false; - if (count($args) != 1) return $this->mwHelpCmd($sender,["fixname"]); - $sender->sendMessage("Running /mw lvdat $args[0] name=$args[0]"); - return $this->mwLevelDatCmd($sender,[$args[0], "name=".$args[0]]); - break; - case "lvdat": - if (!$this->access($sender,"mw.cmd.lvdat")) return false; - return $this->mwLevelDatCmd($sender,$args); - break; - case "ld": - if (!$this->access($sender,"mw.cmd.world.load")) return false; - return $this->mwWorldLoadCmd($sender,$args); - case "unload": - if (!$this->access($sender,"mw.cmd.world.load")) return false; - return $this->mwWorldUnloadCmd($sender,$args); - case "help": - return $this->mwHelpCmd($sender,$args); - default: - $sender->sendMessage(TextFormat::RED."Unknown sub command: ". - TextFormat::RESET.$scmd); - $sender->sendMessage("Use: ".TextFormat::GREEN." /mw help". - TextFormat::RESET); - } - return true; - } else { - $sender->sendMessage("Must specify sub command"); - $sender->sendMessage("Try: ".TextFormat::GREEN." /mw help". - TextFormat::RESET); - return false; - } - } - return false; - } - // Command entry points - private function mwTpCmd(CommandSender $sender,$args) { - if (!isset($args[0])) - return $this->mwHelpCmd($sender,["tp"]); - $level = array_shift($args); - if (isset($args[0])) { - // Teleport others... - if (!$this->access($sender,"mw.cmd.tp.others")) return false; - $player = $this->getServer()->getPlayer($args[0]); - if (!$player) { - $sender->sendMessage("[MW] Player ".$args[0]." can not be found"); - return true; - } - if (!$player->isOnLine()) { - $sender->sendMessage("[MW] ".$args[0]." is offline!"); - return true; - } - if($player->getLevel() == $this->getServer()->getLevelByName($level)) { - $sender->sendMessage("[MW] " . $player->getName() . " is already in " . $level . "!"); - return true; - } - if (!$this->mwAutoLoad($sender,$level)) { - $sender->sendMessage("[MW] Unable to teleport " . $player->getName() . " as\nlevel " . $level . " is not loaded!"); - return true; - } - $player->sendMessage("[MW] Teleporting you to " . $level . " at\n" . $sender->getName() . "'s request..."); - if ($this->teleport($player,$level)) { - if ($this->cfg["settings"]["broadcast-tp"]) { - $this->getServer()->broadcastMessage("[MW] ".$player->getName()." was teleported to $level"); - } else { - $sender->sendMessage("[MW] " . $player->getName() . " has been teleported to " . $level . "!"); - } - } else { - $sender->sendMessage("[MW] unable to teleport ".$player->getName()." to ".$level); - } - return true; - } - // Teleport self... - if (!$this->inGame($sender)) return true; - if ($sender->getLevel() == $this->getServer()->getLevelByName($level)) { - $sender->sendMessage("[MW] You are already in " . $level . "!"); - return true; - } - if(!$this->mwAutoLoad($sender,$level)) { - $sender->sendMessage("[MW] Unable to teleport"); - $sender->sendMessage("[MW] " . $level . " is not loaded!"); - return true; - } - $sender->sendMessage("[MW] Teleporting you to level " . $level . "..."); - if ($this->teleport($sender,$level)) { - if ($this->cfg["settings"]["broadcast-tp"]) { - $this->getServer()->broadcastMessage("[MW] ".$sender->getName()." teleported to $level"); - } else { - $sender->sendMessage("[MW] you were teleported to $level"); - } - } else { - $sender->sendMessage("[MW] Unable to teleport ".$sender->getName()." to $level"); - } - return true; - } - private function mwLsCmd(CommandSender $sender,$args) { - $pageNumber = $this->getPageNumber($args); - if (isset($args[0])) { - if(!$this->mwAutoLoad($sender,$args[0])) { - $sender->sendMessage("[MW] " . $args[0] . " is not loaded!"); - return true; - } - $txt = $this->mwWorldDetails($sender,$args[0]); + $this->tpMgr = null; } else { - $txt = $this->mwWorldList($sender); - } - if ($txt == null) return true; - return $this->paginateText($sender,$pageNumber,$txt); - } - private function mwLevelDatCmd(CommandSender $sender,$args) { - if (!count($args)) return $this->mwHelpCmd($sender,["lvdat"]); - $level = array_shift($args); - if(!$this->mwAutoLoad($sender,$level)) { - $sender->sendMessage("[MW] $level is not loaded!"); - return true; - } - $world = $this->getServer()->getLevelByName($level); - if (!$world) { - $sender->sendMessage("[MW] $level not loaded"); - return null; - } - //==== provider - $provider = $world->getProvider(); - $changed = false; $unload = false; - foreach ($args as $kv) { - $kv = explode("=",$kv,2); - if (count($kv) != 2) { - $sender->sendMessage("Invalid element: $kv[0], ignored"); - continue; - } - list($k,$v) = $kv; - switch ($k) { - case "spawn": - $pos = explode(",",$v); - if (count($pos)!=3) { - $sender->sendMessage("Invalid spawn location: ".implode(",",$pos)); - continue; - } - list($x,$y,$z) = $pos; - $cpos = $provider->getSpawn(); - if (($x=intval($x)) == $cpos->getX() && - ($y=intval($y)) == $cpos->getY() && - ($z=intval($z)) == $cpos->getZ()) { - $sender->sendMessage("Spawn location is unchanged"); - continue; - } - $changed = true; - $provider->setSpawn(new Vector3($x,$y,$z)); - break; - case "seed": - if ($provider->getSeed() != intval($v)) { - $sender->sendMessage("Seed unchanged"); - continue; - } - $changed = true; $unload = true; - $provider->setSeed($v); - break; - case "name": // LevelName String - if ($provider->getName() == $v) { - $sender->sendMessage("Name unchanged"); - continue; - } - $changed = true; - $provider->getLevelData()->LevelName = new String("LevelName",$v); - break; - case "generator": // generatorName(String) - if ($provider->getLevelData()->generatorName == $v) { - $sender->sendMessage("Generator unchanged"); - continue; - } - $changed=true; $unload=true; - $provider->getLevelData()->generatorName=new String("generatorName",$v); - break; - case "preset": // String("generatorOptions"); - if ($provider->getLevelData()->generatorOptions == $v) { - $sender->sendMessage("Preset unchanged"); - continue; - } - $changed=true; $unload=true; - $provider->getLevelData()->generatorOptions = - new String("generatorOptions",$v); - break; - default: - $sender->sendMessage("Unknown key $k, ignored"); - continue; - } - } - if ($changed) { - $sender->sendMessage("Updating level.dat for $level"); - $provider->saveLevelData(); - if ($unload) { - $sender->sendMessage(TextFormat::RED. - "CHANGES WILL NOT TAKE EFFECT UNTIL UNLOAD"); - } - } else { - $sender->sendMessage("Nothing happens"); - } - return true; - } - - private function mwWorldCreateCmd(CommandSender $sender,$args) { - if (!isset($args[0])) - return $this->mwHelpCmd($sender,["create"]); - $level = array_shift($args); - if($this->getServer()->isLevelGenerated($level)) { - $sender->sendMessage("[MW] A world with the name " . $level . " already exists!"); - return true; - } - $seed = null; - $generator = null; - $options = []; - if(isset($args[0])) $seed = intval($args[0]); - if(isset($args[1])) { - $generator = Generator::getGenerator($args[1]); - $sender->sendMessage("Using ".Generator::getGeneratorName($generator)); - } - if(isset($args[2])) $options = ["preset" => $args[2] ]; - $this->getServer()->broadcastMessage("[MW] Creating level " . $level . "... (Expect Lag)"); - $this->getServer()->generateLevel($level, $seed, $generator, $options); - $this->getServer()->loadLevel($level); - return true; - } - private function mwWorldLoadCmd(CommandSender $sender,$args) { - if (!isset($args[0])) - return $this->mwHelpCmd($sender,["ld"]); - if ($args[0] == "--all") { - $sender->sendMessage("[MW] ".TextFormat::RED."Loading ALL levels".TextFormat::RESET); - $args = []; - foreach (glob($this->getServer()->getDataPath(). "worlds/*") as $f) { - $level = basename($f); - if ($this->getServer()->isLevelLoaded($level)) continue; - if (!$this->getServer()->isLevelGenerated($level)) continue; - $args[] = $level; - } - } - foreach ($args as $level) { - if (!$this->mwAutoLoad($sender,$level)) - $sender->sendMessage("[MW] Unable to load $level"); - } - return true; - } - private function mwWorldUnloadCmd(CommandSender $sender,$args) { - if (!isset($args[0])) - return $this->mwHelpCmd($sender,["unload"]); - - // Activate|Deactive unload command - if (isset($args[0]) && $args[0] == '--enable') { - $this->canUnload = true; - $sender->sendMessage("[MW] Unload sub-command enabled"); - $sender->sendMessage("[MW] To disable use: /mw unload --disable"); - return true; - } elseif (isset($args[0]) && $args[0] == '--disable') { - $this->canUnload = true; - $sender->sendMessage("[MW] Unload sub-command disabled"); - $sender->sendMessage("[MW] To enable use: /mw unload --enable"); - return true; - } - if (!$this->canUnload) { - $sender->sendMessage("[MW] Unload sub-command is disabled by default"); - $sender->sendMessage("[MW] this is because that it usually causes the"); - $sender->sendMessage("[MW] server to ".TextFormat::RED."crash.".TextFormat::RESET); - $sender->sendMessage("[MW] Use: ".TextFormat::BLUE."/mw unload --enable".TextFormat::RESET); - $sender->sendMessage("[MW] To activate"); - return true; - } - - // Actual implementation - $force = false; - if (isset($args[0]) && $args[0] == '-f') { - $force = true; - array_shift($args); - } - if (!isset($args[0])) - return $this->mwHelpCmd($sender,["unload"]); - - foreach ($args as $level) { - $level = $args[0]; - if (!$this->getServer()->isLevelLoaded($level)) { - $sender->sendMessage("[MW] Level $level is not loaded."); - continue; - } - $world = $this->getServer()->getLevelByName($level); - if ($world === null) { - $sender->sendMessage("[MW] Unable to get $level"); - continue; - } - if (!$this->getServer()->unloadLevel($world,$force)) { - $sender->sendMessage("[MW] Unable to unload $level. Try -f"); - continue; - } - $sender->sendMessage("[MW] $level unloaded."); - } - return true; - } - private function mwHelpCmd(CommandSender $sender,$args) { - $pageNumber = $this->getPageNumber($args); - $cmds = [ - "tp" => [" [player]", - "Teleport across worlds"], - "ls" => ["[level]", - "List world information"], - "create" => [" [seed [flat|normal [preset]]]", - "Create a new world"], - "lvdat" => [" [attr=value]","Manipulate level.dat"], - "fixname" => ["","Fix level.dat world names"], - "ld" => ["|--all","Load a world"], - "unload" => ["","Attempt to unload a world"], - ]; - if (count($args)) { - foreach ($args as $c) { - if (isset(self::$aliases[$c])) $c = self::$aliases[$c]; - if (isset($cmds[$c])) { - list($a,$b) = $cmds[$c]; - $sender->sendMessage(TextFormat::RED."Usage: /mw $c $a" - .TextFormat::RESET); - $sender->sendMessage($b); - } - } - return true; - } - $txt = ["ManyWorlds sub-commands"]; - foreach ($cmds as $a => $b) { - $ln = "- ".TextFormat::GREEN."/mw ".$a; - foreach (self::$aliases as $i => $j) { - if ($j == $a) $ln .= "|$i"; + $this->canUnload = false; + $this->tpMgr = new TeleportManager($this); + } + $this->modules = []; + foreach ([ + "MwTp", + "MwLs", + "MwCreate", + "MwGenLst", + "MwLoader", + "MwLvDat", + "MwDefault", + ] as $mod) { + $mod = __NAMESPACE__."\\".$mod; + $this->modules[] = new $mod($this); + } + $this->modules[] = new BasicHelp($this); + } + + public function autoLoad(CommandSender $c,$world) { + if ($this->getServer()->isLevelLoaded($world)) return true; + if($c !== null && !MPMU::access($c, "mw.cmd.world.load")) return false; + if(!$this->getServer()->isLevelGenerated($world)) { + if ($c !== null) { + $c->sendMessage(mc::_("[MW] No world with the name %1% exists!", + $world)); } - $ln .= TextFormat::RESET." ".$b[0]; - $txt[] = $ln; + return false; } - return $this->paginateText($sender,$pageNumber,$txt); + $this->getServer()->loadLevel($world); + return $this->getServer()->isLevelLoaded($world); } + ////////////////////////////////////////////////////////////////////// // - // Helper functions + // Command dispatcher // - private function mwAutoLoad(CommandSender $c,$level) { - if ($this->getServer()->isLevelLoaded($level)) return true; - if(!$this->access($c, "mw.cmd.world.load")) return false; - if(!$this->getServer()->isLevelGenerated($level)) { - $c->sendMessage("[MW] No level with the name $level exists!"); - return false; - } - $this->getServer()->loadLevel($level); - return true; - } - private function mwWorldList(CommandSender $sender) { - $dir = $this->getServer()->getDataPath(). "worlds"; - if (!is_dir($dir)) { - $sender->sendMessage("[MW] Missing path $dir"); - return null; - } - $txt = ["HDR"]; - - $auto = $this->getServer()->getProperty("worlds",[]); - $default = $this->getServer()->getDefaultLevel(); - if ($default) $default = $default->getName(); - - $count = 0; - $dh = opendir($dir); - if (!$dh) return null; - while (($file = readdir($dh)) !== false) { - if ($file == '.' || $file == '..') continue; - if (!$this->getServer()->isLevelGenerated($file)) continue; - $attrs = []; - ++$count; - if (isset($auto[$file])) $attrs[] = "auto"; - if ($default == $file) $attrs[]="default"; - if ($this->getServer()->isLevelLoaded($file)) { - $attrs[] = "loaded"; - $np = count($this->getServer()->getLevelByName($file)->getPlayers()); - if ($np) $attrs[] = "players:$np"; - } - $ln = "- $file"; - if (count($attrs)) $ln .= TextFormat::AQUA." (".implode(",",$attrs).")"; - $txt[] = $ln; - } - closedir($dh); - $txt[0] = "Worlds: ".$count; - return $txt; - } - private function mwWorldDetails(CommandSender $sender,$level) { - $txt = []; - $world = $this->getServer()->getLevelByName($level); - if (!$world) { - $sender->sendMessage("[MW] $level not loaded"); - return null; - } - //==== provider - $provider = $world->getProvider(); - $txt[] = "Info for $level"; - $txt[] = TextFormat::AQUA."Provider: ".TextFormat::WHITE. $provider::getProviderName(); - $txt[] = TextFormat::AQUA."Path: ".TextFormat::WHITE.$provider->getPath(); - $txt[] = TextFormat::AQUA."Name: ".TextFormat::WHITE.$provider->getName(); - $txt[] = TextFormat::AQUA."Seed: ".TextFormat::WHITE.$provider->getSeed(); - $txt[] = TextFormat::AQUA."Generator: ".TextFormat::WHITE.$provider->getGenerator(); - $gopts = $provider->getGeneratorOptions(); - if ($gopts["preset"] != "") - $txt[] = TextFormat::AQUA."Generator Presets: ".TextFormat::WHITE. - $gopts["preset"]; - $spawn = $provider->getSpawn(); - $txt[] = TextFormat::AQUA."Spawn: ".TextFormat::WHITE.$spawn->getX().",".$spawn->getY().",".$spawn->getZ(); - $plst = $this->getServer()->getLevelByName($level)->getPlayers(); - $lst = ""; - if (count($plst)) { - foreach ($plst as $p) { - $lst .= (strlen($lst) ? ", " : "").$p->getName(); - } - } - $total = count($plst); - $max = call_user_func($this->maxplayers,$level); - if ($max) $total .= "/$max"; - $txt[] = TextFormat::AQUA."Players(".TextFormat::WHITE.$total. - TextFormat::AQUA."): ".TextFormat::WHITE.$lst; - - $fn = "getWorldInfo"; - foreach ($this->getServer()->getPluginManager()->getPlugins() as $p) { - if ($p->isDisabled()) continue; - if (is_callable([$p,$fn])) { - foreach (call_user_func([$p,$fn],$world->getName()) as $ln) { - $txt[] = $ln; - } - } - } - ////////////////////////////////////////////////////////////////////// - // Checks - //$txt[] = "levelName: ".$world->getName()."\n"; - //$txt[] = "folderName: ".$world->getFolderName()."\n"; - //$txt[] = "providerName: ".$provider->getName()."\n"; - ////////////////////////////////////////////////////////////////////// - - - // Check for warnings... - if ($provider->getName() != $level) { - $txt[] = TextFormat::RED."Folder Name and Level.Dat names do NOT match"; - $txt[] = TextFormat::RED."This can cause intermitent problems"; - if($sender->hasPermission("mw.cmd.lvdat")) { - $txt[] = TextFormat::RED."Use: "; - $txt[] = TextFormat::GREEN."> /mw fixname $level"; - $txt[] = TextFormat::RED."to fix this issue"; - } - } - return $txt; - } - public function _getPlayerLimit($level) { return 0; } - public function maxPlayers1st($level) { - $fn = "getPlayerLimit"; - foreach ($this->getServer()->getPluginManager()->getPlugins() as $p) { - if ($p->isDisabled()) continue; - if (is_callable([$p,$fn])) { - $this->maxplayers = [$p,$fn]; - $this->getLogger()->info(TextFormat::YELLOW."Using plugin ". - $p->getName()." for Player Limits"); - return call_user_func($this->maxplayers,$level); - } - } - $this->maxplayers = [$this,"_".$fn]; - return call_user_func($this->maxplayers,$level); + ////////////////////////////////////////////////////////////////////// + public function onCommand(CommandSender $sender, Command $cmd, $label, array $args) { + if ($cmd->getName() != "mw") return false; + return $this->dispatchSCmd($sender,$cmd,$args); } // - // Public API + // Deprecated Public API // public function mwtp($pl,$pos) { - if ($pos instanceof Position) { + if ($this->tpMgr && ($pos instanceof Position)) { // Using ManyWorlds for teleporting... return $this->teleport($pl,$pos->getLevel()->getName(), new Vector3($pos->getX(), @@ -610,19 +90,15 @@ public function mwtp($pl,$pos) { $pl->teleport($pos); return true; } - public function teleport($player,$level,$spawn=null) { - if (!$this->getServer()->isLevelLoaded($level)) return false; - /* - * Check if we can enforce player limits - */ - $max = call_user_func($this->maxplayers,$level); - if ($max) { - $np = count($this->getServer()->getLevelByName($level)->getPlayers()); - if ($np >= $max) { - $player->sendMessage("Can not teleport to $level, its FULL\n"); - return false; - } + public function teleport($player,$world,$spawn=null) { + if ($this->tpMgr) { + return $this->tpMgr->teleport($player,$world,$spawn); } - return $this->tpManager->teleport($player,$level,$spawn); + if (!$this->getServer()->isLevelLoaded($world)) return false; + $level = $this->owner->getServer()->getLevelByName($world); + if (!$level) return false; + // Try to find a reasonable spawn location + $location = $level->getSafeSpawn($spawn); + $player->teleport($location); } } diff --git a/src/aliuly/manyworlds/MwCreate.php b/src/aliuly/manyworlds/MwCreate.php new file mode 100644 index 0000000..d86cb8f --- /dev/null +++ b/src/aliuly/manyworlds/MwCreate.php @@ -0,0 +1,63 @@ +_ _[seed]_ _[generator]_ _[preset]_ + ** + ** Creates a world named _world_. You can optionally specify a _seed_ + ** as number, the generator (_flat_ or _normal_) and a _preset_ string. + ** + **/ +namespace aliuly\manyworlds; + +use pocketmine\command\CommandSender; +use pocketmine\command\Command; + +use pocketmine\utils\TextFormat; +use pocketmine\level\generator\Generator; + +use aliuly\manyworlds\common\mc; +use aliuly\manyworlds\common\BasicCli; + +class MwCreate extends BasicCli { + public function __construct($owner) { + parent::__construct($owner); + $this->enableSCmd("create",["usage" => mc::_(" [seed] [generator] [preset]"), + "help" => mc::_("Creates a new world"), + "permission" => "mw.cmd.world.create", + "aliases" => ["new"]]); + } + public function onSCommand(CommandSender $c,Command $cc,$scmd,$data,array $args) { + if (count($args) < 1 || count($args)>4) return false; + $world = array_shift($args); + if ($this->owner->getServer()->isLevelGenerated($world)) { + $c->sendMessage(TextFormat::RED. + mc::_("[MW] A world named %1% already exists",$world)); + return true; + } + $seed = null; + $generator = null; + $opts = []; + if (isset($args[0])) $seed = intval($args[0]); + if (isset($args[1])) { + $generator = Generator::getGenerator($args[1]); + if (strtolower($args[1]) != Generator::getGeneratorName($generator)){ + $c->sendMessage(TextFormat::RED. + mc::_("[MW] Unknown generator %1%",$args[1])); + return true; + } + $c->sendMessage(TextFormat::GREEN. + mc::_("[MW] Using %1%", + Generator::getGeneratorName($generator))); + } + if(isset($args[2])) $opts = ["preset" => $args[2] ]; + $this->owner->getServer()->broadcastMessage( + mc::_("[MW] Creating level %1%... (Expect Lag)", $world)); + $this->owner->getServer()->generateLevel($world,$seed,$generator,$opts); + $this->owner->getServer()->loadLevel($world); + return true; + } +} diff --git a/src/aliuly/manyworlds/MwDefault.php b/src/aliuly/manyworlds/MwDefault.php new file mode 100644 index 0000000..99e41bb --- /dev/null +++ b/src/aliuly/manyworlds/MwDefault.php @@ -0,0 +1,54 @@ +_ + ** + ** Teleports you to another world. If _player_ is specified, that + ** player will be teleported. + **/ +namespace aliuly\manyworlds; + +use pocketmine\command\CommandSender; +use pocketmine\command\Command; + +use pocketmine\utils\TextFormat; + +use aliuly\manyworlds\common\mc; +use aliuly\manyworlds\common\BasicCli; + +class MwDefault extends BasicCli { + public function __construct($owner) { + parent::__construct($owner); + $this->enableSCmd("default",["usage" => mc::_(""), + "help" => mc::_("Changes default world"), + "permission" => "mw.cmd.default"]); + } + public function onSCommand(CommandSender $c,Command $cc,$scmd,$data,array $args) { + if (count($args) == 0) return false; + $wname =implode(" ",$args); + $old = $this->owner->getServer()->getConfigString("level-name"); + if ($old == $wname) { + $c->sendMessage(TextFormat::RED.mc::_("No change")); + return true; + } + if (!$this->owner->autoLoad($c,$wname)) { + $c->sendMessage(TextFormat::RED. + mc::_("[MW] Unable to load %1%",$wname)); + $c->sendMessage(TextFormat::RED.mc::_("Change failed!")); + return true; + } + $level = $this->owner->getServer()->getLevelByName($wname); + if ($level === null) { + $c->sendMessage(TextFormat::RED.mc::_("Error GetLevelByName %1%")); + return true; + } + $this->owner->getServer()->setConfigString("level-name",$wname); + $this->owner->getServer()->setDefaultLevel($level); + $c->sendMessage(TextFormat::BLUE.mc::_("Default world changed to %1%",$wname)); + return true; + } +} diff --git a/src/aliuly/manyworlds/MwGenLst.php b/src/aliuly/manyworlds/MwGenLst.php new file mode 100644 index 0000000..edaf62c --- /dev/null +++ b/src/aliuly/manyworlds/MwGenLst.php @@ -0,0 +1,44 @@ +enableSCmd("generators",["usage" => "", + "help" => mc::_("List world generators"), + "permission" => "mw.cmd.world.create", + "aliases" => ["gen","genlst"]]); + } + public function onSCommand(CommandSender $c,Command $cc,$scmd,$data,array $args) { + if (count($args) != 0) return false; + + if (MPMU::apiVersion("1.12.0")) { + $c->sendMessage(implode(", ",Generator::getGeneratorList())); + } else { + $c->sendMessage("normal, flat"); + $c->sendMessage(TextFormat::RED. + mc::_("[MW] Plugin provided world generators\n are not included in\n this list.")); + } + return true; + } +} diff --git a/src/aliuly/manyworlds/MwLoader.php b/src/aliuly/manyworlds/MwLoader.php new file mode 100644 index 0000000..cf72553 --- /dev/null +++ b/src/aliuly/manyworlds/MwLoader.php @@ -0,0 +1,144 @@ +_ + ** + ** Loads _world_ directly. Use _--all_ to load **all** worlds. + ** + ** * unload : Unloads world + ** usage: /mw **unload** _[-f]_ __ + ** + ** Unloads _world_. Use _-f_ to force unloads. + **/ +namespace aliuly\manyworlds; + +use pocketmine\command\CommandSender; +use pocketmine\command\Command; + +use pocketmine\utils\TextFormat; + +use aliuly\manyworlds\common\mc; +use aliuly\manyworlds\common\MPMU; +use aliuly\manyworlds\common\BasicCli; + +class MwLoader extends BasicCli { + public function __construct($owner) { + parent::__construct($owner); + $this->enableSCmd("load",["usage" => mc::_(""), + "help" => mc::_("Load worlds"), + "permission" => "mw.cmd.world.load", + "aliases" => ["ld"]]); + $this->enableSCmd("unload",["usage" => mc::_("[-f] "), + "help" => mc::_("Attempt to unload worlds"), + "permission" => "mw.cmd.world.load"]); + } + public function onSCommand(CommandSender $c,Command $cc,$scmd,$data,array $args) { + if (count($args) == 0) return false; + switch ($scmd) { + case "load": + return $this->mwWorldLoadCmd($c,implode(" ",$args)); + case "unload": + $force = false; + if ($args[0] == "-f") { + $force = true; + array_shift($args); + if (count($args) == 0) return false; + } + return $this->mwWorldUnloadCmd($c,implode(" ",$args),$force); + } + return false; + } + private function mwWorldLoadCmd(CommandSender $sender,$wname) { + if ($wname == "--all") { + $wlst = []; + foreach (glob($this->owner->getServer()->getDataPath(). "worlds/*") as $f) { + $world = basename($f); + if ($this->owner->getServer()->isLevelLoaded($world)) continue; + if (!$this->owner->getServer()->isLevelGenerated($world)) continue; + $wlst[] = $world; + } + if (count($wlst) == 0) { + $sender->sendMessage(TextFormat::RED. + mc::_("[MW] No levels to load")); + return true; + } + $sender->sendMessage( + TextFormat::AQUA. + mc::n( + mc::_("[MW] Loading one level"), + mc::_("[MW] Loading ALL %1% levels",count($wlst)), + count($wlst))); + } else { + if ($this->owner->getServer()->isLevelLoaded($wname)) { + $sender->sendMessage(TextFormat::RED. + mc::_("[MW] %1% already loaded",$wname)); + return true; + } + if (!$this->owner->getServer()->isLevelGenerated($wname)) { + $sender->sendMessage(TextFormat::RED. + mc::_("[MW] %1% does not exists",$wname)); + return true; + } + $wlst = [ $wname ]; + } + foreach ($wlst as $world) { + if (!$this->owner->autoLoad($sender,$world)) { + $sender->sendMessage(TextFormat::RED. + mc::_("[MW] Unable to load %1%",$world)); + } + } + return true; + } + private function mwWorldUnloadCmd(CommandSender $sender,$wname,$force) { + if (MPMU::apiVersion("<1.12.0")) { + // For old stuff... + if ($wname == "--enable") { + $this->owner->canUnload = true; + $sender->sendMessage(TextFormat::YELLOW. + mc::_("[MW] Unload sub-command enabled")); + $sender->sendMessage(TextFormat::YELLOW. + mc::_("[MW] To disable use: /mw unload --disable")); + return true; + } + if ($wname == "--disable") { + $this->owner->canUnload = false; + $sender->sendMessage(TextFormat::GREEN. + mc::_("[MW] Unload sub-command disabled")); + $sender->sendMessage(TextFormat::GREEN. + mc::_("[MW] To enable use: /mw unload --enable")); + return true; + } + if (!$this->owner->canUnload) { + $sender->sendMessage(TextFormat::RED.mc::_("[MW] Unload sub-command is disabled by default")); + $sender->sendMessage(TextFormat::RED.mc::_("[MW] this is because that it usually causes the")); + $sender->sendMessage(TextFormat::RED.mc::_("[MW] server to CRASH!")); + $sender->sendMessage(TextFormat::RED.mc::_("[MW] To activate use:")); + $sender->sendMessage(TextFormat::BLUE.mc::_("- /mw unload --enable")); + return true; + } + } + // Actual implementation + if (!$this->owner->getServer()->isLevelLoaded($wname)) { + $sender->sendMessage(TextFormat::RED.mc::_("[MW] %1% is not loaded.",$wname)); + return true; + } + $level = $this->owner->getServer()->getLevelByName($wname); + if ($level === null) { + $sender->sendMessage(TextFormat::RED.mc::_("[MW] Unable to get %1%",$wname)); + return true; + } + if (!$this->owner->getServer()->unloadLevel($level,$force)) { + if ($force) + $sender->sendMessage(TextFormat::RED.mc::_("[MW] Unable to unload %1%",$wname)); + else + $sender->sendMessage(TextFormat::RED.mc::_("[MW] Unable to unload %1%. Try -f",$wname)); + } else { + $sender->sendMessage(TextFormat::GREEN.mc::_("[MW] %1% unloaded.",$wname)); + } + return true; + } +} diff --git a/src/aliuly/manyworlds/MwLs.php b/src/aliuly/manyworlds/MwLs.php new file mode 100644 index 0000000..580f321 --- /dev/null +++ b/src/aliuly/manyworlds/MwLs.php @@ -0,0 +1,132 @@ +enableSCmd("ls",["usage" => mc::_("[world]"), + "help" => mc::_("List world information"), + "permission" => "mw.cmd.ls", + "aliases" => ["list","info"]]); + } + + private function mwWorldList(CommandSender $sender) { + $dir = $this->owner->getServer()->getDataPath(). "worlds"; + if (!is_dir($dir)) { + $sender->sendMessage(mc::_("[MW] Missing path %1%",$dir)); + return null; + } + $txt = ["HDR"]; + + $auto = $this->owner->getServer()->getProperty("worlds",[]); + $default = $this->owner->getServer()->getDefaultLevel(); + if ($default) $default = $default->getName(); + + $count = 0; + $dh = opendir($dir); + if (!$dh) return null; + while (($file = readdir($dh)) !== false) { + if ($file == '.' || $file == '..') continue; + if (!$this->owner->getServer()->isLevelGenerated($file)) continue; + $attrs = []; + ++$count; + if (isset($auto[$file])) $attrs[] = mc::_("auto"); + if ($default == $file) $attrs[]=mc::_("default"); + if ($this->owner->getServer()->isLevelLoaded($file)) { + $attrs[] = mc::_("loaded"); + $np = count($this->owner->getServer()->getLevelByName($file)->getPlayers()); + if ($np) $attrs[] = mc::_("players:%1%",$np); + } + $ln = "- $file"; + if (count($attrs)) $ln .= TextFormat::AQUA." (".implode(",",$attrs).")"; + $txt[] = $ln; + } + closedir($dh); + $txt[0] = mc::_("Worlds: %1%",$count); + return $txt; + } + private function mwWorldDetails(CommandSender $sender,$world) { + $txt = []; + if ($this->owner->getServer()->isLevelLoaded($world)) { + $unload = false; + } else { + if (!$this->owner->autoLoad($sender,$world)) { + $sender->sendMessage(TextFormat::RED.mc::_("Error getting %1%",$world)); + return null; + } + $unload = true; + } + $level = $this->owner->getServer()->getLevelByName($world); + + //==== provider + $provider = $level->getProvider(); + $txt[] = mc::_("Info for %1%",$world); + $txt[] = TextFormat::AQUA.mc::_("Provider: ").TextFormat::WHITE. $provider::getProviderName(); + $txt[] = TextFormat::AQUA.mc::_("Path: ").TextFormat::WHITE.$provider->getPath(); + $txt[] = TextFormat::AQUA.mc::_("Name: ").TextFormat::WHITE.$provider->getName(); + $txt[] = TextFormat::AQUA.mc::_("Seed: ").TextFormat::WHITE.$provider->getSeed(); + $txt[] = TextFormat::AQUA.mc::_("Generator: ").TextFormat::WHITE.$provider->getGenerator(); + $gopts = $provider->getGeneratorOptions(); + if ($gopts["preset"] != "") + $txt[] = TextFormat::AQUA.mc::_("Generator Presets: ").TextFormat::WHITE. + $gopts["preset"]; + $spawn = $provider->getSpawn(); + $txt[] = TextFormat::AQUA.mc::_("Spawn: ").TextFormat::WHITE.$spawn->getX().",".$spawn->getY().",".$spawn->getZ(); + $plst = $level->getPlayers(); + $lst = ""; + if (count($plst)) { + foreach ($plst as $p) { + $lst .= (strlen($lst) ? ", " : "").$p->getName(); + } + } + $txt[] = TextFormat::AQUA.mc::_("Players(%1%):",count($plst)). + TextFormat::WHITE.$lst; + + // Check for warnings... + if ($provider->getName() != $world) { + $txt[] = TextFormat::RED.mc::_("Folder Name and Level.Dat names do NOT match"); + $txt[] = TextFormat::RED.mc::_("This can cause intermitent problems"); + if($sender->hasPermission("mw.cmd.lvdat")) { + $txt[] = TextFormat::RED.mc::_("Use: "); + $txt[] = TextFormat::GREEN.mc::_("> /mw fixname %1%",$world); + $txt[] = TextFormat::RED.mc::_("to fix this issue"); + } + } + + if ($unload) $this->owner->getServer()->unloadLevel($level); + + return $txt; + } + + public function onSCommand(CommandSender $c,Command $cc,$scmd,$data,array $args) { + $pageNumber = $this->getPageNumber($args); + if (count($args) == 0) { + $txt = $this->mwWorldList($c); + } else { + $wname = implode(" ",$args); + $txt = $this->mwWorldDetails($c,$wname); + } + if ($txt == null) return true; + return $this->paginateText($c,$pageNumber,$txt); + } +} diff --git a/src/aliuly/manyworlds/MwLvDat.php b/src/aliuly/manyworlds/MwLvDat.php new file mode 100644 index 0000000..ab2175b --- /dev/null +++ b/src/aliuly/manyworlds/MwLvDat.php @@ -0,0 +1,147 @@ +_ _[attr=value]_ + ** + ** Change directly some **level.dat** values/attributes. Supported + ** attributes: + ** - spawn=x,y,z : Sets spawn point + ** - seed=randomseed : seed used for terrain generation + ** - name=string : Level name + ** - generator=flat|normal : Terrain generator + ** - preset=string : Presets string. + ** + ** * fixname : fixes name mismatches + ** usage: /mw **fixname** __ + ** + ** Fixes a world's **level.dat** file so that the name matches the + ** folder name. + **/ +namespace aliuly\manyworlds; + +use pocketmine\command\CommandSender; +use pocketmine\command\Command; + +use pocketmine\utils\TextFormat; + +use aliuly\manyworlds\common\mc; +use aliuly\manyworlds\common\BasicCli; + +use pocketmine\level\generator\Generator; +use pocketmine\nbt\NBT; +use pocketmine\nbt\tag\Int; +use pocketmine\nbt\tag\String; +use pocketmine\nbt\tag\Long; +use pocketmine\nbt\tag\Compound; + +class MwLvDat extends BasicCli { + public function __construct($owner) { + parent::__construct($owner); + $this->enableSCmd("lvdat",["usage" => mc::_(" [attr=value]"), + "help" => mc::_("Change level.dat values"), + "permission" => "mw.cmd.lvdat", + "aliases" => ["lv"]]); + $this->enableSCmd("fixname",["usage" => mc::_(""), + "help" => mc::_("Fixes world name"), + "permission" => "mw.cmd.lvdat", + "aliases" => ["fix"]]); + } + public function onSCommand(CommandSender $c,Command $cc,$scmd,$data,array $args) { + if (count($args) == 0) return false; + if ($scmd == "fixname") { + $world = implode(" ",$args); + $c->sendMessage(TextFormat::AQUA.mc::_("Running /mw lvdat %1% name=%1%",$world)); + $args = [ $world , "name=$world" ]; + } + $world = array_shift($args); + if(!$this->owner->autoLoad($c,$world)) { + $c->sendMessage(TextFormat::RED.mc::_("[MW] %1% is not loaded!",$worl)); + return true; + } + $level = $this->owner->getServer()->getLevelByName($world); + if (!$level) { + $c->sendMessage(TextFormat::RED.mc::_("[MW] Unexpected error")); + return true; + } + //==== provider + $provider = $level->getProvider(); + $changed = false; $unload = false; + foreach ($args as $kv) { + $kv = explode("=",$kv,2); + if (count($kv) != 2) { + $c->sendMessage(mc::_("Invalid element: %1%, ignored",$kv[0])); + continue; + } + list($k,$v) = $kv; + switch (strtolower($k)) { + case "spawn": + $pos = explode(",",$v); + if (count($pos)!=3) { + $c->sendMessage(mc::_("Invalid spawn location: %1%",implode(",",$pos))); + continue; + } + list($x,$y,$z) = $pos; + $cpos = $provider->getSpawn(); + if (($x=intval($x)) == $cpos->getX() && + ($y=intval($y)) == $cpos->getY() && + ($z=intval($z)) == $cpos->getZ()) { + $c->sendMessage(mc::_("Spawn location is unchanged")); + continue; + } + $changed = true; + $provider->setSpawn(new Vector3($x,$y,$z)); + break; + case "seed": + if ($provider->getSeed() == intval($v)) { + $c->sendMessage(mc::_("Seed unchanged")); + continue; + } + $changed = true; $unload = true; + $provider->setSeed($v); + break; + case "name": // LevelName String + if ($provider->getName() == $v) { + $c->sendMessage(mc::_("Name unchanged")); + continue; + } + $changed = true; $unload = true; + $provider->getLevelData()->LevelName = new String("LevelName",$v); + break; + case "generator": // generatorName(String) + if ($provider->getLevelData()->generatorName == $v) { + $c->sendMessage(mc::_("Generator unchanged")); + continue; + } + $changed=true; $unload=true; + $provider->getLevelData()->generatorName=new String("generatorName",$v); + break; + case "preset": // String("generatorOptions"); + if ($provider->getLevelData()->generatorOptions == $v) { + $c->sendMessage(mc::_("Preset unchanged")); + continue; + } + $changed=true; $unload=true; + $provider->getLevelData()->generatorOptions =new String("generatorOptions",$v); + break; + default: + $c->sendMessage(mc::_("Unknown key %1%, ignored",$k)); + continue; + } + } + if ($changed) { + $c->sendMessage(mc::_("Updating level.dat for %1%",$world)); + $provider->saveLevelData(); + if ($unload) { + $c->sendMessage(TextFormat::RED. + mc::_("CHANGES WILL NOT TAKE EFFECT UNTIL UNLOAD")); + } + } else { + $c->sendMessage(mc::_("Nothing happens")); + } + return true; + } +} diff --git a/src/aliuly/manyworlds/MwTp.php b/src/aliuly/manyworlds/MwTp.php new file mode 100644 index 0000000..b67b654 --- /dev/null +++ b/src/aliuly/manyworlds/MwTp.php @@ -0,0 +1,77 @@ +_ + ** + ** Teleports you to another world. If _player_ is specified, that + ** player will be teleported. + **/ +namespace aliuly\manyworlds; + +use pocketmine\command\CommandSender; +use pocketmine\command\Command; + +use pocketmine\utils\TextFormat; + +use aliuly\manyworlds\common\mc; +use aliuly\manyworlds\common\MPMU; +use aliuly\manyworlds\common\BasicCli; + +class MwTp extends BasicCli { + public function __construct($owner) { + parent::__construct($owner); + $this->enableSCmd("tp",["usage" => mc::_("[player] "), + "help" => mc::_("Teleport across worlds"), + "permission" => "mw.cmd.tp", + "aliases" => ["teleport"]]); + } + public function onSCommand(CommandSender $c,Command $cc,$scmd,$data,array $args) { + if (count($args) == 0) return false; + $player = $c; + if (count($args) > 1) { + $player = $this->owner->getServer()->getPlayer($args[0]); + if ($player !== null) { + if (!MPMU::access($c,"mw.cmd.tp.others")) return true; + array_shift($args); + } else { + // Compatibility with old versions... + $player = $this->owner->getServer()->getPlayer($args[count($args)-1]); + if ($player !== null) { + if (!MPMU::access($c,"mw.cmd.tp.others")) return true; + array_pop($args); + } else { + $player = $c; + } + } + } + if (!MPMU::inGame($player)) return true; + $wname = implode(" ",$args); + if ($player->getLevel() == $this->owner->getServer()->getLevelByName($wname)) { + $c->sendMessage( + $c == $player ? + mc::_("You are already in %1%",$wname) : + mc::_("%1% is already in %2%",$player->getName(),$wname)); + return true; + } + if (!$this->owner->autoLoad($c,$wname)) { + $c->sendMessage(TextFormat::RED.mc::_("Teleport failed")); + return true; + } + $level = $this->owner->getServer()->getLevelByName($wname); + if ($level === null) { + $c->sendMessage(TextFormat::RED.mc::_("Error GetLevelByName %1%")); + return true; + } + if ($c != $player) { + $player->sendMessage(TextFormat::YELLOW.mc::_("Teleporting you to %1% by %2%", $wname, $c->getName())); + } else { + $c->sendMessage(TextFormat::GREEN.mc::_("Teleporting to %1%",$wname)); + } + $player->teleport($level->getSafeSpawn()); + return true; + } +} diff --git a/src/aliuly/manyworlds/TeleportManager.php b/src/aliuly/manyworlds/TeleportManager.php index 7e9a130..ed721dd 100644 --- a/src/aliuly/manyworlds/TeleportManager.php +++ b/src/aliuly/manyworlds/TeleportManager.php @@ -13,9 +13,7 @@ class TeleportManager implements Listener { public function __construct(PluginBase $plugin) { $this->owner = $plugin; - if (!$this->owner->is15) { - $this->owner->getServer()->getPluginManager()->registerEvents($this, $this->owner); - } + $this->owner->getServer()->getPluginManager()->registerEvents($this, $this->owner); } /** * @priority LOWEST diff --git a/src/aliuly/manyworlds/common/BasicCli.php b/src/aliuly/manyworlds/common/BasicCli.php new file mode 100644 index 0000000..40878e1 --- /dev/null +++ b/src/aliuly/manyworlds/common/BasicCli.php @@ -0,0 +1,109 @@ +owner = $owner; + } + + public function enableSCmd($cmd,$opts) { + $this->owner->registerScmd($cmd,[$this,"onSCommand"],$opts); + } + public function enableCmd($cmd,$yaml) { + $newCmd = new PluginCommand($cmd,$this->owner); + if (isset($yaml["description"])) + $newCmd->setDescription($yaml["description"]); + if (isset($yaml["usage"])) + $newCmd->setUsage($yaml["usage"]); + if(isset($yaml["aliases"]) and is_array($yaml["aliases"])) { + $aliasList = []; + foreach($yaml["aliases"] as $alias) { + if(strpos($alias,":")!== false) { + $this->owner->getLogger()->info("Unable to load alias $alias"); + continue; + } + $aliasList[] = $alias; + } + $newCmd->setAliases($aliasList); + } + if(isset($yaml["permission"])) + $newCmd->setPermission($yaml["permission"]); + if(isset($yaml["permission-message"])) + $newCmd->setPermissionMessage($yaml["permission-message"]); + $newCmd->setExecutor($this); + $cmdMap = $this->owner->getServer()->getCommandMap(); + $cmdMap->register($this->owner->getDescription()->getName(),$newCmd); + } + + // Paginate output + protected function getPageNumber(array &$args) { + $pageNumber = 1; + if (count($args) && is_numeric($args[count($args)-1])) { + $pageNumber = (int)array_pop($args); + if($pageNumber <= 0) $pageNumber = 1; + } + return $pageNumber; + } + protected function paginateText(CommandSender $sender,$pageNumber,array $txt) { + $hdr = array_shift($txt); + if($sender instanceof ConsoleCommandSender){ + $sender->sendMessage( TextFormat::GREEN.$hdr.TextFormat::RESET); + foreach ($txt as $ln) $sender->sendMessage($ln); + return true; + } + $pageHeight = 5; + $lineCount = count($txt); + $pageCount = intval($lineCount/$pageHeight) + ($lineCount % $pageHeight ? 1 : 0); + $hdr = TextFormat::GREEN.$hdr. TextFormat::RESET; + if ($pageNumber > $pageCount) { + $sender->sendMessage($hdr); + $sender->sendMessage("Only $pageCount pages available"); + return true; + } + $hdr .= TextFormat::RED." ($pageNumber of $pageCount)"; + $sender->sendMessage($hdr); + for ($ln = ($pageNumber-1)*$pageHeight;$ln < $lineCount && $pageHeight--;++$ln) { + $sender->sendMessage($txt[$ln]); + } + return true; + } + protected function paginateTable(CommandSender $sender,$pageNumber,array $tab) { + $cols = []; + for($i=0;$i < count($tab[0]);$i++) $cols[$i] = strlen($tab[0][$i]); + foreach ($tab as $row) { + for($i=0;$i < count($row);$i++) { + if (($l=strlen($row[$i])) > $cols[$i]) $cols[$i] = $l; + } + } + $txt = []; + $fmt = ""; + foreach ($cols as $c) { + if (strlen($fmt) > 0) $fmt .= " "; + $fmt .= "%-".$c."s"; + } + foreach ($tab as $row) { + $txt[] = sprintf($fmt,...$row); + } + return $this->paginateText($sender,$pageNumber,$txt); + } + + ////////////////////////////////////////////////////////////////////// + public function getState(CommandSender $player,$default) { + return $this->owner->getState(get_class($this),$player,$default); + } + public function setState(CommandSender $player,$val) { + $this->owner->setState(get_class($this),$player,$val); + } + public function unsetState(CommandSender $player) { + $this->owner->unsetState(get_class($this),$player); + } +} diff --git a/src/aliuly/manyworlds/common/BasicHelp.php b/src/aliuly/manyworlds/common/BasicHelp.php new file mode 100644 index 0000000..5911b40 --- /dev/null +++ b/src/aliuly/manyworlds/common/BasicHelp.php @@ -0,0 +1,64 @@ +enableSCmd("help",["aliases"=>["?"]]); + $this->fmt = $fmt; + } + public function onSCommand(CommandSender $c,Command $cc,$scmd,$data,array $args) { + $cm = $this->owner->getSCmdMap(); + $pageNumber = $this->getPageNumber($args); + + if (count($args)) { + if ($args[0] == "usage") { + if (!isset($cm["usage"][$scmd])) return false; + $c->sendMessage(TextFormat::RED.mc::_("Usage: "). + sprintf($this->fmt, + $cc->getName(), + $scmd, + $cm["usage"][$scmd])); + return true; + } + $txt = [ "Help for ".$cc->getName() ]; + + foreach ($args as $i) { + if (isset($cm["alias"][$i])) $i=$cm["alias"][$i]; + if (!isset($cm["help"][$i]) && !isset($cm["usage"][$i])) { + $txt[] = TextFormat::RED.mc::_("No help for %1%",$i); + continue; + } + $txt[] = TextFormat::YELLOW.mc::_("Help: ").TextFormat::WHITE. + "/".$cc->getName()." $i"; + if (isset($cm["help"][$i])) + $txt[] = TextFormat::YELLOW.mc::_("Description: "). + TextFormat::WHITE.$cm["help"][$i]; + if (isset($cm["usage"][$i])) + $txt[] = TextFormat::YELLOW.mc::_("Usage: "). + TextFormat::WHITE. + sprintf($this->fmt,$cc->getName(),$i,$cm["usage"][$i]); + } + return $this->paginateText($c,$pageNumber,$txt); + } + ksort($cm["help"]); + $txt = [ mc::_("Available sub-commands for %1%",$cc->getName()) ]; + foreach ($cm["help"] as $cn => $desc) { + $ln = TextFormat::GREEN.$cn; + foreach ($cm["alias"] as $i => $j) { + if ($j == $cn) $ln .= "|$i"; + } + $ln .= ": ".TextFormat::WHITE.$desc; + $txt[] = $ln; + } + return $this->paginateText($c,$pageNumber,$txt); + } +} diff --git a/src/aliuly/manyworlds/common/BasicPlugin.php b/src/aliuly/manyworlds/common/BasicPlugin.php new file mode 100644 index 0000000..6c03c80 --- /dev/null +++ b/src/aliuly/manyworlds/common/BasicPlugin.php @@ -0,0 +1,151 @@ + $j) { + $defaults["features"][$i] = $j[1]; + } + $cfg=(new Config($this->getDataFolder()."config.yml", + Config::YAML,$defaults))->getAll(); + $this->modules = []; + foreach ($cfg["features"] as $i=>$j) { + if (!isset($mods[$i])) { + $this->getLogger()->info(mc::_("Unknown feature \"%1%\" ignored.",$i)); + continue; + } + if (!$j) continue; + $class = $mods[$i][0]; + if(strpos($class,"\\") === false) $class = $ns."\\".$class; + if (isset($cfg[$i])) + $this->modules[$i] = new $class($this,$cfg[$i]); + else + $this->modules[$i] = new $class($this); + } + $c = count($this->modules); + if ($c == 0) { + $this->getLogger()->info(mc::_("NO features enabled")); + return; + } + $this->state = []; + $this->getServer()->getPluginManager()->registerEvents($this, $this); + $this->getLogger()->info(mc::n(mc::_("Enabled one feature"), + mc::_("Enable %1% features",$c), + $c)); + if (count($this->scmdMap) && count($this->scmdMap["mgrs"])) { + $this->modules[] = new BasicHelp($this,$xhlp); + } + return $cfg; + } + + public function cfgSave($key,$settings) { + $cfg=new Config($this->getDataFolder()."config.yml",Config::YAML); + $dat = $cfg->getAll(); + $dat[$key] = $settings; + $cfg->setAll($dat); + $cfg->save(); + } + + protected function initSCmdMap() { + $this->scmdMap = [ + "mgrs" => [], + "help" => [], + "usage" => [], + "alias" => [], + "permission" => [], + ]; + } + protected function dispatchSCmd(CommandSender $sender,Command $cmd,array $args,$data=null) { + if (count($args) == 0) { + $sender->sendMessage(mc::_("No sub-command specified")); + return false; + } + $scmd = strtolower(array_shift($args)); + if (isset($this->scmdMap["alias"][$scmd])) { + $scmd = $this->scmdMap["alias"][$scmd]; + } + if (!isset($this->scmdMap["mgrs"][$scmd])) { + $sender->sendMessage(mc::_("Unknown sub-command %2% (try /%1% help)",$cmd->getName(),$scmd)); + return false; + } + if (isset($this->scmdMapd["permission"][$scmd])) { + if (!$sender->hasPermission($this->scmdMapd["permission"][$scmd])) { + $sender->sendMessage(mc::_("You are not allowed to do this")); + return true; + } + } + $callback = $this->scmdMap["mgrs"][$scmd]; + if ($callback($sender,$cmd,$scmd,$data,$args)) return true; + if (isset($this->scmdMap["mgrs"]["help"])) { + $callback = $this->scmdMap["mgrs"]["help"]; + return $callback($sender,$cmd,$scmd,$data,["usage"]); + } + return false; + } + + public function getSCmdMap() { + return $this->scmdMap; + } + public function registerSCmd($cmd,$callable,$opts) { + $cmd = strtolower($cmd); + $this->scmdMap["mgrs"][$cmd] = $callable; + + foreach (["help","usage","permission"] as $p) { + if(isset($opts[$p])) { + $this->scmdMap[$p][$cmd] = $opts[$p]; + } + } + if (isset($opts["aliases"])) { + foreach ($opts["aliases"] as $alias) { + $this->scmdMap["alias"][$alias] = $cmd; + } + } + } + + public function onPlayerQuit(PlayerQuitEvent $ev) { + $n = strtolower($ev->getPlayer()->getName()); + if (isset($this->state[$n])) unset($this->state[$n]); + } + + public function getState($label,$player,$default) { + if ($player instanceof CommandSender) $player = $player->getName(); + $player = strtolower($player); + if (!isset($this->state[$player])) return $default; + if (!isset($this->state[$player][$label])) return $default; + return $this->state[$player][$label]; + } + + public function setState($label,$player,$val) { + if ($player instanceof CommandSender) $player = $player->getName(); + $player = strtolower($player); + if (!isset($this->state[$player])) $this->state[$player] = []; + $this->state[$player][$label] = $val; + } + + public function unsetState($label,$player) { + if ($player instanceof CommandSender) $player = $player->getName(); + $player = strtolower($player); + if (!isset($this->state[$player])) return; + if (!isset($this->state[$player][$label])) return; + unset($this->state[$player][$label]); + } + + +} diff --git a/src/aliuly/manyworlds/common/MPMU.php b/src/aliuly/manyworlds/common/MPMU.php new file mode 100644 index 0000000..db158a3 --- /dev/null +++ b/src/aliuly/manyworlds/common/MPMU.php @@ -0,0 +1,99 @@ +=": + return version_compare($api,trim(substr($version,2))) >= 0; + case "<=": + return version_compare($api,trim(substr($version,2))) <= 0; + case "<>": + case "!=": + return version_compare($api,trim(substr($version,2))) != 0; + } + switch (substr($version,0,1)) { + case "=": + return version_compare($api,trim(substr($version,1))) == 0; + case "!": + case "~": + return version_compare($api,trim(substr($version,1))) != 0; + case "<": + return version_compare($api,trim(substr($version,1))) < 0; + case ">": + return version_compare($api,trim(substr($version,1))) > 0; + } + if (intval($api) != intval($version)) return 0; + return version_compare($api,$version) >= 0; + } + static public function itemName(Item $item) { + $n = $item->getName(); + if ($n != "Unknown") return $n; + if (count(self::$items) == 0) { + $constants = array_keys((new \ReflectionClass("pocketmine\\item\\Item"))->getConstants()); + foreach ($constants as $constant) { + $id = constant("pocketmine\\item\\Item::$constant"); + $constant = str_replace("_", " ", $constant); + self::$items[$id] = $constant; + } + } + if (isset(self::$items[$item->getId()])) + return self::$items[$item->getId()]; + return $n; + } + static public function gamemodeStr($mode) { + if (class_exists(__NAMESPACE__."\\mc",false)) { + switch ($mode) { + case 0: return mc::_("Survival"); + case 1: return mc::_("Creative"); + case 2: return mc::_("Adventure"); + case 3: return mc::_("Spectator"); + } + return mc::_("%1%-mode",$mode); + } + switch ($mode) { + case 0: return "Survival"; + case 1: return "Creative"; + case 2: return "Adventure"; + case 3: return "Spectator"; + } + return "$mode-mode"; + } + + static public function access(CommandSender $sender, $permission,$msg=true) { + if($sender->hasPermission($permission)) return true; + if ($msg) + $sender->sendMessage(mc::_("You do not have permission to do that.")); + return false; + } + static public function inGame(CommandSender $sender,$msg = true) { + if (!($sender instanceof Player)) { + if ($msg) $sender->sendMessage(mc::_("You can only do this in-game")); + return false; + } + return true; + } + static public function iName($player) { + if ($player instanceof Player) { + $player = strtolower($player->getName()); + } + return $player; + } +} diff --git a/src/aliuly/manyworlds/common/mc.php b/src/aliuly/manyworlds/common/mc.php new file mode 100644 index 0000000..9049bf3 --- /dev/null +++ b/src/aliuly/manyworlds/common/mc.php @@ -0,0 +1,67 @@ + "%" ]; + $i = 1; + foreach ($args as $j) { + $vars["%$i%"] = $j; + ++$i; + } + $fmt = strtr($fmt,$vars); + } + return $fmt; + } + public static function n($a,$b,$c) { + return $c == 1 ? $a : $b; + } + public static function plugin_init($plugin,$path) { + if (file_exists($plugin->getDataFolder()."messages.ini")) { + self::load($plugin->getDataFolder()."messages.ini"); + return; + } + $msgs = $path."resources/messages/". + $plugin->getServer()->getProperty("settings.language"). + ".ini"; + if (!file_exists($msgs)) return; + mc::load($msgs); + } + + public static function load($f) { + $potxt = "\n".file_get_contents($f)."\n"; + if (preg_match('/\nmsgid\s/',$potxt)) { + $potxt = preg_replace('/\\\\n"\n"/',"\\n", + preg_replace('/\s+""\s*\n\s*"/'," \"", + $potxt)); + } + foreach (['/\nmsgid "(.+)"\nmsgstr "(.+)"\n/', + '/^\s*"(.+)"\s*=\s*"(.+)"\s*$/m'] as $re) { + $c = preg_match_all($re,$potxt,$mm); + if ($c) { + for ($i=0;$i<$c;++$i) { + if ($mm[2][$i] == "") continue; + eval('$a = "'.$mm[1][$i].'";'); + eval('$b = "'.$mm[2][$i].'";'); + mc::$txt[$a] = $b; + } + return $c; + } + } + return false; + } +}