mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-08 10:53:05 +00:00
Added MemoryManager, new memory properties, improved performance, updated RakLib, fixed misc. bugs
This commit is contained in:
@ -93,12 +93,10 @@ use pocketmine\scheduler\AsyncTask;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\tile\Chest;
|
||||
use pocketmine\tile\Tile;
|
||||
use pocketmine\utils\Cache;
|
||||
use pocketmine\utils\LevelException;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\Random;
|
||||
use pocketmine\utils\ReversePriorityQueue;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\level\particle\Particle;
|
||||
use pocketmine\level\sound\Sound;
|
||||
use pocketmine\entity\Effect;
|
||||
@ -145,6 +143,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
private $cacheChunks = false;
|
||||
|
||||
private $sendTimeTicker = 0;
|
||||
|
||||
/** @var Server */
|
||||
private $server;
|
||||
|
||||
@ -512,6 +512,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
*/
|
||||
public function freeChunk($X, $Z, Player $player){
|
||||
unset($this->usedChunks[$index = Level::chunkHash($X, $Z)][$player->getId()]);
|
||||
|
||||
$this->unloadChunkRequest($X, $Z, true);
|
||||
}
|
||||
|
||||
@ -553,8 +554,9 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
$this->checkTime();
|
||||
|
||||
if(($currentTick % 200) === 0){
|
||||
if(++$this->sendTimeTicker === 200){
|
||||
$this->sendTime();
|
||||
$this->sendTimeTicker = 0;
|
||||
}
|
||||
|
||||
$this->unloadChunks();
|
||||
@ -646,7 +648,11 @@ class Level implements ChunkManager, Metadatable{
|
||||
Server::broadcastPacket($target, $pk->setChannel(Network::CHANNEL_BLOCKS));
|
||||
}
|
||||
|
||||
public function clearCache(){
|
||||
public function clearCache($full = false){
|
||||
if($full){
|
||||
$this->chunkCache = [];
|
||||
}
|
||||
|
||||
$this->blockCache = [];
|
||||
}
|
||||
|
||||
@ -1987,11 +1993,11 @@ class Level implements ChunkManager, Metadatable{
|
||||
}
|
||||
}
|
||||
|
||||
public function chunkRequestCallback($x, $z, $payload){
|
||||
public function chunkRequestCallback($x, $z, &$payload){
|
||||
$index = Level::chunkHash($x, $z);
|
||||
|
||||
if(!isset($this->chunkCache[$index]) and $this->cacheChunks){
|
||||
$this->chunkCache[$index] = $payload;
|
||||
if(!isset($this->chunkCache[$index]) and $this->cacheChunks and $this->server->getMemoryManager()->canUseChunkCache()){
|
||||
$this->chunkCache[$index] =& $payload;
|
||||
}
|
||||
|
||||
if(isset($this->chunkSendTasks[$index])){
|
||||
@ -2077,7 +2083,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @return bool
|
||||
*/
|
||||
public function isChunkInUse($x, $z){
|
||||
return isset($this->usedChunks[Level::chunkHash($x, $z)]) and count($this->usedChunks[Level::chunkHash($x, $z)]) > 0;
|
||||
return isset($this->usedChunks[$index = Level::chunkHash($x, $z)]) and count($this->usedChunks[$index]) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2118,6 +2124,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
return false;
|
||||
}
|
||||
|
||||
$chunk->setChanged(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2145,6 +2153,10 @@ class Level implements ChunkManager, Metadatable{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!$this->isChunkLoaded($x, $z)){
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->timings->doChunkUnload->startTiming();
|
||||
|
||||
$index = Level::chunkHash($x, $z);
|
||||
@ -2154,6 +2166,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
if($chunk !== null and $chunk->getProvider() !== null){
|
||||
$this->server->getPluginManager()->callEvent($ev = new ChunkUnloadEvent($chunk));
|
||||
if($ev->isCancelled()){
|
||||
$this->timings->doChunkUnload->stopTiming();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -2187,6 +2200,10 @@ class Level implements ChunkManager, Metadatable{
|
||||
unset($this->chunkTickList[$index]);
|
||||
unset($this->chunkCache[$index]);
|
||||
|
||||
$refs = \pocketmine\getReferenceCount($chunk);
|
||||
|
||||
//$this->server->getLogger()->debug("Unloaded $x $z (".count($this->getChunks()).") [refs $refs]");
|
||||
|
||||
$this->timings->doChunkUnload->stopTiming();
|
||||
|
||||
return true;
|
||||
|
@ -288,25 +288,25 @@ interface FullChunk{
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getBiomeIdArray();
|
||||
public function &getBiomeIdArray();
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
public function getBiomeColorArray();
|
||||
public function &getBiomeColorArray();
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
public function getHeightMapArray();
|
||||
public function &getHeightMapArray();
|
||||
|
||||
public function getBlockIdArray();
|
||||
public function &getBlockIdArray();
|
||||
|
||||
public function getBlockDataArray();
|
||||
public function &getBlockDataArray();
|
||||
|
||||
public function getBlockSkyLightArray();
|
||||
public function &getBlockSkyLightArray();
|
||||
|
||||
public function getBlockLightArray();
|
||||
public function &getBlockLightArray();
|
||||
|
||||
public function toBinary();
|
||||
|
||||
@ -328,7 +328,7 @@ interface FullChunk{
|
||||
*
|
||||
* @return FullChunk
|
||||
*/
|
||||
public static function fromBinary($data, LevelProvider $provider = null);
|
||||
public static function fromBinary(&$data, LevelProvider $provider = null);
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
@ -336,6 +336,6 @@ interface FullChunk{
|
||||
*
|
||||
* @return FullChunk
|
||||
*/
|
||||
public static function fromFastBinary($data, LevelProvider $provider = null);
|
||||
public static function fromFastBinary(&$data, LevelProvider $provider = null);
|
||||
|
||||
}
|
@ -87,13 +87,13 @@ abstract class BaseFullChunk implements FullChunk{
|
||||
$this->x = (int) $x;
|
||||
$this->z = (int) $z;
|
||||
|
||||
$this->blocks = $blocks;
|
||||
$this->data = $data;
|
||||
$this->skyLight = $skyLight;
|
||||
$this->blockLight = $blockLight;
|
||||
$this->blocks =& $blocks;
|
||||
$this->data =& $data;
|
||||
$this->skyLight =& $skyLight;
|
||||
$this->blockLight =& $blockLight;
|
||||
|
||||
if(strlen($biomeIds) === 256){
|
||||
$this->biomeIds = $biomeIds;
|
||||
$this->biomeIds =& $biomeIds;
|
||||
}else{
|
||||
$this->biomeIds = str_repeat("\x01", 256);
|
||||
}
|
||||
@ -321,31 +321,31 @@ abstract class BaseFullChunk implements FullChunk{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getBlockIdArray(){
|
||||
public function &getBlockIdArray(){
|
||||
return $this->blocks;
|
||||
}
|
||||
|
||||
public function getBlockDataArray(){
|
||||
public function &getBlockDataArray(){
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function getBlockSkyLightArray(){
|
||||
public function &getBlockSkyLightArray(){
|
||||
return $this->skyLight;
|
||||
}
|
||||
|
||||
public function getBlockLightArray(){
|
||||
public function &getBlockLightArray(){
|
||||
return $this->blockLight;
|
||||
}
|
||||
|
||||
public function getBiomeIdArray(){
|
||||
public function &getBiomeIdArray(){
|
||||
return $this->biomeIds;
|
||||
}
|
||||
|
||||
public function getBiomeColorArray(){
|
||||
public function &getBiomeColorArray(){
|
||||
return $this->biomeColors;
|
||||
}
|
||||
|
||||
public function getHeightMapArray(){
|
||||
public function &getHeightMapArray(){
|
||||
return $this->heightMap;
|
||||
}
|
||||
|
||||
@ -357,11 +357,11 @@ abstract class BaseFullChunk implements FullChunk{
|
||||
$this->hasChanged = (bool) $changed;
|
||||
}
|
||||
|
||||
public static function fromFastBinary($data, LevelProvider $provider = null){
|
||||
public static function &fromFastBinary(&$data, LevelProvider $provider = null){
|
||||
static::fromBinary($data, $provider);
|
||||
}
|
||||
|
||||
public function toFastBinary(){
|
||||
public function &toFastBinary(){
|
||||
return $this->toBinary();
|
||||
}
|
||||
|
||||
|
@ -221,7 +221,7 @@ class Chunk extends BaseFullChunk{
|
||||
$this->isGenerated = (bool) $value;
|
||||
}
|
||||
|
||||
public static function fromFastBinary($data, LevelProvider $provider = null){
|
||||
public static function fromFastBinary(&$data, LevelProvider $provider = null){
|
||||
return self::fromBinary($data, $provider);
|
||||
}
|
||||
|
||||
@ -231,7 +231,7 @@ class Chunk extends BaseFullChunk{
|
||||
*
|
||||
* @return Chunk
|
||||
*/
|
||||
public static function fromBinary($data, LevelProvider $provider = null){
|
||||
public static function fromBinary(&$data, LevelProvider $provider = null){
|
||||
try{
|
||||
$chunkX = Binary::readLInt(substr($data, 0, 4));
|
||||
$chunkZ = Binary::readLInt(substr($data, 4, 4));
|
||||
|
@ -276,7 +276,7 @@ class Chunk extends BaseFullChunk{
|
||||
*
|
||||
* @return Chunk
|
||||
*/
|
||||
public static function fromBinary($data, LevelProvider $provider = null){
|
||||
public static function fromBinary(&$data, LevelProvider $provider = null){
|
||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
||||
|
||||
try{
|
||||
@ -293,7 +293,7 @@ class Chunk extends BaseFullChunk{
|
||||
}
|
||||
}
|
||||
|
||||
public static function fromFastBinary($data, LevelProvider $provider = null){
|
||||
public static function fromFastBinary(&$data, LevelProvider $provider = null){
|
||||
|
||||
try{
|
||||
$offset = 0;
|
||||
@ -340,11 +340,11 @@ class Chunk extends BaseFullChunk{
|
||||
}
|
||||
}
|
||||
|
||||
public function toFastBinary(){
|
||||
public function &toFastBinary(){
|
||||
$biomeColors = pack("N*", ...$this->getBiomeColorArray());
|
||||
$heightMap = pack("N*", ...$this->getHeightMapArray());
|
||||
|
||||
return
|
||||
$data =
|
||||
Binary::writeInt($this->x) .
|
||||
Binary::writeInt($this->z) .
|
||||
$this->getBlockIdArray() .
|
||||
@ -355,9 +355,10 @@ class Chunk extends BaseFullChunk{
|
||||
$biomeColors .
|
||||
$heightMap .
|
||||
chr(($this->isPopulated() ? 1 << 1 : 0) + ($this->isGenerated() ? 1 : 0));
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function toBinary(){
|
||||
public function &toBinary(){
|
||||
$nbt = clone $this->getNBT();
|
||||
|
||||
$nbt->xPos = new Int("xPos", $this->x);
|
||||
@ -400,7 +401,8 @@ class Chunk extends BaseFullChunk{
|
||||
$nbt->setName("Level");
|
||||
$writer->setData(new Compound("", ["Level" => $nbt]));
|
||||
|
||||
return $writer->writeCompressed(ZLIB_ENCODING_DEFLATE, RegionLoader::$COMPRESSION_LEVEL);
|
||||
$data =& $writer->writeCompressed(ZLIB_ENCODING_DEFLATE, RegionLoader::$COMPRESSION_LEVEL);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,7 +130,8 @@ class RegionLoader{
|
||||
return null;
|
||||
}
|
||||
|
||||
$chunk = Chunk::fromBinary(fread($this->filePointer, $length - 1), $this->levelProvider);
|
||||
$data = fread($this->filePointer, $length - 1);
|
||||
$chunk = Chunk::fromBinary($data, $this->levelProvider);
|
||||
if($chunk instanceof Chunk){
|
||||
return $chunk;
|
||||
}elseif($forward === false){
|
||||
@ -156,12 +157,15 @@ class RegionLoader{
|
||||
$nbt->TerrainPopulated = new Byte("TerrainPopulated", 0);
|
||||
$nbt->V = new Byte("V", self::VERSION);
|
||||
$nbt->InhabitedTime = new Long("InhabitedTime", 0);
|
||||
$nbt->Biomes = new ByteArray("Biomes", str_repeat(Binary::writeByte(-1), 256));
|
||||
$biomes = str_repeat(Binary::writeByte(-1), 256);
|
||||
$nbt->Biomes = new ByteArray("Biomes", $biomes);
|
||||
$nbt->HeightMap = new IntArray("HeightMap", array_fill(0, 256, 127));
|
||||
$nbt->BiomeColors = new IntArray("BiomeColors", array_fill(0, 256, Binary::readInt("\x00\x85\xb2\x4a")));
|
||||
|
||||
$nbt->Blocks = new ByteArray("Blocks", str_repeat("\x00", 32768));
|
||||
$nbt->Data = new ByteArray("Data", $half = str_repeat("\x00", 16384));
|
||||
$half = str_repeat("\x00", 16384);
|
||||
$full = $half . $half;
|
||||
$nbt->Blocks = new ByteArray("Blocks", $full);
|
||||
$nbt->Data = new ByteArray("Data", $half);
|
||||
$nbt->SkyLight = new ByteArray("SkyLight", $half);
|
||||
$nbt->BlockLight = new ByteArray("BlockLight", $half);
|
||||
|
||||
@ -181,7 +185,7 @@ class RegionLoader{
|
||||
}
|
||||
}
|
||||
|
||||
protected function saveChunk($x, $z, $chunkData){
|
||||
protected function saveChunk($x, $z, &$chunkData){
|
||||
$length = strlen($chunkData) + 1;
|
||||
if($length + 4 > self::MAX_SECTOR_LENGTH){
|
||||
throw new ChunkException("Chunk is too big! ".($length + 4)." > ".self::MAX_SECTOR_LENGTH);
|
||||
@ -208,7 +212,7 @@ class RegionLoader{
|
||||
|
||||
public function writeChunk(FullChunk $chunk){
|
||||
$this->lastUsed = time();
|
||||
$chunkData = $chunk->toBinary();
|
||||
$chunkData = &$chunk->toBinary();
|
||||
if($chunkData !== false){
|
||||
$this->saveChunk($chunk->getX() - ($this->getX() * 32), $chunk->getZ() - ($this->getZ() * 32), $chunkData);
|
||||
}
|
||||
|
Reference in New Issue
Block a user