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