PageRenderTime 24ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/SignWarp/src/aliuly/signwarp/Main.php

https://gitlab.com/Skull3x/pocketmine-plugins
PHP | 368 lines | 316 code | 22 blank | 30 comment | 74 complexity | 70a75c1d0f5ba6d3d713dbd8c3cc6112 MD5 | raw file
  1. <?php
  2. /**
  3. ** CONFIG:config.yml
  4. **/
  5. namespace aliuly\signwarp;
  6. use pocketmine\plugin\PluginBase;
  7. use pocketmine\command\PluginCommand;
  8. use pocketmine\event\Listener;
  9. use pocketmine\command\Command;
  10. use pocketmine\command\CommandSender;
  11. use pocketmine\Player;
  12. use pocketmine\block\Block;
  13. use pocketmine\item\Item;
  14. use pocketmine\tile\Sign;
  15. use pocketmine\utils\Config;
  16. use pocketmine\utils\TextFormat;
  17. use pocketmine\event\block\SignChangeEvent;
  18. use pocketmine\event\block\BlockPlaceEvent;
  19. use pocketmine\event\player\PlayerInteractEvent;
  20. use pocketmine\event\player\PlayerQuitEvent;
  21. use pocketmine\level\Position;
  22. use pocketmine\math\Vector3;
  23. use aliuly\signwarp\common\PluginCallbackTask;
  24. use aliuly\signwarp\common\mc;
  25. use aliuly\signwarp\common\MPMU;
  26. class Main extends PluginBase implements Listener {
  27. const MAX_COORD = 30000000;
  28. const MIN_COORD = -30000000;
  29. const MAX_HEIGHT = 128;
  30. const MIN_HEIGHT = 0;
  31. protected $teleporters;
  32. protected $text;
  33. public function onEnable(){
  34. if (!is_dir($this->getDataFolder())) mkdir($this->getDataFolder());
  35. mc::plugin_init($this,$this->getFile());
  36. $wp = $this->getServer()->getPluginManager()->getPlugin("WorldProtect");
  37. if ($wp !== null && version_compare($wp->getDescription()->getVersion(),"2.1.0") < 0) {
  38. $this->getLogger()->warning(TextFormat::RED.mc::_("This version of SignWarp requires"));
  39. $this->getLogger()->warning(TextFormat::RED.mc::_("at least version 2.1.0 of WorldProtect"));
  40. $this->getLogger()->warning(TextFormat::RED.mc::_("Only version %1% available",$wp->getDescription()->getVersion()));
  41. throw new \RuntimeException("Runtime checks failed");
  42. return;
  43. }
  44. $defaults =
  45. [
  46. "version" => $this->getDescription()->getVersion(),
  47. "# settings" => "configurable variables",
  48. "settings" => [
  49. "# dynamic updates" => "Signs will be udpated with the number of players in a world",
  50. "dynamic-updates" => true,
  51. "# xyz.cmd" => "If true, the **xyz** command will be available",
  52. "xyz.cmd" => true,
  53. ],
  54. "# text" => "Text displayed on the different signs",
  55. "text" => [
  56. "# transfer" => "Fast transfer signs",
  57. "transfer" => [ "[TRANSFER]" ],
  58. "# world" => "World teleport signs",
  59. "world" => [ "[WORLD]" ],
  60. "# warp" => "Local world teleport signs",
  61. "warp" => [ "[WARP]", "[SWARP]" ],
  62. "# players" => "Text to use when displaying player counts",
  63. "players" => [ "Players:" ],
  64. ]
  65. ];
  66. $cfg = (new Config($this->getDataFolder()."config.yml",
  67. Config::YAML,$defaults))->getAll();
  68. if ($this->getServer()->getPluginManager()->getPlugin("FastTransfer")){
  69. $this->getLogger()->info(TextFormat::GREEN.mc::_("Enabling FastTransfer support"));
  70. }else{
  71. $this->getLogger()->warning(TextFormat::BLUE.mc::_("Disabling FastTransfer support"));
  72. $cfg["text"]["transfer"] = [];
  73. }
  74. $this->text = [ "sign" => [] ];
  75. foreach (["world","warp","transfer"] as $n) {
  76. $thist->text[$n] = [];
  77. foreach ($cfg["text"][$n] as $m) {
  78. $this->text[$n][$m] = $m;
  79. $this->text["sign"][$m] = $m;
  80. }
  81. }
  82. $this->text["players"] = $cfg["text"]["players"];
  83. if ($cfg["settings"]["xyz.cmd"]) {
  84. $newCmd = new PluginCommand("xyz",$this);
  85. $newCmd->setDescription(mc::_("Returns x,y,z coordinates"));
  86. $newCmd->setUsage(mc::_("/xyz"));
  87. $newCmd->setPermission("signwarp.cmd.xyz");
  88. $cmdMap = $this->getServer()->getCommandMap();
  89. $cmdMap->registerAll($this->getDescription()->getName(),
  90. [$newCmd]);
  91. $this->getLogger()->info(TextFormat::GREEN.mc::_("enabled /xyz command"));
  92. }
  93. if ($cfg["settings"]["dynamic-updates"]) {
  94. $this->getLogger()->info(TextFormat::GREEN.mc::_("dynamic-updates: ON"));
  95. $tt = new PluginCallbackTask($this,[$this,"updateSigns"],[]);
  96. $this->getServer()->getScheduler()->scheduleRepeatingTask($tt,40);
  97. } else {
  98. $this->getLogger()->info(TextFormat::YELLOW.mc::_("dynamic-updates: OFF"));
  99. }
  100. $this->getServer()->getPluginManager()->registerEvents($this, $this);
  101. }
  102. //////////////////////////////////////////////////////////////////////
  103. //
  104. // Support functions
  105. //
  106. //////////////////////////////////////////////////////////////////////
  107. private function checkSign(Player $pl,array $sign) {
  108. if (isset($this->text["warp"][$sign[0]])) {
  109. // Short warp...
  110. if (empty($sign[1])) {
  111. $pl->sendMessage(mc::_("[SignWarp] No coordinates specified"));
  112. return null;
  113. }
  114. $mv = [];
  115. if ($this->check_coords($sign[1],$mv) !== true) {
  116. $pl->sendMessage(mc::_("[SignWarp] Invalid coordinates %1%",$sign[1]));
  117. return null;
  118. }
  119. return new Position($mv[0],$mv[1],$mv[2],$pl->getLevel());
  120. }
  121. // Long warp!
  122. if (isset($this->text["world"][$sign[0]])) {
  123. if (empty($sign[1])) {
  124. $pl->sendMessage(mc::_("[SignWarp] No World specified"));
  125. return null;
  126. }
  127. // Check level...
  128. if (!$this->getServer()->isLevelGenerated($sign[1])) {
  129. $pl->sendMessage(mc::_("[SignWarp] World \"%1%\" does not exist!",$sign[1]));
  130. return null;
  131. }
  132. if (!$this->getServer()->isLevelLoaded($sign[1])) {
  133. $pl->sendMessage(mc::_("[SignWarp] Loading \"%1%\"",$sign[1]));
  134. if (!$this->getServer()->loadLevel($sign[1])) {
  135. $pl->sendMessage(mc::_("[SignWarp] Unable to load world \"%1%\"",$sign[1]));
  136. return null;
  137. }
  138. }
  139. $l = $this->getServer()->getLevelByName($sign[1]);
  140. if ($l == null) {
  141. $pl->sendMessage(mc::_("[SignWarp] Error loading \"%1%\"",
  142. $sign[1]));
  143. return null;
  144. }
  145. $mv = [];
  146. if ($this->check_coords($sign[2],$mv)) {
  147. $mv = new Vector3($mv[0],$mv[1],$mv[2]);
  148. } else {
  149. $mv = null;
  150. }
  151. return $pos = $l->getSafeSpawn($mv);
  152. }
  153. if (isset($this->text["transfer"][$sign[0]])) {
  154. $address = $sign[1];
  155. $port = $sign[2];
  156. if (empty($address)) return null;
  157. $port = intval($port);
  158. if ($port == 0) $port = 19132; // Default for Minecraft PE
  159. return [$address,$port];
  160. }
  161. $pl->sendMessage(mc::_("[SignWarp] INTERNAL ERROR"));
  162. return null;
  163. }
  164. public function doBreakSign($tile) {
  165. $l = $tile->getLevel();
  166. $l->setBlockIdAt($tile->getX(),$tile->getY(),$tile->getZ(),Block::AIR);
  167. $l->setBlockDataAt($tile->getX(),$tile->getY(),$tile->getZ(),0);
  168. $tile->close();
  169. }
  170. public function breakSign(Player $pl,Sign $tile,$msg = "") {
  171. if ($msg != "") $pl->sendMessage($msg);
  172. $this->getServer()->getScheduler()->scheduleDelayedTask(
  173. new PluginCallbackTask($this,[$this,"doBreakSign"],[$tile]),10
  174. );
  175. }
  176. private function check_coords($line,array &$vec) {
  177. $mv = array();
  178. if (!preg_match('/^\s*(-?\d+)\s+(-?\d+)\s+(-?\d+)\s*$/',$line,$mv)) {
  179. return false;
  180. }
  181. list($line,$x,$y,$z) = $mv;
  182. if ($x <= self::MIN_COORD || $z <= self::MIN_COORD) return false;
  183. if ($x >= self::MAX_COORD || $z >= self::MAX_COORD) return false;
  184. if ($y <= self::MIN_HEIGHT || $y >= self::MAX_HEIGHT) return false;
  185. $vec = [$x,$y,$z];
  186. return true;
  187. }
  188. private function matchCounter($txt) {
  189. foreach ($this->text["players"] as $t) {
  190. if (substr($txt,0,strlen($t)) == $t) return $t;
  191. }
  192. return false;
  193. }
  194. //////////////////////////////////////////////////////////////////////
  195. //
  196. // Internal command
  197. //
  198. //////////////////////////////////////////////////////////////////////
  199. public function onCommand(CommandSender $sender,Command $cmd,$label, array $args) {
  200. switch ($cmd->getName()) {
  201. case "xyz":
  202. if ($sender instanceof Player) {
  203. $pos = $sender->getPosition();
  204. $sender->sendMessage(mc::_("You are at %1%,%2%,%3%",
  205. intval($pos->getX()),
  206. intval($pos->getY()),
  207. intval($pos->getZ())));
  208. } else {
  209. $sender->sendMessage(TextFormat::RED.mc::_("[SignWarp] This command may only be used in-game"));
  210. }
  211. return true;
  212. }
  213. return false;
  214. }
  215. //////////////////////////////////////////////////////////////////////
  216. //
  217. // Event Handlers
  218. //
  219. //////////////////////////////////////////////////////////////////////
  220. public function onQuit(PlayerQuitEvent $event) {
  221. $name = $event->getPlayer()->getName();
  222. if (isset($this->teleporters[$name])) unset($this->teleporters[$name]);
  223. }
  224. public function onBlockPlace(BlockPlaceEvent $event){
  225. $name = $event->getPlayer()->getName();
  226. if (isset($this->teleporters[$name])) {
  227. if (time() - $this->teleporters[$name] < 2)
  228. $event->setCancelled();
  229. else
  230. unset($this->teleporters[$name]);
  231. }
  232. }
  233. public function signChanged(SignChangeEvent $event){
  234. if($event->getBlock()->getId() != Block::SIGN_POST &&
  235. $event->getBlock()->getId() != Block::WALL_SIGN) return;
  236. $pl = $event->getPlayer();
  237. $tile = $pl->getLevel()->getTile($event->getBlock());
  238. if(!($tile instanceof Sign))return;
  239. $sign = $event->getLines();
  240. if (!isset($this->text["sign"][$sign[0]])) return;
  241. if(!$pl->hasPermission("signwarp.place.sign")) {
  242. $this->breakSign($pl,$tile,mc::_("You are not allowed to make Warp signs"));
  243. return;
  244. }
  245. // FastTransfer!
  246. if (isset($this->text["transfer"][$sign[0]])) {
  247. // Fast transfer!
  248. if(!$pl->hasPermission("signwarp.place.transfer.sign")) {
  249. $this->breakSign($pl,$tile,mc::_("You are not allowed to make\nTransfer Warp signs"));
  250. return;
  251. }
  252. }
  253. $pos = $this->checkSign($pl,$sign);
  254. if ($pos === null) {
  255. $this->breakSign($pl,$tile);
  256. return;
  257. }
  258. if ($pos instanceof Position) {
  259. $this->getServer()->broadcastMessage(
  260. isset($this->text["world"][$sign[0]]) ?
  261. mc::_("[SignWarp] Portal to %1% created by %2%",
  262. $pos->getLevel()->getName(),$pl->getName()) :
  263. mc::_("[SignWarp] Warp to %1%,%2%,%3% created by %4%",
  264. $pos->getX(),$pos->getY(),$pos->getZ(),
  265. $pl->getName()));
  266. } else {
  267. $this->getServer()->broadcastMessage(
  268. mc::_("[SignWarp] Transfer portal %1% created by %2%",
  269. implode(":",$pos), $pl->getName()));
  270. }
  271. }
  272. public function playerTouchIt(PlayerInteractEvent $event){
  273. if($event->getBlock()->getId() != Block::SIGN_POST &&
  274. $event->getBlock()->getId() != Block::WALL_SIGN) return;
  275. $pl = $event->getPlayer();
  276. $sign = $pl->getLevel()->getTile($event->getBlock());
  277. if(!($sign instanceof Sign)) return;
  278. $sign = $sign->getText();
  279. if (!isset($this->text["sign"][$sign[0]])) return;
  280. if(!$pl->hasPermission("signwarp.touch.sign")) {
  281. $pl->sendMessage(mc::_("Nothing happens..."));
  282. return;
  283. }
  284. if ($event->getItem()->getId() == Item::SIGN) {
  285. // Check if the user is holding a sign this stops teleports
  286. $pl->sendMessage(mc::_("Can not teleport while holding sign!"));
  287. return;
  288. }
  289. $pos = $this->checkSign($pl,$sign);
  290. if ($pos === null) return;
  291. if ($pos instanceof Position) {
  292. $this->teleporters[$pl->getName()] = time();
  293. $pl->sendMessage(mc::_("Teleporting..."));
  294. $pl->teleport($pos);
  295. return;
  296. }
  297. // FastTransfer
  298. if(!$pl->hasPermission("signwarp.touch.transfer.sign")) {
  299. $pl->sendMessage(mc::_("Did you expect something to happen?"));
  300. return;
  301. }
  302. $this->teleporters[$pl->getName()] = time();
  303. $ft = $this->getServer()->getPluginManager()->getPlugin("FastTransfer");
  304. if (!$ft) {
  305. $this->getLogger()->error(mc::_("FAST TRANSFER NOT INSTALLED"));
  306. $pl->sendMessage(TextFormat::RED.mc::_("Nothing happens!"));
  307. $pl->sendMessage(TextFormat::RED.mc::_("Somebody removed FastTransfer!"));
  308. return;
  309. }
  310. list($addr,$port) = $pos;
  311. $this->getLogger()->info(mc::_("FastTransfer being used hope it works!"));
  312. $this->getLogger()->info(mc::_("- Player: %1% => %2%:%3%",
  313. $pl->getName(),$addr,$port));
  314. $ft->transferPlayer($pl,$addr,$port);
  315. }
  316. //////////////////////////////////////////////////////////////////////
  317. //
  318. // Timed events
  319. //
  320. //////////////////////////////////////////////////////////////////////
  321. public function updateSigns() {
  322. $wp = $this->getServer()->getPluginManager()->getPlugin("WorldProtect");
  323. foreach ($this->getServer()->getLevels() as $lv) {
  324. foreach ($lv->getTiles() as $tile) {
  325. if (!($tile instanceof Sign)) continue;
  326. $sign = $tile->getText();
  327. if(!in_array($sign[0],$this->text["world"])) continue;
  328. if (!($t = $this->matchCounter($sign[3]))) continue;
  329. if (($lv = $this->getServer()->getLevelByName($sign[1])) !== null) {
  330. $cnt = count($lv->getPlayers());
  331. $max = null;
  332. if ($wp !== null) $max = $wp->getMaxPlayers($lv->getName());
  333. if ($max == null)
  334. $upd = $t. TextFormat::BLUE . $cnt;
  335. else
  336. $upd = $t . ($cnt>=$max ? TextFormat::RED : TextFormat::GREEN).
  337. $cnt . "/" . $max;
  338. } else {
  339. $upd = $t.mc::_("N/A");
  340. }
  341. if ($upd == $sign[3]) continue;
  342. $tile->setText($sign[0],$sign[1],$sign[2],$upd);
  343. }
  344. }
  345. }
  346. }