Cleaned up code

This commit is contained in:
Shoghi Cervantes 2015-01-03 16:07:49 +01:00
parent f9762c870a
commit 074c8b876d
No known key found for this signature in database
GPG Key ID: 78464DB0A7837F89
19 changed files with 27 additions and 1293 deletions

View File

@ -1695,7 +1695,7 @@ class Server{
/**
* @param $message
* @param Player[]|null $recipients
* @param Player[] $recipients
*
* @return int
*/
@ -1703,6 +1703,8 @@ class Server{
if(!is_array($recipients)){
return $this->broadcast($message, self::BROADCAST_CHANNEL_USERS);
}
/** @var Player[] $recipients */
foreach($recipients as $recipient){
$recipient->sendMessage($message);
}
@ -1989,16 +1991,6 @@ class Server{
}
}
public function checkMemory(){
//TODO
$info = $this->debugInfo();
$data = $info["memory_usage"] . "," . $info["players"] . "," . $info["entities"];
$i = count($this->memoryStats) - 1;
if($i < 0 or $this->memoryStats[$i] !== $data){
$this->memoryStats[] = $data;
}
}
public function exceptionHandler(\Exception $e, $trace = null){
if($e === null){
return;

View File

@ -1031,7 +1031,7 @@ class Block extends Position implements Metadatable{
return $this->getLevel()->getBlock(Vector3::getSide($side, $step));
}
return Block::get(Item::AIR, 0, new Position($v->x, $v->y, $v->z, null));
return Block::get(Item::AIR, 0, Position::fromObject(Vector3::getSide($side, $step)));
}
/**

View File

@ -77,7 +77,7 @@ class Cactus extends Transparent{
}else{
for($side = 2; $side <= 5; ++$side){
$b = $this->getSide($side);
if(!$b->isFlowable){
if(!$b->canBeFlowedInto()){
$this->getLevel()->useBreakOn($this);
}
}

View File

@ -50,7 +50,8 @@ class FormattedCommandAlias extends Command{
$sender->sendMessage(TextFormat::RED . $e->getMessage());
}else{
$sender->sendMessage(TextFormat::RED . "An internal error occurred while attempting to perform this command");
if(($logger = $sender->getServer()->getLogger()) instanceof MainLogger){
$logger = $sender->getServer()->getLogger();
if($logger instanceof MainLogger){
$logger->logException($e);
}
}

View File

@ -183,7 +183,8 @@ class SimpleCommandMap implements CommandMap{
$target->execute($sender, $sentCommandLabel, $args);
}catch(\Exception $e){
$this->server->getLogger()->critical("Unhandled exception executing command '" . $commandLine . "' in " . $target . ": " . $e->getMessage());
if(($logger = $sender->getServer()->getLogger()) instanceof MainLogger){
$logger = $sender->getServer()->getLogger();
if($logger instanceof MainLogger){
$logger->logException($e);
}
}

View File

@ -827,6 +827,7 @@ abstract class Entity extends Location implements Metadatable{
$this->boundingBox->offset($dx, $dy, $dz);
$this->setPosition(new Vector3(($this->boundingBox->minX + $this->boundingBox->maxX) / 2, $this->boundingBox->minY, ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2));
$this->onGround = $this instanceof Player ? true : false;
return true;
}else{
Timings::$entityMoveTimer->startTiming();

View File

@ -164,14 +164,16 @@ abstract class Living extends Entity implements Damageable{
return $this->deadTicks < 10;
}
parent::entityBaseTick($tickDiff);
$hasUpdate = parent::entityBaseTick($tickDiff);
if($this->dead !== true and $this->isInsideOfSolid()){
$hasUpdate = true;
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_SUFFOCATION, 1);
$this->attack($ev->getFinalDamage(), $ev);
}
if($this->dead !== true and $this->isInsideOfWater()){
$hasUpdate = true;
$this->airTicks -= $tickDiff;
if($this->airTicks <= -20){
$this->airTicks = 0;
@ -188,6 +190,8 @@ abstract class Living extends Entity implements Damageable{
}
Timings::$timerEntityBaseTick->stopTiming();
return $hasUpdate;
}
/**

View File

@ -22,9 +22,6 @@
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\entity\Entity;
abstract class Armor extends Item{
public function getMaxStackSize(){

View File

@ -21,9 +21,7 @@
namespace pocketmine\level;
use pocketmine\block\Air;
use pocketmine\block\Block;
use pocketmine\block\TNT;
use pocketmine\entity\Entity;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;

View File

@ -1089,7 +1089,7 @@ class Level implements ChunkManager, Metadatable{
* @param bool $direct
* @param bool $update
*
* @return bool
* @return bool Whether the block has been updated or not
*/
public function setBlock(Vector3 $pos, Block $block, $direct = false, $update = true){
if($pos->y < 0 or $pos->y >= 128){
@ -1147,7 +1147,11 @@ class Level implements ChunkManager, Metadatable{
$this->updateAround($pos);
}
return true;
}
return false;
}
/**

View File

@ -1,130 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\level;
use pocketmine\level\format\PocketChunkParser;
use pocketmine\nbt\NBT;
use pocketmine\utils\Config;
use pocketmine\utils\MainLogger;
class LevelImport{
private $path;
public function __construct($path){
$this->path = $path;
}
public function import(){
if(file_exists($this->path . "tileEntities.dat")){ //OldPM
$level = unserialize(file_get_contents($this->path . "level.dat"));
MainLogger::getLogger()->info("Importing OldPM level \"" . $level["LevelName"] . "\" to PMF format");
$entities = new Config($this->path . "entities.yml", Config::YAML, unserialize(file_get_contents($this->path . "entities.dat")));
$entities->save();
$tiles = new Config($this->path . "tiles.yml", Config::YAML, unserialize(file_get_contents($this->path . "tileEntities.dat")));
$tiles->save();
}elseif(file_exists($this->path . "chunks.dat") and file_exists($this->path . "level.dat")){ //Pocket
$nbt = new NBT(NBT::LITTLE_ENDIAN);
$nbt->read(substr(file_get_contents($this->path . "level.dat"), 8));
$level = $nbt->getData();
if($level["LevelName"] == ""){
$level["LevelName"] = "world" . time();
}
MainLogger::getLogger()->info("Importing Pocket level \"" . $level->LevelName . "\" to PMF format");
unset($level->Player);
$nbt->read(substr(file_get_contents($this->path . "entities.dat"), 12));
$entities = $nbt->getData();
if(!isset($entities->TileEntities)){
$entities->TileEntities = [];
}
$tiles = $entities->TileEntities;
$entities = $entities->Entities;
$entities = new Config($this->path . "entities.yml", Config::YAML, $entities);
$entities->save();
$tiles = new Config($this->path . "tiles.yml", Config::YAML, $tiles);
$tiles->save();
}else{
return false;
}
$pmf = new LevelFormat($this->path . "level.pmf", [
"name" => $level->LevelName,
"seed" => $level->RandomSeed,
"time" => $level->Time,
"spawnX" => $level->SpawnX,
"spawnY" => $level->SpawnY,
"spawnZ" => $level->SpawnZ,
"height" => 8,
"generator" => "default",
"generatorSettings" => "",
"extra" => ""
]);
$chunks = new PocketChunkParser();
$chunks->loadFile($this->path . "chunks.dat");
$chunks->loadMap();
for($Z = 0; $Z < 16; ++$Z){
for($X = 0; $X < 16; ++$X){
$chunk = [
0 => "",
1 => "",
2 => "",
3 => "",
4 => "",
5 => "",
6 => "",
7 => ""
];
$pmf->initCleanChunk($X, $Z);
for($z = 0; $z < 16; ++$z){
for($x = 0; $x < 16; ++$x){
$block = $chunks->getChunkColumn($X, $Z, $x, $z, 0);
$meta = $chunks->getChunkColumn($X, $Z, $x, $z, 1);
for($Y = 0; $Y < 8; ++$Y){
$chunk[$Y] .= substr($block, $Y << 4, 16);
$chunk[$Y] .= substr($meta, $Y << 3, 8);
$chunk[$Y] .= "\x00\x00\x00\x00\x00\x00\x00\x00";
}
}
}
foreach($chunk as $Y => $data){
$pmf->setMiniChunk($X, $Z, $Y, $data);
}
$pmf->setPopulated($X, $Z);
$pmf->saveChunk($X, $Z);
}
MainLogger::getLogger()->notice("Importing level " . ceil(($Z + 1) / 0.16) . "%");
}
$chunks->map = null;
$chunks = null;
@unlink($this->path . "level.dat");
@unlink($this->path . "level.dat_old");
@unlink($this->path . "player.dat");
@unlink($this->path . "entities.dat");
@unlink($this->path . "chunks.dat");
@unlink($this->path . "chunks.dat.gz");
@unlink($this->path . "tiles.dat");
unset($chunks, $level, $entities, $tiles, $nbt);
return true;
}
}

View File

@ -1,762 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\level\conversor\pmf;
use pocketmine\level\Level;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Enum;
use pocketmine\utils\Binary;
use pocketmine\utils\MainLogger;
class LevelFormat extends PMF{
const VERSION = 2;
const ZLIB_LEVEL = 6;
const ZLIB_ENCODING = 15; //15 = zlib, -15 = raw deflate, 31 = gzip
public $level;
public $levelData = [];
public $isLoaded = true;
private $chunks = [];
private $chunkChange = [];
private $chunkInfo = [];
public $isGenerating = 0;
public function getData($index){
if(!isset($this->levelData[$index])){
return false;
}
return ($this->levelData[$index]);
}
public function setData($index, $data){
if(!isset($this->levelData[$index])){
return false;
}
$this->levelData[$index] = $data;
return true;
}
public function closeLevel(){
$this->chunks = null;
unset($this->chunks, $this->chunkChange, $this->chunkInfo, $this->level);
$this->close();
}
/**
* @param string $file
* @param bool|array $blank default false
*/
public function __construct($file, $blank = false){
$this->chunks = [];
$this->chunkChange = [];
$this->chunkInfo = [];
if(is_array($blank)){
$this->create($file, 0);
$this->levelData = $blank;
$this->createBlank();
$this->isLoaded = true;
}else{
if($this->load($file) !== false){
$this->parseInfo();
if($this->parseLevel() === false){
$this->isLoaded = false;
}else{
$this->isLoaded = true;
}
}else{
$this->isLoaded = false;
}
}
}
public function saveData(){
$this->levelData["version"] = self::VERSION;
@ftruncate($this->fp, 5);
$this->seek(5);
$this->write(chr($this->levelData["version"]));
$this->write(Binary::writeShort(strlen($this->levelData["name"])) . $this->levelData["name"]);
$this->write(Binary::writeInt($this->levelData["seed"]));
$this->write(Binary::writeInt($this->levelData["time"]));
$this->write(Binary::writeFloat($this->levelData["spawnX"]));
$this->write(Binary::writeFloat($this->levelData["spawnY"]));
$this->write(Binary::writeFloat($this->levelData["spawnZ"]));
$this->write(chr($this->levelData["height"]));
$this->write(Binary::writeShort(strlen($this->levelData["generator"])) . $this->levelData["generator"]);
$settings = serialize($this->levelData["generatorSettings"]);
$this->write(Binary::writeShort(strlen($settings)) . $settings);
$extra = zlib_encode($this->levelData["extra"], self::ZLIB_ENCODING, self::ZLIB_LEVEL);
$this->write(Binary::writeShort(strlen($extra)) . $extra);
}
private function createBlank(){
$this->saveData();
@mkdir(dirname($this->file) . "/chunks/", 0755);
}
protected function parseLevel(){
if($this->getType() !== 0x00){
return false;
}
$this->seek(5);
$this->levelData["version"] = ord($this->read(1));
if($this->levelData["version"] > self::VERSION){
MainLogger::getLogger()->error("New unsupported PMF Level format version #" . $this->levelData["version"] . ", current version is #" . self::VERSION);
return false;
}
$this->levelData["name"] = $this->read(Binary::readShort($this->read(2)));
$this->levelData["seed"] = Binary::readInt($this->read(4));
$this->levelData["time"] = Binary::readInt($this->read(4));
$this->levelData["spawnX"] = Binary::readFloat($this->read(4));
$this->levelData["spawnY"] = Binary::readFloat($this->read(4));
$this->levelData["spawnZ"] = Binary::readFloat($this->read(4));
if($this->levelData["version"] === 0){
$this->read(1);
$this->levelData["height"] = ord($this->read(1));
}else{
$this->levelData["height"] = ord($this->read(1));
if($this->levelData["height"] !== 8){
return false;
}
$this->levelData["generator"] = $this->read(Binary::readShort($this->read(2)));
$this->levelData["generatorSettings"] = unserialize($this->read(Binary::readShort($this->read(2))));
}
$this->levelData["extra"] = @zlib_decode($this->read(Binary::readShort($this->read(2))));
$upgrade = false;
if($this->levelData["version"] === 0){
$this->upgrade_From0_To1();
$upgrade = true;
}
if($this->levelData["version"] === 1){
$this->upgrade_From1_To2();
$upgrade = true;
}
if($upgrade === true){
$this->saveData();
}
}
private function upgrade_From0_To1(){
MainLogger::getLogger()->notice("Old PMF Level format version #0 detected, upgrading to version #1");
for($index = 0; $index < 256; ++$index){
$X = $index & 0x0F;
$Z = $index >> 4;
$bitflags = Binary::readShort($this->read(2));
$oldPath = dirname($this->file) . "/chunks/" . $Z . "." . $X . ".pmc";
$chunkOld = gzopen($oldPath, "rb");
$newPath = dirname($this->file) . "/chunks/" . (($X ^ $Z) & 0xff) . "/" . $Z . "." . $X . ".pmc";
@mkdir(dirname($newPath));
$chunkNew = gzopen($newPath, "wb1");
gzwrite($chunkNew, chr($bitflags) . "\x00\x00\x00\x01");
while(gzeof($chunkOld) === false){
gzwrite($chunkNew, gzread($chunkOld, 65535));
}
gzclose($chunkNew);
gzclose($chunkOld);
@unlink($oldPath);
}
$this->levelData["version"] = 1;
$this->levelData["generator"] = "default";
$this->levelData["generatorSettings"] = "";
}
private function upgrade_From1_To2(){
MainLogger::getLogger()->notice("Old PMF Level format version #1 detected, upgrading to version #2");
$nbt = new Compound("", [
new Enum("Entities", []),
new Enum("TileEntities", [])
]);
$nbt->Entities->setTagType(NBT::TAG_Compound);
$nbt->TileEntities->setTagType(NBT::TAG_Compound);
$nbtCodec = new NBT(NBT::BIG_ENDIAN);
$nbtCodec->setData($nbt);
$namedtag = $nbtCodec->write();
$namedtag = Binary::writeInt(strlen($namedtag)) . $namedtag;
foreach(glob(dirname($this->file) . "/chunks/*/*.*.pmc") as $chunkFile){
$oldChunk = zlib_decode(file_get_contents($chunkFile));
$newChunk = substr($oldChunk, 0, 5);
$newChunk .= $namedtag;
$newChunk .= str_repeat("\x01", 256); //Biome indexes (all Plains)
$newChunk .= substr($oldChunk, 5);
file_put_contents($chunkFile, zlib_encode($newChunk, self::ZLIB_ENCODING, self::ZLIB_LEVEL));
}
$this->levelData["version"] = 2;
}
public static function getIndex($X, $Z){
return ($Z << 16) | ($X < 0 ? (~--$X & 0x7fff) | 0x8000 : $X & 0x7fff);
}
public static function getXZ($index, &$X = null, &$Z = null){
$Z = $index >> 16;
$X = ($index & 0x8000) === 0x8000 ? -($index & 0x7fff) : $index & 0x7fff;
return [$X, $Z];
}
private function getChunkPath($X, $Z){
return dirname($this->file) . "/chunks/" . (((int) $X ^ (int) $Z) & 0xff) . "/" . $Z . "." . $X . ".pmc";
}
public function generateChunk($X, $Z){
$path = $this->getChunkPath($X, $Z);
if(!file_exists(dirname($path))){
@mkdir(dirname($path), 0755);
}
$this->initCleanChunk($X, $Z);
if($this->level instanceof Level){
$ret = $this->level->generateChunk($X, $Z);
$this->saveChunk($X, $Z);
$this->populateChunk($X - 1, $Z);
$this->populateChunk($X + 1, $Z);
$this->populateChunk($X, $Z - 1);
$this->populateChunk($X, $Z + 1);
$this->populateChunk($X + 1, $Z + 1);
$this->populateChunk($X + 1, $Z - 1);
$this->populateChunk($X - 1, $Z - 1);
$this->populateChunk($X - 1, $Z + 1);
return $ret;
}
}
public function populateChunk($X, $Z){
if($this->level instanceof Level){
if($this->isGenerating === 0 and
$this->isChunkLoaded($X, $Z) and
!$this->isPopulated($X, $Z) and
$this->isGenerated($X - 1, $Z) and
$this->isGenerated($X, $Z - 1) and
$this->isGenerated($X + 1, $Z) and
$this->isGenerated($X, $Z + 1) and
$this->isGenerated($X + 1, $Z + 1) and
$this->isGenerated($X - 1, $Z - 1) and
$this->isGenerated($X + 1, $Z - 1) and
$this->isGenerated($X - 1, $Z + 1)
){
$this->level->populateChunk($X, $Z);
$this->saveChunk($X, $Z);
}
}
}
public function loadChunk($X, $Z){
if($this->isChunkLoaded($X, $Z)){
return true;
}
$index = self::getIndex($X, $Z);
$path = $this->getChunkPath($X, $Z);
if(!file_exists($path)){
if($this->generateChunk($X, $Z) === false){
return false;
}
if($this->isGenerating === 0){
$this->populateChunk($X, $Z);
}
return true;
}
$chunk = file_get_contents($path);
if($chunk === false){
return false;
}
$chunk = zlib_decode($chunk);
$offset = 0;
$this->chunkInfo[$index] = [
0 => ord($chunk{0}),
1 => Binary::readInt(substr($chunk, 1, 4)),
];
$offset += 5;
$len = Binary::readInt(substr($chunk, $offset, 4));
$offset += 4;
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->read(substr($chunk, $offset, $len));
$this->chunkInfo[$index][2] = $nbt->getData();
$offset += $len;
$this->chunks[$index] = [];
$this->chunkChange[$index] = [-1 => false];
$this->chunkInfo[$index][3] = substr($chunk, $offset, 256); //Biome data
$offset += 256;
for($Y = 0; $Y < 8; ++$Y){
if(($this->chunkInfo[$index][0] & (1 << $Y)) !== 0){
// 4096 + 2048 + 2048, Block Data, Meta, Light
if(strlen($this->chunks[$index][$Y] = substr($chunk, $offset, 8192)) < 8192){
MainLogger::getLogger()->notice("Empty corrupt chunk detected [$X,$Z,:$Y], recovering contents");
$this->fillMiniChunk($X, $Z, $Y);
}
$offset += 8192;
}else{
$this->chunks[$index][$Y] = false;
}
}
if($this->isGenerating === 0 and !$this->isPopulated($X, $Z)){
$this->populateChunk($X, $Z);
}
return true;
}
public function unloadChunk($X, $Z, $save = true){
$X = (int) $X;
$Z = (int) $Z;
if(!$this->isChunkLoaded($X, $Z)){
return false;
}elseif($save !== false){
$this->saveChunk($X, $Z);
}
$index = self::getIndex($X, $Z);
$this->chunks[$index] = null;
$this->chunkChange[$index] = null;
$this->chunkInfo[$index] = null;
unset($this->chunks[$index], $this->chunkChange[$index], $this->chunkInfo[$index]);
return true;
}
public function isChunkLoaded($X, $Z){
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index])){
return false;
}
return true;
}
protected function cleanChunk($X, $Z){
$index = self::getIndex($X, $Z);
if(isset($this->chunks[$index])){
for($Y = 0; $Y < 8; ++$Y){
if($this->chunks[$index][$Y] !== false and substr_count($this->chunks[$index][$Y], "\x00") === 8192){
$this->chunks[$index][$Y] = false;
$this->chunkInfo[$index][0] &= ~(1 << $Y);
}
}
}
}
public function isMiniChunkEmpty($X, $Z, $Y){
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index]) or $this->chunks[$index][$Y] === false){
return true;
}
return false;
}
protected function fillMiniChunk($X, $Z, $Y){
if($this->isChunkLoaded($X, $Z) === false){
return false;
}
$index = self::getIndex($X, $Z);
$this->chunks[$index][$Y] = str_repeat("\x00", 8192);
$this->chunkChange[$index][-1] = true;
$this->chunkChange[$index][$Y] = 8192;
$this->chunkInfo[$index][0] |= 1 << $Y;
return true;
}
public function getMiniChunk($X, $Z, $Y){
if($this->isChunkLoaded($X, $Z) === false and $this->loadChunk($X, $Z) === false){
return str_repeat("\x00", 8192);
}
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index][$Y]) or $this->chunks[$index][$Y] === false){
return str_repeat("\x00", 8192);
}
return $this->chunks[$index][$Y];
}
public function initCleanChunk($X, $Z){
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index])){
$this->chunks[$index] = [
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
];
$this->chunkChange[$index] = [
-1 => true,
0 => 8192,
1 => 8192,
2 => 8192,
3 => 8192,
4 => 8192,
5 => 8192,
6 => 8192,
7 => 8192,
];
$nbt = new Compound("", [
new Enum("Entities", []),
new Enum("TileEntities", [])
]);
$nbt->Entities->setTagType(NBT::TAG_Compound);
$nbt->TileEntities->setTagType(NBT::TAG_Compound);
$this->chunkInfo[$index] = [
0 => 0,
1 => 0,
2 => $nbt,
3 => str_repeat("\x00", 256),
];
}
}
public function setMiniChunk($X, $Z, $Y, $data){
if($this->isGenerating > 0){
$this->initCleanChunk($X, $Z);
}elseif($this->isChunkLoaded($X, $Z) === false){
$this->loadChunk($X, $Z);
}
if(strlen($data) !== 8192){
return false;
}
$index = self::getIndex($X, $Z);
$this->chunks[$index][$Y] = (string) $data;
$this->chunkChange[$index][-1] = true;
$this->chunkChange[$index][$Y] = 8192;
$this->chunkInfo[$index][0] |= 1 << $Y;
return true;
}
public function getBlockID($x, $y, $z){
if($y > 127 or $y < 0){
return 0;
}
$X = $x >> 4;
$Z = $z >> 4;
$Y = $y >> 4;
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index])){
return 0;
}
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$aY = $y - ($Y << 4);
$b = ord($this->chunks[$index][$Y]{(int) ($aY + ($aX << 5) + ($aZ << 9))});
return $b;
}
public function getBiome($x, $z){
$X = $x >> 4;
$Z = $z >> 4;
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index])){
return 0;
}
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
return ord($this->chunkInfo[$index][3]{$aX + ($aZ << 4)});
}
public function setBiome($x, $z, $biome){
$X = $x >> 4;
$Z = $z >> 4;
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index])){
return false;
}
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$this->chunkInfo[$index][3]{$aX + ($aZ << 4)} = chr((int) $biome);
return true;
}
public function setBlockID($x, $y, $z, $block){
if($y > 127 or $y < 0){
return false;
}
$X = $x >> 4;
$Z = $z >> 4;
$Y = $y >> 4;
$block &= 0xFF;
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index])){
return false;
}
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$aY = $y - ($Y << 4);
$this->chunks[$index][$Y]{(int) ($aY + ($aX << 5) + ($aZ << 9))} = chr($block);
if(!isset($this->chunkChange[$index][$Y])){
$this->chunkChange[$index][$Y] = 1;
}else{
++$this->chunkChange[$index][$Y];
}
$this->chunkChange[$index][-1] = true;
return true;
}
public function getBlockDamage($x, $y, $z){
if($y > 127 or $y < 0){
return 0;
}
$X = $x >> 4;
$Z = $z >> 4;
$Y = $y >> 4;
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index])){
return 0;
}
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$aY = $y - ($Y << 4);
$m = ord($this->chunks[$index][$Y]{(int) (($aY >> 1) + 16 + ($aX << 5) + ($aZ << 9))});
if(($y & 1) === 0){
$m = $m & 0x0F;
}else{
$m = $m >> 4;
}
return $m;
}
public function setBlockDamage($x, $y, $z, $damage){
if($y > 127 or $y < 0){
return false;
}
$X = $x >> 4;
$Z = $z >> 4;
$Y = $y >> 4;
$damage &= 0x0F;
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index])){
return false;
}
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$aY = $y - ($Y << 4);
$mindex = (int) (($aY >> 1) + 16 + ($aX << 5) + ($aZ << 9));
$old_m = ord($this->chunks[$index][$Y]{$mindex});
if(($y & 1) === 0){
$m = ($old_m & 0xF0) | $damage;
}else{
$m = ($damage << 4) | ($old_m & 0x0F);
}
if($old_m != $m){
$this->chunks[$index][$Y]{$mindex} = chr($m);
if(!isset($this->chunkChange[$index][$Y])){
$this->chunkChange[$index][$Y] = 1;
}else{
++$this->chunkChange[$index][$Y];
}
$this->chunkChange[$index][-1] = true;
return true;
}
return false;
}
public function getBlock($x, $y, $z){
$X = $x >> 4;
$Z = $z >> 4;
$Y = $y >> 4;
if($y < 0 or $y > 127){
return [0, 0];
}
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index]) and $this->loadChunk($X, $Z) === false){
return [0, 0];
}elseif($this->chunks[$index][$Y] === false){
return [0, 0];
}
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$aY = $y - ($Y << 4);
$b = ord($this->chunks[$index][$Y]{(int) ($aY + ($aX << 5) + ($aZ << 9))});
$m = ord($this->chunks[$index][$Y]{(int) (($aY >> 1) + 16 + ($aX << 5) + ($aZ << 9))});
if(($y & 1) === 0){
$m = $m & 0x0F;
}else{
$m = $m >> 4;
}
return [$b, $m];
}
public function setBlock($x, $y, $z, $block, $meta = 0){
if($y > 127 or $y < 0){
return false;
}
$X = $x >> 4;
$Z = $z >> 4;
$Y = $y >> 4;
$block &= 0xFF;
$meta &= 0x0F;
$index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index]) and $this->loadChunk($X, $Z) === false){
return false;
}elseif($this->chunks[$index][$Y] === false){
$this->fillMiniChunk($X, $Z, $Y);
}
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$aY = $y - ($Y << 4);
$bindex = (int) ($aY + ($aX << 5) + ($aZ << 9));
$mindex = (int) (($aY >> 1) + 16 + ($aX << 5) + ($aZ << 9));
$old_b = ord($this->chunks[$index][$Y]{$bindex});
$old_m = ord($this->chunks[$index][$Y]{$mindex});
if(($y & 1) === 0){
$m = ($old_m & 0xF0) | $meta;
}else{
$m = ($meta << 4) | ($old_m & 0x0F);
}
if($old_b !== $block or $old_m !== $m){
$this->chunks[$index][$Y]{$bindex} = chr($block);
$this->chunks[$index][$Y]{$mindex} = chr($m);
if(!isset($this->chunkChange[$index][$Y])){
$this->chunkChange[$index][$Y] = 1;
}else{
++$this->chunkChange[$index][$Y];
}
$this->chunkChange[$index][-1] = true;
return true;
}
return false;
}
public function getChunkNBT($X, $Z){
if(!$this->isChunkLoaded($X, $Z) and $this->loadChunk($X, $Z) === false){
return false;
}
$index = self::getIndex($X, $Z);
return $this->chunkInfo[$index][2];
}
public function setChunkNBT($X, $Z, Compound $nbt){
if(!$this->isChunkLoaded($X, $Z) and $this->loadChunk($X, $Z) === false){
return false;
}
$index = self::getIndex($X, $Z);
$this->chunkChange[$index][-1] = true;
$this->chunkInfo[$index][2] = $nbt;
}
public function saveChunk($X, $Z, $force = false){
$X = (int) $X;
$Z = (int) $Z;
if(!$this->isChunkLoaded($X, $Z)){
return false;
}
$index = self::getIndex($X, $Z);
if($force !== true and (!isset($this->chunkChange[$index]) or $this->chunkChange[$index][-1] === false)){ //No changes in chunk
return true;
}
$path = $this->getChunkPath($X, $Z);
if(!file_exists(dirname($path))){
@mkdir(dirname($path), 0755);
}
$bitmap = 0;
$this->cleanChunk($X, $Z);
for($Y = 0; $Y < 8; ++$Y){
if($this->chunks[$index][$Y] !== false and ((isset($this->chunkChange[$index][$Y]) and $this->chunkChange[$index][$Y] === 0) or !$this->isMiniChunkEmpty($X, $Z, $Y))){
$bitmap |= 1 << $Y;
}else{
$this->chunks[$index][$Y] = false;
}
$this->chunkChange[$index][$Y] = 0;
}
$this->chunkInfo[$index][0] = $bitmap;
$this->chunkChange[$index][-1] = false;
$chunk = "";
$chunk .= chr($bitmap);
$chunk .= Binary::writeInt($this->chunkInfo[$index][1]);
$namedtag = new NBT(NBT::BIG_ENDIAN);
$namedtag->setData($this->chunkInfo[$index][2]);
$namedtag = $namedtag->write();
$chunk .= Binary::writeInt(strlen($namedtag)) . $namedtag;
$chunk .= $this->chunkInfo[$index][3]; //biomes
for($Y = 0; $Y < 8; ++$Y){
$t = 1 << $Y;
if(($bitmap & $t) === $t){
$chunk .= $this->chunks[$index][$Y];
}
}
file_put_contents($path, zlib_encode($chunk, self::ZLIB_ENCODING, self::ZLIB_LEVEL));
return true;
}
public function setPopulated($X, $Z){
if(!$this->isChunkLoaded($X, $Z)){
return false;
}
$index = self::getIndex($X, $Z);
$this->chunkInfo[$index][1] |= 0b00000000000000000000000000000001;
}
public function unsetPopulated($X, $Z){
if(!$this->isChunkLoaded($X, $Z)){
return false;
}
$index = self::getIndex($X, $Z);
$this->chunkInfo[$index][1] &= ~0b00000000000000000000000000000001;
}
public function isPopulated($X, $Z){
if(!$this->isChunkLoaded($X, $Z)){
return false;
}
$index = self::getIndex($X, $Z);
return ($this->chunkInfo[$index][1] & 0b00000000000000000000000000000001) > 0;
}
public function isGenerated($X, $Z){
return file_exists($this->getChunkPath($X, $Z));
}
public function doSaveRound($force = false){
foreach($this->chunks as $index => $chunk){
self::getXZ($index, $X, $Z);
$this->saveChunk($X, $Z, $force);
}
}
}

