1647 self::$instance = $this;
1648 self::$sleeper = new \Threaded;
1649 $this->autoloader = $autoloader;
1650 $this->logger = $logger;
1651 $this->filePath = $filePath;
1653 if(!file_exists($dataPath .
"worlds/")){
1654 mkdir($dataPath .
"worlds/", 0777);
1657 if(!file_exists($dataPath .
"players/")){
1658 mkdir($dataPath .
"players/", 0777);
1661 if(!file_exists($pluginPath)){
1662 mkdir($pluginPath, 0777);
1665 if(!file_exists($dataPath .
"crashdumps/")){
1666 mkdir($dataPath .
"crashdumps/", 0777);
1669 $this->dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
1670 $this->pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
1672 $this->console =
new CommandReader();
1679 $this->logger->info(
"Loading properties and configuration...");
1680 if(!file_exists($this->dataPath .
"pocketmine.yml")){
1681 if(file_exists($this->dataPath .
"lang.txt")){
1682 $langFile =
new Config($configPath = $this->dataPath .
"lang.txt",
Config::ENUM, []);
1684 foreach ($langFile->getAll(
true) as $langName) {
1685 $wizardLang = $langName;
1688 if(file_exists($this->filePath .
"src/pocketmine/resources/pocketmine_$wizardLang.yml")){
1689 $content = file_get_contents($file = $this->filePath .
"src/pocketmine/resources/pocketmine_$wizardLang.yml");
1691 $content = file_get_contents($file = $this->filePath .
"src/pocketmine/resources/pocketmine_eng.yml");
1694 $content = file_get_contents($file = $this->filePath .
"src/pocketmine/resources/pocketmine_eng.yml");
1696 @file_put_contents($this->dataPath .
"pocketmine.yml", $content);
1698 if(file_exists($this->dataPath .
"lang.txt")){
1699 unlink($this->dataPath .
"lang.txt");
1701 $this->config =
new Config($configPath = $this->dataPath .
"pocketmine.yml",
Config::YAML, []);
1702 $nowLang = $this->
getProperty(
"settings.language",
"eng");
1705 if(strpos(\
pocketmine\
VERSION,
"unsupported") !==
false and getenv(
"CI") ===
false){
1706 if($this->
getProperty(
"settings.enable-testing",
false) !==
true){
1707 throw new ServerException(
"This build is not intended for production use. You may set 'settings.enable-testing: true' under pocketmine.yml to allow use of non-production builds. Do so at your own risk and ONLY if you know what you are doing.");
1709 $this->logger->warning(
"You are using an unsupported build. Do not use this build in a production environment.");
1712 if($defaultLang !=
"unknown" and $nowLang != $defaultLang){
1713 @file_put_contents($configPath, str_replace(
'language: "' . $nowLang .
'"',
'language: "' . $defaultLang .
'"', file_get_contents($configPath)));
1714 $this->config->reload();
1715 unset($this->propertyCache[
"settings.language"]);
1719 if(file_exists($this->filePath .
"src/pocketmine/resources/genisys_$lang.yml")){
1720 $content = file_get_contents($file = $this->filePath .
"src/pocketmine/resources/genisys_$lang.yml");
1722 $content = file_get_contents($file = $this->filePath .
"src/pocketmine/resources/genisys_eng.yml");
1725 if(!file_exists($this->dataPath .
"genisys.yml")){
1726 @file_put_contents($this->dataPath .
"genisys.yml", $content);
1729 $this->advancedConfig =
new Config($this->dataPath .
"genisys.yml",
Config::YAML, []);
1735 $this->properties =
new Config($this->dataPath .
"server.properties",
Config::PROPERTIES, [
1736 "motd" =>
"Minecraft: PE Server",
1737 "server-port" => 19132,
1738 "white-list" =>
false,
1739 "announce-player-achievements" =>
true,
1740 "spawn-protection" => 16,
1741 "max-players" => 20,
1742 "allow-flight" =>
false,
1743 "spawn-animals" =>
true,
1744 "spawn-mobs" =>
true,
1746 "force-gamemode" =>
false,
1747 "hardcore" =>
false,
1750 "generator-settings" =>
"",
1751 "level-name" =>
"world",
1753 "level-type" =>
"DEFAULT",
1754 "enable-query" =>
true,
1755 "enable-rcon" =>
false,
1756 "rcon.password" => substr(base64_encode(random_bytes(20)), 3, 10),
1757 "auto-save" =>
true,
1758 "online-mode" =>
false,
1759 "view-distance" => 8
1763 if(!extension_loaded(
"openssl")){
1764 $this->logger->warning(
"OpenSSL extension not found");
1765 $this->logger->warning(
"Please configure OpenSSL extension for PHP if you want to use Xbox Live authentication or global resource pack.");
1767 }elseif(!$onlineMode){
1768 $this->logger->warning(
"Online mode has been turned off in server.properties");
1769 $this->logger->warning(
"Xbox Live authentication is disabled.");
1772 $this->forceLanguage = $this->
getProperty(
"settings.force-language",
false);
1776 $this->memoryManager =
new MemoryManager($this);
1778 if(($poolSize = $this->
getProperty(
"settings.async-workers",
"auto")) ===
"auto"){
1782 if($processors > 0){
1783 $poolSize = max(1, $processors);
1789 if($this->
getProperty(
"network.batch-threshold", 256) >= 0){
1794 $this->networkCompressionLevel = $this->
getProperty(
"network.compression-level", 7);
1795 $this->networkCompressionAsync = $this->
getProperty(
"network.async-compression",
true);
1797 $this->autoTickRate = (bool) $this->
getProperty(
"level-settings.auto-tick-rate",
true);
1798 $this->autoTickRateLimit = (int) $this->
getProperty(
"level-settings.auto-tick-rate-limit", 20);
1799 $this->alwaysTickPlayers = (int) $this->
getProperty(
"level-settings.always-tick-players",
false);
1800 $this->baseTickRate = (int) $this->
getProperty(
"level-settings.base-tick-rate", 1);
1802 $this->scheduler =
new ServerScheduler();
1808 $this->entityMetadata =
new EntityMetadataStore();
1809 $this->playerMetadata =
new PlayerMetadataStore();
1810 $this->levelMetadata =
new LevelMetadataStore();
1812 $this->operators =
new Config($this->dataPath .
"ops.txt",
Config::ENUM);
1813 $this->whitelist =
new Config($this->dataPath .
"white-list.txt",
Config::ENUM);
1814 if(file_exists($this->dataPath .
"banned.txt") and !file_exists($this->dataPath .
"banned-players.txt")){
1815 @rename($this->dataPath .
"banned.txt", $this->dataPath .
"banned-players.txt");
1817 @touch($this->dataPath .
"banned-players.txt");
1818 $this->banByName =
new BanList($this->dataPath .
"banned-players.txt");
1819 $this->banByName->load();
1820 @touch($this->dataPath .
"banned-ips.txt");
1821 $this->banByIP =
new BanList($this->dataPath .
"banned-ips.txt");
1822 $this->banByIP->load();
1823 @touch($this->dataPath .
"banned-cids.txt");
1824 $this->banByCID =
new BanList($this->dataPath .
"banned-cids.txt");
1825 $this->banByCID->load();
1827 $this->maxPlayers = $this->
getConfigInt(
"max-players", 20);
1834 define(
'pocketmine\DEBUG', (
int) $this->
getProperty(
"debug.level", 1));
1836 if(((
int) ini_get(
'zend.assertions')) > 0 and ((
bool) $this->
getProperty(
"debug.assertions.warn-if-enabled",
true)) !==
false){
1837 $this->logger->warning(
"Debugging assertions are enabled, this may impact on performance. To disable them, set `zend.assertions = -1` in php.ini.");
1840 ini_set(
'assert.exception', (
bool) $this->
getProperty(
"debug.assertions.throw-exception", 0));
1842 if($this->logger instanceof MainLogger){
1843 $this->logger->setLogDebug(\
pocketmine\DEBUG > 1);
1850 $this->logger->info($this->
getLanguage()->translateString(
"pocketmine.server.networkStart", [$this->
getIp() ===
"" ?
"*" : $this->
getIp(), $this->
getPort()]));
1856 $this->network =
new Network($this);
1857 $this->network->setName($this->
getMotd());
1859 $this->logger->info($this->
getLanguage()->translateString(
"pocketmine.server.license", [$this->
getName()]));
1863 $this->consoleSender =
new ConsoleCommandSender();
1864 $this->commandMap =
new SimpleCommandMap($this);
1877 $this->craftingManager =
new CraftingManager();
1879 $this->resourceManager =
new ResourcePackManager($this, $this->
getDataPath() .
"resource_packs" . DIRECTORY_SEPARATOR);
1881 $this->pluginManager =
new PluginManager($this, $this->commandMap);
1883 $this->pluginManager->setUseTimings($this->
getProperty(
"settings.enable-profiling",
false));
1884 $this->profilingTickRate = (float) $this->
getProperty(
"settings.profile-report-trigger", 20);
1885 $this->pluginManager->registerInterface(PharPluginLoader::class);
1886 if($this->folderpluginloader ===
true) {
1887 $this->pluginManager->registerInterface(FolderPluginLoader::class);
1889 $this->pluginManager->registerInterface(ScriptPluginLoader::class);
1892 register_shutdown_function([$this,
"crashDump"]);
1894 $this->queryRegenerateTask =
new QueryRegenerateEvent($this, 5);
1896 $this->network->registerInterface(
new RakLibInterface($this));
1898 $this->pluginManager->loadPlugins($this->pluginPath);
1902 LevelProviderManager::addProvider(Anvil::class);
1903 LevelProviderManager::addProvider(McRegion::class);
1904 LevelProviderManager::addProvider(PMAnvil::class);
1905 if(extension_loaded(
"leveldb")){
1906 $this->logger->debug($this->
getLanguage()->translateString(
"pocketmine.debug.enable"));
1907 LevelProviderManager::addProvider(LevelDB::class);
1920 foreach((array) $this->
getProperty(
"worlds", []) as $name => $worldSetting){
1922 $seed = $this->
getProperty(
"worlds.$name.seed", time());
1925 if(count($options) > 0){
1927 "preset" => implode(
":", $options),
1933 $this->generateLevel($name, $seed, $generator, $options);
1939 if(trim($default) ==
""){
1940 $this->
getLogger()->warning(
"level-name cannot be null, using default");
1944 if($this->
loadLevel($default) ===
false){
1945 $seed = getopt(
"", [
"level-seed::"])[
"level-seed"] ?? $this->properties->get(
"level-seed", time());
1946 if(!is_numeric($seed) or bccomp($seed,
"9223372036854775807") > 0){
1948 }elseif(PHP_INT_SIZE === 8){
1949 $seed = (int) $seed;
1951 $this->generateLevel($default, $seed === 0 ? time() : $seed);
1958 $this->properties->save(
true);
1961 $this->
getLogger()->emergency($this->
getLanguage()->translateString(
"pocketmine.level.defaultError"));
1967 if($this->netherEnabled){
1968 if(!$this->
loadLevel($this->netherName)){
1974 if($this->enderEnabled){
1975 if(!$this->
loadLevel($this->enderName)){
1981 if($this->
getProperty(
"ticks-per.autosave", 6000) > 0){
1982 $this->autoSaveTicks = (int) $this->
getProperty(
"ticks-per.autosave", 6000);
1987 if($this->dserverConfig[
"enable"] and ($this->
getAdvancedProperty(
"dserver.server-list",
"") !=
"")) $this->scheduler->scheduleRepeatingTask(
new CallbackTask([
1990 ]), $this->dserverConfig[
"timer"]);
1992 if($cfgVer > $advVer){
1993 $this->logger->notice(
"Your genisys.yml needs update");
1994 $this->logger->notice(
"Current Version: $advVer Latest Version: $cfgVer");
1998 }
catch(\Throwable $e){