diff --git a/README.md b/README.md
index ac368a4..a844441 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,183 @@
-# WorldProtect
-Griefer protection plugin
+WorldProtect
+============
+
+* Summary: protect worlds from griefers, pvp, limits and borders
+* Dependency Plugins: n/a
+* PocketMine-MP version: 1.4 - API 1.10.0
+* OptionalPlugins: ManyWorlds
+* Categories: World Editing and Management, Admin Tools, Anti-Griefing Tools
+* Plugin Access: Commands, Manages Permission, Data Saving, World Editing
+* WebSite: [github](https://github.com/alejandroliu/pocketmine-plugins/tree/master/WorldProtect)
+
+Overview
+---------
+
+A full featured World protection plugin.
+
+Features:
+
+* Protect worlds from griefers
+* Per world PvP
+* Create limits in your limitless worlds
+* Limit the number of players in a world
+* Show a text file when players enter a world
+
+Basic Usage:
+
+* /motd [level]
+* /wp unprotect|unlock [level]
+* /wp lock [level]
+* /wp protect [level]
+* /wp pvp [level] [on|off]
+* /wp border [level] [x1 z1 x2 z2|none]
+* /wp max [level] [count]
+* /wp add [level] *player*
+* /wp rm [level] *player*
+* /wp motd [level] [text]
+
+Documentation
+-------------
+
+This plugin let's you limit what happens in a world.
+
+It is able to:
+
+* Protect worlds from griefers. Only players within an auth list
+ and/or certain permissions are allowed to place or destroy blocks.
+* Per world PvP. Prevents PvP matches in specific worlds.
+* Create limits in your limitless worlds. So players attempting are
+ not able to work beyond a preset border. This is useful if you want
+ to avoid overloading the server by generating new Terrain.
+* Limit the number of players in a world.
+* Show a text file when players enter a world. To explain players
+ what is allowed (or not allowed) in specific worlds. For example
+ you could warn players when they are entering a PvP world.
+
+Note that limiting players in a world is only supported by
+[ManyWorlds](http://forums.pocketmine.net/plugins/manyworlds.1042/)
+and any plugin that uses ManyWorlds teleport functionality.
+
+### Commands:
+
+Informational:
+
+* motd [level]
+ Show a level specific _message of the day_ type text.
+* wp motd [level] _text_
+ Modify the motd text for the specified level (or the current level).
+ While you can only enter a single line through this command, you can
+ have a multi-line MOTD by modifying the per-world configuration file.
+
+Protect:
+
+* wp lock [level]
+ Place/destroy block is *not* allowed. Not even for ops. This is
+ useful for adventure style worlds.
+* wp protect [level]
+ Place/destroy block is allowed for players that have
+ `wp.cmd.protect.auth` permission (by default *ops*) or players in
+ the `auth` list. (See add/rm sub-commands).
+* wp unlock|unprotect [level]
+ Placing/destroying blocks are allowed.
+* wp status [level]
+ Will show the lock/protect status of a world.
+
+
+Per-world PvP:
+
+* wp pvp [level] [on|off]
+ If nothing is specified it will show the PvP status of the current
+ level. Otherwise PvP will either be activated|de-activated.
+
+World borders:
+
+* wp border [level] [x1 z1 x2 z2|none]
+ If nothing is specified it will show the current borders. If `none`
+ the current borders will be removed. Otherwise a border will be set
+ by the (x1,z1) - (x2,z2) coordinates.
+
+Player Limits:
+
+* wp max [level] [count]
+ If nothing is specified will show the current player limits.
+ Otherwise the world limit will be set by `count`. Set to `0` for
+ limitless worlds.
+
+Auth list:
+
+* wp add [level] *player*
+* wp rm [level] *player*
+
+These commands add or remove players from the world's `auth` list.
+Access to these commands is controlled by standard PocketMine
+permission system. When a world's `auth` list is defined, access to
+these commands are restricted to the people in the `auth` list.
+
+### Configuration
+
+In the plugin's config.yml file you can have:
+
+ settings:
+ player-limits: true
+ world-borders: true
+ world-protect: true
+ per-world-pvp: true
+ motd: true
+
+* player-limits: Enables the per world player limits
+* world-borders: Enables the world border module
+* world-protect: Enables the anti-griefing module
+* per-world-pvp: Enables per world PvP functionality
+* motd : Enable per world MOTD text
+
+### Permission Nodes:
+
+* wp.motd - Display MOTD
+* wp.cmd.all - Allow access to protect command
+* wp.cmd.protect - Change protect mode
+* wp.cmd.protect.auth - Permit place/destroy in protected worlds
+* wp.cmd.border - Allow contfol of border functionality
+* wp.cmd.pvp - Allow PvP controls
+* wp.cmd.limit - Allow control to limit functionality
+* wp.cmd.wpmotd - Allow editing the motd
+
+### ManyWorlds
+
+The World Limit functionality requires the use of ManyWorlds teleport.
+Also, if ManyWorlds is installed, the
+
+ /mw ls [level]
+
+Will show additional information.
+
+Issues
+------
+
+* World names can not contain spaces.
+* Placing a sign on worlds that do not allow placing blocks will crash
+ the MCPE client.
+
+Changes
+-------
+
+* 1.0.0 : Initial release
+
+Copyright
+---------
+
+ WorldProtect
+ Copyright (C) 2015 Alejandro Liu
+ All Rights Reserved.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
diff --git a/media/WorldProtect-icon.png b/media/WorldProtect-icon.png
new file mode 100644
index 0000000..8b7af92
Binary files /dev/null and b/media/WorldProtect-icon.png differ
diff --git a/plugin.yml b/plugin.yml
new file mode 100644
index 0000000..e3e1d45
--- /dev/null
+++ b/plugin.yml
@@ -0,0 +1,49 @@
+main: aliuly\worldprotect\Main
+api: [1.10.0]
+load: STARTUP
+softdepend: [ManyWorlds]
+
+name: WorldProtect
+description: protect worlds from griefers, pvp, limits and borders
+version: 1.0.0
+author: aliuly
+
+commands:
+ worldprotect:
+ description: Manage worlds
+ usage: "/wp [options]"
+ permission: wp.cmd.all
+ aliases: [wp]
+ motd:
+ description: Show the world's message of the day
+ usage: "/motd [world]"
+ permission: wp.motd
+
+permissions:
+ wp.motd:
+ default: true
+ description: "Display MOTD"
+ wp.cmd.all:
+ default: op
+ description: "Allow access to protect command"
+ wp.cmd.protect:
+ default: op
+ description: "Change protect mode"
+ wp.cmd.protect.auth:
+ default: op
+ description: "Permit place/destroy in protected worlds"
+ wp.cmd.border:
+ default: op
+ description: "Allow contfol of border functionality"
+ wp.cmd.pvp:
+ default: op
+ description: "Allow PvP controls"
+ wp.cmd.limit:
+ default: op
+ description: "Allow control to limit functionality"
+ wp.cmd.wpmotd:
+ default: op
+ description: "Allow editing the motd"
+ wp.cmd.addrm:
+ default: op
+ description: "Allow modifying the auth list"
\ No newline at end of file
diff --git a/src/aliuly/worldprotect/Main.php b/src/aliuly/worldprotect/Main.php
new file mode 100644
index 0000000..7cc52fb
--- /dev/null
+++ b/src/aliuly/worldprotect/Main.php
@@ -0,0 +1,637 @@
+ "unlock",
+ "open" => "unlock",
+ ];
+
+ // 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;
+ }
+ // Standard call-backs
+ public function onEnable(){
+ $defaults = [
+ "settings" => [
+ "player-limits" => true,
+ "world-borders" => true,
+ "world-protect" => true,
+ "per-world-pvp" => true,
+ "motd" => true,
+ ],
+ ];
+ @mkdir($this->getDataFolder());
+ $cfg = (new Config($this->getDataFolder()."config.yml",
+ Config::YAML,$defaults))->getAll();
+ if ($cfg["settings"]["player-limits"] &&
+ $this->getServer()->getPluginManager()->getPlugin("ManyWorlds")==null){
+ $this->getLogger()->info(TextFormat::RED.
+ "player-limits functionality ONLY works with the ".
+ TextFormat::WHITE."ManyWorlds".
+ TextFormat::RED." plugin");
+ $cfg["settings"]["player-limits"] = false;
+ }
+ $this->listeners = [];
+ $this->listeners["main"] = new WpListener($this);
+ if ($cfg["settings"]["motd"])
+ $this->listeners["motd"] = new WpMotdMgr($this);
+ if ($cfg["settings"]["world-protect"])
+ $this->listeners["protect"] = new WpProtectMgr($this);
+ if ($cfg["settings"]["world-borders"])
+ $this->listeners["borders"] = new WpBordersMgr($this);
+ if ($cfg["settings"]["per-world-pvp"])
+ $this->listeners["pvp"] = new WpPvpMgr($this);
+ $this->settings = $cfg["settings"];
+
+ $this->wcfg = [];
+ $this->spam = [];
+ }
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Event handlers...
+ //
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Load/Unload Worlds
+ //
+ public function doLoadWorldConfig($sender,$level) {
+ if (!$this->loadWorldConfig($level)) {
+ $sender->sendMessage("Unable to load configuration for world $level");
+ return false;
+ }
+ return true;
+ }
+ public function saveWorldConfig($world) {
+ $f = $this->getServer()->getDataPath(). "worlds/".$world."/wpcfg.yml";
+ $yaml = new Config($f,Config::YAML,[]);
+ $yaml->setAll($this->wcfg[$world]);
+ $yaml->save();
+ }
+ public function loadWorldConfig($level) {
+ if (isset($this->wcfg[$level])) return true; // world is already loaded!
+ // Is this the best way to get the world path?
+ $p = $this->getServer()->getDataPath(). "worlds/".$level;
+ if (!is_dir($p)) return false;
+ $f = $p."/wpcfg.yml";
+
+ $this->wcfg[$level] = (new Config($f,Config::YAML,[]))->getAll();
+ return true;
+ }
+ public function unloadWorldConfig($level) {
+ if (!isset($this->wcfg[$level])) return; // This world is not loaded...
+ unset($this->wcfg[$level]);
+ }
+ //
+ // Show MOTD messages
+ //
+ public function showMotd($name,$level) {
+ if (!isset($this->wcfg[$level]["motd"])) return;
+ $player = $this->getServer()->getPlayer($name);
+ if (!$player) return;
+ if (!$player->hasPermission("wp.motd")) return;
+ if (is_array($this->wcfg[$level]["motd"])) {
+ $ticks = 10;
+ foreach ($this->wcfg[$level]["motd"] as $ln) {
+ getServer()->getScheduler()->scheduleDelayedTask(new CallbackTask([$player,"sendMessage"],[$ln]),$ticks);
+ $ticks += 10;
+ }
+ } else {
+ $player->sendMessage($this->wcfg[$level]["motd"]);
+ }
+ }
+ //
+ // World protect
+ //
+ public function checkBlockPlaceBreak($pname,$level) {
+ if (!isset($this->wcfg[$level]["protect"])) return true;
+ if ($this->wcfg[$level]["protect"] != "protect") return false;
+ if (isset($this->wcfg[$level]["auth"])
+ && count($this->wcfg[$level]["auth"])) {
+ // Check if user is in auth list...
+ if (isset($this->wcfg[$level]["auth"][$pname])) return true;
+ return false;
+ }
+ $player = $this->getServer()->getPlayer($pname);
+ if (!$player) return false;
+ if ($player->hasPermission("wp.cmd.protect.auth")) return true;
+ return false;
+ }
+ //
+ // PvP callback
+ //
+ public function checkPvP($level) {
+ if (!isset($this->wcfg[$level]["pvp"])) return true;
+ return $this->wcfg[$level]["pvp"];
+ }
+ //
+ // Border controls
+ //
+ public function checkMove($level,$x,$z) {
+ if (!isset($this->wcfg[$level]["border"])) return true;
+ list($x1,$z1,$x2,$z2) = $this->wcfg[$level]["border"];
+ if ($x1 < $x && $x < $x2 && $z1 < $z && $z < $z2) return true;
+ return false;
+ }
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Utility functions
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public function msg($pl,$txt) {
+ $n = $pl->getName();
+ if (isset($this->spam[$n])) {
+ // Check if we are spamming...
+ if (time() - $this->spam[$n][0] < self::SPAM_DELAY
+ && $this->spam[$n][1] == $txt) return;
+ }
+ $this->spam[$n] = [ time(), $txt ];
+ $pl->sendMessage($txt);
+ }
+ private function isAuth(CommandSender $sender,$level) {
+ if (!$this->inGame($sender,false)) return true;
+ if (!isset($this->wcfg[$level]["auth"])) return true;
+ if (!count($this->wcfg[$level]["auth"])) return true;
+ if (isset($this->wcfg[$level]["auth"][$sender->getName()])) return true;
+ $sender->sendMessage("[WP] You are not allowed to do this");
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Command entry point
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public function onCommand(CommandSender $sender, Command $cmd, $label, array $args) {
+ switch($cmd->getName()) {
+ case "motd":
+ return $this->motdCmd($sender,$args);
+ case "worldprotect":
+ if(isset($args[0])) {
+ $scmd = strtolower(array_shift($args));
+ if (isset(self::$aliases[$scmd])) $scmd = self::$aliases[$scmd];
+ switch ($scmd) {
+ case "add":
+ if (!$this->access($sender,"wp.cmd.addrm")) return false;
+ return $this->worldProtectAdd($sender,$args);
+ case "rm":
+ if (!$this->access($sender,"wp.cmd.addrm")) return false;
+ return $this->worldProtectRm($sender,$args);
+ case "unlock":
+ case "lock":
+ case "protect":
+ if (!$this->access($sender,"wp.cmd.protect")) return false;
+ if (!$this->settings["world-protect"]) return false;
+ return $this->worldProtectMode($sender,$scmd,$args);
+ case "pvp":
+ if (!$this->access($sender,"wp.cmd.pvp")) return false;
+ if (!$this->settings["per-world-pvp"]) return false;
+ return $this->worldPvpMode($sender,$args);
+ case "border":
+ if (!$this->access($sender,"wp.cmd.border")) return false;
+ if (!$this->settings["world-borders"]) return false;
+ return $this->worldBorderCmd($sender,$args);
+ case "max":
+ if (!$this->access($sender,"wp.cmd.limit")) return false;
+ if (!$this->settings["player-limits"]) return false;
+ return $this->worldLimitCmd($sender,$args);
+ case "motd":
+ if (!$this->access($sender,"wp.cmd.wpmotd")) return false;
+ if (!$this->settings["motd"]) return false;
+ return $this->worldMotdCmd($sender,$args);
+ case "help":
+ return $this->helpCmd($sender,$args);
+ default:
+ $sender->sendMessage(TextFormat::RED."Unknown sub command: ".
+ TextFormat::RESET.$scmd);
+ $sender->sendMessage("Use: ".TextFormat::GREEN." /wp help".
+ TextFormat::RESET);
+ }
+ return true;
+ } else {
+ $sender->sendMessage("Must specify sub command");
+ $sender->sendMessage("Try: ".TextFormat::GREEN." /wp help".
+ TextFormat::RESET);
+ return false;
+ }
+ }
+ return false;
+ }
+ //////////////////////////////////////////////////////////////////////
+ //
+ // Actual commands
+ //
+ //////////////////////////////////////////////////////////////////////
+ private function helpCmd(CommandSender $sender,$args) {
+ $cmds = [
+ "motd" => ["[level] [text]",
+ "View/Edit the world's motd file"],
+ "add" => ["[level] ","Add to authorized list"],
+ "rm" => ["[level] ","Remove from authorized list"],
+ "unlock" => ["[level]","Unprotects a world"],
+ "lock"=>["[level]","Locked. Nobody (including op) can build"],
+ "protect"=>["[level]","Only authorized people can build"],
+ "pvp"=>["[level] [on|off]","Enable|disable pvp"],
+ "border" => ["[level] [x1 z1 x2 z2|none]",
+ "Creates a border in [level] defined by x1,z1 to x2,z2"],
+ "max" => ["[level] [value]",
+ "Limits the number of players in a world to [value] use 0 or -1 to remove limits"],
+ ];
+ 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: /wp $c $a"
+ .TextFormat::RESET);
+ $sender->sendMessage($b);
+ }
+ }
+ return true;
+ }
+ $sender->sendMessage("WorldProtect sub-commands");
+ foreach ($cmds as $a => $b) {
+ $ln = "- ".TextFormat::GREEN."/mw ".$a;
+ foreach (self::$aliases as $i => $j) {
+ if ($j == $a) $ln .= "|$i";
+ }
+ $ln .= TextFormat::RESET." ".$b[0];
+ $sender->sendMessage($ln);
+ }
+ return true;
+ }
+
+ private function motdCmd(CommandSender $sender,$args) {
+ if (count($args) == 0) {
+ if (!$this->inGame($sender)) return true;
+ $level = $sender->getLevel()->getName();
+ } elseif (count($args) > 1) {
+ return $this->helpCmd($sender,["motd"]);
+ } else {
+ $level = $args[0];
+ }
+ if (!$this->doLoadWorldConfig($sender,$level)) return true;
+ if (!isset($this->wcfg[$level]["motd"])) {
+ $sender->sendMessage(TextFormat::RED."Sorry, no \"motd\"".TextFormat::RESET);
+ return true;
+ }
+ if (is_array($this->wcfg[$level]["motd"])) {
+ foreach ($this->wcfg[$level]["motd"] as $ln) {
+ $sender->sendMessage($ln);
+ }
+ } else {
+ $sender->sendMessage($this->wcfg[$level]["motd"]);
+ }
+ return true;
+ }
+ //
+ // Modify auth list
+ //
+ private function worldProtectAdd(CommandSender $sender,$args){
+ if (count($args) == 1) {
+ if (!$this->inGame($sender,false)) {
+ $sender->sendMessage("You need to specify a level");
+ return false;
+ }
+ $user = $args[0];
+ $level = $sender->getLevel()->getName();
+ } elseif (count($args) == 2) {
+ list($level,$user) = $args;
+ }
+ if (!$this->doLoadWorldConfig($sender,$level)) return true;
+ if (!$this->isAuth($sender,$level)) return true;
+ if (!isset($this->wcfg[$level]["auth"])) $this->wcfg[$level]["auth"] = [];
+ if (isset($this->wcfg[$level]["auth"][$user])) {
+ $sender->sendMessage("[WP] $user is already in $level authorized list");
+ return true;
+ }
+ $player = $this->getServer()->getPlayer($user);
+ if (!$player) {
+ $sender->sendMessage("[WP] $user can not be found. Are they off-line?");
+ return true;
+ }
+ if (!$player->isOnline()) {
+ $sender->sendMessage("[WP] $user is offline!");
+ return true;
+ }
+ $this->wcfg[$level]["auth"][$user] = $user;
+ $this->saveWorldConfig($level);
+ $sender->sendMessage("[WP] $user added to $level's authorized list");
+ $player->sendMessage("[WP] You have been added to $level's authorized list");
+ return true;
+ }
+ private function worldProtectRm(CommandSender $sender,$args) {
+ if (count($args) == 1) {
+ if (!$this->inGame($sender,false)) {
+ $sender->sendMessage("You need to specify a level");
+ return false;
+ }
+ $user = $args[0];
+ $level = $sender->getLevel()->getName();
+ } elseif (count($args) == 2) {
+ list($level,$user) = $args;
+ }
+ if (!$this->doLoadWorldConfig($sender,$level)) return true;
+ if (!$this->isAuth($sender,$level)) return true;
+
+ if (!isset($this->wcfg[$level]["auth"][$user])) {
+ $sender->sendMessage("[WP] $user is not in $level authorized list");
+ return true;
+ }
+ $player = $this->getServer()->getPlayer($user);
+ if ($player) {
+ if (!$player->isOnline()) $player = null;
+ }
+ unset($this->wcfg[$level]["auth"][$user]);
+ $this->saveWorldConfig($level);
+ $sender->sendMessage("[WP] $user removed from $level's authorized list");
+ if ($player)
+ $player->sendMessage("[WP] You have been removed from $level's authorized list");
+ return true;
+ }
+ //
+ // World protect
+ //
+ private function worldProtectMode(CommandSender $sender,$mode,$args) {
+ if (count($args) == 0) {
+ if (!$this->inGame($sender)) return true;
+ $level = $sender->getLevel()->getName();
+ } elseif (count($args) == 1) {
+ $level = $args[0];
+ } else {
+ return $this->helpCmd($sender,[$mode]);
+ }
+ if (!$this->doLoadWorldConfig($sender,$level)) return true;
+ if (!$this->isAuth($sender,$level)) return true;
+ if (isset($this->wcfg[$level]["protect"])) {
+ if ($mode == "unlock") {
+ unset($this->wcfg[$level]["protect"]);
+ } elseif ($mode == $this->wcfg[$level]["protect"]) {
+ $sender->sendMessage("[WP] $level was not changed!");
+ return true;
+ } else {
+ $this->wcfg[$level]["protect"] = $mode;
+ }
+ } else {
+ if ($mode == "unlock") {
+ $sender->sendMessage("[WP] $level was not changed!");
+ return true;
+ }
+ $this->wcfg[$level]["protect"] = $mode;
+ }
+ $this->saveWorldConfig($level);
+ $this->getServer()->broadcastMessage("[WP] World $level protection mode changed to $mode");
+ return true;
+ }
+ // pvp mode
+ private function worldPvpMode(CommandSender $sender,$args) {
+ if (count($args) == 0) {
+ if (!$this->inGame($sender)) return true;
+ $level = $sender->getLevel()->getName();
+ $mode = "show";
+ } elseif (count($args) == 1) {
+ if (strtolower($args[0]) == "on" || strtolower($args[0]) == "off") {
+ if (!$this->inGame($sender)) return true;
+ $mode = strtolower($args[0]);
+ $level = $sender->getLevel()->getName();
+ } else {
+ $mode = "show";
+ $level = $args[0];
+ }
+ } elseif (count($args) == 2) {
+ list($level,$mode) = $args;
+ $mode = strtolower($mode);
+ } else {
+ return $this->helpCmd($sender,["pvp"]);
+ }
+ if (!$this->doLoadWorldConfig($sender,$level)) return true;
+ if ($mode == "show") {
+ $sender->sendMessage("PvP status for $level is ".
+ ($this->checkPvP($level) ?
+ TextFormat::RED."ON" :
+ TextFormat::GREEN."OFF"));
+ return true;
+ }
+ if (!$this->isAuth($sender,$level)) return true;
+ if ($mode == "on") {
+ if ($this->checkPvP($level)) {
+ $sender->sendMessage("PvP status unchanged");
+ return true;
+ }
+ $this->wcfg[$level]["pvp"] = true;
+ } else {
+ if (!$this->checkPvP($level)) {
+ $sender->sendMessage("PvP status unchanged");
+ return true;
+ }
+ $this->wcfg[$level]["pvp"] = false;
+ }
+ $this->saveWorldConfig($level);
+ $this->getServer()->broadcastMessage("[WP] World $level PvP changed to $mode");
+ return true;
+ }
+
+ // World borders
+ private function worldBorderCmd(CommandSender $sender,$args) {
+ if (count($args) == 4) {
+ if (!$this->inGame($sender)) return true;
+ $level = $sender->getLevel()->getName();
+ } elseif (count($args) == 5) {
+ $level = array_shift($args);
+ } elseif (count($args) == 2) {
+ $level = array_shift($args);
+ } elseif (count($args) == 1) {
+ if (strtolower($args[0]) == "off") {
+ if (!$this->inGame($sender)) return true;
+ $level = $sender->getLevel()->getName();
+ } else {
+ $level = array_shift($args);
+ }
+ } else {
+ return $this->helpCmd($sender,["border"]);
+ }
+ if (!$this->doLoadWorldConfig($sender,$level)) return true;
+ if (count($args) == 0) {
+ list($x1,$z1,$x2,$z2) = $this->wcfg[$level]["border"];
+ $sender->sendMessage("[WP] Border for $level is ($x1,$z1)-($x2,$z2)");
+ return true;
+ }
+ if (!$this->isAuth($sender,$level)) return true;
+ if (count($args) == 4) {
+ list($x1,$z1,$x2,$z2) = $args;
+ if ($x1 > $x2) list($x1,$x2) = [$x2,$x1];
+ if ($z1 > $z2) list($z1,$z2) = [$z2,$z1];
+ if ($x2 - $x1 < self::MIN_BORDER || $z2 - $z1 < self::MIN_BORDER) {
+ $sender->sendMessage("[WP] Invalid border region");
+ return true;
+ }
+ $this->wcfg[$level]["border"] = [$x1,$z1,$x2,$z2];
+ } else {
+ if (!isset($this->wcfg[$level]["border"])) {
+ $sender->sendMessage("[WP] No border for $level currently");
+ return true;
+ }
+ unset($this->wcfg[$level]["border"]);
+ }
+ $this->saveWorldConfig($level);
+ if (isset($this->wcfg[$level]["border"])) {
+ $this->getServer()->broadcastMessage("[WP] $level border: $x1,$z1,$x2,$z2");
+ } else {
+ $this->getServer()->broadcastMessage("[WP] Borders for $level removed");
+ }
+ return true;
+ }
+
+ // World limits
+ private function worldLimitCmd(CommandSender $sender,$args) {
+ if (count($args) == 0) {
+ if (!$this->inGame($sender)) return true;
+ $level = $sender->getLevel()->getName();
+ $count = "show";
+ } elseif (count($args) == 1) {
+ if (is_numeric($args[0])) {
+ if (!$this->inGame($sender)) return true;
+ $level = $sender->getLevel()->getName();
+ $count = (int)$args[0];
+ } else{
+ $level = $args[0];
+ $count = "show";
+ }
+ } elseif (count($args) == 2) {
+ $level = $args[0];
+ $count = (int)$args[1];
+ } else {
+ return $this->helpCmd($sender,["max"]);
+ }
+ if (!$this->doLoadWorldConfig($sender,$level)) return true;
+ if ($count == "show") {
+ if (isset($this->wcfg[$level]["max-players"])) {
+ $sender->sendMessage("[WP] ".
+ $this->wcfg[$level]["max-players"].
+ " allowed in world $level");
+ } else {
+ $sender->sendMessage("[WP] Max players in $level is un-limited");
+ }
+ return true;
+ }
+ if (!$this->isAuth($sender,$level)) return true;
+ $count = (int)$count;
+ if ($count <= 0) $count = 0;
+ if (isset($this->wcfg[$level]["max-players"])) {
+ if ($count == $this->wcfg[$level]["max-players"]) {
+ $sender->sendMessage("[WP] Max players in $level is unchanged");
+ return true;
+ }
+ } else {
+ if ($count <= 0) {
+ $sender->sendMessage("[WP] Max players in $level is unchanged");
+ return true;
+ }
+ }
+ $this->wcfg[$level]["max-players"] = $count;
+ $this->saveWorldConfig($level);
+ if ($count) {
+ $this->getServer()->broadcastMessage("[WP] Max-players limit for $level set to $count");
+ } else {
+ $this->getServer()->broadcastMessage("[WP] Max-players limits for $level removed");
+ }
+ return true;
+ }
+ //
+ // MOTD stuff...
+ //
+ private function worldMotdCmd(CommandSender $sender,$args) {
+ if (count($args)==0) {
+ if (!$this->inGame($sender)) return true;
+ $level = $sender->getLevel()->getName();
+ } else {
+ if ($this->getServer()->isLevelGenerated($args[0])) {
+ $level = array_shift($args);
+ } else {
+ if (!$this->inGame($sender)) return true;
+ $level = $sender->getLevel()->getName();
+ }
+ }
+ if (count($args) == 0) return $this->motdCmd($sender,[$level]);
+ if (!$this->doLoadWorldConfig($sender,$level)) return true;
+ if (!$this->isAuth($sender,$level)) return true;
+ $ln = implode(" ",$args);
+ if (isset($this->wcfg[$level]["motd"])) {
+ if (!is_array($this->wcfg[$level]["motd"]) &&
+ $this->wcfg[$level]["motd"] == $ln) {
+ $sender->sendMessage("[WP] $level's motd unchanged");
+ return true;
+ }
+ }
+ $this->wcfg[$level]["motd"] = $ln;
+ $this->saveWorldConfig($level);
+ $sender->sendMessage("[WP] $level's motd updated");
+ return true;
+ }
+ //////////////////////////////////////////////////////////////////////
+ //
+ // ManyWorlds entry points
+ //
+ //////////////////////////////////////////////////////////////////////
+ public function getPlayerLimit($level) {
+ if (!isset($this->wcfg[$level])) return 0;
+ if (!isset($this->wcfg[$level]["max-players"])) return 0;
+ return $this->wcfg[$level]["max-players"];
+ }
+ public function getWorldInfo($level) {
+ $txt = [];
+ if (!isset($this->wcfg[$level])) return $txt;
+ if (isset($this->wcfg[$level]["motd"])) {
+ $txt[] = "MOTD:";
+ if (is_array($this->wcfg[$level]["motd"])) {
+ foreach ($this->wcfg[$level]["motd"] as $ln) {
+ $txt[] = TextFormat::BLUE." ".$ln.TextFormat::RESET;
+ }
+ } else {
+ $txt[] = TextFormat::BLUE." ".$this->wcfg[$level]["motd"];
+ }
+ }
+ if (isset($this->wcfg[$level]["protect"]))
+ $txt[] = "Protect Status: ".$this->wcfg[$level]["protect"];
+ if ($this->checkPvP($level)) {
+ $txt[] = "PvP: ".TextFormat::RED."ON";
+ } else {
+ $txt[] = "PvP: ".TextFormat::GREEN."OFF";
+ }
+ if (isset($this->wcfg[$level]["border"])) {
+ $txt[] = "World Borders:".implode(",",$this->wcfg[$level]["border"]);
+ }
+ if (isset($this->wcfg[$level]["max-players"])) {
+ $txt[] = "Max-Players: ".$this->wcfg[$level]["max-players"];
+ }
+ if (isset($this->wcfg[$level]["auth"]) && count($this->wcfg[$level]["auth"])) {
+ $txt[] = "Auth-List(".count($this->wcfg[$level]["auth"])."):".
+ implode(", ",$this->wcfg[$level]["auth"]);
+ }
+ return $txt;
+ }
+}
diff --git a/src/aliuly/worldprotect/WpBordersMgr.php b/src/aliuly/worldprotect/WpBordersMgr.php
new file mode 100644
index 0000000..2b9945d
--- /dev/null
+++ b/src/aliuly/worldprotect/WpBordersMgr.php
@@ -0,0 +1,27 @@
+owner = $plugin;
+ $this->owner->getServer()->getPluginManager()->registerEvents($this, $this->owner);
+ }
+ public function onPlayerMove(PlayerMoveEvent $ev) {
+ $pl = $ev->getPlayer();
+ $pos = $ev->getTo();
+ if ($this->owner->checkMove($pl->getLevel()->getName(),
+ $pos->getX(),$pos->getZ())) return;
+ $this->owner->msg($pl,"You have reached the end of the world");
+ $ev->setCancelled();
+ }
+}
\ No newline at end of file
diff --git a/src/aliuly/worldprotect/WpListener.php b/src/aliuly/worldprotect/WpListener.php
new file mode 100644
index 0000000..c8d6123
--- /dev/null
+++ b/src/aliuly/worldprotect/WpListener.php
@@ -0,0 +1,22 @@
+owner = $plugin;
+ $this->owner->getServer()->getPluginManager()->registerEvents($this, $this->owner);
+ }
+ // Make sure configs are loaded/unloaded
+ public function onLevelLoad(LevelLoadEvent $e) {
+ $this->owner->loadWorldConfig($e->getLevel()->getName());
+ }
+ public function onLevelUnload(LevelUnloadEvent $e) {
+ $this->owner->unloadWorldConfig($e->getLevel()->getName());
+ }
+}
diff --git a/src/aliuly/worldprotect/WpMotdMgr.php b/src/aliuly/worldprotect/WpMotdMgr.php
new file mode 100644
index 0000000..4f7463d
--- /dev/null
+++ b/src/aliuly/worldprotect/WpMotdMgr.php
@@ -0,0 +1,33 @@
+owner = $plugin;
+ $this->owner->getServer()->getPluginManager()->registerEvents($this, $this->owner);
+ }
+ private function showMotd($name,$level,$ticks=10) {
+ $this->owner->getServer()->getScheduler()->scheduleDelayedTask(new CallbackTask([$this->owner,"showMotd"],[$name,$level]),$ticks);
+ }
+ public function onJoin(PlayerJoinEvent $ev) {
+ $pl = $ev->getPlayer();
+ $this->showMotd($pl->getName(),$pl->getLevel()->getName());
+ }
+ public function onLevelChange(EntityLevelChangeEvent $ev) {
+ $pl = $ev->getEntity();
+ if (!($pl instanceof Player)) return;
+ $level = $ev->getTarget()->getName();
+ $this->showMotd($pl->getName(),$level);
+ }
+}
\ No newline at end of file
diff --git a/src/aliuly/worldprotect/WpProtectMgr.php b/src/aliuly/worldprotect/WpProtectMgr.php
new file mode 100644
index 0000000..cc6ca7b
--- /dev/null
+++ b/src/aliuly/worldprotect/WpProtectMgr.php
@@ -0,0 +1,77 @@
+getLevel()->getName();
+ $x = $block->getX();
+ $y = $block->getY();
+ $z = $block->getZ();
+ return implode(":",[$l,$x,$y,$z]);
+ }
+
+
+ public function __construct(Plugin $plugin) {
+ $this->owner = $plugin;
+ $this->owner->getServer()->getPluginManager()->registerEvents($this, $this->owner);
+ $signs = [];
+ }
+
+ public function onBlockBreak(BlockBreakEvent $ev){
+ $pl = $ev->getPlayer();
+ if ($this->owner->checkBlockPlaceBreak($pl->getName(),
+ $pl->getLevel()->getName())) return;
+ $this->owner->msg($pl,"You are not allowed to do that here");
+ $ev->setCancelled();
+ }
+ public function onSignChanged(SignChangeEvent $ev){
+ $h = self::blockAddr($ev->getBlock());
+ if (!isset($this->signs[$h])) return;
+
+ list($id,$meta,$cnt,$time) = $this->signs[$h];
+ if ($cnt == 0) {
+ $this->signs[$h][2] = 1;
+ return;
+ }
+ unset($this->sings[$h]);
+ $block =$ev->getBlock();
+ $l = $block->getLevel();
+ $x = $block->getX();
+ $y = $block->getY();
+ $z = $block->getZ();
+ $l->setBlockIdAt($x,$y,$z,$id);
+ $l->setBlockDataAt($x,$y,$z,$meta);
+ }
+
+ public function onBlockPlace(BlockPlaceEvent $ev){
+ $pl = $ev->getPlayer();
+ if ($this->owner->checkBlockPlaceBreak($pl->getName(),
+ $pl->getLevel()->getName())) return;
+ $this->owner->msg($pl,"You are not allowed to do that here");
+ $id = $ev->getBlock()->getId();
+
+ if ($id == 63) {
+ // Oh no.. placing a SignPost!
+ $h = self::blockAddr($ev->getBlock());
+ $this->signs[$h] = [ $ev->getBlockReplaced()->getId(),
+ $ev->getBlockReplaced()->getDamage(),
+ 0, time() ];
+ return;
+ }
+ $ev->setCancelled();
+ }
+}
\ No newline at end of file
diff --git a/src/aliuly/worldprotect/WpPvpMgr.php b/src/aliuly/worldprotect/WpPvpMgr.php
new file mode 100644
index 0000000..4b81ff9
--- /dev/null
+++ b/src/aliuly/worldprotect/WpPvpMgr.php
@@ -0,0 +1,26 @@
+owner = $plugin;
+ $this->owner->getServer()->getPluginManager()->registerEvents($this, $this->owner);
+ }
+ public function onPvP(EntityDamageEvent $ev) {
+ if(!($ev instanceof EntityDamageByEntityEvent)) return;
+ if (!($ev->getEntity() instanceof Player && $ev->getDamager() instanceof Player)) return;
+ if ($this->owner->checkPvP($ev->getEntity()->getLevel()->getName())) return;
+ $this->owner->msg($ev->getDamager(),"You are not allowed to do that here");
+ $ev->setCancelled();
+ }
+}
\ No newline at end of file