mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 03:06:55 +00:00
Updated Position to use Weak / strong references for Level objects
This commit is contained in:
@ -56,6 +56,20 @@ class Chunk extends BaseChunk{
|
||||
$this->nbt->TileTicks->setTagType(NBT::TAG_Compound);
|
||||
}
|
||||
|
||||
if($this->nbt->Sections instanceof Enum){
|
||||
$this->nbt->Sections->setTagType(NBT::TAG_Compound);
|
||||
}else{
|
||||
$this->nbt->Sections = new Enum("Sections", array());
|
||||
$this->nbt->Sections->setTagType(NBT::TAG_Compound);
|
||||
}
|
||||
|
||||
$sections = array();
|
||||
foreach($this->nbt->Sections as $section){
|
||||
if($section instanceof Compound){
|
||||
$sections[(int) $section["Y"]] = new ChunkSection($section);
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($level, $this->nbt["xPos"], $this->nbt["zPos"], $sections);
|
||||
}
|
||||
}
|
153
src/pocketmine/level/format/anvil/ChunkSection.php
Normal file
153
src/pocketmine/level/format/anvil/ChunkSection.php
Normal file
@ -0,0 +1,153 @@
|
||||
<?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\anvil;
|
||||
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
|
||||
class ChunkSection implements \pocketmine\level\format\ChunkSection{
|
||||
|
||||
private $y;
|
||||
private $blocks;
|
||||
private $data;
|
||||
private $blockLight;
|
||||
private $skyLight;
|
||||
|
||||
public function __construct(Compound $nbt){
|
||||
$this->y = (int) $nbt["Y"];
|
||||
$this->blocks = (string) $nbt["Blocks"];
|
||||
$this->data = (string) $nbt["Data"];
|
||||
$this->blockLight = (string) $nbt["BlockLight"];
|
||||
$this->skyLight = (string) $nbt["SkyLight"];
|
||||
}
|
||||
|
||||
public function getBlockId($x, $y, $z){
|
||||
return ord($this->blocks{($y << 8) + ($z << 4) + $x});
|
||||
}
|
||||
|
||||
public function setBlockId($x, $y, $z, $id){
|
||||
$this->blocks{($y << 8) + ($z << 4) + $x} = chr($id);
|
||||
}
|
||||
|
||||
public function getBlockData($x, $y, $z){
|
||||
$m = ord($this->data{($y << 7) + ($z << 3) + ($x >> 1)});
|
||||
if(($y & 1) === 0){
|
||||
return $m & 0x0F;
|
||||
}else{
|
||||
return $m >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
public function setBlockData($x, $y, $z, $data){
|
||||
$i = ($y << 7) + ($z << 3) + ($x >> 1);
|
||||
$old_m = ord($this->data{$i});
|
||||
if(($y & 1) === 0){
|
||||
$this->data{$i} = chr(($old_m & 0xf0) | ($data & 0x0f));
|
||||
}else{
|
||||
$this->data{$i} = chr((($data & 0x0f) << 4) | ($old_m & 0x0f));
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlock($x, $y, $z, &$blockId, &$meta = null){
|
||||
$i = ($y << 8) + ($z << 4) + $x;
|
||||
$blockId = ord($this->blocks{$i});
|
||||
$m = ord($this->data{$i >> 1});
|
||||
if(($y & 1) === 0){
|
||||
$meta = $m & 0x0F;
|
||||
}else{
|
||||
$meta = $m >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
public function setBlock($x, $y, $z, $blockId = null, $meta = null){
|
||||
$i = ($y << 8) + ($z << 4) + $x;
|
||||
if($blockId !== null){
|
||||
$this->blocks{$i} = chr($blockId);
|
||||
}
|
||||
|
||||
if($meta !== null){
|
||||
$i >>= 1;
|
||||
$old_m = ord($this->data{$i});
|
||||
if(($y & 1) === 0){
|
||||
$this->data{$i} = chr(($old_m & 0xf0) | ($meta & 0x0f));
|
||||
}else{
|
||||
$this->data{$i} = chr((($meta & 0x0f) << 4) | ($old_m & 0x0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlockSkyLight($x, $y, $z){
|
||||
$sl = ord($this->skyLight{($y << 7) + ($z << 3) + ($x >> 1)});
|
||||
if(($y & 1) === 0){
|
||||
return $sl & 0x0F;
|
||||
}else{
|
||||
return $sl >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
public function setBlockSkyLight($x, $y, $z, $level){
|
||||
$i = ($y << 7) + ($z << 3) + ($x >> 1);
|
||||
$old_sl = ord($this->skyLight{$i});
|
||||
if(($y & 1) === 0){
|
||||
$this->skyLight{$i} = chr(($old_sl & 0xf0) | ($level & 0x0f));
|
||||
}else{
|
||||
$this->skyLight{$i} = chr((($level & 0x0f) << 4) | ($old_sl & 0x0f));
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlockLight($x, $y, $z){
|
||||
$l = ord($this->blockLight{($y << 7) + ($z << 3) + ($x >> 1)});
|
||||
if(($y & 1) === 0){
|
||||
return $l & 0x0F;
|
||||
}else{
|
||||
return $l >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
public function setBlockLight($x, $y, $z, $level){
|
||||
$i = ($y << 7) + ($z << 3) + ($x >> 1);
|
||||
$old_l = ord($this->blockLight{$i});
|
||||
if(($y & 1) === 0){
|
||||
$this->blockLight{$i} = chr(($old_l & 0xf0) | ($level & 0x0f));
|
||||
}else{
|
||||
$this->blockLight{$i} = chr((($level & 0x0f) << 4) | ($old_l & 0x0f));
|
||||
}
|
||||
}
|
||||
|
||||
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};
|
||||
}
|
||||
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};
|
||||
}
|
||||
return $column;
|
||||
}
|
||||
|
||||
}
|
@ -45,10 +45,10 @@ class RegionLoader{
|
||||
protected $lastSector;
|
||||
protected $locationTable = array();
|
||||
|
||||
public function __construct($path, $regionX, $regionZ){
|
||||
public function __construct($path,/*Level $level, */$regionX, $regionZ){
|
||||
$this->x = $regionX;
|
||||
$this->z = $regionZ;
|
||||
$this->filePath = $path . "region/r.$regionX.$regionZ.mca";
|
||||
$this->filePath = /*$level->getPath()*/$path . "region/r.$regionX.$regionZ.mca";
|
||||
touch($this->filePath);
|
||||
$this->filePointer = fopen($this->filePath, "r+b");
|
||||
flock($this->filePointer, LOCK_EX);
|
||||
@ -113,6 +113,8 @@ class RegionLoader{
|
||||
if(!$chunk instanceof Compound){
|
||||
return false;
|
||||
}
|
||||
return $chunk;
|
||||
//$chunk = new Chunk($level, $chunk);
|
||||
}
|
||||
|
||||
public function generateChunk($x, $z){
|
||||
@ -138,7 +140,7 @@ class RegionLoader{
|
||||
$writer->setData(new Compound("", array($nbt)));
|
||||
$chunkData = $writer->writeCompressed(self::COMPRESSION_ZLIB, self::$COMPRESSION_LEVEL);
|
||||
$length = strlen($chunkData) + 1;
|
||||
$sectors = ($length + 4) >> 12;
|
||||
$sectors = (int) ceil(($length + 4) / 4096);
|
||||
$index = self::getChunkOffset($x, $z);
|
||||
if($this->locationTable[$index][1] < $sectors){
|
||||
$this->locationTable[$index][0] = $this->lastSector += $sectors; //The GC will clean this shift later
|
||||
@ -153,11 +155,42 @@ class RegionLoader{
|
||||
return $x + ($z << 5);
|
||||
}
|
||||
|
||||
public function doSlowCleanUp(){
|
||||
for($i = 0; $i < 1024; ++$i){
|
||||
if($this->locationTable[$i][0] === 0 or $this->locationTable[$i][1] === 0){
|
||||
continue;
|
||||
}
|
||||
fseek($this->filePointer, $this->locationTable[$i][0] << 12);
|
||||
$chunk = fread($this->filePointer, $this->locationTable[$i][1] << 12);
|
||||
$length = Binary::readInt(substr($chunk, 0, 4));
|
||||
if($length <= 1){
|
||||
$this->locationTable[$i] = array(0, 0, 0); //Non-generated chunk, remove it from index
|
||||
}
|
||||
$chunk = zlib_decode(substr($chunk, 5));
|
||||
if(strlen($chunk) <= 1){
|
||||
$this->locationTable[$i] = array(0, 0, 0); //Corrupted chunk, remove it
|
||||
continue;
|
||||
}
|
||||
$chunk = chr(self::COMPRESSION_ZLIB) . zlib_encode($chunk, 15, 9);
|
||||
$chunk = Binary::writeInt(strlen($chunk)) . $chunk;
|
||||
$sectors = (int) ceil(strlen($chunk) / 4096);
|
||||
if($sectors > $this->locationTable[$i][1]){
|
||||
$this->locationTable[$i][0] = $this->lastSector += $sectors;
|
||||
}
|
||||
fseek($this->filePointer, $this->locationTable[$i][0] << 12);
|
||||
fwrite($this->filePointer, str_pad($chunk, $sectors << 12, "\x00", STR_PAD_RIGHT));
|
||||
}
|
||||
$this->writeLocationTable();
|
||||
$n = $this->cleanGarbage();
|
||||
$this->writeLocationTable();
|
||||
return $n;
|
||||
}
|
||||
|
||||
private function cleanGarbage(){
|
||||
$sectors = array();
|
||||
foreach($this->locationTable as $index => $data){ //Calculate file usage
|
||||
if($data[0] === 0 or $data[1] === 0){
|
||||
$this->locationTable[$index] = array(0, 0);
|
||||
$this->locationTable[$index] = array(0, 0, 0);
|
||||
continue;
|
||||
}
|
||||
for($i = 0; $i < $data[1]; ++$i){
|
||||
@ -186,9 +219,9 @@ class RegionLoader{
|
||||
fwrite($this->filePointer, $old, 4096);
|
||||
}
|
||||
$this->locationTable[$index][0] -= $shift;
|
||||
$lastSector = $sector;
|
||||
}
|
||||
ftruncate($this->filePointer, ($sector + 1) << 12); //Truncate to the end of file written
|
||||
|
||||
return $shift;
|
||||
}
|
||||
|
||||
@ -198,20 +231,16 @@ class RegionLoader{
|
||||
$table = fread($this->filePointer, 4 * 1024 * 2);
|
||||
for($i = 0; $i < 1024; ++$i){
|
||||
$index = Binary::readInt(substr($table, $i << 2, 4));
|
||||
$this->locationTable[$i] = array(($index & ~0xff) >> 8, $index & 0xff);
|
||||
$this->locationTable[$i] = array(($index & ~0xff) >> 8, $index & 0xff, Binary::readInt(substr($table, 4096 + ($i << 2), 4)));
|
||||
if(($this->locationTable[$i][0] + $this->locationTable[$i][1] - 1) > $this->lastSector){
|
||||
$this->lastSector = $this->locationTable[$i][0] + $this->locationTable[$i][1] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Time of modification
|
||||
for($i = 0; $i < 1024; ++$i){
|
||||
$this->locationTable[$i][2] = Binary::readInt(substr($table, 4096 + ($i << 2), 4));
|
||||
}
|
||||
}
|
||||
|
||||
private function writeLocationTable(){
|
||||
$table = "";
|
||||
|
||||
for($i = 0; $i < 1024; ++$i){
|
||||
$table .= Binary::writeInt(($this->locationTable[$i][0] << 8) | $this->locationTable[$i][1]);
|
||||
}
|
||||
@ -241,6 +270,7 @@ class RegionLoader{
|
||||
|
||||
$time = time();
|
||||
for($i = 0; $i < 1024; ++$i){
|
||||
$this->locationTable[$i][2] = $time;
|
||||
$table .= Binary::writeInt($time);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user