View File

@ -1,144 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
/**
* PMF (PocketMine Format) handling
*/
namespace pocketmine\level\conversor\pmf;
use pocketmine\utils\MainLogger;
class PMF{
const VERSION = 0x01;
protected $fp;
protected $file;
private $version;
private $type;
public function __construct($file, $new = false, $type = 0, $version = PMF::VERSION){
if($new === true){
$this->create($file, $type, $version);
}else{
if($this->load($file) !== true){
$this->parseInfo();
}
}
}
public function getVersion(){
return $this->version;
}
public function getType(){
return $this->type;
}
public function load($file){
$this->close();
$this->file = $file;
if(($this->fp = @fopen($file, "c+b")) !== false){
fseek($this->fp, 0, SEEK_END);
if(ftell($this->fp) >= 5){ //Header + 2 Bytes
@flock($this->fp, LOCK_EX);
return true;
}
$this->close();
}
return false;
}
public function parseInfo(){
$this->seek(0);
if(fread($this->fp, 3) !== "PMF"){
return false;
}
$this->version = ord($this->read(1));
switch($this->version){
case 0x01:
$this->type = ord($this->read(1));
break;
default:
MainLogger::getLogger()->alert("Tried loading non-supported PMF version " . $this->version . " on file " . $this->file);
return false;
}
return true;
}
public function getFile(){
return $this->file;
}
public function close(){
unset($this->version, $this->type, $this->file);
if(is_object($this->fp)){
@flock($this->fp, LOCK_UN);
fclose($this->fp);
}
}
public function create($file, $type, $version = PMF::VERSION){
$this->file = $file;
@mkdir(dirname($this->file), 0755, true);
if(!is_resource($this->fp)){
if(($this->fp = @fopen($file, "c+b")) === false){
return false;
}
}
$this->seek(0);
$this->write("PMF" . chr((int) $version) . chr((int) $type));
return true;
}
public function read($length){
if($length <= 0){
return "";
}
if(is_resource($this->fp)){
return fread($this->fp, (int) $length);
}
return false;
}
public function write($string, $length = false){
if(is_resource($this->fp)){
return ($length === false ? fwrite($this->fp, $string) : fwrite($this->fp, $string, $length));
}
return false;
}
public function seek($offset, $whence = SEEK_SET){
if(is_resource($this->fp)){
return fseek($this->fp, (int) $offset, (int) $whence);
}
return false;
}
}

