Updated to v0.9.0 build 2, now using Anvil worlds

This commit is contained in:
Shoghi Cervantes 2014-06-11 00:06:46 +02:00
parent fa50cbf4b3
commit 109b6dbf44
20 changed files with 235 additions and 107 deletions

View File

@ -83,6 +83,7 @@ use pocketmine\scheduler\CallbackTask;
use pocketmine\tile\Sign;
use pocketmine\tile\Spawnable;
use pocketmine\tile\Tile;
use pocketmine\utils\ReversePriorityQueue;
use pocketmine\utils\TextFormat;
/**
@ -199,7 +200,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
protected function initEntity(){
$this->getLevel()->players[spl_object_hash($this)] = $this;
parent::initEntity();
}
@ -515,7 +515,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
return false;
}else{
$index = null;
LevelFormat::getXZ($index, $this->lastChunk[0], $this->lastChunk[1]);
Level::getXZ($index, $this->lastChunk[0], $this->lastChunk[1]);
unset($this->chunksLoaded[$index]);
}
}else{*/
@ -535,16 +535,17 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$index = key($this->chunksOrder);
$distance = @$this->chunksOrder[$index];
if($index === null or $distance === null){
$this->orderChunks();
if($this->chunkScheduled === 0){
$this->server->getScheduler()->scheduleDelayedTask(new CallbackTask(array($this, "getNextChunk"), array(false, true)), 60);
}
return false;
}
$X = null;
$Z = null;
LevelFormat::getXZ($index, $X, $Z);
Level::getXZ($index, $X, $Z);
if(!$this->getLevel()->isChunkPopulated($X, $Z)){
$this->orderChunks();
if($this->chunkScheduled === 0 or $force === true){
@ -564,8 +565,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$pk = new FullChunkDataPacket;
$pk->chunkX = $X;
$pk->chunkZ = $Z;
$pk->data = $this->getLevel()->getOrderedChunk($X, $Z, $Yndex);
$pk->data = $this->getLevel()->getNetworkChunk($X, $Z, $Yndex);
$cnt = $this->dataPacket($pk, true);
if($cnt === false){
return false;
}
@ -622,43 +624,38 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$startZ = $centerZ - $this->viewDistance;
$finalX = $centerX + $this->viewDistance;
$finalZ = $centerZ + $this->viewDistance;
$generateQueue = new ReversePriorityQueue();
for($X = $startX; $X <= $finalX; ++$X){
for($Z = $startZ; $Z <= $finalZ; ++$Z){
$distance = abs($X - $centerX) + abs($Z - $centerZ);
$index = LevelFormat::getIndex($X, $Z);
$index = Level::chunkHash($X, $Z);
if(!isset($this->chunksLoaded[$index]) or $this->chunksLoaded[$index] !== 0){
if($this->getLevel()->isChunkPopulated($X, $Z)){
$newOrder[$index] = $distance;
}else{
$generateQueue->insert([$X, $Z], $distance);
}
}
unset($lastChunk[$index]);
}
}
asort($newOrder);
$this->chunksOrder = $newOrder;
$index = key($this->chunksOrder);
LevelFormat::getXZ($index, $X, $Z);
$radius = 1;
for($z = $Z - $radius; $z <= ($Z + $radius); ++$z){
for($x = $X - $radius; $x <= ($X + $radius); ++$x){
$this->getLevel()->loadChunk($x, $z);
if(!$this->getLevel()->isChunkPopulated($x, $z)){
$this->getLevel()->loadChunk($x - 1, $z);
$this->getLevel()->loadChunk($x + 1, $z);
$this->getLevel()->loadChunk($x, $z - 1);
$this->getLevel()->loadChunk($x, $z + 1);
$this->getLevel()->loadChunk($x + 1, $z + 1);
$this->getLevel()->loadChunk($x + 1, $z - 1);
$this->getLevel()->loadChunk($x - 1, $z - 1);
$this->getLevel()->loadChunk($x - 1, $z + 1);
}
}
$i = 0;
while($generateQueue->count() > 0 and $i < 8){
$d = $generateQueue->extract();
$this->getLevel()->generateChunk($d[0], $d[1]);
++$i;
}
foreach($lastChunk as $index => $Yndex){
if($Yndex === 0){
$X = null;
$Z = null;
LevelFormat::getXZ($index, $X, $Z);
Level::getXZ($index, $X, $Z);
foreach($this->getLevel()->getChunkEntities($X, $Z) as $entity){
if($entity !== $this){
$entity->despawnFrom($this);
@ -1146,7 +1143,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$nbt["lastPlayed"] = floor(microtime(true) * 1000);
$this->server->saveOfflinePlayerData($this->username, $nbt);
parent::__construct($this->getLevel(), $nbt);
parent::__construct($this->getLevel()->getChunkAt($nbt["Pos"][0], $nbt["Pos"][2], true), $nbt);
$this->inventory->setHeldItemSlot($this->getCreativeBlock(Item::get(Item::STONE, 0, 1)));
$this->loggedIn = true;
@ -1971,7 +1968,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
*/
public function close($message = "", $reason = "generic reason"){
if($this->connected === true){
unset($this->getLevel()->players[spl_object_hash($this)]);
if($this->username != ""){
$this->server->getPluginManager()->callEvent($ev = new PlayerQuitEvent($this, $message));
if($this->loggedIn === true){

View File

@ -75,7 +75,7 @@ namespace pocketmine {
const VERSION = "Alpha_1.4dev";
const API_VERSION = "1.0.0";
const CODENAME = "絶好(Zekkou)ケーキ(Cake)";
const MINECRAFT_VERSION = "v0.9.0 alpha build 1";
const MINECRAFT_VERSION = "v0.9.0 alpha build 2";
const PHP_VERSION = "5.5";
if(\Phar::running(true) !== ""){

View File

@ -776,7 +776,7 @@ class Server{
* @param Level $level
*/
public function setDefaultLevel($level){
if($level === null or ($this->isLevelLoaded($level->getName()) and $level !== $this->levelDefault)){
if($level === null or ($this->isLevelLoaded($level->getFolderName()) and $level !== $this->levelDefault)){
$this->levelDefault = $level;
}
}
@ -810,7 +810,7 @@ class Server{
*/
public function getLevelByName($name){
foreach($this->getLevels() as $level){
if($level->getName() === $name){
if($level->getFolderName() === $name){
return $level;
}
}
@ -823,7 +823,7 @@ class Server{
* @param bool $forceUnload
*/
public function unloadLevel(Level $level, $forceUnload = false){
if($level->unload($forceUnload) === true and $this->isLevelLoaded($level->getName())){
if($level->unload($forceUnload) === true and $this->isLevelLoaded($level->getFolderName())){
unset($this->levels[$level->getID()]);
}
}
@ -852,6 +852,7 @@ class Server{
$path = $this->getDataPath() . "worlds/" . $name . "/";
$provider = LevelProviderManager::getProvider($path);
if($provider === null){
$this->logger->error("Could not load level \"" . $name . "\"");
@ -862,7 +863,7 @@ class Server{
// @rename($path . "tileEntities.yml", $path . "tiles.yml");
//}
$level = new Level($this, $path, $provider);
$level = new Level($this, $name, $path, $provider);
$this->levels[$level->getID()] = $level;
/*foreach($entities->getAll() as $entity){
if(!isset($entity["id"])){
@ -994,7 +995,7 @@ class Server{
/** @var \pocketmine\level\format\LevelProvider $provider */
$provider::generate($path, $name, $seed, $generator, $options);
$level = new Level($this, $path, $provider);
$level = new Level($this, $name, $path, $provider);
$this->levels[$level->getID()] = $level;
for($Z = 6; $Z <= 10; ++$Z){
for($X = 6; $X <= 10; ++$X){
@ -1015,15 +1016,19 @@ class Server{
return false;
}
$path = $this->getDataPath() . "worlds/" . $name . "/";
if(!($this->getLevelByName($name) instanceof Level) and !file_exists($path . "level.pmf")){
if(file_exists($path)){
if(!($this->getLevelByName($name) instanceof Level)){
if(LevelProviderManager::getProvider($path) === null){
return false;
}
/*if(file_exists($path)){
$level = new LevelImport($path);
if($level->import() === false){ //Try importing a world
return false;
}
}else{
return false;
}
}*/
}
return true;
@ -1356,9 +1361,9 @@ class Server{
LevelProviderManager::addProvider($this, "pocketmine\\level\\format\\anvil\\Anvil");
Generator::addGenerator("pocketmine\\level\\generator\\Flat", "flat");
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "normal");
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "default");
//Generator::addGenerator("pocketmine\\level\\generator\\Flat", "flat");
//Generator::addGenerator("pocketmine\\level\\generator\\Normal", "normal");
//Generator::addGenerator("pocketmine\\level\\generator\\Normal", "default");
if($this->getDefaultLevel() === null){
$default = $this->getConfigString("level-name", "world");

View File

@ -589,7 +589,7 @@ abstract class Entity extends Position implements Metadatable{
if($Yndex !== 0xff){
$X = null;
$Z = null;
LevelFormat::getXZ($index, $X, $Z);
Level::getXZ($index, $X, $Z);
foreach($this->getLevel()->getChunkEntities($X, $Z) as $entity){
$entity->despawnFrom($this);
}

View File

@ -60,6 +60,7 @@ use pocketmine\tile\Sign;
use pocketmine\tile\Tile;
use pocketmine\utils\Cache;
use pocketmine\utils\ReversePriorityQueue;
use raklib\Binary;
class Level implements ChunkManager, Metadatable{
@ -109,6 +110,8 @@ class Level implements ChunkManager, Metadatable{
private $startCheck;
private $startTime;
private $folderName;
/** @var Block[][] */
protected $changedBlocks = [];
protected $changedCount = [];
@ -140,12 +143,13 @@ class Level implements ChunkManager, Metadatable{
* Init the default level data
*
* @param Server $server
* @param string $name
* @param string $path
* @param string $provider Class that extends LevelProvider
*
* @throws \Exception
*/
public function __construct(Server $server, $path, $provider){
public function __construct(Server $server, $name, $path, $provider){
$this->levelId = static::$levelIdCounter++;
$this->server = $server;
if(is_subclass_of($provider, "pocketmine\\level\\format\\LevelProvider", true)){
@ -157,6 +161,8 @@ class Level implements ChunkManager, Metadatable{
$generator = Generator::getGenerator($this->provider->getGenerator());
$this->server->getGenerationManager()->openLevel($this, $generator, $this->provider->getGeneratorOptions());
$this->folderName = $name;
$this->startTime = $this->time = (int) $this->provider->getTime();
$this->nextSave = $this->startCheck = microtime(true);
$this->nextSave = microtime(true) + 90;
@ -523,7 +529,7 @@ class Level implements ChunkManager, Metadatable{
public function getBlock(Vector3 $pos){
$blockId = null;
$meta = null;
$this->getChunkAt($pos->x >> 4, $pos->z >> 4)->getBlock($pos->x & 0x0f, $pos->y & 0x7f, $pos->z & 0x0f, $blockId, $meta);
$this->getChunkAt($pos->x >> 4, $pos->z >> 4, true)->getBlock($pos->x & 0x0f, $pos->y & 0x7f, $pos->z & 0x0f, $blockId, $meta);
return Block::get($blockId, $meta, Position::fromObject(clone $pos, $this));
}
@ -1059,7 +1065,7 @@ class Level implements ChunkManager, Metadatable{
* @return Chunk
*/
public function getChunkAt($x, $z, $create = false){
$this->provider->getChunk($x, $z, $create);
return $this->provider->getChunk($x, $z, $create);
}
/**
@ -1160,6 +1166,63 @@ class Level implements ChunkManager, Metadatable{
$this->server->getPluginManager()->callEvent(new SpawnChangeEvent($this, $previousSpawn));
}
/**
* Gets a full chunk or parts of it for networking usage, allows cache usage
*
* @param int $X
* @param int $Z
* @param int $Yndex bitmap of chunks to be returned
*
* @return bool|mixed|string
*/
public function getNetworkChunk($X, $Z, $Yndex){
if(ADVANCED_CACHE == true and $Yndex === 0xff){
$identifier = "world:".($this->getName()).":" . Level::chunkHash($X, $Z);
if(($cache = Cache::get($identifier)) !== false){
return $cache;
}
}
$orderedIds = "";
$orderedData = "";
$orderedSkyLight = "";
$orderedLight = "";
$flag = chr($Yndex);
/** @var \pocketmine\level\format\ChunkSection[] $sections */
$sections = [];
foreach($this->getChunkAt($X, $Z, true)->getSections() as $section){
$sections[$section->getY()] = $section;
}
for($x = 0; $x < 16; ++$x){
for($z = 0; $z < 16; ++$z){
for($Y = 0; $Y < 8; ++$Y){
$orderedIds .= $sections[$Y]->getBlockIdColumn($x, $z);
$orderedData .= $sections[$Y]->getBlockDataColumn($x, $z);
$orderedSkyLight .= $sections[$Y]->getBlockSkyLightColumn($x, $z);
$orderedLight .= $sections[$Y]->getBlockLightColumn($x, $z);
}
}
}
$biomeIDs = str_repeat("\x04", 256);
if($X % 5 === 0 and $Z % 5 === 0){
$ppm = base64_decode("mpqahISEbW1tZmZmZmZmXl5eXl5eXl5eXl5eXl5eXl5eZmZmZmZmbW1thISEmpqafX19bW1tbW1tS5ubS5qdfbXTSpSbS5ubTJ6cSpWZfbXTSpWZTJ6cbW1tbW1tfX19bW1tbW1tfbXSfbbVSI+dfdL/fbrafbfVSZKefbjYfbjYfbXSSpWZfbTRbW1tbW1tZmZmTKGdSpSbfbrbfbzdfdL/SI+dfbnZfdL/fdL/SZKeSpKYSYyWfbbVS5iaZmZmXl5eS6CiSZmmfdL/fbzeSZCcSpSbfbfVSJKifdL/SpegfbXTfbfWfbXTS5ubXl5eXl5efdL/fdL/fdL/fbrbfbbVSpKYfbTRSpecSpieSZCcfbjYSZCcSpegS52iXl5eXl5eSpegfbnZSZSfSZGafbbVxsYAxsYAxsYAxsYAfbjYfdL/SZikfdL/fdL/Xl5eXl5eSpSbfbjYSpegS5qdfbTRxsYA1tYA1tYAxsYASpegfdL/SZahfbfXSpegXl5eXl5efbfWfdL/AAAAAAAAAAAAxsYA1tYAAAAAxsYAS56gSp2lAAAAfbfVS5iaXl5eXl5efbXSSZWjAAAAfbnZfbjYAAAAxsYAAAAAAAAASZOgAAAAAAAAfbfWSpWZXl5eXl5eTJ6cS56gAAAAAAAAAAAASpegS5ubAAAAfdL/AAAAfdL/AAAASZOgfbfVXl5eXl5eTKKfSp2lAAAAfdL/fdL/Sp2lS56gAAAAfdL/SZamSpyjAAAAfdL/fdL/Xl5eZmZmS6CifdL/AAAASZamSZmmfdL/SZqoAAAAfdL/SJOlfdL/AAAAfbnZSpegZmZmbW1tbW1tfdL/AAAAfbXSSpegfdL/fdL/AAAAfbfXfbrbfdL/AAAAfbbVbW1tbW1tfX19bW1tbW1tAAAAfbTRS5qdSp2lfdL/AAAAS5ubSpSbfbfVAAAAbW1tbW1tfX19mpqahISEbW1tZmZmZmZmXl5eXl5eXl5eXl5eXl5eXl5eZmZmZmZmbW1thISEmpqa");
$grassColor = "\x01" . implode("\x01", str_split($ppm, 3));
}else{
$grassColor = str_repeat("\x01\x85\xb2\x4a", 256);
}
$ordered = zlib_encode(Binary::writeLInt($X) . Binary::writeLInt($Z) . $orderedIds . $orderedData . $orderedSkyLight . $orderedLight . $biomeIDs . $grassColor, ZLIB_ENCODING_DEFLATE, 8);
if(ADVANCED_CACHE == true and $Yndex === 0xff){
Cache::add($identifier, $ordered, 60);
}
return $ordered;
}
/**
* Removes the entity from the level index
*
@ -1351,6 +1414,15 @@ class Level implements ChunkManager, Metadatable{
return $this->provider->getName();
}
/**
* Returns the Level folder name
*
* @return string
*/
public function getFolderName(){
return $this->folderName;
}
/**
* Sets the current time on the level
*
@ -1395,7 +1467,7 @@ class Level implements ChunkManager, Metadatable{
* @param int $seed
*/
public function setSeed($seed){
$this->provider->setSeed();
$this->provider->setSeed($seed);
}

View File

@ -117,7 +117,7 @@ interface ChunkSection{
public function setBlockLight($x, $y, $z, $level);
/**
* Returns a id column from high y to low y
* Returns a id column from low y to high y
*
* @param int $x 0-15
* @param int $z 0-15
@ -127,7 +127,7 @@ interface ChunkSection{
public function getBlockIdColumn($x, $z);
/**
* Returns a data column from high y to low y
* Returns a data column from low y to high y
*
* @param int $x 0-15
* @param int $z 0-15
@ -136,6 +136,26 @@ interface ChunkSection{
*/
public function getBlockDataColumn($x, $z);
/**
* Returns a skylight column from low y to high y
*
* @param int $x 0-15
* @param int $z 0-15
*
* @return string[8]
*/
public function getBlockSkyLightColumn($x, $z);
/**
* Returns a data column from low y to high y
*
* @param int $x 0-15
* @param int $z 0-15
*
* @return string[8]
*/
public function getBlockLightColumn($x, $z);
public function getIdArray();
public function getDataArray();

View File

@ -93,10 +93,11 @@ interface LevelProvider{
/**
* @param int $X
* @param int $Z
* @param bool $create
*
* @return bool
*/
public function loadChunk($X, $Z);
public function loadChunk($X, $Z, $create = false);
/**
* @param int $X

View File

@ -44,7 +44,7 @@ class Anvil extends BaseLevelProvider{
public static function isValid($path){
return file_exists(realpath($path) . "level.dat") and file_exists(realpath($path) . "region/");
return file_exists($path . "/level.dat") and is_dir($path . "/region/");
}
public static function generate($path, $name, $seed, $generator, array $options = []){
@ -109,7 +109,7 @@ class Anvil extends BaseLevelProvider{
}
}
public function loadChunk($chunkX, $chunkZ){
public function loadChunk($chunkX, $chunkZ, $create = false){
$index = Level::chunkHash($chunkX, $chunkZ);
if(isset($this->chunks[$index])){
return true;
@ -117,7 +117,8 @@ class Anvil extends BaseLevelProvider{
$regionX = $regionZ = null;
self::getRegionIndex($chunkX, $chunkZ, $regionX, $regionZ);
$this->loadRegion($regionX, $regionZ);
$chunk = $this->getRegion($regionX, $regionZ)->readChunk($chunkX - $regionX * 32, $chunkZ - $regionZ * 32, true); //generate empty chunk if not loaded
$chunk = $this->getRegion($regionX, $regionZ)->readChunk($chunkX - $regionX * 32, $chunkZ - $regionZ * 32, $create); //generate empty chunk if not loaded
if($chunk instanceof Chunk){
$this->chunks[$index] = $chunk;
}else{
@ -173,13 +174,10 @@ class Anvil extends BaseLevelProvider{
$index = Level::chunkHash($chunkX, $chunkZ);
if(isset($this->chunks[$index])){
return $this->chunks[$index];
}elseif($create !== true){
return null;
}else{
$this->loadChunk($chunkX, $chunkZ, $create);
return isset($this->chunks[$index]) ? $this->chunks[$index] : null;
}
$this->loadChunk($chunkX, $chunkZ);
return $this->getChunk($chunkX, $chunkZ, false);
}
public function setChunk($chunkX, $chunkZ, SimpleChunk $chunk){
@ -195,8 +193,8 @@ class Anvil extends BaseLevelProvider{
"Y" => new Byte("Y", $y),
"Blocks" => new ByteArray("Blocks", $chunk->getSectionIds($y)),
"Data" => new ByteArray("Data", $chunk->getSectionData($y)),
"BlockLight" => new ByteArray("BlockLight", str_repeat("\xff", 2048)), //TODO
"SkyLight" => new ByteArray("SkyLight", str_repeat("\x00", 2048)) //TODO
"SkyLight" => new ByteArray("SkyLight", str_repeat("\xff", 2048)), //TODO
"BlockLight" => new ByteArray("BlockLight", str_repeat("\x00", 2048)) //TODO
]));
$newChunk->setSection($y, $section);
}
@ -239,7 +237,6 @@ class Anvil extends BaseLevelProvider{
public function close(){
$this->unloadChunks();
foreach($this->regions as $index => $region){
$region->doSlowCleanUp();
$region->close();
unset($this->regions[$index]);
}

View File

@ -37,28 +37,28 @@ class Chunk extends BaseChunk{
public function __construct(LevelProvider $level, Compound $nbt){
$this->nbt = $nbt;
if($this->nbt->Entities instanceof Enum){
if(isset($this->nbt->Entities) and $this->nbt->Entities instanceof Enum){
$this->nbt->Entities->setTagType(NBT::TAG_Compound);
}else{
$this->nbt->Entities = new Enum("Entities", []);
$this->nbt->Entities->setTagType(NBT::TAG_Compound);
}
if($this->nbt->TileEntities instanceof Enum){
if(isset($this->nbt->TileEntities) and $this->nbt->TileEntities instanceof Enum){
$this->nbt->TileEntities->setTagType(NBT::TAG_Compound);
}else{
$this->nbt->TileEntities = new Enum("TileEntities", []);
$this->nbt->TileEntities->setTagType(NBT::TAG_Compound);
}
if($this->nbt->TileTicks instanceof Enum){
if(isset($this->nbt->TileTicks) and $this->nbt->TileTicks instanceof Enum){
$this->nbt->TileTicks->setTagType(NBT::TAG_Compound);
}else{
$this->nbt->TileTicks = new Enum("TileTicks", []);
$this->nbt->TileTicks->setTagType(NBT::TAG_Compound);
}
if($this->nbt->Sections instanceof Enum){
if(isset($this->nbt->Sections) and $this->nbt->Sections instanceof Enum){
$this->nbt->Sections->setTagType(NBT::TAG_Compound);
}else{
$this->nbt->Sections = new Enum("Sections", []);

View File

@ -138,19 +138,38 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{
public function getBlockIdColumn($x, $z){
$i = ($z << 4) + $x;
$column = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
for($y = 15; $y >= 0; --$y){
$column{15 - $y} = $this->blocks{($y << 8) + $i};
$column = "";
for($y = 0; $y < 16; ++$y){
$column .= $this->blocks{($y << 8) + $i};
}
return $column;
}
public function getBlockDataColumn($x, $z){
$i = ($z << 3) + ($x >> 1);
$column = "\x00\x00\x00\x00\x00\x00\x00\x00";
for($y = 7; $y >= 0; --$y){
$column{7 - $y} = $this->data{($y << 7) + $i};
$column = "";
for($y = 0; $y < 8; ++$y){
$column .= $this->data{($y << 7) + $i};
}
return $column;
}
public function getBlockSkyLightColumn($x, $z){
$i = ($z << 3) + ($x >> 1);
$column = "";
for($y = 0; $y < 8; ++$y){
$column .= $this->skyLight{($y << 7) + $i};
}
return $column;
}
public function getBlockLightColumn($x, $z){
$i = ($z << 3) + ($x >> 1);
$column = "";
for($y = 0; $y < 8; ++$y){
$column .= $this->blockLight{($y << 7) + $i};
}
return $column;

View File

@ -120,13 +120,12 @@ class RegionLoader{
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->readCompressed(fread($this->filePointer, $length - 1), $compression);
$chunk = $nbt->getData()->Level;
if(!$chunk instanceof Compound){
$chunk = $nbt->getData();
if(!isset($chunk->Level) or !($chunk->Level instanceof Compound)){
return false;
}
return new Chunk($this->levelProvider, $chunk);
return new Chunk($this->levelProvider, $chunk->Level);
}
public function chunkExists($x, $z){
@ -159,7 +158,8 @@ class RegionLoader{
protected function saveChunk($x, $z, Compound $nbt){
$writer = new NBT(NBT::BIG_ENDIAN);
$writer->setData(new Compound("", array($nbt)));
$nbt->setName("Level");
$writer->setData(new Compound("", array("Level" => $nbt)));
$chunkData = $writer->writeCompressed(self::COMPRESSION_ZLIB, self::$COMPRESSION_LEVEL);
$length = strlen($chunkData) + 1;
$sectors = (int) ceil(($length + 4) / 4096);
@ -171,6 +171,7 @@ class RegionLoader{
fseek($this->filePointer, $this->locationTable[$index][0] << 12);
fwrite($this->filePointer, str_pad(Binary::writeInt($length) . chr(self::COMPRESSION_ZLIB) . $chunkData, $sectors << 12, "\x00", STR_PAD_RIGHT));
$this->writeLocationIndex($index);
}
public function removeChunk($x, $z){
@ -225,6 +226,7 @@ class RegionLoader{
}
public function close(){
$this->writeLocationTable();
flock($this->filePointer, LOCK_UN);
fclose($this->filePointer);
}

View File

@ -132,43 +132,43 @@ abstract class BaseChunk implements Chunk{
}
public function getBlock($x, $y, $z, &$blockId, &$meta = null){
return $this->sections[$y >> 4]->getBlock($x, $y - ($y >> 4), $z, $blockId, $meta);
return $this->sections[$y >> 4]->getBlock($x, $y & 0x0f, $z, $blockId, $meta);
}
public function setBlock($x, $y, $z, $blockId = null, $meta = null){
$this->sections[$y >> 4]->setBlock($x, $y - ($y >> 4), $z, $blockId, $meta);
$this->sections[$y >> 4]->setBlock($x, $y & 0x0f, $z, $blockId, $meta);
}
public function getBlockId($x, $y, $z){
return $this->sections[$y >> 4]->getBlockId($x, $y - ($y >> 4), $z);
return $this->sections[$y >> 4]->getBlockId($x, $y & 0x0f, $z);
}
public function setBlockId($x, $y, $z, $id){
$this->sections[$y >> 4]->setBlockId($x, $y - ($y >> 4), $z, $id);
$this->sections[$y >> 4]->setBlockId($x, $y & 0x0f, $z, $id);
}
public function getBlockData($x, $y, $z){
return $this->sections[$y >> 4]->getBlockData($x, $y - ($y >> 4), $z);
return $this->sections[$y >> 4]->getBlockData($x, $y & 0x0f, $z);
}
public function setBlockData($x, $y, $z, $data){
$this->sections[$y >> 4]->setBlockData($x, $y - ($y >> 4), $z, $data);
$this->sections[$y >> 4]->setBlockData($x, $y & 0x0f, $z, $data);
}
public function getBlockSkyLight($x, $y, $z){
return $this->sections[$y >> 4]->getBlockSkyLight($x, $y - ($y >> 4), $z);
return $this->sections[$y >> 4]->getBlockSkyLight($x, $y & 0x0f, $z);
}
public function setBlockSkyLight($x, $y, $z, $data){
$this->sections[$y >> 4]->getBlockSkyLight($x, $y - ($y >> 4), $z, $data);
$this->sections[$y >> 4]->getBlockSkyLight($x, $y & 0x0f, $z, $data);
}
public function getBlockLight($x, $y, $z){
return $this->sections[$y >> 4]->getBlockSkyLight($x, $y - ($y >> 4), $z);
return $this->sections[$y >> 4]->getBlockSkyLight($x, $y & 0x0f, $z);
}
public function setBlockLight($x, $y, $z, $data){
$this->sections[$y >> 4]->getBlockSkyLight($x, $y - ($y >> 4), $z, $data);
$this->sections[$y >> 4]->getBlockSkyLight($x, $y & 0x0f, $z, $data);
}
public function getHighestBlockAt($x, $z){

View File

@ -37,7 +37,7 @@ abstract class BaseLevelProvider implements LevelProvider{
protected $levelData;
public function __construct(Level $level, $path){
$this->level = $level->getServer();
$this->level = $level;
$this->path = $path;
@mkdir($this->path, 0777, true);
$nbt = new NBT(NBT::BIG_ENDIAN);

View File

@ -50,6 +50,14 @@ class EmptyChunkSection implements ChunkSection{
return "\x00\x00\x00\x00\x00\x00\x00\x00";
}
final public function getBlockSkyLightColumn($x, $z){
return "\x00\x00\x00\x00\x00\x00\x00\x00";
}
final public function getBlockLightColumn($x, $z){
return "\x00\x00\x00\x00\x00\x00\x00\x00";
}
final public function getBlock($x, $y, $z, &$id = null, &$meta = null){
$id = 0;
$meta = 0;

View File

@ -59,7 +59,7 @@ class Flat extends Generator{
$this->preset = "2;7,2x3,2;1;";
//$this->preset = "2;7,59x1,3x3,2;1;spawn(radius=10 block=89),decoration(treecount=80 grasscount=45)";
$this->options = $options;
if(isset($options["preset"])){
if(isset($options["preset"]) and $options["preset"] != ""){
$this->parsePreset($options["preset"]);
}else{
$this->parsePreset($this->preset);
@ -112,13 +112,9 @@ class Flat extends Generator{
$this->chunk = new SimpleChunk(null, null, SimpleChunk::FLAG_GENERATED);
for($Y = 0; $Y < 8; ++$Y){
$this->chunks[$Y] = "";
$startY = $Y << 4;
$endY = $startY + 16;
for($Z = 0; $Z < 16; ++$Z){
for($X = 0; $X < 16; ++$X){
for($y = $startY; $y < $endY; ++$y){
for($y = 0; $y < 128; ++$y){
if($this->structure[$y][0] !== 0){
$this->chunk->setBlockId($X, $y, $Z, $this->structure[$y][0]);
}
@ -128,7 +124,6 @@ class Flat extends Generator{
}
}
}
}
preg_match_all('#(([0-9a-z_]{1,})\(?([0-9a-z_ =:]{0,})\)?),?#', $options, $matches);
foreach($matches[2] as $i => $option){
@ -164,6 +159,7 @@ class Flat extends Generator{
foreach($this->populators as $populator){
$populator->populate($this->level, $chunkX, $chunkZ, $this->random);
}
}
public function getSpawn(){

View File

@ -83,6 +83,7 @@ class GenerationChunkManager implements ChunkManager{
public function generateChunk($chunkX, $chunkZ){
$this->chunks[Level::chunkHash($chunkX, $chunkZ)] = new SimpleChunk($chunkX, $chunkZ, 0);
$this->generator->generateChunk($chunkX, $chunkZ);
$this->setChunkGenerated($chunkX, $chunkZ);
}
public function populateChunk($chunkX, $chunkZ){
@ -99,6 +100,8 @@ class GenerationChunkManager implements ChunkManager{
}
$this->generator->populateChunk($chunkX, $chunkZ);
$this->setChunkPopulated($chunkX, $chunkZ);
}
public function isChunkGenerated($chunkX, $chunkZ){
@ -109,6 +112,14 @@ class GenerationChunkManager implements ChunkManager{
return $this->getChunk($chunkX, $chunkZ)->isPopulated();
}
public function setChunkGenerated($chunkX, $chunkZ){
$this->getChunk($chunkX, $chunkZ)->setGenerated(true);
}
public function setChunkPopulated($chunkX, $chunkZ){
$this->getChunk($chunkX, $chunkZ)->setPopulated(true);
}
protected function requestChunk($chunkX, $chunkZ){
$chunk = $this->manager->requestChunk($this->levelID, $chunkX, $chunkZ);
$this->chunks[Level::chunkHash($chunkX, $chunkZ)] = $chunk;

View File

@ -122,11 +122,11 @@ class GenerationManager{
$chunkX = $r[1];
$chunkZ = $r[2];
$this->generateChunk($levelID, $chunkX, $chunkZ);
}
}else{
$this->readPacket();
}
}
}
protected function openLevel($levelID, $seed, $class, array $options){
if(!isset($this->levels[$levelID])){

View File

@ -44,7 +44,8 @@ abstract class Generator{
return Generator::$list[$name];
}
return "pocketmine\\level\\generator\\Normal";
//return "pocketmine\\level\\generator\\Normal";
return "pocketmine\\level\\generator\\Flat";
}
public static function getGeneratorName($class){

View File

@ -30,7 +30,7 @@ interface Info{
/**
* Actual Minecraft: PE protocol version
*/
const CURRENT_PROTOCOL = 14; //WTF Mojang
const CURRENT_PROTOCOL = 15;
const LOGIN_PACKET = 0x82;

@ -1 +1 @@
Subproject commit 345009779b039fa9c0238fd0a57df5eeff2a2753
Subproject commit cac93ad971a0b2792f4bb9873c73a76254dd1f7d