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",
103 "igbinary" =>
"igbinary",
105 "leveldb" =>
"LevelDB",
106 "mbstring" =>
"Multibyte String",
107 "morton" =>
"morton",
108 "openssl" =>
"OpenSSL",
111 "pmmpthread" =>
"pmmpthread",
112 "reflection" =>
"Reflection",
113 "sockets" =>
"Sockets",
120 foreach($extensions as $ext => $name){
121 if(!extension_loaded($ext)){
122 $messages[] =
"Unable to find the $name ($ext) extension.";
126 if(($pmmpthread_version = phpversion(
"pmmpthread")) !==
false){
127 if(version_compare($pmmpthread_version,
"6.1.0") < 0 || version_compare($pmmpthread_version,
"7.0.0") >= 0){
128 $messages[] =
"pmmpthread ^6.1.0 is required, while you have $pmmpthread_version.";
132 if(($leveldb_version = phpversion(
"leveldb")) !==
false){
133 if(version_compare($leveldb_version,
"0.2.1") < 0){
134 $messages[] =
"php-leveldb >= 0.2.1 is required, while you have $leveldb_version.";
136 if(!defined(
'LEVELDB_ZLIB_RAW_COMPRESSION')){
137 $messages[] =
"Given version of php-leveldb doesn't support ZLIB_RAW compression (use https://github.com/pmmp/php-leveldb)";
141 $chunkutils2_version = phpversion(
"chunkutils2");
142 $wantedVersionLock =
"0.3";
143 $wantedVersionMin =
"$wantedVersionLock.0";
144 if($chunkutils2_version !==
false && (
145 version_compare($chunkutils2_version, $wantedVersionMin) < 0 ||
146 preg_match(
"/^" . preg_quote($wantedVersionLock,
"/") .
"\.\d+(?:-dev)?$/", $chunkutils2_version) === 0
148 $messages[] =
"chunkutils2 ^$wantedVersionMin is required, while you have $chunkutils2_version.";
151 if(($libdeflate_version = phpversion(
"libdeflate")) !==
false){
153 if(version_compare($libdeflate_version,
"0.2.0") < 0 || version_compare($libdeflate_version,
"0.3.0") >= 0){
154 $messages[] =
"php-libdeflate ^0.2.0 is required, while you have $libdeflate_version.";
158 if(extension_loaded(
"pocketmine")){
159 $messages[] =
"The native PocketMine extension is no longer supported.";
162 if(!defined(
'AF_INET6')){
163 $messages[] =
"IPv6 support is required, but your PHP binary was built without IPv6 support.";
236 if(count($messages = check_platform_dependencies()) > 0){
238 $binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
239 critical_error("Selected PHP binary does not satisfy some requirements.");
240 foreach($messages as $m){
241 echo " - $m" . PHP_EOL;
243 critical_error("PHP binary used: " . $binary);
244 critical_error("Loaded php.ini: " . (($file = php_ini_loaded_file()) !== false ? $file : "none"));
245 $phprc = getenv("PHPRC");
246 critical_error("Value of PHPRC environment variable: " . ($phprc === false ? "" : $phprc));
247 critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
256 $bootstrap = dirname(__FILE__, 2) . '/vendor/autoload.php
';
257 if(!is_file($bootstrap)){
258 critical_error("Composer autoloader not found at " . $bootstrap);
259 critical_error("Please install/update Composer dependencies or use provided builds.");
262 require_once($bootstrap);
265 if($composerGitHash !== null){
266 //we can't verify dependency versions
if we were installed without
using git
267 $currentGitHash = explode(
"-", VersionInfo::GIT_HASH())[0];
268 if($currentGitHash !== $composerGitHash){
269 critical_error(
"Composer dependencies and/or autoloader are out of sync.");
271 critical_error(
"- Composer dependencies were last synchronized for revision $composerGitHash");
272 critical_error(
"Out-of-sync Composer dependencies may result in crashes and classes not being found.");
273 critical_error(
"Please synchronize Composer dependencies before running the server.");
278 ErrorToExceptionHandler::set();
281 printf(
"%s %s (git hash %s) for Minecraft: Bedrock Edition %s\n", VersionInfo::NAME, VersionInfo::VERSION()->getFullVersion(
true), VersionInfo::GIT_HASH(), ProtocolInfo::MINECRAFT_VERSION);
285 $cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd())));
288 Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
290 if(!@mkdir($dataPath, 0777,
true) && !is_dir($dataPath)){
291 critical_error(
"Unable to create/access data directory at $dataPath. Check that the target location is accessible by the current user.");
295 $dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
297 $lockFilePath = Path::join($dataPath,
'server.lock');
299 $pid = Filesystem::createLockFile($lockFilePath);
300 }
catch(\InvalidArgumentException $e){
302 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.");
306 critical_error(
"Another " . VersionInfo::NAME .
" instance (PID $pid) is already using this folder (" . realpath($dataPath) .
").");
307 critical_error(
"Please stop the other server first before running a new one.");
311 if(!@mkdir($pluginPath, 0777,
true) && !is_dir($pluginPath)){
312 critical_error(
"Unable to create plugin directory at $pluginPath. Check that the target location is accessible by the current user.");
315 $pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
322 Terminal::init(
true);
324 Terminal::init(
false);
330 $logger =
new MainLogger($logFile, Terminal::hasFormattingCodes(),
"Server",
new \DateTimeZone(Timezone::get()),
false, Path::join($dataPath,
"log_archive"));
331 if($logFile ===
null){
332 $logger->
notice(
"Logging to file disabled. Ensure logs are collected by other means (e.g. Docker logs).");
335 \GlobalLogger::set($logger);
342 $installer =
new SetupWizard($dataPath);
343 if(!$installer->run()){
352 $autoloader =
new ThreadSafeClassLoader();
353 $autoloader->register(
false);
355 new Server($autoloader, $logger, $dataPath, $pluginPath);
357 $logger->
info(
"Stopping other threads");
359 $killer =
new ServerKiller(8);
363 if(ThreadManager::getInstance()->stopAll() > 0){
364 $logger->
debug(
"Some threads could not be stopped, performing a force-kill");
365 Process::kill(Process::pid());
369 $logger->shutdownLogWriterThread();
371 echo Terminal::$FORMAT_RESET . PHP_EOL;
373 Filesystem::releaseLockFile($lockFilePath);