public function __construct(Server $server, $type, $playerList = []) { $endpoint = "http://" . $server->getProperty("anonymous-statistics.host", "stats.pocketmine.net") . "/"; $data = []; $data["uniqueServerId"] = $server->getServerUniqueId()->toString(); $data["uniqueMachineId"] = Utils::getMachineUniqueId()->toString(); $data["uniqueRequestId"] = UUID::fromData($server->getServerUniqueId(), microtime(true))->toString(); switch ($type) { case self::TYPE_OPEN: $data["event"] = "open"; $version = new VersionString(); $data["server"] = ["port" => $server->getPort(), "software" => $server->getName(), "fullVersion" => $version->get(true), "version" => $version->get(), "build" => $version->getBuild(), "api" => $server->getApiVersion(), "minecraftVersion" => $server->getVersion(), "protocol" => Info::CURRENT_PROTOCOL]; $data["system"] = ["operatingSystem" => Utils::getOS(), "cores" => Utils::getCoreCount(), "phpVersion" => PHP_VERSION, "machine" => php_uname("a"), "release" => php_uname("r"), "platform" => php_uname("i")]; $data["players"] = ["count" => 0, "limit" => $server->getMaxPlayers()]; $plugins = []; foreach ($server->getPluginManager()->getPlugins() as $p) { $d = $p->getDescription(); $plugins[$d->getName()] = ["name" => $d->getName(), "version" => $d->getVersion(), "enabled" => $p->isEnabled()]; } $data["plugins"] = $plugins; break; case self::TYPE_STATUS: $data["event"] = "status"; $data["server"] = ["ticksPerSecond" => $server->getTicksPerSecondAverage(), "tickUsage" => $server->getTickUsageAverage(), "ticks" => $server->getTick()]; //This anonymizes the user ids so they cannot be reversed to the original foreach ($playerList as $k => $v) { $playerList[$k] = md5($v); } $players = []; foreach ($server->getOnlinePlayers() as $p) { if ($p->isOnline()) { $players[] = md5($p->getUniqueId()->toBinary()); } } $data["players"] = ["count" => count($players), "limit" => $server->getMaxPlayers(), "currentList" => $players, "historyList" => array_values($playerList)]; $info = Utils::getMemoryUsage(true); $data["system"] = ["mainMemory" => $info[0], "totalMemory" => $info[1], "availableMemory" => $info[2], "threadCount" => Utils::getThreadCount()]; break; case self::TYPE_CLOSE: $data["event"] = "close"; $data["crashing"] = $server->isRunning(); break; } $this->endpoint = $endpoint . "api/post"; $this->data = json_encode($data); }
/** * @param string $directory * @param array $newLoaders * * @return Plugin[] */ public function loadPlugins($directory, $newLoaders = null) { if (is_dir($directory)) { $plugins = []; $loadedPlugins = []; $dependencies = []; $softDependencies = []; if (is_array($newLoaders)) { $loaders = []; foreach ($newLoaders as $key) { if (isset($this->fileAssociations[$key])) { $loaders[$key] = $this->fileAssociations[$key]; } } } else { $loaders = $this->fileAssociations; } foreach ($loaders as $loader) { foreach (new \RegexIterator(new \DirectoryIterator($directory), $loader->getPluginFilters()) as $file) { if ($file === "." or $file === "..") { continue; } $file = $directory . $file; try { $description = $loader->getPluginDescription($file); if ($description instanceof PluginDescription) { $name = $description->getName(); if (stripos($name, "pocketmine") !== false or stripos($name, "minecraft") !== false or stripos($name, "mojang") !== false) { $this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.restrictedName"])); continue; } elseif (strpos($name, " ") !== false) { $this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.plugin.spacesDiscouraged", [$name])); } if (isset($plugins[$name]) or $this->getPlugin($name) instanceof Plugin) { $this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.duplicateError", [$name])); continue; } $compatible = false; //Check multiple dependencies foreach ($description->getCompatibleApis() as $version) { //Format: majorVersion.minorVersion.patch $version = array_map("intval", explode(".", $version)); $apiVersion = array_map("intval", explode(".", $this->server->getApiVersion())); //Completely different API version if ($version[0] !== $apiVersion[0]) { continue; } //If the plugin requires new API features, being backwards compatible if ($version[1] > $apiVersion[1]) { continue; } $compatible = true; break; } if ($compatible === false) { $this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.incompatibleAPI"])); continue; } $plugins[$name] = $file; $softDependencies[$name] = (array) $description->getSoftDepend(); $dependencies[$name] = (array) $description->getDepend(); foreach ($description->getLoadBefore() as $before) { if (isset($softDependencies[$before])) { $softDependencies[$before][] = $name; } else { $softDependencies[$before] = [$name]; } } } } catch (\Exception $e) { $this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.fileError", [$file, $directory, $e->getMessage()])); $logger = $this->server->getLogger(); if ($logger instanceof MainLogger) { $logger->logException($e); } } } } while (count($plugins) > 0) { $missingDependency = true; foreach ($plugins as $name => $file) { if (isset($dependencies[$name])) { foreach ($dependencies[$name] as $key => $dependency) { if (isset($loadedPlugins[$dependency]) or $this->getPlugin($dependency) instanceof Plugin) { unset($dependencies[$name][$key]); } elseif (!isset($plugins[$dependency])) { $this->server->getLogger()->critical($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.unknownDependency"])); break; } } if (count($dependencies[$name]) === 0) { unset($dependencies[$name]); } } if (isset($softDependencies[$name])) { foreach ($softDependencies[$name] as $key => $dependency) { if (isset($loadedPlugins[$dependency]) or $this->getPlugin($dependency) instanceof Plugin) { unset($softDependencies[$name][$key]); } } if (count($softDependencies[$name]) === 0) { unset($softDependencies[$name]); } } if (!isset($dependencies[$name]) and !isset($softDependencies[$name])) { unset($plugins[$name]); $missingDependency = false; if ($plugin = $this->loadPlugin($file, $loaders) and $plugin instanceof Plugin) { $loadedPlugins[$name] = $plugin; } else { $this->server->getLogger()->critical($this->server->getLanguage()->translateString("pocketmine.plugin.genericLoadError", [$name])); } } } if ($missingDependency === true) { foreach ($plugins as $name => $file) { if (!isset($dependencies[$name])) { unset($softDependencies[$name]); unset($plugins[$name]); $missingDependency = false; if ($plugin = $this->loadPlugin($file, $loaders) and $plugin instanceof Plugin) { $loadedPlugins[$name] = $plugin; } else { $this->server->getLogger()->critical($this->server->getLanguage()->translateString("pocketmine.plugin.genericLoadError", [$name])); } } } //No plugins loaded :( if ($missingDependency === true) { foreach ($plugins as $name => $file) { $this->server->getLogger()->critical($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.circularDependency"])); } $plugins = []; } } } TimingsCommand::$timingStart = microtime(true); return $loadedPlugins; } else { TimingsCommand::$timingStart = microtime(true); return []; } }
/** * @param CommandSender $sender * @param Server $server */ public function sendServerInfo(CommandSender $sender, Server $server) { $sender->sendMessage("Name: " . $server->getServerName()); $sender->sendMessage("Motd: " . $server->getMotd()); $sender->sendMessage("Network-motd: " . $server->getNetwork()->getMotd()); $sender->sendMessage("Address: " . $server->getIp() . ":" . $server->getPort()); $sender->sendMessage("Players: " . count($server->getOnlinePlayers()) . "/" . $server->getMaxPlayers()); $sender->sendMessage("Difficulty: " . $server->getDifficulty()); $sender->sendMessage("Default-gamemode: " . $server->getDefaultGamemode()); $sender->sendMessage("Unique-id: " . $server->getServerUniqueId()); $sender->sendMessage("TPS: " . $server->getTicksPerSecond()); $sender->sendMessage("Average-TPS: " . $server->getTicksPerSecondAverage()); $sender->sendMessage("Codename: " . $server->getCodename()); $sender->sendMessage("API-version: " . $server->getApiVersion()); $sender->sendMessage("MCPE-version: " . $server->getVersion()); $sender->sendMessage("Is-hardcore: " . ($server->isHardcore() ? TextFormat::GREEN . "yes" : TextFormat::RED . "no")); $sender->sendMessage("Is-running: " . ($server->isRunning() ? TextFormat::GREEN . "yes" : TextFormat::RED . "no")); $sender->sendMessage("Is-whitelisted: " . ($server->hasWhitelist() ? TextFormat::GREEN . "yes" : TextFormat::RED . "no")); }
/** * @param string $directory * @param array $newLoaders * * @return Plugin[] */ public function loadPlugins($directory, $newLoaders = null) { if (is_dir($directory)) { $plugins = []; $loadedPlugins = []; $dependencies = []; $softDependencies = []; if (is_array($newLoaders)) { $loaders = []; foreach ($newLoaders as $key) { if (isset($this->fileAssociations[$key])) { $loaders[$key] = $this->fileAssociations[$key]; } } } else { $loaders = $this->fileAssociations; } foreach ($loaders as $loader) { foreach (new \RegexIterator(new \DirectoryIterator($directory), $loader->getPluginFilters()) as $file) { if ($file === "." or $file === "..") { continue; } $file = $directory . $file; try { $description = $loader->getPluginDescription($file); if ($description instanceof PluginDescription) { $name = $description->getName(); if (stripos($name, "pocketmine") !== false or stripos($name, "minecraft") !== false or stripos($name, "mojang") !== false) { $this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.restrictedName"])); continue; } elseif (strpos($name, " ") !== false) { $this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.plugin.spacesDiscouraged", [$name])); } if (isset($plugins[$name]) or $this->getPlugin($name) instanceof Plugin) { $this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.duplicateError", [$name])); continue; } //1=outdated plugin, 2=outdated server, 4=minor, 8=normal $compatibility = 0; //Check multiple dependencies foreach ($description->getCompatibleApis() as $versionString) { //Format: majorVersion.minorVersion.patch $version = array_map("intval", explode(".", $versionString)); $apiVersion = array_map("intval", explode(".", $this->server->getApiVersion())); //Completely different API version: too old if ($version[0] < $apiVersion[0]) { $compatibility |= 1; continue; } //Completely different API version: too new if ($version[0] > $apiVersion[0]) { $compatibility |= 2; continue; } //If the plugin requires new API features, being backwards compatible if ($version[1] > $apiVersion[1]) { $compatibility |= 4; continue; } $compatibility |= 8; break; } if (($compatibility & 8) === 0) { $accept1 = $this->server->getProperty("settings.incompatible-plugins.plugin-too-old", false); $accept2 = $this->server->getProperty("settings.incompatible-plugins.plugin-too-new.major", false); $accept4 = $this->server->getProperty("settings.incompatible-plugins.plugin-too-new.minor", false); if (!$accept1) { $compatibility &= ~1; } if (!$accept2) { $compatibility &= ~2; } if (!$accept4) { $compatibility &= ~4; } if ($compatibility === 0) { if (($compatibility & 4) === 0) { $this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.incompatibleAPI.minorTooNew"])); } elseif (($compatibility & 2) === 0) { $this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.incompatibleAPI.majortooNew"])); } else { $this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.incompatibleAPI.majorTooOld"])); } continue; #Abort loading of this plugin, move on to the next } elseif ($compatibility & 4) { $this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.plugin.incompatibleAPIWarning.minorTooNew", [$name])); } elseif ($compatibility & 2) { $this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.plugin.incompatibleAPIWarning.majorTooNew", [$name])); } elseif ($compatibility & 1) { $this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.plugin.incompatibleAPIWarning.majorTooOld", [$name])); } } $plugins[$name] = $file; $softDependencies[$name] = (array) $description->getSoftDepend(); $dependencies[$name] = (array) $description->getDepend(); foreach ($description->getLoadBefore() as $before) { if (isset($softDependencies[$before])) { $softDependencies[$before][] = $name; } else { $softDependencies[$before] = [$name]; } } } } catch (Throwable $e) { $this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.fileError", [$file, $directory, $e->getMessage()])); $this->server->getLogger()->logException($e); } } } while (count($plugins) > 0) { $missingDependency = true; foreach ($plugins as $name => $file) { if (isset($dependencies[$name])) { foreach ($dependencies[$name] as $key => $dependency) { if (isset($loadedPlugins[$dependency]) or $this->getPlugin($dependency) instanceof Plugin) { unset($dependencies[$name][$key]); } elseif (!isset($plugins[$dependency])) { $this->server->getLogger()->critical($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.unknownDependency"])); break; } } if (count($dependencies[$name]) === 0) { unset($dependencies[$name]); } } if (isset($softDependencies[$name])) { foreach ($softDependencies[$name] as $key => $dependency) { if (isset($loadedPlugins[$dependency]) or $this->getPlugin($dependency) instanceof Plugin) { unset($softDependencies[$name][$key]); } } if (count($softDependencies[$name]) === 0) { unset($softDependencies[$name]); } } if (!isset($dependencies[$name]) and !isset($softDependencies[$name])) { unset($plugins[$name]); $missingDependency = false; if ($plugin = $this->loadPlugin($file, $loaders) and $plugin instanceof Plugin) { $loadedPlugins[$name] = $plugin; } else { $this->server->getLogger()->critical($this->server->getLanguage()->translateString("pocketmine.plugin.genericLoadError", [$name])); } } } if ($missingDependency === true) { foreach ($plugins as $name => $file) { if (!isset($dependencies[$name])) { unset($softDependencies[$name]); unset($plugins[$name]); $missingDependency = false; if ($plugin = $this->loadPlugin($file, $loaders) and $plugin instanceof Plugin) { $loadedPlugins[$name] = $plugin; } else { $this->server->getLogger()->critical($this->server->getLanguage()->translateString("pocketmine.plugin.genericLoadError", [$name])); } } } //No plugins loaded :( if ($missingDependency === true) { foreach ($plugins as $name => $file) { $this->server->getLogger()->critical($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.circularDependency"])); } $plugins = []; } } } TimingsCommand::$timingStart = microtime(true); return $loadedPlugins; } else { TimingsCommand::$timingStart = microtime(true); return []; } }
/** * @param string $directory * @param array $newLoaders * * @return Plugin[] */ public function loadPlugins($directory, $newLoaders = \null) { if (\is_dir($directory)) { $plugins = []; $loadedPlugins = []; $dependencies = []; $softDependencies = []; if (\is_array($newLoaders)) { $loaders = []; foreach ($newLoaders as $key) { if (isset($this->fileAssociations[$key])) { $loaders[$key] = $this->fileAssociations[$key]; } } } else { $loaders = $this->fileAssociations; } foreach ($loaders as $loader) { foreach (new \RegexIterator(new \DirectoryIterator($directory), $loader->getPluginFilters()) as $file) { if ($file === "." or $file === "..") { continue; } $file = $directory . $file; try { $description = $loader->getPluginDescription($file); if ($description instanceof PluginDescription) { $name = $description->getName(); if (\stripos($name, "pocketmine") !== \false or \stripos($name, "minecraft") !== \false or \stripos($name, "mojang") !== \false) { $this->server->getLogger()->error("Could not load plugin '" . $name . "': restricted name"); continue; } elseif (\strpos($name, " ") !== \false) { $this->server->getLogger()->warning("Plugin '" . $name . "' uses spaces in its name, this is discouraged"); } if (isset($plugins[$name]) or $this->getPlugin($name) instanceof Plugin) { $this->server->getLogger()->error("Could not load duplicate plugin '" . $name . "': plugin exists"); continue; } $compatible = \false; //Check multiple dependencies foreach ($description->getCompatibleApis() as $version) { //Format: majorVersion.minorVersion.patch $version = \array_map("intval", \explode(".", $version)); $apiVersion = \array_map("intval", \explode(".", $this->server->getApiVersion())); //Completely different API version if ($version[0] !== $apiVersion[0]) { continue; } //If the plugin requires new API features, being backwards compatible if ($version[1] > $apiVersion[1]) { continue; } $compatible = \true; break; } if ($compatible === \false) { $this->server->getLogger()->error("Could not load plugin '" . $name . "': API version not compatible"); continue; } $plugins[$name] = $file; $softDependencies[$name] = (array) $description->getSoftDepend(); $dependencies[$name] = (array) $description->getDepend(); foreach ($description->getLoadBefore() as $before) { if (isset($softDependencies[$before])) { $softDependencies[$before][] = $name; } else { $softDependencies[$before] = [$name]; } } } } catch (\Exception $e) { $this->server->getLogger()->error("Could not load '" . $file . "' in folder '" . $directory . "': " . $e->getMessage()); $logger = $this->server->getLogger(); if ($logger instanceof MainLogger) { $logger->logException($e); } } } } while (\count($plugins) > 0) { $missingDependency = \true; foreach ($plugins as $name => $file) { if (isset($dependencies[$name])) { foreach ($dependencies[$name] as $key => $dependency) { if (isset($loadedPlugins[$dependency]) or $this->getPlugin($dependency) instanceof Plugin) { unset($dependencies[$name][$key]); } elseif (!isset($plugins[$dependency])) { $this->server->getLogger()->critical("Could not load plugin '" . $name . "': Unknown dependency"); break; } } if (\count($dependencies[$name]) === 0) { unset($dependencies[$name]); } } if (isset($softDependencies[$name])) { foreach ($softDependencies[$name] as $key => $dependency) { if (isset($loadedPlugins[$dependency]) or $this->getPlugin($dependency) instanceof Plugin) { unset($softDependencies[$name][$key]); } } if (\count($softDependencies[$name]) === 0) { unset($softDependencies[$name]); } } if (!isset($dependencies[$name]) and !isset($softDependencies[$name])) { unset($plugins[$name]); $missingDependency = \false; if ($plugin = $this->loadPlugin($file, $loaders) and $plugin instanceof Plugin) { $loadedPlugins[$name] = $plugin; } else { $this->server->getLogger()->critical("Could not load plugin '" . $name . "'"); } } } if ($missingDependency === \true) { foreach ($plugins as $name => $file) { if (!isset($dependencies[$name])) { unset($softDependencies[$name]); unset($plugins[$name]); $missingDependency = \false; if ($plugin = $this->loadPlugin($file, $loaders) and $plugin instanceof Plugin) { $loadedPlugins[$name] = $plugin; } else { $this->server->getLogger()->critical("Could not load plugin '" . $name . "'"); } } } //No plugins loaded :( if ($missingDependency === \true) { foreach ($plugins as $name => $file) { $this->server->getLogger()->critical("Could not load plugin '" . $name . "': circular dependency detected"); } $plugins = []; } } } TimingsCommand::$timingStart = \microtime(\true); return $loadedPlugins; } else { TimingsCommand::$timingStart = \microtime(\true); return []; } }