mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-06 09:56:06 +00:00
PHP7 to master
This commit is contained in:
@ -73,15 +73,15 @@ use pocketmine\metadata\EntityMetadataStore;
|
||||
use pocketmine\metadata\LevelMetadataStore;
|
||||
use pocketmine\metadata\PlayerMetadataStore;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Double;
|
||||
use pocketmine\nbt\tag\Enum;
|
||||
use pocketmine\nbt\tag\Float;
|
||||
use pocketmine\nbt\tag\Int;
|
||||
use pocketmine\nbt\tag\Long;
|
||||
use pocketmine\nbt\tag\Short;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\DoubleTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\FloatTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\LongTag;
|
||||
use pocketmine\nbt\tag\ShortTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\network\CompressBatchedTask;
|
||||
use pocketmine\network\Network;
|
||||
use pocketmine\network\protocol\BatchPacket;
|
||||
@ -117,7 +117,6 @@ use pocketmine\utils\ServerException;
|
||||
use pocketmine\utils\ServerKiller;
|
||||
use pocketmine\utils\Terminal;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\TextWrapper;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\UUID;
|
||||
use pocketmine\utils\VersionString;
|
||||
@ -132,6 +131,9 @@ class Server{
|
||||
/** @var Server */
|
||||
private static $instance = null;
|
||||
|
||||
/** @var \Threaded */
|
||||
private static $sleeper = null;
|
||||
|
||||
/** @var BanList */
|
||||
private $banByName = null;
|
||||
|
||||
@ -360,13 +362,6 @@ class Server{
|
||||
return $this->getConfigString("server-ip", "0.0.0.0");
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function getServerName(){
|
||||
return $this->getConfigString("motd", "Minecraft: PE Server");
|
||||
}
|
||||
|
||||
public function getServerUniqueId(){
|
||||
return $this->serverID;
|
||||
}
|
||||
@ -656,56 +651,6 @@ class Server{
|
||||
return round((array_sum($this->useAverage) / count($this->useAverage)) * 100, 2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* @param $address
|
||||
* @param int $timeout
|
||||
*/
|
||||
public function blockAddress($address, $timeout = 300){
|
||||
$this->network->blockAddress($address, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* @param $address
|
||||
* @param $port
|
||||
* @param $payload
|
||||
*/
|
||||
public function sendPacket($address, $port, $payload){
|
||||
$this->network->sendPacket($address, $port, $payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* @return SourceInterface[]
|
||||
*/
|
||||
public function getInterfaces(){
|
||||
return $this->network->getInterfaces();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* @param SourceInterface $interface
|
||||
*/
|
||||
public function addInterface(SourceInterface $interface){
|
||||
$this->network->registerInterface($interface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* @param SourceInterface $interface
|
||||
*/
|
||||
public function removeInterface(SourceInterface $interface){
|
||||
$interface->shutdown();
|
||||
$this->network->unregisterInterface($interface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleCommandMap
|
||||
*/
|
||||
@ -743,7 +688,7 @@ class Server{
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return Compound
|
||||
* @return CompoundTag
|
||||
*/
|
||||
public function getOfflinePlayerData($name){
|
||||
$name = strtolower($name);
|
||||
@ -754,7 +699,7 @@ class Server{
|
||||
$nbt->readCompressed(file_get_contents($path . "$name.dat"));
|
||||
|
||||
return $nbt->getData();
|
||||
}catch(\Exception $e){ //zlib decode error / corrupt data
|
||||
}catch(\Throwable $e){ //zlib decode error / corrupt data
|
||||
rename($path . "$name.dat", $path . "$name.dat.bak");
|
||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
|
||||
}
|
||||
@ -762,38 +707,38 @@ class Server{
|
||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerNotFound", [$name]));
|
||||
}
|
||||
$spawn = $this->getDefaultLevel()->getSafeSpawn();
|
||||
$nbt = new Compound("", [
|
||||
new Long("firstPlayed", floor(microtime(true) * 1000)),
|
||||
new Long("lastPlayed", floor(microtime(true) * 1000)),
|
||||
new Enum("Pos", [
|
||||
new Double(0, $spawn->x),
|
||||
new Double(1, $spawn->y),
|
||||
new Double(2, $spawn->z)
|
||||
$nbt = new CompoundTag("", [
|
||||
new LongTag("firstPlayed", floor(microtime(true) * 1000)),
|
||||
new LongTag("lastPlayed", floor(microtime(true) * 1000)),
|
||||
new ListTag("Pos", [
|
||||
new DoubleTag(0, $spawn->x),
|
||||
new DoubleTag(1, $spawn->y),
|
||||
new DoubleTag(2, $spawn->z)
|
||||
]),
|
||||
new String("Level", $this->getDefaultLevel()->getName()),
|
||||
//new String("SpawnLevel", $this->getDefaultLevel()->getName()),
|
||||
//new Int("SpawnX", (int) $spawn->x),
|
||||
//new Int("SpawnY", (int) $spawn->y),
|
||||
//new Int("SpawnZ", (int) $spawn->z),
|
||||
//new Byte("SpawnForced", 1), //TODO
|
||||
new Enum("Inventory", []),
|
||||
new Compound("Achievements", []),
|
||||
new Int("playerGameType", $this->getGamemode()),
|
||||
new Enum("Motion", [
|
||||
new Double(0, 0.0),
|
||||
new Double(1, 0.0),
|
||||
new Double(2, 0.0)
|
||||
new StringTag("Level", $this->getDefaultLevel()->getName()),
|
||||
//new StringTag("SpawnLevel", $this->getDefaultLevel()->getName()),
|
||||
//new IntTag("SpawnX", (int) $spawn->x),
|
||||
//new IntTag("SpawnY", (int) $spawn->y),
|
||||
//new IntTag("SpawnZ", (int) $spawn->z),
|
||||
//new ByteTag("SpawnForced", 1), //TODO
|
||||
new ListTag("Inventory", []),
|
||||
new CompoundTag("Achievements", []),
|
||||
new IntTag("playerGameType", $this->getGamemode()),
|
||||
new ListTag("Motion", [
|
||||
new DoubleTag(0, 0.0),
|
||||
new DoubleTag(1, 0.0),
|
||||
new DoubleTag(2, 0.0)
|
||||
]),
|
||||
new Enum("Rotation", [
|
||||
new Float(0, 0.0),
|
||||
new Float(1, 0.0)
|
||||
new ListTag("Rotation", [
|
||||
new FloatTag(0, 0.0),
|
||||
new FloatTag(1, 0.0)
|
||||
]),
|
||||
new Float("FallDistance", 0.0),
|
||||
new Short("Fire", 0),
|
||||
new Short("Air", 300),
|
||||
new Byte("OnGround", 1),
|
||||
new Byte("Invulnerable", 0),
|
||||
new String("NameTag", $name),
|
||||
new FloatTag("FallDistance", 0.0),
|
||||
new ShortTag("Fire", 0),
|
||||
new ShortTag("Air", 300),
|
||||
new ByteTag("OnGround", 1),
|
||||
new ByteTag("Invulnerable", 0),
|
||||
new StringTag("NameTag", $name),
|
||||
]);
|
||||
$nbt->Pos->setTagType(NBT::TAG_Double);
|
||||
$nbt->Inventory->setTagType(NBT::TAG_Compound);
|
||||
@ -814,39 +759,39 @@ class Server{
|
||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerOld", [$name]));
|
||||
foreach($data->get("inventory") as $slot => $item){
|
||||
if(count($item) === 3){
|
||||
$nbt->Inventory[$slot + 9] = new Compound("", [
|
||||
new Short("id", $item[0]),
|
||||
new Short("Damage", $item[1]),
|
||||
new Byte("Count", $item[2]),
|
||||
new Byte("Slot", $slot + 9),
|
||||
new Byte("TrueSlot", $slot + 9)
|
||||
$nbt->Inventory[$slot + 9] = new CompoundTag("", [
|
||||
new ShortTag("id", $item[0]),
|
||||
new ShortTag("Damage", $item[1]),
|
||||
new ByteTag("Count", $item[2]),
|
||||
new ByteTag("Slot", $slot + 9),
|
||||
new ByteTag("TrueSlot", $slot + 9)
|
||||
]);
|
||||
}
|
||||
}
|
||||
foreach($data->get("hotbar") as $slot => $itemSlot){
|
||||
if(isset($nbt->Inventory[$itemSlot + 9])){
|
||||
$item = $nbt->Inventory[$itemSlot + 9];
|
||||
$nbt->Inventory[$slot] = new Compound("", [
|
||||
new Short("id", $item["id"]),
|
||||
new Short("Damage", $item["Damage"]),
|
||||
new Byte("Count", $item["Count"]),
|
||||
new Byte("Slot", $slot),
|
||||
new Byte("TrueSlot", $item["TrueSlot"])
|
||||
$nbt->Inventory[$slot] = new CompoundTag("", [
|
||||
new ShortTag("id", $item["id"]),
|
||||
new ShortTag("Damage", $item["Damage"]),
|
||||
new ByteTag("Count", $item["Count"]),
|
||||
new ByteTag("Slot", $slot),
|
||||
new ByteTag("TrueSlot", $item["TrueSlot"])
|
||||
]);
|
||||
}
|
||||
}
|
||||
foreach($data->get("armor") as $slot => $item){
|
||||
if(count($item) === 2){
|
||||
$nbt->Inventory[$slot + 100] = new Compound("", [
|
||||
new Short("id", $item[0]),
|
||||
new Short("Damage", $item[1]),
|
||||
new Byte("Count", 1),
|
||||
new Byte("Slot", $slot + 100)
|
||||
$nbt->Inventory[$slot + 100] = new CompoundTag("", [
|
||||
new ShortTag("id", $item[0]),
|
||||
new ShortTag("Damage", $item[1]),
|
||||
new ByteTag("Count", 1),
|
||||
new ByteTag("Slot", $slot + 100)
|
||||
]);
|
||||
}
|
||||
}
|
||||
foreach($data->get("achievements") as $achievement => $status){
|
||||
$nbt->Achievements[$achievement] = new Byte($achievement, $status == true ? 1 : 0);
|
||||
$nbt->Achievements[$achievement] = new ByteTag($achievement, $status == true ? 1 : 0);
|
||||
}
|
||||
unlink($path . "$name.yml");
|
||||
}
|
||||
@ -858,10 +803,10 @@ class Server{
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param Compound $nbtTag
|
||||
* @param CompoundTag $nbtTag
|
||||
* @param bool $async
|
||||
*/
|
||||
public function saveOfflinePlayerData($name, Compound $nbtTag, $async = false){
|
||||
public function saveOfflinePlayerData($name, CompoundTag $nbtTag, $async = false){
|
||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
||||
try{
|
||||
$nbt->setData($nbtTag);
|
||||
@ -871,11 +816,9 @@ class Server{
|
||||
}else{
|
||||
file_put_contents($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed());
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->critical($this->getLanguage()->translateString("pocketmine.data.saveError", [$name, $e->getMessage()]));
|
||||
if(\pocketmine\DEBUG > 1 and $this->logger instanceof MainLogger){
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1082,12 +1025,10 @@ class Server{
|
||||
|
||||
try{
|
||||
$level = new Level($this, $name, $path, $provider);
|
||||
}catch(\Exception $e){
|
||||
}catch(\Throwable $e){
|
||||
|
||||
$this->logger->error($this->getLanguage()->translateString("pocketmine.level.loadError", [$name, $e->getMessage()]));
|
||||
if($this->logger instanceof MainLogger){
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
$this->logger->logException($e);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1142,11 +1083,9 @@ class Server{
|
||||
$level->initLevel();
|
||||
|
||||
$level->setTickRate($this->baseTickRate);
|
||||
}catch(\Exception $e){
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->error($this->getLanguage()->translateString("pocketmine.level.generateError", [$name, $e->getMessage()]));
|
||||
if($this->logger instanceof MainLogger){
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
$this->logger->logException($e);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1438,10 +1377,16 @@ class Server{
|
||||
/**
|
||||
* @return Server
|
||||
*/
|
||||
public static function getInstance(){
|
||||
public static function getInstance() : Server{
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public static function microSleep(int $microseconds){
|
||||
Server::$sleeper->synchronized(function(int $ms){
|
||||
Server::$sleeper->wait($ms);
|
||||
}, $microseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ClassLoader $autoloader
|
||||
* @param \ThreadedLogger $logger
|
||||
@ -1451,256 +1396,261 @@ class Server{
|
||||
*/
|
||||
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;
|
||||
if(!file_exists($dataPath . "worlds/")){
|
||||
mkdir($dataPath . "worlds/", 0777);
|
||||
}
|
||||
|
||||
if(!file_exists($dataPath . "players/")){
|
||||
mkdir($dataPath . "players/", 0777);
|
||||
}
|
||||
try{
|
||||
|
||||
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("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);
|
||||
$this->filePath = $filePath;
|
||||
if(!file_exists($dataPath . "worlds/")){
|
||||
mkdir($dataPath . "worlds/", 0777);
|
||||
}
|
||||
@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);
|
||||
if(!file_exists($dataPath . "players/")){
|
||||
mkdir($dataPath . "players/", 0777);
|
||||
}
|
||||
}
|
||||
|
||||
ServerScheduler::$WORKERS = $poolSize;
|
||||
if(!file_exists($pluginPath)){
|
||||
mkdir($pluginPath, 0777);
|
||||
}
|
||||
|
||||
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->dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
|
||||
$this->pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
|
||||
|
||||
$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->console = new CommandReader();
|
||||
|
||||
$this->scheduler = new ServerScheduler();
|
||||
$version = new VersionString($this->getPocketMineVersion());
|
||||
|
||||
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->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->entityMetadata = new EntityMetadataStore();
|
||||
$this->playerMetadata = new PlayerMetadataStore();
|
||||
$this->levelMetadata = new LevelMetadataStore();
|
||||
$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->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->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->maxPlayers = $this->getConfigInt("max-players", 20);
|
||||
$this->setAutoSave($this->getConfigBoolean("auto-save", true));
|
||||
$this->memoryManager = new MemoryManager($this);
|
||||
|
||||
if($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3){
|
||||
$this->setConfigInt("difficulty", 3);
|
||||
}
|
||||
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.start", [TextFormat::AQUA . $this->getVersion()]));
|
||||
|
||||
define("pocketmine\\DEBUG", (int) $this->getProperty("debug.level", 1));
|
||||
if($this->logger instanceof MainLogger){
|
||||
$this->logger->setLogDebug(\pocketmine\DEBUG > 1);
|
||||
}
|
||||
if(($poolSize = $this->getProperty("settings.async-workers", "auto")) === "auto"){
|
||||
$poolSize = ServerScheduler::$WORKERS;
|
||||
$processors = Utils::getCoreCount() - 2;
|
||||
|
||||
if(\pocketmine\DEBUG >= 0){
|
||||
@cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion());
|
||||
}
|
||||
if($processors > 0){
|
||||
$poolSize = max(1, $processors);
|
||||
}
|
||||
}
|
||||
|
||||
$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());
|
||||
ServerScheduler::$WORKERS = $poolSize;
|
||||
|
||||
$this->getLogger()->debug("Server unique id: " . $this->getServerUniqueId());
|
||||
$this->getLogger()->debug("Machine unique id: " . Utils::getMachineUniqueId());
|
||||
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->network = new Network($this);
|
||||
$this->network->setName($this->getMotd());
|
||||
$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", @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()]));
|
||||
$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();
|
||||
Timings::init();
|
||||
|
||||
$this->consoleSender = new ConsoleCommandSender();
|
||||
$this->commandMap = new SimpleCommandMap($this);
|
||||
$this->consoleSender = new ConsoleCommandSender();
|
||||
$this->commandMap = new SimpleCommandMap($this);
|
||||
|
||||
$this->registerEntities();
|
||||
$this->registerTiles();
|
||||
$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();
|
||||
InventoryType::init();
|
||||
Block::init();
|
||||
Item::init();
|
||||
Biome::init();
|
||||
Effect::init();
|
||||
Enchantment::init();
|
||||
Attribute::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 = (float) $this->getProperty("settings.profile-report-trigger", 20);
|
||||
$this->pluginManager->registerInterface(PharPluginLoader::class);
|
||||
$this->pluginManager->registerInterface(ScriptPluginLoader::class);
|
||||
$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 = (float) $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"]);
|
||||
register_shutdown_function([$this, "crashDump"]);
|
||||
|
||||
$this->queryRegenerateTask = new QueryRegenerateEvent($this, 5);
|
||||
$this->queryRegenerateTask = new QueryRegenerateEvent($this, 5);
|
||||
$this->network->registerInterface(new RakLibInterface($this));
|
||||
|
||||
$this->network->registerInterface(new RakLibInterface($this));
|
||||
$this->pluginManager->loadPlugins($this->pluginPath);
|
||||
|
||||
$this->pluginManager->loadPlugins($this->pluginPath);
|
||||
$this->updater = new AutoUpdater($this, $this->getProperty("auto-updater.host", "www.pocketmine.net"));
|
||||
|
||||
$this->updater = new AutoUpdater($this, $this->getProperty("auto-updater.host", "www.pocketmine.net"));
|
||||
$this->enablePlugins(PluginLoadOrder::STARTUP);
|
||||
|
||||
$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);
|
||||
}
|
||||
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");
|
||||
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 = [];
|
||||
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->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->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);
|
||||
}
|
||||
|
||||
|
||||
$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();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1808,7 +1758,7 @@ class Server{
|
||||
$packet->encode();
|
||||
$packet->isEncoded = true;
|
||||
if(Network::$BATCH_THRESHOLD >= 0 and strlen($packet->buffer) >= Network::$BATCH_THRESHOLD){
|
||||
Server::getInstance()->batchPackets($players, [$packet->buffer], false, $packet->getChannel());
|
||||
Server::getInstance()->batchPackets($players, [$packet->buffer], false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1826,9 +1776,8 @@ class Server{
|
||||
* @param Player[] $players
|
||||
* @param DataPacket[]|string $packets
|
||||
* @param bool $forceSync
|
||||
* @param int $channel
|
||||
*/
|
||||
public function batchPackets(array $players, array $packets, $forceSync = false, $channel = 0){
|
||||
public function batchPackets(array $players, array $packets, $forceSync = false){
|
||||
Timings::$playerNetworkTimer->startTiming();
|
||||
$str = "";
|
||||
|
||||
@ -1851,7 +1800,7 @@ class Server{
|
||||
}
|
||||
|
||||
if(!$forceSync and $this->networkCompressionAsync){
|
||||
$task = new CompressBatchedTask($str, $targets, $this->networkCompressionLevel, $channel);
|
||||
$task = new CompressBatchedTask($str, $targets, $this->networkCompressionLevel);
|
||||
$this->getScheduler()->scheduleAsyncTask($task);
|
||||
}else{
|
||||
$this->broadcastPacketsCallback(zlib_encode($str, ZLIB_ENCODING_DEFLATE, $this->networkCompressionLevel), $targets);
|
||||
@ -1897,15 +1846,6 @@ class Server{
|
||||
$this->pluginManager->enablePlugin($plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Plugin $plugin
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function loadPlugin(Plugin $plugin){
|
||||
$this->enablePlugin($plugin);
|
||||
}
|
||||
|
||||
public function disablePlugins(){
|
||||
$this->pluginManager->disablePlugins();
|
||||
}
|
||||
@ -1932,10 +1872,6 @@ class Server{
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function dispatchCommand(CommandSender $sender, $commandLine){
|
||||
if(!($sender instanceof CommandSender)){
|
||||
throw new ServerException("CommandSender is not valid");
|
||||
}
|
||||
|
||||
if($this->commandMap->dispatch($sender, $commandLine)){
|
||||
return true;
|
||||
}
|
||||
@ -1970,8 +1906,6 @@ class Server{
|
||||
$this->reloadWhitelist();
|
||||
$this->operators->reload();
|
||||
|
||||
$this->memoryManager->doObjectCleanup();
|
||||
|
||||
foreach($this->getIPBans()->getEntries() as $entry){
|
||||
$this->getNetwork()->blockAddress($entry->getName(), -1);
|
||||
}
|
||||
@ -1988,11 +1922,6 @@ class Server{
|
||||
* Shutdowns the server correctly
|
||||
*/
|
||||
public function shutdown(){
|
||||
if($this->isRunning){
|
||||
$killer = new ServerKiller(90);
|
||||
$killer->start();
|
||||
$killer->detach();
|
||||
}
|
||||
$this->isRunning = false;
|
||||
}
|
||||
|
||||
@ -2041,7 +1970,8 @@ class Server{
|
||||
$this->properties->save();
|
||||
|
||||
$this->getLogger()->debug("Closing console");
|
||||
$this->console->kill();
|
||||
$this->console->shutdown();
|
||||
$this->console->notify();
|
||||
|
||||
$this->getLogger()->debug("Stopping network interfaces");
|
||||
foreach($this->network->getInterfaces() as $interface){
|
||||
@ -2049,11 +1979,10 @@ class Server{
|
||||
$this->network->unregisterInterface($interface);
|
||||
}
|
||||
|
||||
$this->memoryManager->doObjectCleanup();
|
||||
|
||||
gc_collect_cycles();
|
||||
}catch(\Exception $e){
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->emergency("Crashed while crashing, killing process");
|
||||
$this->logger->emergency(get_class($e) . ": ". $e->getMessage());
|
||||
@kill(getmypid());
|
||||
}
|
||||
|
||||
@ -2111,7 +2040,7 @@ class Server{
|
||||
}
|
||||
}
|
||||
|
||||
public function exceptionHandler(\Exception $e, $trace = null){
|
||||
public function exceptionHandler(\Throwable $e, $trace = null){
|
||||
if($e === null){
|
||||
return;
|
||||
}
|
||||
@ -2134,9 +2063,7 @@ class Server{
|
||||
|
||||
$errfile = cleanPath($errfile);
|
||||
|
||||
if($this->logger instanceof MainLogger){
|
||||
$this->logger->logException($e, $trace);
|
||||
}
|
||||
$this->logger->logException($e, $trace);
|
||||
|
||||
$lastError = [
|
||||
"type" => $type,
|
||||
@ -2166,7 +2093,7 @@ class Server{
|
||||
$this->logger->emergency($this->getLanguage()->translateString("pocketmine.crash.create"));
|
||||
try{
|
||||
$dump = new CrashDump($this);
|
||||
}catch(\Exception $e){
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->critical($this->getLanguage()->translateString("pocketmine.crash.error", $e->getMessage()));
|
||||
return;
|
||||
}
|
||||
@ -2226,7 +2153,7 @@ class Server{
|
||||
if($next > microtime(true)){
|
||||
try{
|
||||
time_sleep_until($next);
|
||||
}catch(\Exception $e){
|
||||
}catch(\Throwable $e){
|
||||
//Sometimes $next is less than the current time. High load?
|
||||
}
|
||||
}
|
||||
@ -2345,11 +2272,9 @@ class Server{
|
||||
$level->tickRateCounter = $level->getTickRate();
|
||||
}
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->critical($this->getLanguage()->translateString("pocketmine.level.tickError", [$level->getName(), $e->getMessage()]));
|
||||
if(\pocketmine\DEBUG > 1 and $this->logger instanceof MainLogger){
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2440,11 +2365,9 @@ class Server{
|
||||
if(strlen($payload) > 2 and substr($payload, 0, 2) === "\xfe\xfd" and $this->queryHandler instanceof QueryHandler){
|
||||
$this->queryHandler->handle($address, $port, $payload);
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
}catch(\Throwable $e){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
if($this->logger instanceof MainLogger){
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
|
||||
$this->getNetwork()->blockAddress($address, 600);
|
||||
@ -2498,10 +2421,8 @@ class Server{
|
||||
if($this->queryHandler !== null){
|
||||
$this->queryHandler->regenerateInfo();
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
if($this->logger instanceof MainLogger){
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user