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;
+ }
+}