View File

@ -37,6 +37,7 @@ abstract class LevelProviderManager{
if(!is_subclass_of($class, LevelProvider::class)){
throw new LevelException("Class is not a subclass of LevelProvider");
}
/** @var LevelProvider $class */
self::$providers[strtolower($class::getProviderName())] = $class;
}

View File

@ -1,229 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\level\format;
use pocketmine\utils\Binary;
/**
* WARNING: This code is old, and only supports the file format partially (reverse engineering)
* It can break, lock, or hit you in the face in any moment.
*
*/
class PocketChunkParser{
private $location;
private $raw = "";
private $file;
public $sectorLength = 4096; //16 * 16 * 16
public $chunkLength = 86016; //21 * $sectorLength
public $map = [];
public function __construct(){
}
private function loadLocationTable(){
$this->location = [];
for($offset = 0; $offset < 0x1000; $offset += 4){
$data = Binary::readLInt(substr($this->raw, $offset, 4));
$sectors = $data & 0xff;
if($sectors === 0){
continue;
}
$sectorLocation = $data >> 8;
$this->location[$offset >> 2] = $sectorLocation * $this->sectorLength; //$this->getOffset($X, $Z, $sectors);
}
}
public function loadFile($file){
if(file_exists($file . ".gz")){
$this->raw = gzinflate(file_get_contents($file . ".gz"));
$r = @gzinflate($this->raw);
if($r !== false and $r != ""){
$this->raw = $r;
}
@unlink($file . ".gz");
file_put_contents($file, $this->raw);
}elseif(!file_exists($file)){
return false;
}else{
$this->raw = file_get_contents($file);
}
$this->file = $file;
$this->chunkLength = $this->sectorLength * ord($this->raw{0});
return true;
}
public function loadRaw($raw, $file){
$this->file = $file;
$this->raw = $raw;
$this->chunkLength = $this->sectorLength * ord($this->raw{0});
return true;
}
private function getOffset($X, $Z){
return $this->location[$X + ($Z << 5)];
}
public function getChunk($X, $Z){
$X = (int) $X;
$Z = (int) $Z;
return substr($this->raw, $this->getOffset($X, $Z), $this->chunkLength);
}
public function writeChunk($X, $Z){
$X = (int) $X;
$Z = (int) $Z;
if(!isset($this->map[$X][$Z])){
return false;
}
$chunk = "";
foreach($this->map[$X][$Z] as $section => $data){
for($i = 0; $i < 256; ++$i){
$chunk .= $data[$i];
}
}
return Binary::writeLInt(strlen($chunk)) . $chunk;
}
public function parseChunk($X, $Z){
$X = (int) $X;
$Z = (int) $Z;
$offset = $this->getOffset($X, $Z);
$len = Binary::readLInt(substr($this->raw, $offset, 4));
$offset += 4;
$chunk = [
0 => [], //Block
1 => [], //Data
2 => [], //SkyLight
3 => [], //BlockLight
];
foreach($chunk as $section => &$data){
$l = $section === 0 ? 128 : 64;
for($i = 0; $i < 256; ++$i){
$data[$i] = substr($this->raw, $offset, $l);
$offset += $l;
}
}
return $chunk;
}
public function loadMap(){
if($this->raw == ""){
return false;
}
$this->loadLocationTable();
for($x = 0; $x < 16; ++$x){
$this->map[$x] = [];
for($z = 0; $z < 16; ++$z){
$this->map[$x][$z] = $this->parseChunk($x, $z);
}
}
$this->raw = "";
return true;
}
public function saveMap($final = false){
$fp = fopen($this->file, "r+b");
flock($fp, LOCK_EX);
foreach($this->map as $x => $d){
foreach($d as $z => $chunk){
fseek($fp, $this->getOffset($x, $z));
fwrite($fp, $this->writeChunk($x, $z), $this->chunkLength);
}
}
flock($fp, LOCK_UN);
fclose($fp);
$original = filesize($this->file);
file_put_contents($this->file . ".gz", gzdeflate(gzdeflate(file_get_contents($this->file), 9), 9)); //Double compression for flat maps
$compressed = filesize($this->file . ".gz");
if($final === true){
@unlink($this->file);
}
}
public function getFloor($x, $z){
$X = $x >> 4;
$Z = $z >> 4;
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$index = $aZ + ($aX << 4);
for($y = 127; $y <= 0; --$y){
if($this->map[$X][$Z][0][$index]{$y} !== "\x00"){
break;
}
}
return $y;
}
public function getBlock($x, $y, $z){
$x = (int) $x;
$y = (int) $y;
$z = (int) $z;
$X = $x >> 4;
$Z = $z >> 4;
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$index = $aZ + ($aX << 4);
$block = ord($this->map[$X][$Z][0][$index]{$y});
$meta = ord($this->map[$X][$Z][1][$index]{$y >> 1});
if(($y & 1) === 0){
$meta = $meta & 0x0F;
}else{
$meta = $meta >> 4;
}
return [$block, $meta];
}
public function getChunkColumn($X, $Z, $x, $z, $type = 0){
$index = $z + ($x << 4);
return $this->map[$X][$Z][$type][$index];
}
public function setBlock($x, $y, $z, $block, $meta = 0){
$x = (int) $x;
$y = (int) $y;
$z = (int) $z;
$X = $x >> 4;
$Z = $z >> 4;
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$index = $aZ + ($aX << 4);
$this->map[$X][$Z][0][$index]{$y} = chr($block);
$old_meta = ord($this->map[$X][$Z][1][$index]{$y >> 1});
if(($y & 1) === 0){
$meta = ($old_meta & 0xF0) | ($meta & 0x0F);
}else{
$meta = (($meta << 4) & 0xF0) | ($old_meta & 0x0F);
}
$this->map[$X][$Z][1][$index]{$y >> 1} = chr($meta);
}
}

