PageRenderTime 44ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/BasicHUD/src/aliuly/hud/Main.php

https://gitlab.com/Skull3x/pocketmine-plugins
PHP | 412 lines | 357 code | 28 blank | 27 comment | 73 complexity | 65c76d17a5741a53ec71bb94cbf03806 MD5 | raw file
  1. <?php
  2. /**
  3. ** CONFIG:main
  4. **/
  5. namespace aliuly\hud;
  6. use pocketmine\plugin\PluginBase;
  7. use pocketmine\utils\TextFormat;
  8. use pocketmine\Player;
  9. use pocketmine\utils\Config;
  10. use pocketmine\scheduler\PluginTask;
  11. use pocketmine\event\Listener;
  12. use pocketmine\event\player\PlayerQuitEvent;
  13. use pocketmine\event\player\PlayerCommandPreprocessEvent;
  14. use pocketmine\event\player\PlayerItemHeldEvent;
  15. use pocketmine\event\server\RemoteServerCommandEvent;
  16. use pocketmine\event\server\ServerCommandEvent;
  17. use pocketmine\permission\Permission;
  18. use pocketmine\item\Item;
  19. use pocketmine\command\CommandExecutor;
  20. use pocketmine\command\CommandSender;
  21. use pocketmine\command\Command;
  22. use aliuly\hud\common\mc;
  23. use aliuly\hud\common\MPMU;
  24. use aliuly\hud\common\ItemName;
  25. interface Formatter {
  26. static public function formatString(Main $plugin,$format,Player $player);
  27. }
  28. abstract class FixedFormat implements Formatter {
  29. static public function formatString(Main $plugin,$format,Player $player) {
  30. return $format;
  31. }
  32. }
  33. abstract class PhpFormat implements Formatter {
  34. static public function formatString(Main $plugin,$format,Player $player) {
  35. ob_start();
  36. eval("?>".$format);
  37. return ob_get_clean();
  38. }
  39. }
  40. abstract class StrtrFormat implements Formatter {
  41. static public function formatString(Main $plugin,$format,Player $player) {
  42. $vars = $plugin->getVars($player);
  43. return strtr($format,$vars);
  44. }
  45. }
  46. class PopupTask extends PluginTask{
  47. public function __construct(Main $plugin){
  48. parent::__construct($plugin);
  49. }
  50. public function getPlugin(){
  51. return $this->owner;
  52. }
  53. public function onRun($currentTick){
  54. $plugin = $this->getPlugin();
  55. if ($plugin->isDisabled()) return;
  56. foreach ($plugin->getServer()->getOnlinePlayers() as $pl) {
  57. if (!$pl->hasPermission("basichud.user")) continue;
  58. $msg = $plugin->getMessage($pl);
  59. if ($msg !== null) $pl->sendPopup($msg);
  60. }
  61. }
  62. }
  63. class Main extends PluginBase implements Listener,CommandExecutor {
  64. protected $_getMessage; // Message function (to disabled)
  65. protected $_getVars; // Customize variables
  66. protected $format; // HUD format
  67. protected $sendPopup; // Message to popup through API
  68. protected $disabled; // HUD disabled by command
  69. protected $perms; // Attachable permissions
  70. protected $consts; // These are constant variables...
  71. protected $perms_cache; // Permissions cache
  72. static public function pickFormatter($format) {
  73. if (strpos($format,"<?php") !== false|| strpos($format,"<?=") !== false) {
  74. return __NAMESPACE__."\\PhpFormat";
  75. }
  76. if (strpos($format,"{") !== false && strpos($format,"}")) {
  77. return __NAMESPACE__."\\StrtrFormat";
  78. }
  79. return __NAMESPACE__."\\FixedFormat";
  80. }
  81. static public function bearing($deg) {
  82. // Determine bearing
  83. if (22.5 <= $deg && $deg < 67.5) {
  84. return "NW";
  85. } elseif (67.5 <= $deg && $deg < 112.5) {
  86. return "N";
  87. } elseif (112.5 <= $deg && $deg < 157.5) {
  88. return "NE";
  89. } elseif (157.5 <= $deg && $deg < 202.5) {
  90. return "E";
  91. } elseif (202.5 <= $deg && $deg < 247.5) {
  92. return "SE";
  93. } elseif (247.5 <= $deg && $deg < 292.5) {
  94. return "S";
  95. } elseif (292.5 <= $deg && $deg < 337.5) {
  96. return "SW";
  97. } else {
  98. return "W";
  99. }
  100. return (int)$deg;
  101. }
  102. /**
  103. * Gets the contents of an embedded resource on the plugin file.
  104. *
  105. * @param string $filename
  106. *
  107. * @return string, or null
  108. */
  109. public function getResourceContents($filename){
  110. $fp = $this->getResource($filename);
  111. if($fp === null){
  112. return null;
  113. }
  114. $contents = stream_get_contents($fp);
  115. fclose($fp);
  116. return $contents;
  117. }
  118. private function changePermission($player,$perm,$bool) {
  119. $n = strtolower($player->getName());
  120. if (!isset($this->perms[$n])) {
  121. $this->perms[$n] = $player->addAttachment($this);
  122. }
  123. $attach = $this->perms[$n];
  124. $attach->setPermission($perm,$bool);
  125. if (isset($this->perms_cache[$n])) unset($this->perms_cache[$n]);
  126. }
  127. public function getMessage($player) {
  128. $fn = $this->_getMessage;
  129. return $fn($this,$player);
  130. }
  131. public function getVars($player) {
  132. $vars = $this->consts;
  133. foreach ([
  134. "{tps}" => $this->getServer()->getTicksPerSecond(),
  135. "{player}" => $player->getName(),
  136. "{world}" => $player->getLevel()->getName(),
  137. "{x}" => (int)$player->getX(),
  138. "{y}" => (int)$player->getY(),
  139. "{z}" => (int)$player->getZ(),
  140. "{yaw}" => (int)$player->getYaw(),
  141. "{pitch}" => (int)$player->getPitch(),
  142. "{bearing}" => self::bearing($player->getYaw()),
  143. ] as $a => $b) {
  144. $vars[$a] = $b;
  145. }
  146. $fn = $this->_getVars;
  147. $fn($this,$vars,$player);
  148. return $vars;
  149. }
  150. public function defaultGetMessage($player) {
  151. $n = strtolower($player->getName());
  152. if (isset($this->sendPopup[$n])) {
  153. // An API user wants to post a Popup...
  154. list($msg,$timer) = $this->sendPopup[$n];
  155. if (microtime(true) < $timer) return $msg;
  156. unset($this->sendPopup[$n]);
  157. }
  158. if (isset($this->disabled[$n])) return null;
  159. // Manage custom groups
  160. if (is_array($this->format[0])) {
  161. if (!isset($this->perms_cache[$n])) {
  162. $i = 0;
  163. foreach ($this->format as $rr) {
  164. list($rank,$fmt,$formatter) = $rr;
  165. if ($player->hasPermission("basichud.rank.".$rank)) {
  166. $this->perms_cache[$n] = $i;
  167. break;
  168. }
  169. ++$i;
  170. }
  171. } else {
  172. list($rank,$fmt,$formatter) = $this->format[$rank = $this->perms_cache[$n]];
  173. }
  174. } else {
  175. list($fmt,$formatter) = $this->format;
  176. }
  177. $txt = $formatter::formatString($this,$fmt,$player);
  178. return $txt;
  179. }
  180. public function onEnable(){
  181. $this->disabled = [];
  182. $this->sendPopup = [];
  183. $this->perms = [];
  184. if (!is_dir($this->getDataFolder())) mkdir($this->getDataFolder());
  185. /* Save default resources */
  186. $this->saveResource("message-example.php",true);
  187. $this->saveResource("vars-example.php",true);
  188. mc::plugin_init($this,$this->getFile());
  189. // These are constants that should be pre calculated
  190. $this->consts = [
  191. "{BasicHUD}" => $this->getDescription()->getFullName(),
  192. "{MOTD}" => $this->getServer()->getMotd(),
  193. "{10SPACE}" => str_repeat(" ",10),
  194. "{20SPACE}" => str_repeat(" ",20),
  195. "{30SPACE}" => str_repeat(" ",30),
  196. "{40SPACE}" => str_repeat(" ",40),
  197. "{50SPACE}" => str_repeat(" ",50),
  198. "{NL}" => "\n",
  199. "{BLACK}" => TextFormat::BLACK,
  200. "{DARK_BLUE}" => TextFormat::DARK_BLUE,
  201. "{DARK_GREEN}" => TextFormat::DARK_GREEN,
  202. "{DARK_AQUA}" => TextFormat::DARK_AQUA,
  203. "{DARK_RED}" => TextFormat::DARK_RED,
  204. "{DARK_PURPLE}" => TextFormat::DARK_PURPLE,
  205. "{GOLD}" => TextFormat::GOLD,
  206. "{GRAY}" => TextFormat::GRAY,
  207. "{DARK_GRAY}" => TextFormat::DARK_GRAY,
  208. "{BLUE}" => TextFormat::BLUE,
  209. "{GREEN}" => TextFormat::GREEN,
  210. "{AQUA}" => TextFormat::AQUA,
  211. "{RED}" => TextFormat::RED,
  212. "{LIGHT_PURPLE}" => TextFormat::LIGHT_PURPLE,
  213. "{YELLOW}" => TextFormat::YELLOW,
  214. "{WHITE}" => TextFormat::WHITE,
  215. "{OBFUSCATED}" => TextFormat::OBFUSCATED,
  216. "{BOLD}" => TextFormat::BOLD,
  217. "{STRIKETHROUGH}" => TextFormat::STRIKETHROUGH,
  218. "{UNDERLINE}" => TextFormat::UNDERLINE,
  219. "{ITALIC}" => TextFormat::ITALIC,
  220. "{RESET}" => TextFormat::RESET,
  221. ];
  222. $defaults = [
  223. "version" => $this->getDescription()->getVersion(),
  224. "# ticks" => "How often to refresh the popup",
  225. "ticks" => 10,
  226. "# format" => "Display format",
  227. "format" => "{GREEN}{BasicHUD} {WHITE}{world} ({x},{y},{z}) {bearing}",
  228. ];
  229. $cf = (new Config($this->getDataFolder()."config.yml",
  230. Config::YAML,$defaults))->getAll();
  231. if (is_array($cf["format"])) {
  232. // Multiple format specified...
  233. // save them and also register the appropriate permissions
  234. $this->format = [];
  235. foreach ($cf["format"] as $rank=>$fmt) {
  236. $this->format[] = [ $rank, $fmt, self::pickFormatter($fmt) ];
  237. $p = new Permission("basichud.rank.".$rank,
  238. "BasicHUD format ".$rank, false);
  239. $this->getServer()->getPluginManager()->addPermission($p);
  240. }
  241. } else {
  242. // Single format only
  243. $this->format = [ $cf["format"], self::pickFormatter($cf["format"]) ];
  244. }
  245. $this->_getMessage = null;
  246. $code = '$this->_getMessage = function($plugin,$player){ ';
  247. if (file_exists($this->getDataFolder()."message.php")) {
  248. $code .= file_get_contents($this->getDataFolder()."message.php");
  249. } else {
  250. $code .= $this->getResourceContents("message-example.php");
  251. }
  252. $code .= '};';
  253. if (eval($code) === false) {
  254. $err = error_get_last();
  255. $this->getLogger()->error(mc::_("PHP error in message.php, %1%: %2%",$err["line"], $err["message"]));
  256. }
  257. $this->_getVars = null;
  258. if (file_exists($this->getDataFolder()."vars.php")) {
  259. $code = '$this->_getVars = function($plugin,&$vars,$player){ '.
  260. file_get_contents($this->getDataFolder()."vars.php").
  261. '};'."\n";
  262. //echo $code."\n";//##DEBUG
  263. if (eval($code) === false) {
  264. $err = error_get_last();
  265. $this->getLogger()->error(mc::_("PHP error in vars.php, %1%: %2%",$err["line"], $err["message"]));
  266. }
  267. } else {
  268. // Empty function (this means we do not need to test _getVars)
  269. $this->_getVars = function(){};
  270. }
  271. if ($this->_getVars == null || $this->_getMessage == null) {
  272. if ($this->_getVars == null) $this->getLogger()->error(TextFormat::RED.mc::_("Error in vars.php"));
  273. if ($this->_getMessage == null) $this->getLogger()->error(TextFormat::RED.mc::_("Error in message.php"));
  274. throw new \RunTimeException("Error loading custom code!");
  275. return;
  276. }
  277. $this->getServer()->getScheduler()->scheduleRepeatingTask(new PopupTask($this), $cf["ticks"]);
  278. $this->getServer()->getPluginManager()->registerEvents($this, $this);
  279. }
  280. // We clear the permissions cache in the event of a command
  281. // next time we schedule to fetch the HUD message it will be recomputed
  282. private function onCmdEvent() {
  283. $this->perms_cache = [];
  284. }
  285. public function onPlayerCmd(PlayerCommandPreprocessEvent $ev) {
  286. $this->onCmdEvent();
  287. }
  288. public function onRconCmd(RemoteServerCommandEvent $ev) {
  289. $this->onCmdEvent();
  290. }
  291. public function onConsoleCmd(ServerCommandEvent $ev) {
  292. $this->onCmdEvent();
  293. }
  294. public function onQuit(PlayerQuitEvent $ev) {
  295. $n = strtolower($ev->getPlayer()->getName());
  296. if (isset($this->perms_cache[$n])) unset($this->perms_cache[$n]);
  297. if (isset($this->sendPopup[$n])) unset($this->sendPopup[$n]);
  298. if (isset($this->disabled[$n])) unset($this->disabled[$n]);
  299. if (isset($this->perms[$n])) {
  300. $attach = $this->perms[$n];
  301. unset($this->perms[$n]);
  302. $ev->getPlayer()->removeAttachment($attach);
  303. }
  304. }
  305. public function onItemHeld(PlayerItemHeldEvent $ev){
  306. if ($ev->getItem()->getId() == Item::AIR) return;
  307. $this->sendPopup($ev->getPlayer(),ItemName::str($ev->getItem()),2);
  308. }
  309. public function onCommand(CommandSender $sender, Command $cmd, $label, array $args) {
  310. if ($cmd->getName() != "hud") return false;
  311. if (!MPMU::inGame($sender)) return true;
  312. $n = strtolower($sender->getName());
  313. if (count($args) == 0) {
  314. if (isset($this->disabled[$n])) {
  315. $sender->sendMessage(mc::_("HUD is OFF"));
  316. return true;
  317. }
  318. if (is_array($this->format[0])) {
  319. foreach ($this->format as $rr) {
  320. list($rank,,) = $rr;
  321. if ($sender->hasPermission("basichud.rank.".$rank)) break;
  322. }
  323. $sender->sendMessage(mc::_("HUD using format %1%",$rank));
  324. $fl = [];
  325. foreach ($this->format as $rr) {
  326. list($rank,,) = $rr;
  327. $fl[] = $rank;
  328. }
  329. if ($sender->hasPermission("basichud.cmd.switch")) {
  330. $sender->sendMessage(mc::_("Available formats: %1%",
  331. implode(", ",$fl)));
  332. }
  333. return true;
  334. }
  335. $sender->sendMessage(mc::_("HUD is ON"));
  336. return true;
  337. }
  338. if (count($args) != 1) return false;
  339. $mode = strtolower(array_shift($args));
  340. if (is_array($this->format[0])) {
  341. // Check if the input matches any of the ranks...
  342. foreach ($this->format as $rr1) {
  343. list($rank,,) = $rr1;
  344. if (strtolower($rank) == $mode) {
  345. // OK, user wants to switch to this format...
  346. if (!MPMU::access($sender,"basichud.cmd.switch")) return true;
  347. foreach ($this->format as $rr2) {
  348. list($rn,,) = $rr2;
  349. if ($rank == $rn) {
  350. $this->changePermission($sender,"basichud.rank.".$rn,true);
  351. } else {
  352. $this->changePermission($sender,"basichud.rank.".$rn,false);
  353. }
  354. }
  355. $sender->sendMessage(mc::_("Switching to format %1%",$rank));
  356. return true;
  357. }
  358. }
  359. }
  360. if (!MPMU::access($sender,"basichud.cmd.toggle")) return true;
  361. $mode = filter_var($mode,FILTER_VALIDATE_BOOLEAN);
  362. if ($mode) {
  363. if (isset($this->disabled[$n])) unset($this->disabled[$n]);
  364. $sender->sendMessage(mc::_("Turning on HUD"));
  365. return true;
  366. }
  367. $this->disabled[$n] = $n;
  368. $sender->sendMessage(mc::_("Turning off HUD"));
  369. return true;
  370. }
  371. /**
  372. * @API
  373. */
  374. public function sendPopup($player,$msg,$length=3) {
  375. if ($this->isEnabled()) {
  376. if ($player->hasPermission("basichud.user")) {
  377. $n = strtolower($player->getName());
  378. $this->sendPopup[$n] = [ $msg, microtime(true)+$length ];
  379. $msg = $this->getMessage($player);
  380. }
  381. }
  382. if ($msg !== null) $player->sendPopup($msg);
  383. }
  384. }