diff --git a/src/pocketmine/Achievement.php b/src/pocketmine/Achievement.php index d48ec4b0e..f220ec53c 100644 --- a/src/pocketmine/Achievement.php +++ b/src/pocketmine/Achievement.php @@ -107,7 +107,7 @@ abstract class Achievement{ public static function broadcast(Player $player, $achievementId){ if(isset(Achievement::$list[$achievementId])){ - $translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"]]); + $translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]); if(Server::getInstance()->getConfigString("announce-player-achievements", true) === true){ Server::getInstance()->broadcastMessage($translation); }else{ diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 19649093e..69f4ae976 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -1443,7 +1443,7 @@ class Server{ $this->memoryManager = new MemoryManager($this); - $this->logger->info($this->getLanguage()->translateString("pocketmine.server.start", [TextFormat::AQUA . $this->getVersion()])); + $this->logger->info($this->getLanguage()->translateString("pocketmine.server.start", [TextFormat::AQUA . $this->getVersion() . TextFormat::RESET])); if(($poolSize = $this->getProperty("settings.async-workers", "auto")) === "auto"){ $poolSize = ServerScheduler::$WORKERS; diff --git a/src/pocketmine/plugin/PluginDescription.php b/src/pocketmine/plugin/PluginDescription.php index fa7eee210..d725e242c 100644 --- a/src/pocketmine/plugin/PluginDescription.php +++ b/src/pocketmine/plugin/PluginDescription.php @@ -27,6 +27,7 @@ class PluginDescription{ private $name; private $main; private $api; + private $extensions = []; private $depend = []; private $softDepend = []; private $loadBefore = []; @@ -75,6 +76,17 @@ class PluginDescription{ if(isset($plugin["depend"])){ $this->depend = (array) $plugin["depend"]; } + if(isset($plugin["extensions"])){ + $extensions = (array) $plugin["extensions"]; + $isLinear = $extensions === array_values($extensions); + foreach($extensions as $k => $v){ + if($isLinear){ + $k = $v; + $v = "*"; + } + $this->extensions[$k] = is_array($v) ? $v : [$v]; + } + } if(isset($plugin["softdepend"])){ $this->softDepend = (array) $plugin["softdepend"]; } @@ -149,6 +161,50 @@ class PluginDescription{ return $this->commands; } + /** + * @return array + */ + public function getRequiredExtensions(){ + return $this->extensions; + } + + /** + * Checks if the current PHP runtime has the extensions required by the plugin. + * + * @throws PluginException if there are required extensions missing or have incompatible version, or if the version constraint cannot be parsed + */ + public function checkRequiredExtensions(){ + foreach($this->extensions as $name => $versionConstrs){ + if(!extension_loaded($name)){ + throw new PluginException("Required extension $name not loaded"); + } + + if(!is_array($versionConstrs)){ + $versionConstrs = [$versionConstrs]; + } + $gotVersion = phpversion($name); + foreach($versionConstrs as $constr){ // versionConstrs_loop + if($constr === "*"){ + continue; + } + if($constr === ""){ + throw new PluginException("One of the extension version constraints of $name is empty. Consider quoting the version string in plugin.yml"); + } + foreach(["<=", "le", "<>", "!=", "ne", "<", "lt", "==", "=", "eq", ">=", "ge", ">", "gt"] as $comparator){ + // warning: the > character should be quoted in YAML + if(substr($constr, 0, strlen($comparator)) === $comparator){ + $version = substr($constr, strlen($comparator)); + if(!version_compare($gotVersion, $version, $comparator)){ + throw new PluginException("Required extension $name has an incompatible version ($gotVersion not $constr)"); + } + continue 2; // versionConstrs_loop + } + } + throw new PluginException("Error parsing version constraint: $constr"); + } + } + } + /** * @return array */ @@ -218,4 +274,4 @@ class PluginDescription{ public function getWebsite(){ return $this->website; } -} \ No newline at end of file +} diff --git a/src/pocketmine/plugin/PluginManager.php b/src/pocketmine/plugin/PluginManager.php index ec1aaf822..a43620a9b 100644 --- a/src/pocketmine/plugin/PluginManager.php +++ b/src/pocketmine/plugin/PluginManager.php @@ -147,6 +147,13 @@ class PluginManager{ if(preg_match($loader->getPluginFilters(), basename($path)) > 0){ $description = $loader->getPluginDescription($path); if($description instanceof PluginDescription){ + try{ + $description->checkRequiredExtensions(); + }catch(PluginException $ex){ + $this->server->getLogger()->error($ex->getMessage()); + return null; + } + if(($plugin = $loader->loadPlugin($path)) instanceof Plugin){ $this->plugins[$plugin->getDescription()->getName()] = $plugin;