mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-21 00:07:30 +00:00
Extract ServerConfigGroup from Server
this API isn't very nice, but it's pretty much the same as the original, and at least this can be _kinda_ unit-tested...
This commit is contained in:
parent
b05fab3e3c
commit
fe649d8d70
@ -183,7 +183,7 @@ class CrashDump{
|
||||
private function extraData() : void{
|
||||
global $argv;
|
||||
|
||||
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
||||
if($this->server->getConfigGroup()->getProperty("auto-report.send-settings", true) !== false){
|
||||
$this->data["parameters"] = (array) $argv;
|
||||
$this->data["server.properties"] = @file_get_contents($this->server->getDataPath() . "server.properties");
|
||||
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $this->data["server.properties"]);
|
||||
@ -199,7 +199,7 @@ class CrashDump{
|
||||
}
|
||||
$this->data["extensions"] = $extensions;
|
||||
|
||||
if($this->server->getProperty("auto-report.send-phpinfo", true) !== false){
|
||||
if($this->server->getConfigGroup()->getProperty("auto-report.send-phpinfo", true) !== false){
|
||||
ob_start();
|
||||
phpinfo();
|
||||
$this->data["phpinfo"] = ob_get_contents();
|
||||
@ -261,7 +261,7 @@ class CrashDump{
|
||||
$this->addLine("Code:");
|
||||
$this->data["code"] = [];
|
||||
|
||||
if($this->server->getProperty("auto-report.send-code", true) !== false and file_exists($error["fullFile"])){
|
||||
if($this->server->getConfigGroup()->getProperty("auto-report.send-code", true) !== false and file_exists($error["fullFile"])){
|
||||
$file = @file($error["fullFile"], FILE_IGNORE_NEW_LINES);
|
||||
if($file !== false){
|
||||
for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10 and isset($file[$l]); ++$l){
|
||||
|
@ -118,15 +118,15 @@ class MemoryManager{
|
||||
$this->server = $server;
|
||||
$this->logger = new \PrefixedLogger($server->getLogger(), "Memory Manager");
|
||||
|
||||
$this->init();
|
||||
$this->init($server->getConfigGroup());
|
||||
}
|
||||
|
||||
private function init() : void{
|
||||
$this->memoryLimit = ((int) $this->server->getProperty("memory.main-limit", 0)) * 1024 * 1024;
|
||||
private function init(ServerConfigGroup $config) : void{
|
||||
$this->memoryLimit = ((int) $config->getProperty("memory.main-limit", 0)) * 1024 * 1024;
|
||||
|
||||
$defaultMemory = 1024;
|
||||
|
||||
if(preg_match("/([0-9]+)([KMGkmg])/", $this->server->getConfigString("memory-limit", ""), $matches) > 0){
|
||||
if(preg_match("/([0-9]+)([KMGkmg])/", $config->getConfigString("memory-limit", ""), $matches) > 0){
|
||||
$m = (int) $matches[1];
|
||||
if($m <= 0){
|
||||
$defaultMemory = 0;
|
||||
@ -148,7 +148,7 @@ class MemoryManager{
|
||||
}
|
||||
}
|
||||
|
||||
$hardLimit = ((int) $this->server->getProperty("memory.main-hard-limit", $defaultMemory));
|
||||
$hardLimit = ((int) $config->getProperty("memory.main-hard-limit", $defaultMemory));
|
||||
|
||||
if($hardLimit <= 0){
|
||||
ini_set("memory_limit", '-1');
|
||||
@ -156,22 +156,22 @@ class MemoryManager{
|
||||
ini_set("memory_limit", $hardLimit . "M");
|
||||
}
|
||||
|
||||
$this->globalMemoryLimit = ((int) $this->server->getProperty("memory.global-limit", 0)) * 1024 * 1024;
|
||||
$this->checkRate = (int) $this->server->getProperty("memory.check-rate", 20);
|
||||
$this->continuousTrigger = (bool) $this->server->getProperty("memory.continuous-trigger", true);
|
||||
$this->continuousTriggerRate = (int) $this->server->getProperty("memory.continuous-trigger-rate", 30);
|
||||
$this->globalMemoryLimit = ((int) $config->getProperty("memory.global-limit", 0)) * 1024 * 1024;
|
||||
$this->checkRate = (int) $config->getProperty("memory.check-rate", 20);
|
||||
$this->continuousTrigger = (bool) $config->getProperty("memory.continuous-trigger", true);
|
||||
$this->continuousTriggerRate = (int) $config->getProperty("memory.continuous-trigger-rate", 30);
|
||||
|
||||
$this->garbageCollectionPeriod = (int) $this->server->getProperty("memory.garbage-collection.period", 36000);
|
||||
$this->garbageCollectionTrigger = (bool) $this->server->getProperty("memory.garbage-collection.low-memory-trigger", true);
|
||||
$this->garbageCollectionAsync = (bool) $this->server->getProperty("memory.garbage-collection.collect-async-worker", true);
|
||||
$this->garbageCollectionPeriod = (int) $config->getProperty("memory.garbage-collection.period", 36000);
|
||||
$this->garbageCollectionTrigger = (bool) $config->getProperty("memory.garbage-collection.low-memory-trigger", true);
|
||||
$this->garbageCollectionAsync = (bool) $config->getProperty("memory.garbage-collection.collect-async-worker", true);
|
||||
|
||||
$this->lowMemChunkRadiusOverride = (int) $this->server->getProperty("memory.max-chunks.chunk-radius", 4);
|
||||
$this->lowMemChunkGC = (bool) $this->server->getProperty("memory.max-chunks.trigger-chunk-collect", true);
|
||||
$this->lowMemChunkRadiusOverride = (int) $config->getProperty("memory.max-chunks.chunk-radius", 4);
|
||||
$this->lowMemChunkGC = (bool) $config->getProperty("memory.max-chunks.trigger-chunk-collect", true);
|
||||
|
||||
$this->lowMemDisableChunkCache = (bool) $this->server->getProperty("memory.world-caches.disable-chunk-cache", true);
|
||||
$this->lowMemClearWorldCache = (bool) $this->server->getProperty("memory.world-caches.low-memory-trigger", true);
|
||||
$this->lowMemDisableChunkCache = (bool) $config->getProperty("memory.world-caches.disable-chunk-cache", true);
|
||||
$this->lowMemClearWorldCache = (bool) $config->getProperty("memory.world-caches.low-memory-trigger", true);
|
||||
|
||||
$this->dumpWorkers = (bool) $this->server->getProperty("memory.memory-dump.dump-async-worker", true);
|
||||
$this->dumpWorkers = (bool) $config->getProperty("memory.memory-dump.dump-async-worker", true);
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
|
231
src/Server.php
231
src/Server.php
@ -99,7 +99,6 @@ use pocketmine\world\generator\GeneratorManager;
|
||||
use pocketmine\world\generator\normal\Normal;
|
||||
use pocketmine\world\World;
|
||||
use pocketmine\world\WorldManager;
|
||||
use function array_key_exists;
|
||||
use function array_shift;
|
||||
use function array_sum;
|
||||
use function base64_encode;
|
||||
@ -114,12 +113,10 @@ use function file_put_contents;
|
||||
use function filemtime;
|
||||
use function get_class;
|
||||
use function getmypid;
|
||||
use function getopt;
|
||||
use function implode;
|
||||
use function ini_set;
|
||||
use function is_a;
|
||||
use function is_array;
|
||||
use function is_bool;
|
||||
use function is_string;
|
||||
use function json_decode;
|
||||
use function max;
|
||||
@ -275,13 +272,8 @@ class Server{
|
||||
/** @var QueryInfo */
|
||||
private $queryInfo;
|
||||
|
||||
/** @var Config */
|
||||
private $properties;
|
||||
/** @var mixed[] */
|
||||
private $propertyCache = [];
|
||||
|
||||
/** @var Config */
|
||||
private $config;
|
||||
/** @var ServerConfigGroup */
|
||||
private $configGroup;
|
||||
|
||||
/** @var Player[] */
|
||||
private $playerList = [];
|
||||
@ -342,11 +334,11 @@ class Server{
|
||||
}
|
||||
|
||||
public function getPort() : int{
|
||||
return $this->getConfigInt("server-port", 19132);
|
||||
return $this->configGroup->getConfigInt("server-port", 19132);
|
||||
}
|
||||
|
||||
public function getViewDistance() : int{
|
||||
return max(2, $this->getConfigInt("view-distance", 8));
|
||||
return max(2, $this->configGroup->getConfigInt("view-distance", 8));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -357,7 +349,7 @@ class Server{
|
||||
}
|
||||
|
||||
public function getIp() : string{
|
||||
$str = $this->getConfigString("server-ip");
|
||||
$str = $this->configGroup->getConfigString("server-ip");
|
||||
return $str !== "" ? $str : "0.0.0.0";
|
||||
}
|
||||
|
||||
@ -369,30 +361,30 @@ class Server{
|
||||
}
|
||||
|
||||
public function getGamemode() : GameMode{
|
||||
return GameMode::fromMagicNumber($this->getConfigInt("gamemode", 0) & 0b11);
|
||||
return GameMode::fromMagicNumber($this->configGroup->getConfigInt("gamemode", 0) & 0b11);
|
||||
}
|
||||
|
||||
public function getForceGamemode() : bool{
|
||||
return $this->getConfigBool("force-gamemode", false);
|
||||
return $this->configGroup->getConfigBool("force-gamemode", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Server global difficulty. Note that this may be overridden in individual worlds.
|
||||
*/
|
||||
public function getDifficulty() : int{
|
||||
return $this->getConfigInt("difficulty", World::DIFFICULTY_NORMAL);
|
||||
return $this->configGroup->getConfigInt("difficulty", World::DIFFICULTY_NORMAL);
|
||||
}
|
||||
|
||||
public function hasWhitelist() : bool{
|
||||
return $this->getConfigBool("white-list", false);
|
||||
return $this->configGroup->getConfigBool("white-list", false);
|
||||
}
|
||||
|
||||
public function isHardcore() : bool{
|
||||
return $this->getConfigBool("hardcore", false);
|
||||
return $this->configGroup->getConfigBool("hardcore", false);
|
||||
}
|
||||
|
||||
public function getMotd() : string{
|
||||
return $this->getConfigString("motd", \pocketmine\NAME . " Server");
|
||||
return $this->configGroup->getConfigString("motd", \pocketmine\NAME . " Server");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -493,7 +485,7 @@ class Server{
|
||||
}
|
||||
|
||||
public function shouldSavePlayerData() : bool{
|
||||
return (bool) $this->getProperty("player.save-player-data", true);
|
||||
return (bool) $this->configGroup->getProperty("player.save-player-data", true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -625,74 +617,8 @@ class Server{
|
||||
return $this->getPlayerByRawUUID($uuid->toBinary());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $defaultValue
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getProperty(string $variable, $defaultValue = null){
|
||||
if(!array_key_exists($variable, $this->propertyCache)){
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
$this->propertyCache[$variable] = $v[$variable];
|
||||
}else{
|
||||
$this->propertyCache[$variable] = $this->config->getNested($variable);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->propertyCache[$variable] ?? $defaultValue;
|
||||
}
|
||||
|
||||
public function getConfigString(string $variable, string $defaultValue = "") : string{
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
return (string) $v[$variable];
|
||||
}
|
||||
|
||||
return $this->properties->exists($variable) ? (string) $this->properties->get($variable) : $defaultValue;
|
||||
}
|
||||
|
||||
public function setConfigString(string $variable, string $value) : void{
|
||||
$this->properties->set($variable, $value);
|
||||
}
|
||||
|
||||
public function getConfigInt(string $variable, int $defaultValue = 0) : int{
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
return (int) $v[$variable];
|
||||
}
|
||||
|
||||
return $this->properties->exists($variable) ? (int) $this->properties->get($variable) : $defaultValue;
|
||||
}
|
||||
|
||||
public function setConfigInt(string $variable, int $value) : void{
|
||||
$this->properties->set($variable, $value);
|
||||
}
|
||||
|
||||
public function getConfigBool(string $variable, bool $defaultValue = false) : bool{
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
$value = $v[$variable];
|
||||
}else{
|
||||
$value = $this->properties->exists($variable) ? $this->properties->get($variable) : $defaultValue;
|
||||
}
|
||||
|
||||
if(is_bool($value)){
|
||||
return $value;
|
||||
}
|
||||
switch(strtolower($value)){
|
||||
case "on":
|
||||
case "true":
|
||||
case "1":
|
||||
case "yes":
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setConfigBool(string $variable, bool $value) : void{
|
||||
$this->properties->set($variable, $value ? "1" : "0");
|
||||
public function getConfigGroup() : ServerConfigGroup{
|
||||
return $this->configGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -775,7 +701,7 @@ class Server{
|
||||
* @return string[][]
|
||||
*/
|
||||
public function getCommandAliases() : array{
|
||||
$section = $this->getProperty("aliases");
|
||||
$section = $this->configGroup->getProperty("aliases");
|
||||
$result = [];
|
||||
if(is_array($section)){
|
||||
foreach($section as $key => $value){
|
||||
@ -827,7 +753,7 @@ class Server{
|
||||
$this->dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
|
||||
$this->pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
|
||||
|
||||
$this->logger->info("Loading pocketmine.yml...");
|
||||
$this->logger->info("Loading server configuration");
|
||||
if(!file_exists($this->dataPath . "pocketmine.yml")){
|
||||
$content = file_get_contents(\pocketmine\RESOURCE_PATH . "pocketmine.yml");
|
||||
if(\pocketmine\IS_DEVELOPMENT_BUILD){
|
||||
@ -835,37 +761,38 @@ class Server{
|
||||
}
|
||||
@file_put_contents($this->dataPath . "pocketmine.yml", $content);
|
||||
}
|
||||
$this->config = new Config($this->dataPath . "pocketmine.yml", Config::YAML, []);
|
||||
|
||||
$this->logger->info("Loading server properties...");
|
||||
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, [
|
||||
"motd" => \pocketmine\NAME . " Server",
|
||||
"server-port" => 19132,
|
||||
"white-list" => false,
|
||||
"max-players" => 20,
|
||||
"gamemode" => 0,
|
||||
"force-gamemode" => false,
|
||||
"hardcore" => false,
|
||||
"pvp" => true,
|
||||
"difficulty" => World::DIFFICULTY_NORMAL,
|
||||
"generator-settings" => "",
|
||||
"level-name" => "world",
|
||||
"level-seed" => "",
|
||||
"level-type" => "DEFAULT",
|
||||
"enable-query" => true,
|
||||
"auto-save" => true,
|
||||
"view-distance" => 8,
|
||||
"xbox-auth" => true,
|
||||
"language" => "eng"
|
||||
]);
|
||||
$this->configGroup = new ServerConfigGroup(
|
||||
new Config($this->dataPath . "pocketmine.yml", Config::YAML, []),
|
||||
new Config($this->dataPath . "server.properties", Config::PROPERTIES, [
|
||||
"motd" => \pocketmine\NAME . " Server",
|
||||
"server-port" => 19132,
|
||||
"white-list" => false,
|
||||
"max-players" => 20,
|
||||
"gamemode" => 0,
|
||||
"force-gamemode" => false,
|
||||
"hardcore" => false,
|
||||
"pvp" => true,
|
||||
"difficulty" => World::DIFFICULTY_NORMAL,
|
||||
"generator-settings" => "",
|
||||
"level-name" => "world",
|
||||
"level-seed" => "",
|
||||
"level-type" => "DEFAULT",
|
||||
"enable-query" => true,
|
||||
"auto-save" => true,
|
||||
"view-distance" => 8,
|
||||
"xbox-auth" => true,
|
||||
"language" => "eng"
|
||||
])
|
||||
);
|
||||
|
||||
$debugLogLevel = (int) $this->getProperty("debug.level", 1);
|
||||
$debugLogLevel = (int) $this->configGroup->getProperty("debug.level", 1);
|
||||
if($this->logger instanceof MainLogger){
|
||||
$this->logger->setLogDebug($debugLogLevel > 1);
|
||||
}
|
||||
|
||||
$this->forceLanguage = (bool) $this->getProperty("settings.force-language", false);
|
||||
$selectedLang = $this->getConfigString("language", $this->getProperty("settings.language", Language::FALLBACK_LANGUAGE));
|
||||
$this->forceLanguage = (bool) $this->configGroup->getProperty("settings.force-language", false);
|
||||
$selectedLang = $this->configGroup->getConfigString("language", $this->configGroup->getProperty("settings.language", Language::FALLBACK_LANGUAGE));
|
||||
try{
|
||||
$this->language = new Language($selectedLang);
|
||||
}catch(LanguageNotFoundException $e){
|
||||
@ -881,7 +808,7 @@ class Server{
|
||||
$this->logger->info($this->getLanguage()->translateString("language.selected", [$this->getLanguage()->getName(), $this->getLanguage()->getLang()]));
|
||||
|
||||
if(\pocketmine\IS_DEVELOPMENT_BUILD){
|
||||
if(!((bool) $this->getProperty("settings.enable-dev-builds", false))){
|
||||
if(!((bool) $this->configGroup->getProperty("settings.enable-dev-builds", false))){
|
||||
$this->logger->emergency($this->language->translateString("pocketmine.server.devBuild.error1", [\pocketmine\NAME]));
|
||||
$this->logger->emergency($this->language->translateString("pocketmine.server.devBuild.error2"));
|
||||
$this->logger->emergency($this->language->translateString("pocketmine.server.devBuild.error3"));
|
||||
@ -903,7 +830,7 @@ class Server{
|
||||
|
||||
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.start", [TextFormat::AQUA . $this->getVersion() . TextFormat::RESET]));
|
||||
|
||||
if(($poolSize = $this->getProperty("settings.async-workers", "auto")) === "auto"){
|
||||
if(($poolSize = $this->configGroup->getProperty("settings.async-workers", "auto")) === "auto"){
|
||||
$poolSize = 2;
|
||||
$processors = Utils::getCoreCount() - 2;
|
||||
|
||||
@ -914,25 +841,25 @@ class Server{
|
||||
$poolSize = max(1, (int) $poolSize);
|
||||
}
|
||||
|
||||
$this->asyncPool = new AsyncPool($poolSize, max(-1, (int) $this->getProperty("memory.async-worker-hard-limit", 256)), $this->autoloader, $this->logger);
|
||||
$this->asyncPool = new AsyncPool($poolSize, max(-1, (int) $this->configGroup->getProperty("memory.async-worker-hard-limit", 256)), $this->autoloader, $this->logger);
|
||||
|
||||
$netCompressionThreshold = -1;
|
||||
if($this->getProperty("network.batch-threshold", 256) >= 0){
|
||||
$netCompressionThreshold = (int) $this->getProperty("network.batch-threshold", 256);
|
||||
if($this->configGroup->getProperty("network.batch-threshold", 256) >= 0){
|
||||
$netCompressionThreshold = (int) $this->configGroup->getProperty("network.batch-threshold", 256);
|
||||
}
|
||||
|
||||
$netCompressionLevel = (int) $this->getProperty("network.compression-level", 7);
|
||||
$netCompressionLevel = (int) $this->configGroup->getProperty("network.compression-level", 7);
|
||||
if($netCompressionLevel < 1 or $netCompressionLevel > 9){
|
||||
$this->logger->warning("Invalid network compression level $netCompressionLevel set, setting to default 7");
|
||||
$netCompressionLevel = 7;
|
||||
}
|
||||
ZlibCompressor::setInstance(new ZlibCompressor($netCompressionLevel, $netCompressionThreshold, ZlibCompressor::DEFAULT_MAX_DECOMPRESSION_SIZE));
|
||||
|
||||
$this->networkCompressionAsync = (bool) $this->getProperty("network.async-compression", true);
|
||||
$this->networkCompressionAsync = (bool) $this->configGroup->getProperty("network.async-compression", true);
|
||||
|
||||
NetworkCipher::$ENABLED = (bool) $this->getProperty("network.enable-encryption", true);
|
||||
NetworkCipher::$ENABLED = (bool) $this->configGroup->getProperty("network.enable-encryption", true);
|
||||
|
||||
$this->doTitleTick = ((bool) $this->getProperty("console.title-tick", true)) && Terminal::hasFormattingCodes();
|
||||
$this->doTitleTick = ((bool) $this->configGroup->getProperty("console.title-tick", true)) && Terminal::hasFormattingCodes();
|
||||
|
||||
$this->operators = new Config($this->dataPath . "ops.txt", Config::ENUM);
|
||||
$this->whitelist = new Config($this->dataPath . "white-list.txt", Config::ENUM);
|
||||
@ -946,9 +873,9 @@ class Server{
|
||||
$this->banByIP = new BanList($this->dataPath . "banned-ips.txt");
|
||||
$this->banByIP->load();
|
||||
|
||||
$this->maxPlayers = $this->getConfigInt("max-players", 20);
|
||||
$this->maxPlayers = $this->configGroup->getConfigInt("max-players", 20);
|
||||
|
||||
$this->onlineMode = $this->getConfigBool("xbox-auth", true);
|
||||
$this->onlineMode = $this->configGroup->getConfigBool("xbox-auth", true);
|
||||
if($this->onlineMode){
|
||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.auth.enabled"));
|
||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.authProperty.enabled"));
|
||||
@ -958,8 +885,8 @@ class Server{
|
||||
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.authProperty.disabled"));
|
||||
}
|
||||
|
||||
if($this->getConfigBool("hardcore", false) and $this->getDifficulty() < World::DIFFICULTY_HARD){
|
||||
$this->setConfigInt("difficulty", World::DIFFICULTY_HARD);
|
||||
if($this->configGroup->getConfigBool("hardcore", false) and $this->getDifficulty() < World::DIFFICULTY_HARD){
|
||||
$this->configGroup->setConfigInt("difficulty", World::DIFFICULTY_HARD);
|
||||
}
|
||||
|
||||
@cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion());
|
||||
@ -980,8 +907,8 @@ class Server{
|
||||
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.license", [$this->getName()]));
|
||||
|
||||
Timings::init();
|
||||
TimingsHandler::setEnabled((bool) $this->getProperty("settings.enable-profiling", false));
|
||||
$this->profilingTickRate = (float) $this->getProperty("settings.profile-report-trigger", 20);
|
||||
TimingsHandler::setEnabled((bool) $this->configGroup->getProperty("settings.enable-profiling", false));
|
||||
$this->profilingTickRate = (float) $this->configGroup->getProperty("settings.profile-report-trigger", 20);
|
||||
|
||||
$this->commandMap = new SimpleCommandMap($this);
|
||||
|
||||
@ -1004,13 +931,13 @@ class Server{
|
||||
$this->forceShutdown();
|
||||
return;
|
||||
}
|
||||
$this->pluginManager = new PluginManager($this, ((bool) $this->getProperty("plugins.legacy-data-dir", true)) ? null : $this->getDataPath() . "plugin_data" . DIRECTORY_SEPARATOR, $pluginGraylist);
|
||||
$this->pluginManager = new PluginManager($this, ((bool) $this->configGroup->getProperty("plugins.legacy-data-dir", true)) ? null : $this->getDataPath() . "plugin_data" . DIRECTORY_SEPARATOR, $pluginGraylist);
|
||||
$this->pluginManager->registerInterface(new PharPluginLoader($this->autoloader));
|
||||
$this->pluginManager->registerInterface(new ScriptPluginLoader());
|
||||
|
||||
$providerManager = WorldProviderManager::getInstance();
|
||||
if(
|
||||
($format = $providerManager->getProviderByName($formatName = (string) $this->getProperty("level-settings.default-format"))) !== null and
|
||||
($format = $providerManager->getProviderByName($formatName = (string) $this->configGroup->getProperty("level-settings.default-format"))) !== null and
|
||||
is_a($format, WritableWorldProvider::class, true)
|
||||
){
|
||||
$providerManager->setDefault($format);
|
||||
@ -1019,10 +946,10 @@ class Server{
|
||||
}
|
||||
|
||||
$this->worldManager = new WorldManager($this, $this->dataPath . "/worlds");
|
||||
$this->worldManager->setAutoSave($this->getConfigBool("auto-save", $this->worldManager->getAutoSave()));
|
||||
$this->worldManager->setAutoSaveInterval((int) $this->getProperty("ticks-per.autosave", 6000));
|
||||
$this->worldManager->setAutoSave($this->configGroup->getConfigBool("auto-save", $this->worldManager->getAutoSave()));
|
||||
$this->worldManager->setAutoSaveInterval((int) $this->configGroup->getProperty("ticks-per.autosave", 6000));
|
||||
|
||||
$this->updater = new AutoUpdater($this, $this->getProperty("auto-updater.host", "update.pmmp.io"));
|
||||
$this->updater = new AutoUpdater($this, $this->configGroup->getProperty("auto-updater.host", "update.pmmp.io"));
|
||||
|
||||
$this->queryInfo = new QueryInfo($this);
|
||||
|
||||
@ -1031,7 +958,7 @@ class Server{
|
||||
$this->pluginManager->loadPlugins($this->pluginPath);
|
||||
$this->enablePlugins(PluginLoadOrder::STARTUP());
|
||||
|
||||
foreach((array) $this->getProperty("worlds", []) as $name => $options){
|
||||
foreach((array) $this->configGroup->getProperty("worlds", []) as $name => $options){
|
||||
if($options === null){
|
||||
$options = [];
|
||||
}elseif(!is_array($options)){
|
||||
@ -1053,18 +980,18 @@ class Server{
|
||||
}
|
||||
|
||||
if($this->worldManager->getDefaultWorld() === null){
|
||||
$default = $this->getConfigString("level-name", "world");
|
||||
$default = $this->configGroup->getConfigString("level-name", "world");
|
||||
if(trim($default) == ""){
|
||||
$this->getLogger()->warning("level-name cannot be null, using default");
|
||||
$default = "world";
|
||||
$this->setConfigString("level-name", "world");
|
||||
$this->configGroup->setConfigString("level-name", "world");
|
||||
}
|
||||
if(!$this->worldManager->loadWorld($default, true)){
|
||||
$this->worldManager->generateWorld(
|
||||
$default,
|
||||
Generator::convertSeed($this->getConfigString("level-seed")),
|
||||
GeneratorManager::getInstance()->getGenerator($this->getConfigString("level-type")),
|
||||
["preset" => $this->getConfigString("generator-settings")]
|
||||
Generator::convertSeed($this->configGroup->getConfigString("level-seed")),
|
||||
GeneratorManager::getInstance()->getGenerator($this->configGroup->getConfigString("level-type")),
|
||||
["preset" => $this->configGroup->getConfigString("generator-settings")]
|
||||
);
|
||||
}
|
||||
|
||||
@ -1083,7 +1010,7 @@ class Server{
|
||||
$this->network->registerInterface(new RakLibInterface($this));
|
||||
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.networkStart", [$this->getIp(), $this->getPort()]));
|
||||
|
||||
if($this->getConfigBool("enable-query", true)){
|
||||
if($this->configGroup->getConfigBool("enable-query", true)){
|
||||
$this->network->registerRawPacketHandler(new QueryHandler($this));
|
||||
}
|
||||
|
||||
@ -1091,7 +1018,7 @@ class Server{
|
||||
$this->network->blockAddress($entry->getName(), -1);
|
||||
}
|
||||
|
||||
if((bool) $this->getProperty("network.upnp-forwarding", false)){
|
||||
if((bool) $this->configGroup->getProperty("network.upnp-forwarding", false)){
|
||||
try{
|
||||
$this->network->registerInterface(new UPnP($this->logger, Internet::getInternalIP(), $this->getPort()));
|
||||
}catch(\RuntimeException $e){
|
||||
@ -1099,14 +1026,12 @@ class Server{
|
||||
}
|
||||
}
|
||||
|
||||
if((bool) $this->getProperty("settings.send-usage", true)){
|
||||
if((bool) $this->configGroup->getProperty("settings.send-usage", true)){
|
||||
$this->sendUsageTicker = 6000;
|
||||
$this->sendUsage(SendUsageTask::TYPE_OPEN);
|
||||
}
|
||||
|
||||
if($this->properties->hasChanged()){
|
||||
$this->properties->save();
|
||||
}
|
||||
$this->configGroup->save();
|
||||
|
||||
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.defaultGameMode", [$this->getGamemode()->getTranslationKey()]));
|
||||
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.donate", [TextFormat::AQUA . "https://patreon.com/pocketminemp" . TextFormat::RESET]));
|
||||
@ -1380,7 +1305,7 @@ class Server{
|
||||
}
|
||||
|
||||
if($this->network instanceof Network){
|
||||
$this->network->getSessionManager()->close($this->getProperty("settings.shutdown-message", "Server closed"));
|
||||
$this->network->getSessionManager()->close($this->configGroup->getProperty("settings.shutdown-message", "Server closed"));
|
||||
}
|
||||
|
||||
if($this->worldManager instanceof WorldManager){
|
||||
@ -1398,9 +1323,9 @@ class Server{
|
||||
$this->asyncPool->shutdown();
|
||||
}
|
||||
|
||||
if($this->properties !== null and $this->properties->hasChanged()){
|
||||
if($this->configGroup !== null){
|
||||
$this->getLogger()->debug("Saving properties");
|
||||
$this->properties->save();
|
||||
$this->configGroup->save();
|
||||
}
|
||||
|
||||
if($this->console instanceof CommandReader){
|
||||
@ -1485,7 +1410,7 @@ class Server{
|
||||
|
||||
$this->logger->emergency($this->getLanguage()->translateString("pocketmine.crash.submit", [$dump->getPath()]));
|
||||
|
||||
if($this->getProperty("auto-report.enabled", true) !== false){
|
||||
if($this->configGroup->getProperty("auto-report.enabled", true) !== false){
|
||||
$report = true;
|
||||
|
||||
$stamp = $this->getDataPath() . "crashdumps/.last_crash";
|
||||
@ -1514,7 +1439,7 @@ class Server{
|
||||
}
|
||||
|
||||
if($report){
|
||||
$url = ((bool) $this->getProperty("auto-report.use-https", true) ? "https" : "http") . "://" . $this->getProperty("auto-report.host", "crash.pmmp.io") . "/submit/api";
|
||||
$url = ((bool) $this->configGroup->getProperty("auto-report.use-https", true) ? "https" : "http") . "://" . $this->configGroup->getProperty("auto-report.host", "crash.pmmp.io") . "/submit/api";
|
||||
$reply = Internet::postURL($url, [
|
||||
"report" => "yes",
|
||||
"name" => $this->getName() . " " . $this->getPocketMineVersion(),
|
||||
@ -1593,7 +1518,7 @@ class Server{
|
||||
}
|
||||
|
||||
public function sendUsage(int $type = SendUsageTask::TYPE_STATUS) : void{
|
||||
if((bool) $this->getProperty("anonymous-statistics.enabled", true)){
|
||||
if((bool) $this->configGroup->getProperty("anonymous-statistics.enabled", true)){
|
||||
$this->asyncPool->submitTask(new SendUsageTask($this, $type, $this->uniquePlayers));
|
||||
}
|
||||
$this->uniquePlayers = [];
|
||||
|
128
src/ServerConfigGroup.php
Normal file
128
src/ServerConfigGroup.php
Normal file
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\utils\Config;
|
||||
use function array_key_exists;
|
||||
use function getopt;
|
||||
use function is_bool;
|
||||
use function strtolower;
|
||||
|
||||
final class ServerConfigGroup{
|
||||
|
||||
/** @var Config */
|
||||
private $pocketmineYml;
|
||||
/** @var Config */
|
||||
private $serverProperties;
|
||||
|
||||
/**
|
||||
* @var mixed[]
|
||||
* @phpstan-var array<string, mixed>
|
||||
*/
|
||||
private $propertyCache = [];
|
||||
|
||||
public function __construct(Config $pocketmineYml, Config $serverProperties){
|
||||
$this->pocketmineYml = $pocketmineYml;
|
||||
$this->serverProperties = $serverProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $defaultValue
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getProperty(string $variable, $defaultValue = null){
|
||||
if(!array_key_exists($variable, $this->propertyCache)){
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
$this->propertyCache[$variable] = $v[$variable];
|
||||
}else{
|
||||
$this->propertyCache[$variable] = $this->pocketmineYml->getNested($variable);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->propertyCache[$variable] ?? $defaultValue;
|
||||
}
|
||||
|
||||
public function getConfigString(string $variable, string $defaultValue = "") : string{
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
return (string) $v[$variable];
|
||||
}
|
||||
|
||||
return $this->serverProperties->exists($variable) ? (string) $this->serverProperties->get($variable) : $defaultValue;
|
||||
}
|
||||
|
||||
public function setConfigString(string $variable, string $value) : void{
|
||||
$this->serverProperties->set($variable, $value);
|
||||
}
|
||||
|
||||
public function getConfigInt(string $variable, int $defaultValue = 0) : int{
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
return (int) $v[$variable];
|
||||
}
|
||||
|
||||
return $this->serverProperties->exists($variable) ? (int) $this->serverProperties->get($variable) : $defaultValue;
|
||||
}
|
||||
|
||||
public function setConfigInt(string $variable, int $value) : void{
|
||||
$this->serverProperties->set($variable, $value);
|
||||
}
|
||||
|
||||
public function getConfigBool(string $variable, bool $defaultValue = false) : bool{
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
$value = $v[$variable];
|
||||
}else{
|
||||
$value = $this->serverProperties->exists($variable) ? $this->serverProperties->get($variable) : $defaultValue;
|
||||
}
|
||||
|
||||
if(is_bool($value)){
|
||||
return $value;
|
||||
}
|
||||
switch(strtolower($value)){
|
||||
case "on":
|
||||
case "true":
|
||||
case "1":
|
||||
case "yes":
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setConfigBool(string $variable, bool $value) : void{
|
||||
$this->serverProperties->set($variable, $value ? "1" : "0");
|
||||
}
|
||||
|
||||
public function save() : void{
|
||||
if($this->serverProperties->hasChanged()){
|
||||
$this->serverProperties->save();
|
||||
}
|
||||
if($this->pocketmineYml->hasChanged()){
|
||||
$this->pocketmineYml->save();
|
||||
}
|
||||
}
|
||||
}
|
@ -56,7 +56,7 @@ class DefaultGamemodeCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
$sender->getServer()->setConfigInt("gamemode", $gameMode->getMagicNumber());
|
||||
$sender->getServer()->getConfigGroup()->setConfigInt("gamemode", $gameMode->getMagicNumber());
|
||||
$sender->sendMessage(new TranslationContainer("commands.defaultgamemode.success", [$gameMode->getTranslationKey()]));
|
||||
return true;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ class DifficultyCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
if($difficulty !== -1){
|
||||
$sender->getServer()->setConfigInt("difficulty", $difficulty);
|
||||
$sender->getServer()->getConfigGroup()->setConfigInt("difficulty", $difficulty);
|
||||
|
||||
//TODO: add per-world support
|
||||
foreach($sender->getServer()->getWorldManager()->getWorlds() as $world){
|
||||
|
@ -119,7 +119,7 @@ class TimingsCommand extends VanillaCommand{
|
||||
];
|
||||
fclose($fileTimings);
|
||||
|
||||
$host = $sender->getServer()->getProperty("timings.host", "timings.pmmp.io");
|
||||
$host = $sender->getServer()->getConfigGroup()->getProperty("timings.host", "timings.pmmp.io");
|
||||
|
||||
$sender->getServer()->getAsyncPool()->submitTask(new class($sender, $host, $agent, $data) extends BulkCurlTask{
|
||||
private const TLS_KEY_SENDER = "sender";
|
||||
|
@ -64,12 +64,12 @@ class WhitelistCommand extends VanillaCommand{
|
||||
|
||||
return true;
|
||||
case "on":
|
||||
$sender->getServer()->setConfigBool("white-list", true);
|
||||
$sender->getServer()->getConfigGroup()->setConfigBool("white-list", true);
|
||||
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.whitelist.enabled"));
|
||||
|
||||
return true;
|
||||
case "off":
|
||||
$sender->getServer()->setConfigBool("white-list", false);
|
||||
$sender->getServer()->getConfigGroup()->setConfigBool("white-list", false);
|
||||
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.whitelist.disabled"));
|
||||
|
||||
return true;
|
||||
|
@ -97,7 +97,7 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{
|
||||
$threadToMainBuffer,
|
||||
new InternetAddress($this->server->getIp(), $this->server->getPort(), 4),
|
||||
$this->rakServerId,
|
||||
(int) $this->server->getProperty("network.max-mtu-size", 1492),
|
||||
(int) $this->server->getConfigGroup()->getProperty("network.max-mtu-size", 1492),
|
||||
self::MCPE_RAKNET_PROTOCOL_VERSION,
|
||||
$this->sleeper
|
||||
);
|
||||
|
@ -76,7 +76,7 @@ final class QueryInfo{
|
||||
|
||||
public function __construct(Server $server){
|
||||
$this->serverName = $server->getMotd();
|
||||
$this->listPlugins = $server->getProperty("settings.query-plugins", true);
|
||||
$this->listPlugins = $server->getConfigGroup()->getProperty("settings.query-plugins", true);
|
||||
$this->plugins = $server->getPluginManager()->getPlugins();
|
||||
$this->players = $server->getOnlinePlayers();
|
||||
|
||||
|
@ -269,8 +269,8 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
|
||||
$this->xuid = $this->playerInfo->getXuid();
|
||||
|
||||
$this->perm = new PermissibleBase($this);
|
||||
$this->chunksPerTick = (int) $this->server->getProperty("chunk-sending.per-tick", 4);
|
||||
$this->spawnThreshold = (int) (($this->server->getProperty("chunk-sending.spawn-radius", 4) ** 2) * M_PI);
|
||||
$this->chunksPerTick = (int) $this->server->getConfigGroup()->getProperty("chunk-sending.per-tick", 4);
|
||||
$this->spawnThreshold = (int) (($this->server->getConfigGroup()->getProperty("chunk-sending.spawn-radius", 4) ** 2) * M_PI);
|
||||
|
||||
$namedtag = $this->server->getOfflinePlayerData($this->username); //TODO: make this async
|
||||
|
||||
@ -556,7 +556,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
|
||||
public function setViewDistance(int $distance) : void{
|
||||
$this->viewDistance = $this->server->getAllowedViewDistance($distance);
|
||||
|
||||
$this->spawnThreshold = (int) (min($this->viewDistance, $this->server->getProperty("chunk-sending.spawn-radius", 4)) ** 2 * M_PI);
|
||||
$this->spawnThreshold = (int) (min($this->viewDistance, $this->server->getConfigGroup()->getProperty("chunk-sending.spawn-radius", 4)) ** 2 * M_PI);
|
||||
|
||||
$this->nextChunkOrderRun = 0;
|
||||
|
||||
@ -836,7 +836,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
|
||||
|
||||
$this->spawnToAll();
|
||||
|
||||
if($this->server->getUpdater()->hasUpdate() and $this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE) and $this->server->getProperty("auto-updater.on-update.warn-ops", true)){
|
||||
if($this->server->getUpdater()->hasUpdate() and $this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE) and $this->server->getConfigGroup()->getProperty("auto-updater.on-update.warn-ops", true)){
|
||||
$this->server->getUpdater()->showPlayerUpdate($this);
|
||||
}
|
||||
|
||||
@ -1675,7 +1675,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
|
||||
$oldItem = clone $heldItem;
|
||||
|
||||
$ev = new EntityDamageByEntityEvent($this, $entity, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $heldItem->getAttackPoints());
|
||||
if(!$this->canInteract($entity->getLocation(), 8) or ($entity instanceof Player and !$this->server->getConfigBool("pvp"))){
|
||||
if(!$this->canInteract($entity->getLocation(), 8) or ($entity instanceof Player and !$this->server->getConfigGroup()->getConfigBool("pvp"))){
|
||||
$ev->setCancelled();
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ class SendUsageTask extends AsyncTask{
|
||||
* @phpstan-param array<string, string> $playerList
|
||||
*/
|
||||
public function __construct(Server $server, int $type, array $playerList = []){
|
||||
$endpoint = "http://" . $server->getProperty("anonymous-statistics.host", "stats.pocketmine.net") . "/";
|
||||
$endpoint = "http://" . $server->getConfigGroup()->getProperty("anonymous-statistics.host", "stats.pocketmine.net") . "/";
|
||||
|
||||
$data = [];
|
||||
$data["uniqueServerId"] = $server->getServerUniqueId()->toString();
|
||||
|
@ -57,7 +57,7 @@ class AutoUpdater{
|
||||
$this->logger = new \PrefixedLogger($server->getLogger(), "Auto Updater");
|
||||
$this->endpoint = "http://$endpoint/api/";
|
||||
|
||||
if((bool) $server->getProperty("auto-updater.enabled", true)){
|
||||
if((bool) $server->getConfigGroup()->getProperty("auto-updater.enabled", true)){
|
||||
$this->doCheck();
|
||||
}
|
||||
}
|
||||
@ -77,7 +77,7 @@ class AutoUpdater{
|
||||
$this->checkUpdate();
|
||||
if($this->hasUpdate()){
|
||||
(new UpdateNotifyEvent($this))->call();
|
||||
if((bool) $this->server->getProperty("auto-updater.on-update.warn-console", true)){
|
||||
if((bool) $this->server->getConfigGroup()->getProperty("auto-updater.on-update.warn-console", true)){
|
||||
$this->showConsoleUpdate();
|
||||
}
|
||||
}else{
|
||||
@ -187,7 +187,7 @@ class AutoUpdater{
|
||||
* Returns the channel used for update checking (stable, beta, dev)
|
||||
*/
|
||||
public function getChannel() : string{
|
||||
$channel = strtolower($this->server->getProperty("auto-updater.preferred-channel", "stable"));
|
||||
$channel = strtolower($this->server->getConfigGroup()->getProperty("auto-updater.preferred-channel", "stable"));
|
||||
if($channel !== "stable" and $channel !== "beta" and $channel !== "alpha" and $channel !== "development"){
|
||||
$channel = "stable";
|
||||
}
|
||||
|
@ -347,12 +347,13 @@ class World implements ChunkManager{
|
||||
|
||||
$this->time = $this->provider->getWorldData()->getTime();
|
||||
|
||||
$this->chunkTickRadius = min($this->server->getViewDistance(), max(1, (int) $this->server->getProperty("chunk-ticking.tick-radius", 4)));
|
||||
$this->chunksPerTick = (int) $this->server->getProperty("chunk-ticking.per-tick", 40);
|
||||
$this->tickedBlocksPerSubchunkPerTick = (int) $this->server->getProperty("chunk-ticking.blocks-per-subchunk-per-tick", self::DEFAULT_TICKED_BLOCKS_PER_SUBCHUNK_PER_TICK);
|
||||
$this->chunkPopulationQueueSize = (int) $this->server->getProperty("chunk-generation.population-queue-size", 2);
|
||||
$cfg = $this->server->getConfigGroup();
|
||||
$this->chunkTickRadius = min($this->server->getViewDistance(), max(1, (int) $cfg->getProperty("chunk-ticking.tick-radius", 4)));
|
||||
$this->chunksPerTick = (int) $cfg->getProperty("chunk-ticking.per-tick", 40);
|
||||
$this->tickedBlocksPerSubchunkPerTick = (int) $cfg->getProperty("chunk-ticking.blocks-per-subchunk-per-tick", self::DEFAULT_TICKED_BLOCKS_PER_SUBCHUNK_PER_TICK);
|
||||
$this->chunkPopulationQueueSize = (int) $cfg->getProperty("chunk-generation.population-queue-size", 2);
|
||||
|
||||
$dontTickBlocks = array_fill_keys($this->server->getProperty("chunk-ticking.disable-block-ticking", []), true);
|
||||
$dontTickBlocks = array_fill_keys($cfg->getProperty("chunk-ticking.disable-block-ticking", []), true);
|
||||
|
||||
foreach(BlockFactory::getInstance()->getAllKnownStates() as $state){
|
||||
if(!isset($dontTickBlocks[$state->getId()]) and $state->ticksRandomly()){
|
||||
|
@ -65,16 +65,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/Server.php
|
||||
|
||||
-
|
||||
message: "#^Cannot cast array\\<int, mixed\\>\\|string\\|false to string\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/Server.php
|
||||
|
||||
-
|
||||
message: "#^Cannot cast array\\<int, mixed\\>\\|string\\|false to int\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/Server.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
@ -90,6 +80,16 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/Server.php
|
||||
|
||||
-
|
||||
message: "#^Cannot cast array\\<int, mixed\\>\\|string\\|false to string\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/ServerConfigGroup.php
|
||||
|
||||
-
|
||||
message: "#^Cannot cast array\\<int, mixed\\>\\|string\\|false to int\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/ServerConfigGroup.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\world\\\\format\\\\Chunk\\:\\:setFullBlock\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user