View File

@ -21,12 +21,10 @@
namespace pocketmine\level\format\generic;
use pocketmine\entity\Entity;
use pocketmine\level\format\Chunk;
use pocketmine\level\format\ChunkSection;
use pocketmine\level\format\LevelProvider;
use pocketmine\nbt\tag\Compound;
use pocketmine\tile\Tile;
use pocketmine\utils\Binary;
use pocketmine\utils\ChunkException;

View File

@ -173,12 +173,13 @@ class Permission{
* @param string|Permission $name
* @param $value
*
* @return Permission|void
* @return Permission|void Permission if $name is a string, void if it's a Permission
*/
public function addParent($name, $value){
if($name instanceof Permission){
$name->getChildren()[$this->getName()] = $value;
$name->recalculatePermissibles();
return;
}else{
$perm = Server::getInstance()->getPluginManager()->getPermission($name);
if($perm === null){

View File

@ -251,7 +251,8 @@ class PluginManager{
}
}catch(\Exception $e){
$this->server->getLogger()->error("Could not load '" . $file . "' in folder '" . $directory . "': " . $e->getMessage());
if(($logger = $this->server->getLogger()) instanceof MainLogger){
$logger = $this->server->getLogger();
if($logger instanceof MainLogger){
$logger->logException($e);
}
}
@ -669,7 +670,8 @@ class PluginManager{
$registration->callEvent($event);
}catch(\Exception $e){
$this->server->getLogger()->critical("Could not pass event " . $event->getEventName() . " to " . $registration->getPlugin()->getDescription()->getFullName() . ": " . $e->getMessage() . " on " . get_class($registration->getListener()));
if(($logger = $this->server->getLogger()) instanceof MainLogger){
$logger = $this->server->getLogger();
if($logger instanceof MainLogger){
$logger->logException($e);
}
}

View File

@ -21,7 +21,6 @@
namespace pocketmine\scheduler;
use pocketmine\Server;
use pocketmine\utils\Utils;
class SendUsageTask extends AsyncTask{