78        if(version_compare(MIN_PHP_VERSION, PHP_VERSION) > 0){
 
   81                "PHP >= " . MIN_PHP_VERSION . 
" is required, but you have PHP " . PHP_VERSION . 
"." 
   88            $messages[] = 
"32-bit systems/PHP are no longer supported. Please upgrade to a 64-bit system, or use a 64-bit PHP binary if this is a 64-bit system.";
 
   91        if(php_sapi_name() !== 
"cli"){
 
   92            $messages[] = 
"Only PHP CLI is supported.";
 
   96            "chunkutils2" => 
"PocketMine ChunkUtils v2",
 
   98            "crypto" => 
"php-crypto",
 
  101            "encoding" => 
"pmmp/ext-encoding",
 
  104            "igbinary" => 
"igbinary",
 
  106            "leveldb" => 
"LevelDB",
 
  107            "mbstring" => 
"Multibyte String",
 
  108            "morton" => 
"morton",
 
  109            "openssl" => 
"OpenSSL",
 
  112            "pmmpthread" => 
"pmmpthread",
 
  113            "reflection" => 
"Reflection",
 
  114            "sockets" => 
"Sockets",
 
  121        foreach($extensions as $ext => $name){
 
  122            if(!extension_loaded($ext)){
 
  123                $messages[] = 
"Unable to find the $name ($ext) extension.";
 
  127        if(($pmmpthread_version = phpversion(
"pmmpthread")) !== 
false){
 
  128            if(version_compare($pmmpthread_version, 
"6.1.0") < 0 || version_compare($pmmpthread_version, 
"7.0.0") >= 0){
 
  129                $messages[] = 
"pmmpthread ^6.1.0 is required, while you have $pmmpthread_version.";
 
  133        if(($leveldb_version = phpversion(
"leveldb")) !== 
false){
 
  134            if(version_compare($leveldb_version, 
"0.2.1") < 0){
 
  135                $messages[] = 
"php-leveldb >= 0.2.1 is required, while you have $leveldb_version.";
 
  137            if(!defined(
'LEVELDB_ZLIB_RAW_COMPRESSION')){
 
  138                $messages[] = 
"Given version of php-leveldb doesn't support ZLIB_RAW compression (use https://github.com/pmmp/php-leveldb)";
 
  142        $chunkutils2_version = phpversion(
"chunkutils2");
 
  143        $wantedVersionLock = 
"0.3";
 
  144        $wantedVersionMin = 
"$wantedVersionLock.0";
 
  145        if($chunkutils2_version !== 
false && (
 
  146            version_compare($chunkutils2_version, $wantedVersionMin) < 0 ||
 
  147            preg_match(
"/^" . preg_quote($wantedVersionLock, 
"/") . 
"\.\d+(?:-dev)?$/", $chunkutils2_version) === 0 
 
  149            $messages[] = 
"chunkutils2 ^$wantedVersionMin is required, while you have $chunkutils2_version.";
 
  152        if(($libdeflate_version = phpversion(
"libdeflate")) !== 
false){
 
  154            if(version_compare($libdeflate_version, 
"0.2.0") < 0 || version_compare($libdeflate_version, 
"0.3.0") >= 0){
 
  155                $messages[] = 
"php-libdeflate ^0.2.0 is required, while you have $libdeflate_version.";
 
  159        if(($encoding_version = phpversion(
"encoding")) !== 
false){
 
  160            if(version_compare($encoding_version, 
"1.0.0") < 0 || version_compare($encoding_version, 
"2.0.0") >= 0){
 
  161                $messages[] = 
"pmmp/ext-encoding ^1.0.0 is required, while you have $encoding_version.";
 
  165        if(extension_loaded(
"pocketmine")){
 
  166            $messages[] = 
"The native PocketMine extension is no longer supported.";
 
  169        if(!defined(
'AF_INET6')){
 
  170            $messages[] = 
"IPv6 support is required, but your PHP binary was built without IPv6 support.";
 
 
  243        if(count($messages = check_platform_dependencies()) > 0){
 
  245            $binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
 
  246            critical_error("Selected PHP binary does not satisfy some requirements.");
 
  247            foreach($messages as $m){
 
  248                echo " - $m" . PHP_EOL;
 
  250            critical_error("PHP binary used: " . $binary);
 
  251            critical_error("Loaded php.ini: " . (($file = php_ini_loaded_file()) !== false ? $file : "none"));
 
  252            $phprc = getenv("PHPRC");
 
  253            critical_error("Value of PHPRC environment variable: " . ($phprc === false ? "" : $phprc));
 
  254            critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
 
  263        $bootstrap = dirname(__FILE__, 2) . '/vendor/autoload.php
'; 
  264        if(!is_file($bootstrap)){ 
  265            critical_error("Composer autoloader not found at " . $bootstrap); 
  266            critical_error("Please install/update Composer dependencies or use provided builds."); 
  269        require_once($bootstrap); 
  272        if($composerGitHash !== null){ 
  273            //we can't verify dependency versions 
if we were installed without 
using git
 
  274            $currentGitHash = explode(
"-", VersionInfo::GIT_HASH(), 2)[0];
 
  275            if($currentGitHash !== $composerGitHash){
 
  276                critical_error(
"Composer dependencies and/or autoloader are out of sync.");
 
  278                critical_error(
"- Composer dependencies were last synchronized for revision $composerGitHash");
 
  279                critical_error(
"Out-of-sync Composer dependencies may result in crashes and classes not being found.");
 
  280                critical_error(
"Please synchronize Composer dependencies before running the server.");
 
  285        ErrorToExceptionHandler::set();
 
  288            printf(
"%s %s (git hash %s) for Minecraft: Bedrock Edition %s\n", VersionInfo::NAME, VersionInfo::VERSION()->getFullVersion(
true), VersionInfo::GIT_HASH(), ProtocolInfo::MINECRAFT_VERSION);
 
  292        if(defined(
'pocketmine\ORIGINAL_PHAR_PATH')){
 
  294            Filesystem::addCleanedPath(ORIGINAL_PHAR_PATH, Filesystem::CLEAN_PATH_SRC_PREFIX);
 
  297        $cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd())));
 
  300        Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
 
  302        if(!@mkdir($dataPath, 0777, 
true) && !is_dir($dataPath)){
 
  303            critical_error(
"Unable to create/access data directory at $dataPath. Check that the target location is accessible by the current user.");
 
  307        $dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
 
  309        $lockFilePath = Path::join($dataPath, 
'server.lock');
 
  311            $pid = Filesystem::createLockFile($lockFilePath);
 
  312        }
catch(\InvalidArgumentException $e){
 
  314            critical_error(
"Please ensure that there is enough space on the disk and that the current user has read/write permissions to the selected data directory $dataPath.");
 
  318            critical_error(
"Another " . VersionInfo::NAME . 
" instance (PID $pid) is already using this folder (" . realpath($dataPath) . 
").");
 
  319            critical_error(
"Please stop the other server first before running a new one.");
 
  323        if(!@mkdir($pluginPath, 0777, 
true) && !is_dir($pluginPath)){
 
  324            critical_error(
"Unable to create plugin directory at $pluginPath. Check that the target location is accessible by the current user.");
 
  327        $pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
 
  334            Terminal::init(
true);
 
  336            Terminal::init(
false);
 
  342        $logger = 
new MainLogger($logFile, Terminal::hasFormattingCodes(), 
"Server", 
new \DateTimeZone(Timezone::get()), 
false, Path::join($dataPath, 
"log_archive"));
 
  343        if($logFile === 
null){
 
  344            $logger->
notice(
"Logging to file disabled. Ensure logs are collected by other means (e.g. Docker logs).");
 
  347        \GlobalLogger::set($logger);
 
  354                $installer = 
new SetupWizard($dataPath);
 
  355                if(!$installer->run()){
 
  364            $autoloader = 
new ThreadSafeClassLoader();
 
  365            $autoloader->register(
false);
 
  367            new Server($autoloader, $logger, $dataPath, $pluginPath);
 
  369            $logger->
info(
"Stopping other threads");
 
  371            $killer = 
new ServerKiller(8);
 
  375            if(ThreadManager::getInstance()->stopAll() > 0){
 
  376                $logger->
debug(
"Some threads could not be stopped, performing a force-kill");
 
  377                Process::kill(Process::pid());
 
  381        $logger->shutdownLogWriterThread();
 
  383        echo Terminal::$FORMAT_RESET . PHP_EOL;
 
  385        Filesystem::releaseLockFile($lockFilePath);