public function onSCommand(CommandSender $c, Command $cc, $scmd, $data, array $args) { if (count($args) < 1 || count($args) > 4) { return false; } $world = array_shift($args); if ($this->owner->getServer()->isLevelGenerated($world)) { $c->sendMessage(TextFormat::RED . mc::_("[MW] A world named %1% already exists", $world)); return true; } $seed = null; $generator = null; $opts = []; if (isset($args[0])) { $seed = intval($args[0]); } if (isset($args[1])) { $generator = Generator::getGenerator($args[1]); if (strtolower($args[1]) != Generator::getGeneratorName($generator)) { $c->sendMessage(TextFormat::RED . mc::_("[MW] Unknown generator %1%", $args[1])); return true; } $c->sendMessage(TextFormat::GREEN . mc::_("[MW] Using %1%", Generator::getGeneratorName($generator))); } if (isset($args[2])) { $opts = ["preset" => $args[2]]; } $this->owner->getServer()->broadcastMessage(mc::_("[MW] Creating level %1%... (Expect Lag)", $world)); $this->owner->getServer()->generateLevel($world, $seed, $generator, $opts); $this->owner->getServer()->loadLevel($world); return true; }
public function __construct(Level $level, $path) { $this->level = $level; $this->path = $path; if (!file_exists($this->path)) { mkdir($this->path, 0777, true); } $nbt = new NBT(NBT::LITTLE_ENDIAN); $nbt->read(substr(file_get_contents($this->getPath() . "level.dat"), 8)); $levelData = $nbt->getData(); if ($levelData instanceof CompoundTag) { $this->levelData = $levelData; if (!isset($this->levelData["GameRules"])) { $this->levelData["GameRules"] = (new GameRules())->getRules(); } } else { throw new LevelException("Invalid level.dat"); } if (!isset($this->levelData->generatorName)) { $this->levelData->generatorName = new StringTag("generatorName", Generator::getGenerator("DEFAULT")); } if (!isset($this->levelData->generatorOptions)) { $this->levelData->generatorOptions = new StringTag("generatorOptions", ""); } $this->db = new \LevelDB($this->path . "db", ["compression" => LEVELDB_ZLIB_COMPRESSION]); }
public function onCommand(CommandSender $sender, Command $command, $label, array $args) { if (strtolower($command->getName()) === "buyworld") { if (count($args) < 1 || count($args) > 4) { return false; } if (EconomyAPI::getInstance()->myMoney($sender->getName()) < 10000) { $sender->sendMessage(TextFormat::RED . "[HyperPlot] You don't have enought money. It cost \$10000"); return true; } $world = array_shift($args); if (strlen($world) < 3) { $sender->sendMessage(TextFormat::RED . "[HyperPlot] Small World name"); return true; } if ($this->getServer()->isLevelGenerated($world)) { $sender->sendMessage(TextFormat::RED . "[HyperPlot] A world named " . $world . " already exists"); return true; } EconomyAPI::getInstance()->reduceMoney($sender->getName(), 10000); $this->getServer()->broadcastMessage($sender->sendMessage(TextFormat::RED . "[HyperPlot] Creating level " . $sender->getName() . "-" . $world . "...")); $generator = Generator::getGenerator("ownworld"); $this->getServer()->generateLevel($sender->getName() . "-" . $world, null, $generator, []); $this->getServer()->loadLevel($sender->getName() . "-" . $world); return true; } return false; }
public function __construct(Level $level, $path) { $this->level = $level; $this->path = $path; if (!file_exists($this->path)) { mkdir($this->path, 0777, true); } $nbt = new NBT(NBT::BIG_ENDIAN); $nbt->readCompressed(file_get_contents($this->getPath() . "level.dat")); $levelData = $nbt->getData(); if ($levelData->Data instanceof Compound) { $this->levelData = $levelData->Data; } else { throw new LevelException("Invalid level.dat"); } if (!isset($this->levelData->generatorName)) { $this->levelData->generatorName = new String("generatorName", Generator::getGenerator("DEFAULT")); } if (!isset($this->levelData->generatorOptions)) { $this->levelData->generatorOptions = new String("generatorOptions", ""); } }
/** * Init the default level data * * @param Server $server * @param string $name * @param string $path * @param string $provider Class that extends LevelProvider * * @throws \Exception */ public function __construct(Server $server, $name, $path, $provider) { $this->blockStates = Block::$fullList; $this->levelId = static::$levelIdCounter++; $this->blockMetadata = new BlockMetadataStore($this); $this->server = $server; $this->autoSave = $server->getAutoSave(); /** @var LevelProvider $provider */ if (is_subclass_of($provider, LevelProvider::class, true)) { $this->provider = new $provider($this, $path); } else { throw new LevelException("Provider is not a subclass of LevelProvider"); } $this->server->getLogger()->info($this->server->getLanguage()->translateString("pocketmine.level.preparing", [$this->provider->getName()])); $this->generator = Generator::getGenerator($this->provider->getGenerator()); $this->blockOrder = $provider::getProviderOrder(); $this->useSections = $provider::usesChunkSection(); $this->folderName = $name; $this->updateQueue = new ReversePriorityQueue(); $this->updateQueue->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); $this->time = (int) $this->provider->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->chunkGenerationQueueSize = (int) $this->server->getProperty("chunk-generation.queue-size", 8); $this->chunkPopulationQueueSize = (int) $this->server->getProperty("chunk-generation.population-queue-size", 2); $this->chunkTickList = []; $this->clearChunksOnTick = (bool) $this->server->getProperty("chunk-ticking.clear-tick-list", true); $this->cacheChunks = (bool) $this->server->getProperty("chunk-sending.cache-chunks", false); $this->timings = new LevelTimings($this); $this->temporalPosition = new Position(0, 0, 0, $this); $this->temporalVector = new Vector3(0, 0, 0); $this->tickRate = 1; }
/** * Init the default level data * * @param Server $server * @param string $name * @param string $path * @param string $provider Class that extends LevelProvider * * @throws \Exception */ public function __construct(Server $server, $name, $path, $provider) { $this->levelId = static::$levelIdCounter++; $this->blockMetadata = new BlockMetadataStore($this); $this->server = $server; /** @var LevelProvider $provider */ if (is_subclass_of($provider, "pocketmine\\level\\format\\LevelProvider", true)) { $this->provider = new $provider($this, $path); } else { throw new \Exception("Provider is not a subclass of LevelProvider"); } $this->server->getLogger()->info("Preparing level \"" . $this->provider->getName() . "\""); $generator = Generator::getGenerator($this->provider->getGenerator()); $this->server->getGenerationManager()->openLevel($this, $generator, $this->provider->getGeneratorOptions()); $this->blockOrder = $provider::getProviderOrder(); $this->useSections = $provider::usesChunkSection(); $this->folderName = $name; $this->updateQueue = new ReversePriorityQueue(); $this->updateQueue->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); $this->time = (int) $this->provider->getTime(); $this->chunkTickRadius = min($this->server->getViewDistance(), max(1, (int) $this->server->getProperty("chunk-ticking.tick-radius", 3))); $this->chunksPerTick = (int) $this->server->getProperty("chunk-ticking.per-tick", 80); $this->chunkTickList = []; $this->clearChunksOnTick = (bool) $this->server->getProperty("chunk-ticking.clear-tick-list", false); $this->timings = new LevelTimings($this); }
/** * @param \ClassLoader $autoloader * @param \ThreadedLogger $logger * @param string $filePath * @param string $dataPath * @param string $pluginPath */ public function __construct(\ClassLoader $autoloader, \ThreadedLogger $logger, $filePath, $dataPath, $pluginPath) { self::$instance = $this; $this->autoloader = $autoloader; $this->logger = $logger; $this->filePath = $filePath; if (!file_exists($dataPath . "worlds/")) { mkdir($dataPath . "worlds/", 0777); } if (!file_exists($dataPath . "players/")) { mkdir($dataPath . "players/", 0777); } if (!file_exists($dataPath . "CrashDump/")) { mkdir($dataPath . "CrashDump/", 0777); } if (!file_exists($pluginPath)) { mkdir($pluginPath, 0777); } $this->dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR; $this->pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR; $this->console = new CommandReader(); $version = new VersionString($this->getPocketMineVersion()); $this->logger->info(TextFormat::GREEN . " ____ _ _ __ __ _ " . TextFormat::AQUA . " _____ _ _ _ "); $this->logger->info(TextFormat::GREEN . " | _ \\ ___ ___| | _____| |_| \\/ (_)_ __ ___ " . TextFormat::AQUA . "| ____| (_) |_ ___ "); $this->logger->info(TextFormat::GREEN . " | |_) / _ \\ / __| |/ / _ \\ __| |\\/| | | '_ \\ / _ \\ _____ " . TextFormat::AQUA . "| _| | | | __/ _ \\ "); $this->logger->info(TextFormat::GREEN . " | __/ (_) | (__| < __/ |_| | | | | | | | __/ |_____| " . TextFormat::AQUA . "| |___| | | || __/"); $this->logger->info(TextFormat::GREEN . " |_| \\___/ \\___|_|\\_\\___|\\__|_| |_|_|_| |_|\\___| " . TextFormat::AQUA . "|_____|_|_|\\__\\___|"); $this->logger->info(TextFormat::GREEN . " Version: " . TextFormat::AQUA . $version); $this->logger->info("Loading pocketmine.yml..."); if (!file_exists($this->dataPath . "pocketmine.yml")) { $content = file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml"); if ($version->isDev()) { $content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content); } @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" => "Minecraft: PE Server", "server-port" => 19132, "white-list" => false, "announce-player-achievements" => true, "spawn-protection" => 16, "max-players" => 20, "allow-flight" => false, "spawn-animals" => true, "spawn-mobs" => true, "gamemode" => 0, "force-gamemode" => false, "hardcore" => false, "pvp" => true, "difficulty" => 1, "generator-settings" => "", "level-name" => "world", "level-seed" => "", "level-type" => "DEFAULT", "enable-query" => true, "enable-rcon" => false, "rcon.password" => substr(base64_encode(@Utils::getRandomBytes(20, false)), 3, 10), "auto-save" => true]); $this->forceLanguage = $this->getProperty("settings.force-language", false); $this->baseLang = new BaseLang($this->getProperty("settings.language", BaseLang::FALLBACK_LANGUAGE)); $this->logger->info($this->getLanguage()->translateString("language.selected", [$this->getLanguage()->getName(), $this->getLanguage()->getLang()])); $this->memoryManager = new MemoryManager($this); $this->logger->info($this->getLanguage()->translateString("pocketmine.server.start", [TextFormat::AQUA . $this->getVersion()])); if (($poolSize = $this->getProperty("settings.async-workers", "auto")) === "auto") { $poolSize = ServerScheduler::$WORKERS; $processors = Utils::getCoreCount() - 2; if ($processors > 0) { $poolSize = max(1, $processors); } } ServerScheduler::$WORKERS = $poolSize; if ($this->getProperty("network.batch-threshold", 256) >= 0) { Network::$BATCH_THRESHOLD = (int) $this->getProperty("network.batch-threshold", 256); } else { Network::$BATCH_THRESHOLD = -1; } $this->networkCompressionLevel = $this->getProperty("network.compression-level", 7); $this->networkCompressionAsync = $this->getProperty("network.async-compression", true); $this->autoTickRate = (bool) $this->getProperty("level-settings.auto-tick-rate", true); $this->autoTickRateLimit = (int) $this->getProperty("level-settings.auto-tick-rate-limit", 20); $this->alwaysTickPlayers = (int) $this->getProperty("level-settings.always-tick-players", false); $this->baseTickRate = (int) $this->getProperty("level-settings.base-tick-rate", 1); $this->scheduler = new ServerScheduler(); if ($this->getConfigBoolean("enable-rcon", false) === true) { $this->rcon = new RCON($this, $this->getConfigString("rcon.password", ""), $this->getConfigInt("rcon.port", $this->getPort()), ($ip = $this->getIp()) != "" ? $ip : "0.0.0.0", $this->getConfigInt("rcon.threads", 1), $this->getConfigInt("rcon.clients-per-thread", 50)); } $this->entityMetadata = new EntityMetadataStore(); $this->playerMetadata = new PlayerMetadataStore(); $this->levelMetadata = new LevelMetadataStore(); $this->operators = new Config($this->dataPath . "ops.txt", Config::ENUM); $this->whitelist = new Config($this->dataPath . "white-list.txt", Config::ENUM); if (file_exists($this->dataPath . "banned.txt") and !file_exists($this->dataPath . "banned-players.txt")) { @rename($this->dataPath . "banned.txt", $this->dataPath . "banned-players.txt"); } @touch($this->dataPath . "banned-players.txt"); $this->banByName = new BanList($this->dataPath . "banned-players.txt"); $this->banByName->load(); @touch($this->dataPath . "banned-ips.txt"); $this->banByIP = new BanList($this->dataPath . "banned-ips.txt"); $this->banByIP->load(); $this->maxPlayers = $this->getConfigInt("max-players", 20); $this->setAutoSave($this->getConfigBoolean("auto-save", true)); if ($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3) { $this->setConfigInt("difficulty", 3); } define("pocketmine\\DEBUG", (int) $this->getProperty("debug.level", 1)); if ($this->logger instanceof MainLogger) { $this->logger->setLogDebug(\pocketmine\DEBUG > 1); } if (\pocketmine\DEBUG >= 0) { @cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion()); } $this->logger->info($this->getLanguage()->translateString("pocketmine.server.networkStart", [$this->getIp() === "" ? "*" : $this->getIp(), $this->getPort()])); define("BOOTUP_RANDOM", @Utils::getRandomBytes(16)); $this->serverID = Utils::getMachineUniqueId($this->getIp() . $this->getPort()); $this->getLogger()->debug("Server unique id: " . $this->getServerUniqueId()); $this->getLogger()->debug("Machine unique id: " . Utils::getMachineUniqueId()); $this->network = new Network($this); $this->network->setName($this->getMotd()); $this->logger->info($this->getLanguage()->translateString("pocketmine.server.info", [$this->getName(), ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(true) . TextFormat::WHITE, $this->getCodename(), $this->getApiVersion()])); $this->logger->info($this->getLanguage()->translateString("pocketmine.server.license", [$this->getName()])); Timings::init(); $this->consoleSender = new ConsoleCommandSender(); $this->commandMap = new SimpleCommandMap($this); $this->registerEntities(); $this->registerTiles(); InventoryType::init(); Block::init(); Item::init(); Biome::init(); Effect::init(); Enchantment::init(); Attribute::init(); /** TODO: @deprecated */ TextWrapper::init(); $this->craftingManager = new CraftingManager(); $this->pluginManager = new PluginManager($this, $this->commandMap); $this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender); $this->pluginManager->setUseTimings($this->getProperty("settings.enable-profiling", false)); $this->profilingTickRate = (double) $this->getProperty("settings.profile-report-trigger", 20); $this->pluginManager->registerInterface(PharPluginLoader::class); $this->pluginManager->registerInterface(ScriptPluginLoader::class); set_exception_handler([$this, "exceptionHandler"]); register_shutdown_function([$this, "crashDump"]); $this->queryRegenerateTask = new QueryRegenerateEvent($this, 5); $this->network->registerInterface(new RakLibInterface($this)); $this->pluginManager->loadPlugins($this->pluginPath); $this->updater = new AutoUpdater($this, $this->getProperty("auto-updater.host", "www.pocketmine.net")); $this->enablePlugins(PluginLoadOrder::STARTUP); LevelProviderManager::addProvider($this, Anvil::class); LevelProviderManager::addProvider($this, McRegion::class); if (extension_loaded("leveldb")) { $this->logger->debug($this->getLanguage()->translateString("pocketmine.debug.enable")); LevelProviderManager::addProvider($this, LevelDB::class); } Generator::addGenerator(Flat::class, "flat"); Generator::addGenerator(Normal::class, "normal"); Generator::addGenerator(Normal::class, "default"); Generator::addGenerator(Nether::class, "hell"); Generator::addGenerator(Nether::class, "nether"); foreach ((array) $this->getProperty("worlds", []) as $name => $worldSetting) { if ($this->loadLevel($name) === false) { $seed = $this->getProperty("worlds.{$name}.seed", time()); $options = explode(":", $this->getProperty("worlds.{$name}.generator", Generator::getGenerator("default"))); $generator = Generator::getGenerator(array_shift($options)); if (count($options) > 0) { $options = ["preset" => implode(":", $options)]; } else { $options = []; } $this->generateLevel($name, $seed, $generator, $options); } } if ($this->getDefaultLevel() === null) { $default = $this->getConfigString("level-name", "world"); if (trim($default) == "") { $this->getLogger()->warning("level-name cannot be null, using default"); $default = "world"; $this->setConfigString("level-name", "world"); } if ($this->loadLevel($default) === false) { $seed = $this->getConfigInt("level-seed", time()); $this->generateLevel($default, $seed === 0 ? time() : $seed); } $this->setDefaultLevel($this->getLevelByName($default)); } $this->properties->save(true); if (!$this->getDefaultLevel() instanceof Level) { $this->getLogger()->emergency($this->getLanguage()->translateString("pocketmine.level.defaultError")); $this->forceShutdown(); return; } if ($this->getProperty("ticks-per.autosave", 6000) > 0) { $this->autoSaveTicks = (int) $this->getProperty("ticks-per.autosave", 6000); } $this->enablePlugins(PluginLoadOrder::POSTWORLD); $this->start(); }
/** * @param \ClassLoader $autoloader * @param \ThreadedLogger $logger * @param string $filePath * @param string $dataPath * @param string $pluginPath */ public function __construct(\ClassLoader $autoloader, \ThreadedLogger $logger, $filePath, $dataPath, $pluginPath) { self::$instance = $this; $this->autoloader = $autoloader; $this->logger = $logger; $this->filePath = $filePath; if (!file_exists($dataPath . "worlds/")) { mkdir($dataPath . "worlds/", 0777); } if (!file_exists($dataPath . "players/")) { mkdir($dataPath . "players/", 0777); } if (!file_exists($pluginPath)) { mkdir($pluginPath, 0777); } $this->dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR; $this->pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR; $this->console = new CommandReader(); $version = new VersionString($this->getPocketMineVersion()); $this->logger->info("Starting Minecraft: PE server version " . TextFormat::AQUA . $this->getVersion()); $this->logger->info("Loading pocketmine-soft.yml..."); if (!file_exists($this->dataPath . "pocketmine-soft.yml")) { $content = file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine-soft.yml"); @file_put_contents($this->dataPath . "pocketmine-soft.yml", $content); } $this->softConfig = new Config($this->dataPath . "pocketmine-soft.yml", Config::YAML, []); $this->logger->info("Loading pocketmine.yml..."); if (!file_exists($this->dataPath . "pocketmine.yml")) { $content = file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml"); @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" => "Minecraft: PE Server", "server-port" => 19132, "memory-limit" => "256M", "white-list" => false, "announce-player-achievements" => true, "spawn-protection" => 16, "max-players" => 20, "allow-flight" => false, "spawn-animals" => true, "spawn-mobs" => true, "gamemode" => 0, "force-gamemode" => false, "hardcore" => false, "pvp" => true, "difficulty" => 1, "generator-settings" => "", "level-name" => "world", "level-seed" => "", "level-type" => "DEFAULT", "enable-query" => true, "enable-rcon" => false, "rcon.password" => substr(base64_encode(@Utils::getRandomBytes(20, false)), 3, 10), "auto-save" => true]); ServerScheduler::$WORKERS = 4; if ($this->getProperty("network.batch-threshold", 256) >= 0) { Network::$BATCH_THRESHOLD = (int) $this->getProperty("network.batch-threshold", 256); } else { Network::$BATCH_THRESHOLD = -1; } $this->networkCompressionLevel = $this->getProperty("network.compression-level", 7); $this->networkCompressionAsync = $this->getProperty("network.async-compression", true); $this->scheduler = new ServerScheduler(); if ($this->getConfigBoolean("enable-rcon", false) === true) { $this->rcon = new RCON($this, $this->getConfigString("rcon.password", ""), $this->getConfigInt("rcon.port", $this->getPort()), ($ip = $this->getIp()) != "" ? $ip : "0.0.0.0", $this->getConfigInt("rcon.threads", 1), $this->getConfigInt("rcon.clients-per-thread", 50)); } $this->entityMetadata = new EntityMetadataStore(); $this->playerMetadata = new PlayerMetadataStore(); $this->levelMetadata = new LevelMetadataStore(); $this->operators = new Config($this->dataPath . "ops.txt", Config::ENUM); $this->whitelist = new Config($this->dataPath . "white-list.txt", Config::ENUM); if (file_exists($this->dataPath . "banned.txt") and !file_exists($this->dataPath . "banned-players.txt")) { @rename($this->dataPath . "banned.txt", $this->dataPath . "banned-players.txt"); } @touch($this->dataPath . "banned-players.txt"); $this->banByName = new BanList($this->dataPath . "banned-players.txt"); $this->banByName->load(); @touch($this->dataPath . "banned-ips.txt"); $this->banByIP = new BanList($this->dataPath . "banned-ips.txt"); $this->banByIP->load(); $this->maxPlayers = $this->getConfigInt("max-players", 20); $this->setAutoSave($this->getConfigBoolean("auto-save", true)); if (($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "256M")))) !== false) { $value = ["M" => 1, "G" => 1024]; $real = (int) substr($memory, 0, -1) * $value[substr($memory, -1)]; if ($real < 128) { $this->logger->warning($this->getName() . " may not work right with less than 128MB of RAM", true, true, 0); } @ini_set("memory_limit", $memory); } else { $this->setConfigString("memory-limit", "256M"); } $this->network = new Network($this); if ($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3) { $this->setConfigInt("difficulty", 3); } define("pocketmine\\DEBUG", (int) $this->getProperty("debug.level", 1)); if ($this->logger instanceof MainLogger) { $this->logger->setLogDebug(\pocketmine\DEBUG > 1); } define("ADVANCED_CACHE", $this->getProperty("settings.advanced-cache", false)); if (ADVANCED_CACHE == true) { $this->logger->info("Advanced cache enabled"); } Level::$COMPRESSION_LEVEL = $this->getProperty("chunk-sending.compression-level", 8); if (defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0) { @\cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion()); } $this->logger->info("Starting Minecraft PE server on " . ($this->getIp() === "" ? "*" : $this->getIp()) . ":" . $this->getPort()); define("BOOTUP_RANDOM", @Utils::getRandomBytes(16)); $this->serverID = Utils::getMachineUniqueId($this->getIp() . $this->getPort()); $this->addInterface($this->mainInterface = new RakLibInterface($this)); $this->logger->info("This server is running " . $this->getName() . " version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(true) . TextFormat::WHITE . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")"); $this->logger->info($this->getName() . " is distributed under the LGPL License"); PluginManager::$pluginParentTimer = new TimingsHandler("** Plugins"); Timings::init(); $this->consoleSender = new ConsoleCommandSender(); $this->commandMap = new SimpleCommandMap($this); $this->registerEntities(); $this->registerTiles(); InventoryType::init(); Block::init(); Item::init(); TextWrapper::init(); $this->craftingManager = new CraftingManager(); $this->pluginManager = new PluginManager($this, $this->commandMap); $this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender); $this->pluginManager->setUseTimings($this->getProperty("settings.enable-profiling", false)); $this->pluginManager->registerInterface(PharPluginLoader::class); \set_exception_handler([$this, "exceptionHandler"]); register_shutdown_function([$this, "crashDump"]); $plugins = $this->pluginManager->loadPlugins($this->pluginPath); $configPlugins = $this->getAdvancedProperty("plugins", []); if (count($configPlugins) > 0) { $this->getLogger()->info("Checking extra plugins"); $loadNew = false; foreach ($configPlugins as $plugin => $download) { if (!isset($plugins[$plugin])) { $path = $this->pluginPath . "/" . $plugin . ".phar"; if (substr($download, 0, 4) === "http") { $this->getLogger()->info("Downloading " . $plugin); file_put_contents($path, Utils::getURL($download)); } else { file_put_contents($path, file_get_contents($download)); } $loadNew = true; } } if ($loadNew) { $this->pluginManager->loadPlugins($this->pluginPath); } } $this->enablePlugins(PluginLoadOrder::STARTUP); if ($this->getProperty("chunk-generation.use-async", true)) { $this->generationManager = new GenerationRequestManager($this); } else { $this->generationManager = new GenerationInstanceManager($this); } LevelProviderManager::addProvider($this, Anvil::class); LevelProviderManager::addProvider($this, McRegion::class); if (extension_loaded("leveldb")) { $this->logger->debug("Enabling LevelDB support"); LevelProviderManager::addProvider($this, LevelDB::class); } Generator::addGenerator(Flat::class, "flat"); Generator::addGenerator(Normal::class, "normal"); Generator::addGenerator(Normal::class, "default"); foreach ((array) $this->getProperty("worlds", []) as $name => $worldSetting) { if ($this->loadLevel($name) === false) { $seed = $this->getProperty("worlds.{$name}.seed", time()); $options = explode(":", $this->getProperty("worlds.{$name}.generator", Generator::getGenerator("default"))); $generator = Generator::getGenerator(array_shift($options)); if (count($options) > 0) { $options = ["preset" => implode(":", $options)]; } else { $options = []; } $this->generateLevel($name, $seed, $generator, $options); } } if ($this->getDefaultLevel() === null) { $default = $this->getConfigString("level-name", "world"); if (trim($default) == "") { $this->getLogger()->warning("level-name cannot be null, using default"); $default = "world"; $this->setConfigString("level-name", "world"); } if ($this->loadLevel($default) === false) { $seed = $this->getConfigInt("level-seed", time()); $this->generateLevel($default, $seed === 0 ? time() : $seed); } $this->setDefaultLevel($this->getLevelByName($default)); } $this->properties->save(); if (!$this->getDefaultLevel() instanceof Level) { $this->getLogger()->emergency("No default level has been loaded"); $this->forceShutdown(); return; } $this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([Cache::class, "cleanup"]), $this->getProperty("ticks-per.cache-cleanup", 900), $this->getProperty("ticks-per.cache-cleanup", 900)); if ($this->getAutoSave() and $this->getProperty("ticks-per.autosave", 6000) > 0) { $this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "doAutoSave"]), $this->getProperty("ticks-per.autosave", 6000), $this->getProperty("ticks-per.autosave", 6000)); } if ($this->getProperty("chunk-gc.period-in-ticks", 600) > 0) { $this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "doLevelGC"]), $this->getProperty("chunk-gc.period-in-ticks", 600), $this->getProperty("chunk-gc.period-in-ticks", 600)); } $this->scheduler->scheduleRepeatingTask(new GarbageCollectionTask(), 900); $this->enablePlugins(PluginLoadOrder::POSTWORLD); if ($this->getAdvancedProperty("main.player-shuffle", 0) > 0) { $this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "shufflePlayers"]), $this->getAdvancedProperty("main.player-shuffle", 0), $this->getAdvancedProperty("main.player-shuffle", 0)); } $this->start(); }
/** * Init the default level data * * @param Server $server * @param string $name * @param string $path * @param string $provider Class that extends LevelProvider * * @throws \Exception */ public function __construct(Server $server, $name, $path, $provider) { $this->blockStates = Block::$fullList; $this->levelId = static::$levelIdCounter++; $this->blockMetadata = new BlockMetadataStore($this); $this->server = $server; $this->autoSave = $server->getAutoSave(); /** @var LevelProvider $provider */ if (is_subclass_of($provider, LevelProvider::class, true)) { $this->provider = new $provider($this, $path); } else { throw new LevelException("Provider is not a subclass of LevelProvider"); } $this->server->getLogger()->info($this->server->getLanguage()->translateString("pocketmine.level.preparing", [$this->provider->getName()])); $this->generator = Generator::getGenerator($this->provider->getGenerator()); $this->blockOrder = $provider::getProviderOrder(); $this->useSections = $provider::usesChunkSection(); $this->folderName = $name; $this->updateQueue = new ReversePriorityQueue(); $this->updateQueue->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); $this->time = (int) $this->provider->getTime(); $this->weatherEnabled = (bool) $this->getServer()->getProperty("weather-settings.enable-weather"); $this->weatherMinutes = $this->getServer()->getProperty("weather-settings.weather-minutes"); if ($this->weatherMinutes === strtolower("random") || $this->weatherMinutes === null) { $this->weatherMinutes = mt_rand(3, 5); } if ($this->weatherEnabled === true) { $this->raining = $this->provider->isRaining(); $this->rainTime = $this->provider->getRainTime(); if ($this->rainTime <= 0) { $this->setRainTime($this->weatherMinutes * 20 * 60); } $this->randomWeather = mt_rand(0, 400); $this->thundering = $this->provider->isThundering(); $this->thunderTime = $this->provider->getThunderTime(); if ($this->thunderTime <= 0) { $this->setThunderTime($this->weatherMinutes * 20 * 60); } } foreach ($this->getServer()->getProperty("disable-block-ticking", []) as $id) { $ticked = isset($this->randomTickBlocks[$id]); if ($ticked === true) { unset($this->randomTickBlocks[$id]); } } $this->updateRedstoneQueue = new ReversePriorityQueue(); $this->updateRedstoneQueue->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); $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->chunkGenerationQueueSize = (int) $this->server->getProperty("chunk-generation.queue-size", 8); $this->chunkPopulationQueueSize = (int) $this->server->getProperty("chunk-generation.population-queue-size", 2); $this->chunkTickList = []; $this->clearChunksOnTick = (bool) $this->server->getProperty("chunk-ticking.clear-tick-list", true); $this->cacheChunks = (bool) $this->server->getProperty("chunk-sending.cache-chunks", false); $this->timings = new LevelTimings($this); $this->temporalPosition = new Position(0, 0, 0, $this); $this->temporalVector = new Vector3(0, 0, 0); $this->temporalVector2 = new Vector3(0, 0, 0); $this->tickRate = 1; }
/** * Init the default level data * * @param Server $server * @param string $name * @param string $path * @param string $provider Class that extends LevelProvider * * @throws \Exception */ public function __construct(Server $server, $name, $path, $provider) { $this->blockStates = Block::$fullList; $this->levelId = static::$levelIdCounter++; $this->blockMetadata = new BlockMetadataStore($this); $this->server = $server; $this->autoSave = $server->getAutoSave(); /** @var LevelProvider $provider */ if (\is_subclass_of($provider, LevelProvider::class, \true)) { $this->provider = new $provider($this, $path); } else { throw new LevelException("Provider is not a subclass of LevelProvider"); } $this->server->getLogger()->info("Preparing level \"" . $this->provider->getName() . "\""); $this->generator = Generator::getGenerator($this->provider->getGenerator()); $this->blockOrder = $provider::getProviderOrder(); $this->useSections = $provider::usesChunkSection(); $this->folderName = $name; $this->updateQueue = new ReversePriorityQueue(); $this->updateQueue->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); $this->time = (int) $this->provider->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", 0); $this->chunkTickList = []; $this->clearChunksOnTick = (bool) $this->server->getProperty("chunk-ticking.clear-tick-list", \false); $this->timings = new LevelTimings($this); $this->temporalPosition = new Position(0, 0, 0, $this); $this->temporalVector = new Vector3(0, 0, 0); }
/** * @param \ClassLoader $autoloader * @param \ThreadedLogger $logger * @param string $filePath * @param string $dataPath * @param string $pluginPath */ public function __construct(\ClassLoader $autoloader, \ThreadedLogger $logger, $filePath, $dataPath, $pluginPath) { self::$instance = $this; self::$sleeper = new \Threaded(); $this->autoloader = $autoloader; $this->logger = $logger; $this->filePath = $filePath; try { if (!file_exists($dataPath . "worlds/")) { mkdir($dataPath . "worlds/", 0777); } if (!file_exists($dataPath . "players/")) { mkdir($dataPath . "players/", 0777); } if (!file_exists($pluginPath)) { mkdir($pluginPath, 0777); } if (!file_exists($dataPath . "crashdumps/")) { mkdir($dataPath . "crashdumps/", 0777); } $this->dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR; $this->pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR; $this->console = new CommandReader(); $version = new VersionString($this->getPocketMineVersion()); $this->version = $version; $this->aboutstring = "\n\n\t\t §5PocketMine-iTX §3Genisys §fis a fork of PocketMine-MP.\n\t\t Powered by §5iTX Technologies LLC.\n\t\t §fVersion: §6" . $this->getPocketMineVersion() . "\n\t\t §fClient Version: §d0.13.1 alpha\n\t\t §fYou could get the lastest code on https://github.com/iTXTech/Genisys\n\t\t §fDonate link: http://pl.zxda.net/plugins/203.html\n\t\t §f如果你在免费使用本核心,希望你可以进入上面的链接捐赠给我们,这会成为我们前进的动力。\n\t\t\n"; $this->about(); $this->logger->info("Loading pocketmine.yml..."); if (!file_exists($this->dataPath . "pocketmine.yml")) { $content = file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml"); if ($version->isDev()) { $content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content); } @file_put_contents($this->dataPath . "pocketmine.yml", $content); } $this->config = new Config($this->dataPath . "pocketmine.yml", Config::YAML, []); $this->logger->info("Loading genisys.yml..."); $lang = $this->getProperty("settings.language", BaseLang::FALLBACK_LANGUAGE); if (file_exists($this->filePath . "src/pocketmine/resources/genisys_{$lang}.yml")) { $content = file_get_contents($file = $this->filePath . "src/pocketmine/resources/genisys_{$lang}.yml"); } else { $content = file_get_contents($file = $this->filePath . "src/pocketmine/resources/genisys_eng.yml"); } if (!file_exists($this->dataPath . "genisys.yml")) { @file_put_contents($this->dataPath . "genisys.yml", $content); } $internelConfig = new Config($file, Config::YAML, []); $this->advancedConfig = new Config($this->dataPath . "genisys.yml", Config::YAML, []); $cfgVer = $this->getAdvancedProperty("config.version", 0, $internelConfig); $advVer = $this->getAdvancedProperty("config.version", 0); $this->loadAdvancedConfig(); if ($this->expWriteAhead > 0) { $this->generateExpCache($this->expWriteAhead); } $this->logger->info("Loading server properties..."); $this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, ["motd" => "Minecraft: PE Server", "server-port" => 19132, "white-list" => false, "announce-player-achievements" => true, "spawn-protection" => 16, "max-players" => 20, "allow-flight" => false, "spawn-animals" => true, "spawn-mobs" => true, "gamemode" => 0, "force-gamemode" => false, "hardcore" => false, "pvp" => true, "difficulty" => 1, "generator-settings" => "", "level-name" => "world", "level-seed" => "", "level-type" => "DEFAULT", "enable-query" => true, "enable-rcon" => false, "rcon.password" => substr(base64_encode(@Utils::getRandomBytes(20, false)), 3, 10), "auto-save" => true]); $this->forceLanguage = $this->getProperty("settings.force-language", false); $this->baseLang = new BaseLang($this->getProperty("settings.language", BaseLang::FALLBACK_LANGUAGE)); $this->logger->info($this->getLanguage()->translateString("language.selected", [$this->getLanguage()->getName(), $this->getLanguage()->getLang()])); $this->memoryManager = new MemoryManager($this); $this->logger->info($this->getLanguage()->translateString("pocketmine.server.start", [TextFormat::AQUA . $this->getVersion()])); if (($poolSize = $this->getProperty("settings.async-workers", "auto")) === "auto") { $poolSize = ServerScheduler::$WORKERS; $processors = Utils::getCoreCount() - 2; if ($processors > 0) { $poolSize = max(1, $processors); } } ServerScheduler::$WORKERS = $poolSize; if ($this->getProperty("network.batch-threshold", 256) >= 0) { Network::$BATCH_THRESHOLD = (int) $this->getProperty("network.batch-threshold", 256); } else { Network::$BATCH_THRESHOLD = -1; } $this->networkCompressionLevel = $this->getProperty("network.compression-level", 7); $this->networkCompressionAsync = $this->getProperty("network.async-compression", true); $this->autoTickRate = (bool) $this->getProperty("level-settings.auto-tick-rate", true); $this->autoTickRateLimit = (int) $this->getProperty("level-settings.auto-tick-rate-limit", 20); $this->alwaysTickPlayers = (int) $this->getProperty("level-settings.always-tick-players", false); $this->baseTickRate = (int) $this->getProperty("level-settings.base-tick-rate", 1); $this->scheduler = new ServerScheduler(); if ($this->getConfigBoolean("enable-rcon", false) === true) { $this->rcon = new RCON($this, $this->getConfigString("rcon.password", ""), $this->getConfigInt("rcon.port", $this->getPort()), ($ip = $this->getIp()) != "" ? $ip : "0.0.0.0", $this->getConfigInt("rcon.threads", 1), $this->getConfigInt("rcon.clients-per-thread", 50)); } $this->entityMetadata = new EntityMetadataStore(); $this->playerMetadata = new PlayerMetadataStore(); $this->levelMetadata = new LevelMetadataStore(); $this->operators = new Config($this->dataPath . "ops.txt", Config::ENUM); $this->whitelist = new Config($this->dataPath . "white-list.txt", Config::ENUM); if (file_exists($this->dataPath . "banned.txt") and !file_exists($this->dataPath . "banned-players.txt")) { @rename($this->dataPath . "banned.txt", $this->dataPath . "banned-players.txt"); } @touch($this->dataPath . "banned-players.txt"); $this->banByName = new BanList($this->dataPath . "banned-players.txt"); $this->banByName->load(); @touch($this->dataPath . "banned-ips.txt"); $this->banByIP = new BanList($this->dataPath . "banned-ips.txt"); $this->banByIP->load(); @touch($this->dataPath . "banned-cids.txt"); $this->banByCID = new BanList($this->dataPath . "banned-cids.txt"); $this->banByCID->load(); $this->maxPlayers = $this->getConfigInt("max-players", 20); $this->setAutoSave($this->getConfigBoolean("auto-save", true)); if ($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3) { $this->setConfigInt("difficulty", 3); } define("pocketmine\\DEBUG", (int) $this->getProperty("debug.level", 1)); if ($this->logger instanceof MainLogger) { $this->logger->setLogDebug(\pocketmine\DEBUG > 1); } if (\pocketmine\DEBUG >= 0) { @cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion()); } $this->logger->info($this->getLanguage()->translateString("pocketmine.server.networkStart", [$this->getIp() === "" ? "*" : $this->getIp(), $this->getPort()])); define("BOOTUP_RANDOM", @Utils::getRandomBytes(16)); $this->serverID = Utils::getMachineUniqueId($this->getIp() . $this->getPort()); $this->getLogger()->debug("Server unique id: " . $this->getServerUniqueId()); $this->getLogger()->debug("Machine unique id: " . Utils::getMachineUniqueId()); $this->network = new Network($this); $this->network->setName($this->getMotd()); $this->logger->info($this->getLanguage()->translateString("pocketmine.server.info", [$this->getName(), $this->getPocketMineVersion(), $this->getCodename(), $this->getApiVersion()])); $this->logger->info($this->getLanguage()->translateString("pocketmine.server.license", [$this->getName()])); Timings::init(); $this->consoleSender = new ConsoleCommandSender(); $this->commandMap = new SimpleCommandMap($this); $this->registerEntities(); $this->registerTiles(); InventoryType::init(min(32, $this->inventoryNum)); //Bigger than 32 with cause problems Block::init(); Item::init(); Biome::init(); Effect::init(); Enchantment::init(); Attribute::init(); /** TODO: @deprecated */ //TextWrapper::init(); $this->craftingManager = new CraftingManager($this->readRecipesFromJson); $this->pluginManager = new PluginManager($this, $this->commandMap); $this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender); $this->pluginManager->setUseTimings($this->getProperty("settings.enable-profiling", false)); $this->profilingTickRate = (double) $this->getProperty("settings.profile-report-trigger", 20); $this->pluginManager->registerInterface(PharPluginLoader::class); $this->pluginManager->registerInterface(FolderPluginLoader::class); $this->pluginManager->registerInterface(ScriptPluginLoader::class); //set_exception_handler([$this, "exceptionHandler"]); register_shutdown_function([$this, "crashDump"]); $this->queryRegenerateTask = new QueryRegenerateEvent($this, 5); $this->network->registerInterface(new RakLibInterface($this)); $this->pluginManager->loadPlugins($this->pluginPath); //$this->updater = new AutoUpdater($this, $this->getProperty("auto-updater.host", "www.pocketmine.net")); $this->enablePlugins(PluginLoadOrder::STARTUP); LevelProviderManager::addProvider($this, Anvil::class); LevelProviderManager::addProvider($this, McRegion::class); if (extension_loaded("leveldb")) { $this->logger->debug($this->getLanguage()->translateString("pocketmine.debug.enable")); LevelProviderManager::addProvider($this, LevelDB::class); } Generator::addGenerator(Flat::class, "flat"); Generator::addGenerator(Normal::class, "normal"); Generator::addGenerator(Normal::class, "default"); Generator::addGenerator(Nether::class, "hell"); Generator::addGenerator(Nether::class, "nether"); foreach ((array) $this->getProperty("worlds", []) as $name => $worldSetting) { if ($this->loadLevel($name) === false) { $seed = $this->getProperty("worlds.{$name}.seed", time()); $options = explode(":", $this->getProperty("worlds.{$name}.generator", Generator::getGenerator("default"))); $generator = Generator::getGenerator(array_shift($options)); if (count($options) > 0) { $options = ["preset" => implode(":", $options)]; } else { $options = []; } $this->generateLevel($name, $seed, $generator, $options); } } if ($this->getDefaultLevel() === null) { $default = $this->getConfigString("level-name", "world"); if (trim($default) == "") { $this->getLogger()->warning("level-name cannot be null, using default"); $default = "world"; $this->setConfigString("level-name", "world"); } if ($this->loadLevel($default) === false) { $seed = $this->getConfigInt("level-seed", time()); $this->generateLevel($default, $seed === 0 ? time() : $seed); } $this->setDefaultLevel($this->getLevelByName($default)); } $this->properties->save(true); if (!$this->getDefaultLevel() instanceof Level) { $this->getLogger()->emergency($this->getLanguage()->translateString("pocketmine.level.defaultError")); $this->forceShutdown(); return; } if ($this->netherEnabled) { if (!$this->loadLevel($this->netherName)) { //$this->logger->info("正在生成地狱 ".$this->netherName); $this->generateLevel($this->netherName, time(), Generator::getGenerator("nether")); } $this->netherLevel = $this->getLevelByName($this->netherName); } if ($this->getProperty("ticks-per.autosave", 6000) > 0) { $this->autoSaveTicks = (int) $this->getProperty("ticks-per.autosave", 6000); } $this->enablePlugins(PluginLoadOrder::POSTWORLD); if ($this->aiEnabled) { $this->aiHolder = new AIHolder($this); } if ($this->dserverConfig["enable"] and $this->getAdvancedProperty("dserver.server-list", "") != "") { $this->scheduler->scheduleRepeatingTask(new CallbackTask([$this, "updateDServerInfo"]), $this->dserverConfig["timer"]); } if ($cfgVer != $advVer) { $this->logger->notice("Your genisys.yml needs update"); $this->logger->notice("Current Version: {$advVer} Latest Version: {$cfgVer}"); } $this->generateRecipeList(); $this->start(); } catch (\Throwable $e) { $this->exceptionHandler($e); } }
/** * @param \ClassLoader $autoloader * @param \ThreadedLogger $logger * @param string $filePath * @param string $dataPath * @param string $pluginPath */ public function __construct(\ClassLoader $autoloader, \ThreadedLogger $logger, $filePath, $dataPath, $pluginPath) { self::$instance = $this; self::$sleeper = new \Threaded(); $this->autoloader = $autoloader; $this->logger = $logger; $this->filePath = $filePath; try { if (!file_exists($dataPath . "crashdumps/")) { mkdir($dataPath . "crashdumps/", 0777); } if (!file_exists($dataPath . "worlds/")) { mkdir($dataPath . "worlds/", 0777); } if (!file_exists($dataPath . "players/")) { mkdir($dataPath . "players/", 0777); } if (!file_exists($pluginPath)) { mkdir($pluginPath, 0777); } $this->dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR; $this->pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR; $this->console = new CommandReader($logger); $version = new VersionString($this->getPocketMineVersion()); $reloadpreConfig = false; $this->logger->info("Loading pocketmine.yml..."); if (!file_exists($this->dataPath . "pocketmine.yml")) { //$content = $this->translateConfig(file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml"),"eng"); $content = \file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml"); @\file_put_contents($this->dataPath . "pocketmine.yml", $content); } else { $this->config = new Config($this->dataPath . "pocketmine.yml", Config::YAML, []); $internal_config = yaml_parse(file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml")); if ($this->getProperty("version", 0) < $internal_config['version']) { $this->logger->warning("Outdated pocketmine.yml"); if ($this->getProperty("settings.config-update", true)) { $this->logger->info("Updating pocketmine.yml..."); if (!$this->getProperty("temp-file", false)) { rename($this->dataPath . "pocketmine.yml", $this->dataPath . "pocketmine.yml." . time() . ".bak"); } //$content = $this->translateConfig(file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml"),$this->getProperty("settings.language", "eng")); $content = \file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml"); @\file_put_contents($this->dataPath . "pocketmine.yml", $content); } else { $this->logger->info("Ignore outdated pocketmine.yml"); } } unset($inernal_config); } $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" => "Minecraft: PE Server", "server-port" => 19132, "white-list" => false, "announce-player-achievements" => true, "spawn-protection" => 16, "max-players" => 20, "allow-flight" => false, "spawn-animals" => true, "spawn-mobs" => true, "gamemode" => 0, "force-gamemode" => false, "hardcore" => false, "pvp" => true, "difficulty" => 1, "generator-settings" => "", "level-name" => "world", "level-seed" => "", "level-type" => "DEFAULT", "enable-query" => true, "enable-rcon" => false, "rcon.password" => substr(base64_encode(random_bytes(20)), 3, 10), "auto-save" => true, "online-mode" => false]); if (!extension_loaded("openssl") && $this->getConfigBoolean("online-mode", false)) { $this->logger->warning("The OpenSSL extension is not loaded, and this is required for XBOX authentication to work. If you want to use Xbox Live auth, please use PHP binarys with OpenSSL, or recompile PHP with the OpenSSL extension."); //TODO:TRANSLATE $this->setConfigBool("online-mode", false); } if (extension_loaded("xdebug")) { if (!$this->getProperty("debug.allow-xdebug", false)) { $this->logger->critical("Please do not use a PHP installation with the xDebug extension loaded for a Production server. If you do want to use it however, set debug.allow-xdebug to true."); //TODO:TRANSLATE return; } else { $this->logger->warning("xDebug is enabled, this decreases Performance. Use this for development purposes only."); //TODO:TRANSLATE } } if (!$this->getProperty("I/O.log-to-file", true)) { $this->logger->disable(); $this->logger->info("MainLogger will not write to server.log"); //TODO:TRANSLATE } else { $this->logger->enable(); $this->logger->info("MainLogger will write to server.log"); //TODO:TRANSLATE } $this->forceLanguage = $this->getProperty("settings.force-language", false); $this->baseLang = new BaseLang($this->getProperty("settings.language", BaseLang::FALLBACK_LANGUAGE)); $this->logger->info($this->getLanguage()->translateString("language.selected", [$this->getLanguage()->getName(), $this->getLanguage()->getLang()])); $this->memoryManager = new MemoryManager($this); $this->logger->info($this->getLanguage()->translateString("pocketmine.server.start", [TextFormat::AQUA . $this->getVersion()])); if (($poolSize = $this->getProperty("settings.async-workers", "auto")) === "auto") { $poolSize = ServerScheduler::$WORKERS; $processors = Utils::getCoreCount() - 2; if ($processors > 0) { $poolSize = max(1, $processors); } } ServerScheduler::$WORKERS = $poolSize; if ($this->getProperty("network.batch-threshold", 256) >= 0) { Network::$BATCH_THRESHOLD = (int) $this->getProperty("network.batch-threshold", 256); } else { Network::$BATCH_THRESHOLD = -1; } $this->networkCompressionLevel = $this->getProperty("network.compression-level", 7); $this->networkCompressionAsync = $this->getProperty("network.async-compression", true); $this->autoTickRate = (bool) $this->getProperty("level-settings.auto-tick-rate", true); $this->autoTickRateLimit = (int) $this->getProperty("level-settings.auto-tick-rate-limit", 20); $this->alwaysTickPlayers = (int) $this->getProperty("level-settings.always-tick-players", false); $this->baseTickRate = (int) $this->getProperty("level-settings.base-tick-rate", 1); $this->scheduler = new ServerScheduler(); if ($this->getConfigBoolean("enable-rcon", false) === true) { $this->rcon = new RCON($this, $this->getConfigString("rcon.password", ""), $this->getConfigInt("rcon.port", $this->getPort()), ($ip = $this->getIp()) != "" ? $ip : "0.0.0.0", $this->getConfigInt("rcon.threads", 1), $this->getConfigInt("rcon.clients-per-thread", 50)); } $this->entityMetadata = new EntityMetadataStore(); $this->playerMetadata = new PlayerMetadataStore(); $this->levelMetadata = new LevelMetadataStore(); $this->operators = new Config($this->dataPath . "ops.txt", Config::ENUM); $this->whitelist = new Config($this->dataPath . "white-list.txt", Config::ENUM); if (file_exists($this->dataPath . "banned.txt") and !file_exists($this->dataPath . "banned-players.txt")) { @rename($this->dataPath . "banned.txt", $this->dataPath . "banned-players.txt"); } @touch($this->dataPath . "banned-players.txt"); $this->banByName = new BanList($this->dataPath . "banned-players.txt"); $this->banByName->load(); @touch($this->dataPath . "banned-ips.txt"); $this->banByIP = new BanList($this->dataPath . "banned-ips.txt"); $this->banByIP->load(); $this->maxPlayers = $this->getConfigInt("max-players", 20); $this->setAutoSave($this->getConfigBoolean("auto-save", true)); if ($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3) { $this->setConfigInt("difficulty", 3); } define('pocketmine\\DEBUG', (int) $this->getProperty("debug.level", 1)); ini_set('assert.exception', 1); if ($this->logger instanceof MainLogger) { $this->logger->setLogDebug(\pocketmine\DEBUG > 1); } if (\pocketmine\DEBUG >= 0) { @cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion()); } $this->logger->info($this->getLanguage()->translateString("pocketmine.server.networkStart", [$this->getIp() === "" ? "*" : $this->getIp(), $this->getPort()])); define("BOOTUP_RANDOM", random_bytes(16)); $this->serverID = Utils::getMachineUniqueId($this->getIp() . $this->getPort()); $this->getLogger()->debug("Server unique id: " . $this->getServerUniqueId()); $this->getLogger()->debug("Machine unique id: " . Utils::getMachineUniqueId()); $this->network = new Network($this); $this->network->setName($this->getMotd()); $this->logger->info($this->getLanguage()->translateString("pocketmine.server.info", [$this->getName(), $this->getPocketMineVersion(), $this->getCodename(), $this->getApiVersion(), $this->getPocketMineBuild()])); $this->logger->info($this->getLanguage()->translateString("pocketmine.server.license", [$this->getName()])); Timings::init(); $this->consoleSender = new ConsoleCommandSender(); $this->commandMap = new SimpleCommandMap($this); $this->registerEntities(); $this->registerTiles(); InventoryType::init(); Block::init(); Item::init(); Biome::init(); Effect::init(); Enchantment::init(); Attribute::init(); EnchantmentLevelTable::init(); Color::init(); $this->craftingManager = new CraftingManager(); $this->pluginManager = new PluginManager($this, $this->commandMap); $this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender); $this->pluginManager->setUseTimings($this->getProperty("settings.enable-profiling", false)); $this->profilingTickRate = (double) $this->getProperty("settings.profile-report-trigger", 20); $this->pluginManager->registerInterface(PharPluginLoader::class); $this->pluginManager->registerInterface(ScriptPluginLoader::class); register_shutdown_function([$this, "crashDump"]); $this->queryRegenerateTask = new QueryRegenerateEvent($this, 5); $this->network->registerInterface(new RakLibInterface($this)); $this->pluginManager->loadPlugins($this->pluginPath); $this->updater = new AutoUpdater($this, $this->getProperty("auto-updater.host", "jenkins.clearskyteam.org")); $this->enablePlugins(PluginLoadOrder::STARTUP); LevelProviderManager::addProvider($this, Anvil::class); LevelProviderManager::addProvider($this, McRegion::class); if (extension_loaded("leveldb")) { $this->logger->debug($this->getLanguage()->translateString("pocketmine.debug.enable")); LevelProviderManager::addProvider($this, LevelDB::class); } Generator::addGenerator(Flat::class, "flat"); Generator::addGenerator(Normal::class, "normal"); Generator::addGenerator(Normal::class, "default"); Generator::addGenerator(Nether::class, "hell"); Generator::addGenerator(Nether::class, "nether"); foreach ((array) $this->getProperty("worlds", []) as $name => $worldSetting) { if ($this->loadLevel($name) === false) { $seed = $this->getProperty("worlds.{$name}.seed", time()); $options = explode(":", $this->getProperty("worlds.{$name}.generator", Generator::getGenerator("default"))); $generator = Generator::getGenerator(array_shift($options)); if (count($options) > 0) { $options = ["preset" => implode(":", $options)]; } else { $options = []; } $this->generateLevel($name, $seed, $generator, $options); } } if ($this->getDefaultLevel() === null) { $default = $this->getConfigString("level-name", "world"); if (trim($default) == "") { $this->getLogger()->warning("level-name cannot be null, using default"); $default = "world"; $this->setConfigString("level-name", "world"); } if ($this->loadLevel($default) === false) { $seed = getopt("", ["level-seed::"])["level-seed"] ?? $this->properties->get("level-seed", time()); if (!is_numeric($seed) or bccomp($seed, "9223372036854775807") > 0) { $seed = Utils::javaStringHash($seed); } elseif (PHP_INT_SIZE === 8) { $seed = (int) $seed; } $this->generateLevel($default, $seed === 0 ? time() : $seed); } $this->setDefaultLevel($this->getLevelByName($default)); } $this->properties->save(true); if (!$this->getDefaultLevel() instanceof Level) { $this->getLogger()->emergency($this->getLanguage()->translateString("pocketmine.level.defaultError")); $this->forceShutdown(); return; } if ($this->getProperty("ticks-per.autosave", 6000) > 0) { $this->autoSaveTicks = (int) $this->getProperty("ticks-per.autosave", 6000); } $this->enablePlugins(PluginLoadOrder::POSTWORLD); $this->start(); } catch (\Throwable $e) { $this->exceptionHandler($e); } }
public function createHell() { $generator = Generator::getGenerator("nether"); $bool = $this->getServer()->generateLevel("nether", null, $generator); if (!$this->getServer()->getLevelByName("nether") instanceof Level) { $this->getServer()->loadLevel("nether"); } if (!$bool) { $level = $this->getServer()->getLevelByName("nether"); if ($level instanceof Level) { $spawn = $level->getSafeSpawn(); $level->generateChunk($spawn->x, $spawn->z); $x = $spawn->x; $y = $spawn->y; $z = $spawn->z; $hellDoorData = $this->locationProvider->getLocationToName("@hellLocation"); $hellDoorData->savePosition(new Position($x, $y + 2, $z, $level)); $z -= 2; // DOOR CREATE $doorLength = 6; $doorHeight = 10; $portalBlock = new Block(90); $vector = new Vector3($x, $y, $z); $centerX = $x + $doorLength / 2; for ($dx = 0; $dx <= $doorLength - 1; $dx++) { $level->setBlock($vector->setComponents($centerX + $dx, $y, $z), $portalBlock); $level->setBlock($vector->setComponents($centerX + $dx, $y + $doorHeight, $z), $portalBlock); } for ($dy = 0; $dy <= $doorHeight - 1; $dy++) { $level->setBlock($vector->setComponents($centerX - $doorLength / 2, $y + $dy, $z), $portalBlock); $level->setBlock($vector->setComponents($centerX + $doorLength / 2, $y + $dy, $z), $portalBlock); } $startX = $centerX - $doorLength / 2; $startY = $y; $startZ = $z; $endX = $centerX + $doorLength / 2; $endY = $y + $doorHeight; $endZ = $z; if ($startX > $endX) { $backup = $endX; $endX = $startX; $startX = $backup; } if ($startY > $endY) { $backup = $endY; $endY = $startY; $startY = $backup; } if ($startZ > $endZ) { $backup = $endZ; $endZ = $startZ; $startZ = $backup; } $startY++; $endY = $endY - 2; if ($startZ == $endZ) { $startX++; $endX--; } else { $startZ++; $endZ--; } for ($x = $startX; $x <= $endX; $x++) { for ($y = $startY; $y <= $endY; $y++) { for ($z = $startZ; $z <= $endZ; $z++) { $level->setBlock($vector->setComponents($x, $y, $z), $portalBlock); } } } } } }
/** * Init the default level data * * @param Server $server * @param string $name * @param string $path * @param string $provider Class that extends LevelProvider * * @throws \Exception */ public function __construct(Server $server, string $name, string $path, string $provider) { $this->blockStates = Block::$fullList; $this->levelId = static::$levelIdCounter++; $this->blockMetadata = new BlockMetadataStore($this); $this->server = $server; $this->autoSave = $server->getAutoSave(); /** Weather Config Loader */ $this->rainprob = $this->getServer()->getProperty("level-settings.weather.rain.possibility", 10); $this->raintime[] = $this->getServer()->getProperty("level-settings.weather.rain.time.min", 30); $this->raintime[] = $this->getServer()->getProperty("level-settings.weather.rain.time.max", 120); $this->rainfall[] = $this->getServer()->getProperty("level-settings.weather.rain.rainfall.min", 1000); $this->rainfall[] = $this->getServer()->getProperty("level-settings.weather.rain.rainfall.max", 100000); /** @var LevelProvider $provider */ if (is_subclass_of($provider, LevelProvider::class, true)) { $this->provider = new $provider($this, $path); } else { throw new LevelException("Provider is not a subclass of LevelProvider"); } $this->server->getLogger()->info($this->server->getLanguage()->translateString("pocketmine.level.preparing", [$this->provider->getName()])); $this->generator = Generator::getGenerator($this->provider->getGenerator()); $this->blockOrder = $provider::getProviderOrder(); $this->useSections = $provider::usesChunkSection(); $this->folderName = $name; $this->updateQueue = new ReversePriorityQueue(); $this->updateQueue->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); $this->time = (int) $this->provider->getTime(); /** Set dimension */ if ($server->netherName == $this->folderName) { $this->setDimension(self::DIMENSION_NETHER); } else { $this->setDimension(self::DIMENSION_NORMAL); } $this->gamerules = new GameRules($this->provider->getGameRules()); $this->getGameRule("doDaylightCycle") ? $this->startTime() : $this->stopTime(); /** Random ticking */ foreach ($this->getServer()->getProperty("chunk-ticking.disabled-randomly-ticking-blocks", []) as $id) { $ticked = isset($this->randomTickBlocks[$id]); if ($ticked === true) { unset($this->randomTickBlocks[$id]); } } $this->updateRedstoneQueue = new ReversePriorityQueue(); $this->updateRedstoneQueue->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); $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->chunkGenerationQueueSize = (int) $this->server->getProperty("chunk-generation.queue-size", 8); $this->chunkPopulationQueueSize = (int) $this->server->getProperty("chunk-generation.population-queue-size", 2); $this->chunkTickList = []; $this->clearChunksOnTick = (bool) $this->server->getProperty("chunk-ticking.clear-tick-list", true); $this->cacheChunks = (bool) $this->server->getProperty("chunk-sending.cache-chunks", false); $this->timings = new LevelTimings($this); $this->temporalPosition = new Position(0, 0, 0, $this); $this->temporalVector = new Vector3(0, 0, 0); $this->tickRate = 1; }