public function generateChunk($chunkX, $chunkZ) { if ($this->emptyChunk !== null) { //Use the cached empty chunk instead of generating a new one $this->chunk = clone $this->emptyChunk; } else { $this->chunk = clone $this->level->getChunk($chunkX, $chunkZ); $this->chunk->setGenerated(); $c = Biome::getBiome(1)->getColor(); $R = $c >> 16; $G = $c >> 8 & 0xff; $B = $c & 0xff; for ($Z = 0; $Z < 16; ++$Z) { for ($X = 0; $X < 16; ++$X) { $this->chunk->setBiomeId($X, $Z, 1); $this->chunk->setBiomeColor($X, $Z, $R, $G, $B); for ($y = 0; $y < 128; ++$y) { $this->chunk->setBlockId($X, $y, $Z, Block::AIR); } } } $spawn = $this->getSpawn(); if ($spawn->getX() >> 4 === $chunkX and $spawn->getZ() >> 4 === $chunkZ) { $this->chunk->setBlockId(0, 64, 0, Block::GRASS); } else { $this->emptyChunk = $this->chunk; } } $chunk = clone $this->chunk; $chunk->setX($chunkX); $chunk->setZ($chunkZ); $this->level->setChunk($chunkX, $chunkZ, $chunk); }
public function execute(CommandSender $sender, array $args) { if (count($args) === 0) { $biomes = TextFormat::WHITE . implode(", ", array_keys($this->biomes)); $sender->sendMessage($this->translateString("biome.possible", [$biomes])); return true; } elseif (count($args) !== 1) { return false; } $player = $sender->getServer()->getPlayer($sender->getName()); $biome = strtoupper($args[0]); $plot = $this->getPlugin()->getPlotByPosition($player->getPosition()); if ($plot === null) { $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return true; } if ($plot->owner !== $sender->getName()) { $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); return true; } if (!isset($this->biomes[$biome])) { $sender->sendMessage(TextFormat::RED . $this->translateString("biome.invalid")); $biomes = implode(", ", array_keys($this->biomes)); $sender->sendMessage(TextFormat::RED . $this->translateString("biome.possible", [$biomes])); return true; } $biome = Biome::getBiome($this->biomes[$biome]); if ($this->getPlugin()->setPlotBiome($plot, $biome)) { $sender->sendMessage($this->translateString("biome.success", [$biome->getName()])); } else { $sender->sendMessage(TextFormat::RED . $this->translateString("error")); } return true; }
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) { $chunk = $level->getChunk($chunkX, $chunkZ); for ($x = 0; $x < 16; ++$x) { for ($z = 0; $z < 16; ++$z) { $biome = Biome::getBiome($chunk->getBiomeId($x, $z)); $cover = $biome->getGroundCover(); if (count($cover) > 0) { $diffY = 0; if (!$cover[0]->isSolid()) { $diffY = 1; } $column = $chunk->getBlockIdColumn($x, $z); for ($y = 127; $y > 0; --$y) { if ($column[$y] !== "" and !Block::get(ord($column[$y]))->isTransparent()) { break; } } $startY = min(127, $y + $diffY); $endY = $startY - count($cover); for ($y = $startY; $y > $endY and $y >= 0; --$y) { $b = $cover[$startY - $y]; if ($column[$y] === "" and $b->isSolid()) { break; } if ($b->getDamage() === 0) { $chunk->setBlockId($x, $y, $z, $b->getId()); } else { $chunk->setBlock($x, $y, $z, $b->getId(), $b->getDamage()); } } } } } }
public function execute(CommandSender $sender, array $args) { if (count($args) !== 1) { return false; } $player = $sender->getServer()->getPlayer($sender->getName()); $biome = strtoupper($args[0]); $plot = $this->getPlugin()->getPlotByPosition($player->getPosition()); if ($plot === null) { $sender->sendMessage(TextFormat::RED . "You are not standing on an island"); return true; } if ($plot->owner !== $sender->getName()) { $sender->sendMessage(TextFormat::RED . "You are not the owner of this island"); return true; } if (!isset($this->biomes[$biome])) { $sender->sendMessage(TextFormat::RED . "That biome doesn't exist"); $biomes = implode(", ", array_keys($this->biomes)); $sender->sendMessage(TextFormat::RED . "The possible biomes are: {$biomes}"); return true; } $biome = Biome::getBiome($this->biomes[$biome]); if ($this->getPlugin()->setPlotBiome($plot, $biome)) { $sender->sendMessage(TextFormat::GREEN . "Changed the island biome"); } else { $sender->sendMessage(TextFormat::RED . "Could not change the island biome"); } return true; }
protected function parsePreset($preset, $chunkX, $chunkZ) { $this->preset = $preset; $preset = explode(";", $preset); $version = (int) $preset[0]; $blocks = isset($preset[1]) ? $preset[1] : ""; $biome = isset($preset[2]) ? $preset[2] : 1; $options = isset($preset[3]) ? $preset[3] : ""; preg_match_all('#^(([0-9]*x|)([0-9]{1,3})(|:[0-9]{0,2}))$#m', str_replace(",", "\n", $blocks), $matches); $y = 0; $this->structure = []; $this->chunks = []; foreach ($matches[3] as $i => $b) { $b = Item::fromString($b . $matches[4][$i]); $cnt = $matches[2][$i] === "" ? 1 : intval($matches[2][$i]); for ($cY = $y, $y += $cnt; $cY < $y; ++$cY) { $this->structure[$cY] = [$b->getId(), $b->getDamage()]; } } $this->floorLevel = $y; for (; $y < 0xff; ++$y) { $this->structure[$y] = [0, 0]; } $this->chunk = clone $this->level->getChunk($chunkX, $chunkZ); $this->chunk->setGenerated(); $c = Biome::getBiome($biome)->getColor(); $R = $c >> 16; $G = $c >> 8 & 0xff; $B = $c & 0xff; for ($Z = 0; $Z < 16; ++$Z) { for ($X = 0; $X < 16; ++$X) { $this->chunk->setBiomeId($X, $Z, $biome); $this->chunk->setBiomeColor($X, $Z, $R, $G, $B); for ($y = 0; $y < 128; ++$y) { $this->chunk->setBlock($X, $y, $Z, ...$this->structure[$y]); } } } preg_match_all('#(([0-9a-z_]{1,})\\(?([0-9a-z_ =:]{0,})\\)?),?#', $options, $matches); foreach ($matches[2] as $i => $option) { $params = true; if ($matches[3][$i] !== "") { $params = []; $p = explode(" ", $matches[3][$i]); foreach ($p as $k) { $k = explode("=", $k); if (isset($k[1])) { $params[$k[0]] = $k[1]; } } } $this->options[$option] = $params; } }
public function onRun() { Block::init(); Biome::init(); $manager = new SimpleChunkManager($this->seed); $this->saveToThreadStore("generation.level{$this->levelId}.manager", $manager); /** @var Generator $generator */ $generator = $this->generator; $generator = new $generator($this->settings); $generator->init($manager, new Random($manager->getSeed())); $this->saveToThreadStore("generation.level{$this->levelId}.generator", $generator); }
protected function checkOldBiomes($data) { if (strlen($data) !== 256) { return; } for ($x = 0; $x < 16; ++$x) { for ($z = 0; $z < 16; ++$z) { $biome = Biome::getBiome(ord($data[($z << 4) + $x])); $this->setBiomeId($x, $z, $biome->getId()); $c = $biome->getColor(); $this->setBiomeColor($x, $z, $c >> 16, $c >> 8 & 0xff, $c & 0xff); } } }
protected static function register($id, Biome $biome) { self::$biomes[(int) $id] = $biome; $biome->setId((int) $id); $biome->grassColor = self::generateBiomeColor($biome->getTemperature(), $biome->getRainfall()); $flowerPopFound = false; foreach ($biome->getPopulators() as $populator) { if ($populator instanceof Flower) { $flowerPopFound = true; break; } } if ($flowerPopFound === false) { $flower = new Flower(); $biome->addPopulator($flower); } }
public function generateChunk($chunkX, $chunkZ) { $spawn = $this->getSpawn(); // Adjust spawn so it is relative to current chunk... $spawn->x = $spawn->x - ($chunkX << 4); $spawn->z = $spawn->z - ($chunkZ << 4); $inSpawn = -$this->radius <= $spawn->x && $spawn->x < 16 + $this->radius && -$this->radius <= $spawn->z && $spawn->z < 16 + $this->radius; if ($inSpawn || $this->chunk === null) { $chunk = $this->level->getChunk($chunkX, $chunkZ); $chunk->setGenerated(); $c = Biome::getBiome($this->biome)->getColor(); $R = $c >> 16; $G = $c >> 8 & 0xff; $B = $c & 0xff; $rad2 = $this->radius * $this->radius; for ($Z = 0; $Z < 16; ++$Z) { for ($X = 0; $X < 16; ++$X) { $chunk->setBiomeId($X, $Z, $biome); $chunk->setBiomeColor($X, $Z, $R, $G, $B); $chunk->setBlock($X, 0, $Z, $this->baseFloor, 0); for ($y = 1; $y < 128; ++$y) { $chunk->setBlock($X, $y, $Z, Block::AIR, 0); } if (self::inSpawn($rad2, $spawn->x, $spawn->z, $X, $Z)) { $chunk->setBlock($X, $this->floorLevel, $Z, $this->block); } } } if (!$inSpawn) { $this->chunk = clone $chunk; } } else { $chunk = clone $this->chunk; } $chunk->setX($chunkX); $chunk->setZ($chunkZ); $this->level->setChunk($chunkX, $chunkZ, $chunk); }
public function generateChunk($chunkX, $chunkZ) { $this->chunk = clone $this->level->getChunk($chunkX, $chunkZ); $this->chunk->setGenerated(); $c = Biome::getBiome(1)->getColor(); $R = $c >> 16; $G = $c >> 8 & 0xff; $B = $c & 0xff; for ($Z = 0; $Z < 16; ++$Z) { for ($X = 0; $X < 16; ++$X) { $this->chunk->setBiomeId($X, $Z, 1); $this->chunk->setBiomeColor($X, $Z, $R, $G, $B); for ($y = 0; $y < 128; ++$y) { $this->chunk->setBlockId($X, $y, $Z, Block::AIR); } } } $this->chunk->setBlockId(8, 64, 8, Block::GRASS); $chunk = clone $this->chunk; $chunk->setX($chunkX); $chunk->setZ($chunkZ); $this->level->setChunk($chunkX, $chunkZ, $chunk); }
protected static function register($id, Biome $biome) { self::$biomes[(int) $id] = $biome; $biome->setId((int) $id); }
/** * @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(); }
/** * Changes the biome of a plot * * @api * @param Plot $plot * @param Biome $biome * @return bool */ public function setPlotBiome(Plot $plot, Biome $biome) { $plotLevel = $this->getLevelSettings($plot->levelName); if ($plotLevel === null) { return false; } $level = $this->getServer()->getLevelByName($plot->levelName); $pos = $this->getPlotPosition($plot); $plotSize = $plotLevel->plotSize; $xMax = $pos->x + $plotSize; $zMax = $pos->z + $plotSize; $chunkIndexes = []; for ($x = $pos->x; $x < $xMax; $x++) { for ($z = $pos->z; $z < $zMax; $z++) { $index = Level::chunkHash($x >> 4, $z >> 4); if (!in_array($index, $chunkIndexes)) { $chunkIndexes[] = $index; } $color = $biome->getColor(); $R = $color >> 16; $G = $color >> 8 & 0xff; $B = $color & 0xff; $level->setBiomeColor($x, $z, $R, $G, $B); } } foreach ($chunkIndexes as $index) { Level::getXZ($index, $X, $Z); $chunk = $level->getChunk($X, $Z); foreach ($level->getChunkPlayers($X, $Z) as $player) { $player->onChunkChanged($chunk); } } $plot->biome = $biome->getName(); $this->dataProvider->savePlot($plot); return true; }
public function populateChunk($chunkX, $chunkZ) { $this->random->setSeed(0xdeadbeef ^ $chunkX << 8 ^ $chunkZ ^ $this->level->getSeed()); foreach ($this->populators as $populator) { $populator->populate($this->level, $chunkX, $chunkZ, $this->random); } $chunk = $this->level->getChunk($chunkX, $chunkZ); $biome = Biome::getBiome($chunk->getBiomeId(7, 7)); $biome->populateChunk($this->level, $chunkX, $chunkZ, $this->random); }
protected static function register($id, Biome $biome) { self::$biomes[(int) $id] = $biome; $biome->setId((int) $id); $biome->grassColor = self::generateBiomeColor($biome->getTemperature(), $biome->getRainfall()); }
public function generateChunk($chunkX, $chunkZ) { $shape = $this->getShape($chunkX << 4, $chunkZ << 4); $chunk = $this->level->getChunk($chunkX, $chunkZ); $chunk->setGenerated(); $c = Biome::getBiome(1)->getColor(); $R = $c >> 16; $G = $c >> 8 & 0xff; $B = $c & 0xff; $bottomBlockId = $this->bottomBlock->getId(); $bottomBlockMeta = $this->bottomBlock->getDamage(); $plotFillBlockId = $this->plotFillBlock->getId(); $plotFillBlockMeta = $this->plotFillBlock->getDamage(); $plotFloorBlockId = $this->plotFloorBlock->getId(); $plotFloorBlockMeta = $this->plotFloorBlock->getDamage(); $roadBlockId = $this->roadBlock->getId(); $roadBlockMeta = $this->roadBlock->getDamage(); $wallBlockId = $this->wallBlock->getId(); $wallBlockMeta = $this->wallBlock->getDamage(); $groundHeight = $this->groundHeight; for ($Z = 0; $Z < 16; ++$Z) { for ($X = 0; $X < 16; ++$X) { $chunk->setBiomeId($X, $Z, 1); $chunk->setBiomeColor($X, $Z, $R, $G, $B); $chunk->setBlock($X, 0, $Z, $bottomBlockId, $bottomBlockMeta); for ($y = 1; $y < $groundHeight; ++$y) { $chunk->setBlock($X, $y, $Z, $plotFillBlockId, $plotFillBlockMeta); } $type = $shape[$Z << 4 | $X]; if ($type === self::PLOT) { $chunk->setBlock($X, $groundHeight, $Z, $plotFloorBlockId, $plotFloorBlockMeta); } elseif ($type === self::ROAD) { $chunk->setBlock($X, $groundHeight, $Z, $roadBlockId, $roadBlockMeta); } else { $chunk->setBlock($X, $groundHeight, $Z, $roadBlockId, $roadBlockMeta); $chunk->setBlock($X, $groundHeight + 1, $Z, $wallBlockId, $wallBlockMeta); } } } $chunk->setX($chunkX); $chunk->setZ($chunkZ); $this->level->setChunk($chunkX, $chunkZ, $chunk); }
/** * @param int $x * @param int $z * @param bool $generate * * @return bool */ public function loadChunk($x, $z, $generate = true) { if (isset($this->chunks[$index = Level::chunkHash($x, $z)])) { return true; } $this->timings->syncChunkLoadTimer->startTiming(); $this->cancelUnloadChunkRequest($x, $z); $chunk = $this->provider->getChunk($x, $z, $generate); if ($chunk === null) { if ($generate) { throw new \InvalidStateException("Could not create new Chunk"); } return false; } if ($this->provider->getProviderName() == "mcregion") { if ($chunk->getBiomeColor(0, 0) == [0, 0, 0]) { for ($x = 0; $x < 16; ++$x) { for ($z = 0; $z < 16; ++$z) { $biome = Biome::getBiome(Biome::PLAINS); $chunk->setBiomeId($x, $z, $biome->getId()); $c = $biome->getColor(); $chunk->setBiomeColor($x, $z, $c >> 16, $c >> 8 & 0xff, $c & 0xff); } } } } $this->chunks[$index] = $chunk; $chunk->initChunk(); if ($chunk->getProvider() !== null) { $this->server->getPluginManager()->callEvent(new ChunkLoadEvent($chunk, !$chunk->isGenerated())); } else { $this->unloadChunk($x, $z, false); $this->timings->syncChunkLoadTimer->stopTiming(); return false; } if (!$chunk->isLightPopulated() and $chunk->isPopulated() and $this->getServer()->getProperty("chunk-ticking.light-updates", false)) { $this->getServer()->getScheduler()->scheduleAsyncTask(new LightPopulationTask($this, $chunk)); } if ($this->isChunkInUse($x, $z)) { foreach ($this->getChunkLoaders($x, $z) as $loader) { $loader->onChunkLoaded($chunk); } } else { $this->unloadChunkRequest($x, $z); } $this->timings->syncChunkLoadTimer->stopTiming(); return true; }
public function generateChunk($chunkX, $chunkZ) { $CX = $chunkX % 5 < 0 ? $chunkX % 5 + 5 : $chunkX % 5; $CZ = $chunkZ % 5 < 0 ? $chunkZ % 5 + 5 : $chunkZ % 5; switch ($CX . ":" . $CZ) { case '0:0': if ($this->chunk1 === null) { $this->chunk1 = clone $this->level->getChunk($chunkX, $chunkZ); $c = Biome::getBiome(1)->getColor(); $R = $c >> 16; $G = $c >> 8 & 0xff; $B = $c & 0xff; for ($x = 0; $x < 16; $x++) { for ($z = 0; $z < 16; $z++) { $this->chunk1->setBiomeColor($x, $z, $R, $G, $B); } } for ($x = 4; $x < 11; $x++) { for ($z = 4; $z < 11; $z++) { $this->chunk1->setBlockId($x, self::bedrockheight + (68 - 64), $z, Block::GRASS); } } for ($x = 5; $x < 10; $x++) { for ($z = 5; $z < 10; $z++) { $this->chunk1->setBlockId($x, self::bedrockheight + (67 - 64), $z, Block::DIRT); $this->chunk1->setBlockId($x, self::bedrockheight + (72 - 64), $z, Block::LEAVES); // 72 } } for ($x = 6; $x < 9; $x++) { for ($z = 6; $z < 9; $z++) { $this->chunk1->setBlockId($x, self::bedrockheight + (73 - 64), $z, Block::LEAVES); // 73 $this->chunk1->setBlockId($x, self::bedrockheight + (66 - 64), $z, Block::DIRT); // 66 } } $this->chunk1->setBlockId(7, self::bedrockheight + (64 - 64), 7, Block::BEDROCK); // 0 $this->chunk1->setBlockId(7, self::bedrockheight + (65 - 64), 7, Block::SAND); // 1 $this->chunk1->setBlockId(7, self::bedrockheight + (66 - 64), 7, Block::SAND); // 2 $this->chunk1->setBlockId(7, self::bedrockheight + (67 - 64), 7, Block::SAND); // 3 $this->chunk1->setBlockId(7, self::bedrockheight + (69 - 64), 7, Block::LOG); // 5 $this->chunk1->setBlockId(7, self::bedrockheight + (70 - 64), 7, Block::LOG); // 6 $this->chunk1->setBlockId(7, self::bedrockheight + (71 - 64), 7, Block::LOG); // 7 $this->chunk1->setBlockId(7, self::bedrockheight + (72 - 64), 7, Block::LOG); // 8 $this->chunk1->setBlockId(7, self::bedrockheight + (73 - 64), 7, Block::LOG); // 9 $this->chunk1->setBlockId(4, self::bedrockheight + (68 - 64), 4, Block::AIR); // 68 $this->chunk1->setBlockId(4, self::bedrockheight + (68 - 64), 10, Block::AIR); $this->chunk1->setBlockId(10, self::bedrockheight + (68 - 64), 4, Block::AIR); $this->chunk1->setBlockId(10, self::bedrockheight + (68 - 64), 10, Block::AIR); $this->chunk1->setBlockId(5, self::bedrockheight + (72 - 64), 5, Block::AIR); // 72 $this->chunk1->setBlockId(5, self::bedrockheight + (72 - 64), 9, Block::AIR); $this->chunk1->setBlockId(9, self::bedrockheight + (72 - 64), 5, Block::AIR); $this->chunk1->setBlockId(9, self::bedrockheight + (72 - 64), 9, Block::AIR); $this->chunk1->setBlockId(5, self::bedrockheight + (73 - 64), 7, Block::LEAVES); // 73 $this->chunk1->setBlockId(7, self::bedrockheight + (73 - 64), 5, Block::LEAVES); $this->chunk1->setBlockId(9, self::bedrockheight + (73 - 64), 7, Block::LEAVES); $this->chunk1->setBlockId(7, self::bedrockheight + (73 - 64), 9, Block::LEAVES); $this->chunk1->setBlockId(7, self::bedrockheight + (74 - 64), 6, Block::LEAVES); // 74 $this->chunk1->setBlockId(6, self::bedrockheight + (74 - 64), 7, Block::LEAVES); $this->chunk1->setBlockId(8, self::bedrockheight + (74 - 64), 7, Block::LEAVES); $this->chunk1->setBlockId(7, self::bedrockheight + (74 - 64), 8, Block::LEAVES); $this->chunk1->setBlockId(7, self::bedrockheight + (75 - 64), 7, Block::LEAVES); // 75 // $this->chunk1->setBlockId(7, self::bedrockheight + (69 - 64), 8, Block::CHEST); $this->chunk1->setBlockId(7, self::bedrockheight + (65 - 64), 8, Block::DIRT); // 65 $this->chunk1->setBlockId(8, self::bedrockheight + (65 - 64), 7, Block::DIRT); $this->chunk1->setBlockId(7, self::bedrockheight + (65 - 64), 6, Block::DIRT); $this->chunk1->setBlockId(6, self::bedrockheight + (65 - 64), 7, Block::DIRT); $this->chunk1->setBlockId(5, self::bedrockheight + (66 - 64), 7, Block::DIRT); // 66 $this->chunk1->setBlockId(7, self::bedrockheight + (66 - 64), 5, Block::DIRT); $this->chunk1->setBlockId(9, self::bedrockheight + (66 - 64), 7, Block::DIRT); $this->chunk1->setBlockId(7, self::bedrockheight + (66 - 64), 9, Block::DIRT); $this->chunk1->setBlockId(4, self::bedrockheight + (67 - 64), 7, Block::DIRT); // 67 $this->chunk1->setBlockId(7, self::bedrockheight + (67 - 64), 4, Block::DIRT); $this->chunk1->setBlockId(7, self::bedrockheight + (67 - 64), 10, Block::DIRT); $this->chunk1->setBlockId(10, self::bedrockheight + (67 - 64), 7, Block::DIRT); } $chunk = clone $this->chunk1; $chunk->setX($chunkX); $chunk->setZ($chunkZ); $this->level->setChunk($chunkX, $chunkZ, $chunk); break; default: if ($this->chunk2 === null) { $this->chunk2 = clone $this->level->getChunk($chunkX, $chunkZ); $c = Biome::getBiome(1)->getColor(); $R = $c >> 16; $G = $c >> 8 & 0xff; $B = $c & 0xff; for ($x = 0; $x < 16; $x++) { for ($z = 0; $z < 16; $z++) { $this->chunk2->setBiomeColor($x, $z, $R, $G, $B); } } $chunk = clone $this->chunk2; $chunk->setX($chunkX); $chunk->setZ($chunkZ); $this->level->setChunk($chunkX, $chunkZ, $chunk); break; } } }
public function addBiome(Biome $biome) { $this->biomes[$biome->getId()] = $biome; }
/** * @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); } }