mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-20 16:00:20 +00:00
Level optimization, added new chunk/block hashes
This commit is contained in:
parent
ddfc9d9ce1
commit
04ecbd1a76
@ -607,6 +607,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$X = null;
|
||||
$Z = null;
|
||||
Level::getXZ($index, $X, $Z);
|
||||
|
||||
if(!$this->level->isChunkPopulated($X, $Z)){
|
||||
$this->level->generateChunk($X, $Z);
|
||||
if($this->spawned){
|
||||
@ -687,7 +688,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
for($Z = -$side; $Z <= $side; ++$Z){
|
||||
$chunkX = $X + $centerX;
|
||||
$chunkZ = $Z + $centerZ;
|
||||
if(!isset($this->usedChunks[$index = "$chunkX:$chunkZ"])){
|
||||
if(!isset($this->usedChunks[$index = Level::chunkHash($chunkX, $chunkZ)])){
|
||||
$newOrder[$index] = abs($X) + abs($Z);
|
||||
}else{
|
||||
$currentQueue[$index] = abs($X) + abs($Z);
|
||||
|
@ -538,6 +538,8 @@ class Block extends Position implements Metadatable{
|
||||
/** @var \SplFixedArray */
|
||||
public static $solid = null;
|
||||
/** @var \SplFixedArray */
|
||||
public static $hardness = null;
|
||||
/** @var \SplFixedArray */
|
||||
public static $transparent = null;
|
||||
|
||||
protected $id;
|
||||
@ -579,6 +581,7 @@ class Block extends Position implements Metadatable{
|
||||
self::$light = new \SplFixedArray(256);
|
||||
self::$lightFilter = new \SplFixedArray(256);
|
||||
self::$solid = new \SplFixedArray(256);
|
||||
self::$hardness = new \SplFixedArray(256);
|
||||
self::$transparent = new \SplFixedArray(256);
|
||||
self::$list[self::AIR] = Air::class;
|
||||
self::$list[self::STONE] = Stone::class;
|
||||
@ -739,6 +742,7 @@ class Block extends Position implements Metadatable{
|
||||
|
||||
self::$solid[$id] = $block->isSolid();
|
||||
self::$transparent[$id] = $block->isTransparent();
|
||||
self::$hardness[$id] = $block->getHardness();
|
||||
self::$light[$id] = $block->getLightLevel();
|
||||
|
||||
if($block->isSolid()){
|
||||
|
@ -83,25 +83,27 @@ class Explosion{
|
||||
return false;
|
||||
}
|
||||
|
||||
$pointer = new Vector3(0, 0, 0);
|
||||
$vector = new Vector3(0, 0, 0);
|
||||
$vBlock = new Vector3(0, 0, 0);
|
||||
|
||||
$mRays = $this->rays - 1;
|
||||
$mRays = intval($this->rays - 1);
|
||||
for($i = 0; $i < $this->rays; ++$i){
|
||||
for($j = 0; $j < $this->rays; ++$j){
|
||||
//break 2 gets here
|
||||
for($k = 0; $k < $this->rays; ++$k){
|
||||
if($i == 0 or $i == $mRays or $j == 0 or $j == $mRays or $k == 0 or $k == $mRays){
|
||||
if($i === 0 or $i === $mRays or $j === 0 or $j === $mRays or $k === 0 or $k === $mRays){
|
||||
$vector->setComponents($i / $mRays * 2 - 1, $j / $mRays * 2 - 1, $k / $mRays * 2 - 1);
|
||||
$vector->setComponents(($vector->x / ($len = $vector->length())) * $this->stepLen, ($vector->y / $len) * $this->stepLen, ($vector->z / $len) * $this->stepLen);
|
||||
$pointer->setComponents($this->source->x, $this->source->y, $this->source->z);
|
||||
$pointerX = $this->source->x;
|
||||
$pointerY = $this->source->y;
|
||||
$pointerZ = $this->source->z;
|
||||
|
||||
for($blastForce = $this->size * (mt_rand(700, 1300) / 1000); $blastForce > 0; $blastForce -= $this->stepLen * 0.75){
|
||||
$x = (int) $pointer->x;
|
||||
$y = (int) $pointer->y;
|
||||
$z = (int) $pointer->z;
|
||||
$vBlock->setComponents($pointer->x >= $x ? $x : $x - 1, $pointer->y >= $y ? $y : $y - 1, $pointer->z >= $z ? $z : $z - 1);
|
||||
$x = (int) $pointerX;
|
||||
$y = (int) $pointerY;
|
||||
$z = (int) $pointerZ;
|
||||
$vBlock->x = $pointerX >= $x ? $x : $x - 1;
|
||||
$vBlock->y = $pointerY >= $y ? $y : $y - 1;
|
||||
$vBlock->z = $pointerZ >= $z ? $z : $z - 1;
|
||||
if($vBlock->y < 0 or $vBlock->y > 127){
|
||||
break;
|
||||
}
|
||||
@ -110,15 +112,14 @@ class Explosion{
|
||||
if($block->getId() !== 0){
|
||||
$blastForce -= ($block->getHardness() / 5 + 0.3) * $this->stepLen;
|
||||
if($blastForce > 0){
|
||||
$index = ($block->x << 15) + ($block->z << 7) + $block->y;
|
||||
if(!isset($this->affectedBlocks[$index])){
|
||||
if(!isset($this->affectedBlocks[$index = Level::blockHash($block->x, $block->y, $block->z)])){
|
||||
$this->affectedBlocks[$index] = $block;
|
||||
}
|
||||
}
|
||||
}
|
||||
$pointer->x += $vector->x;
|
||||
$pointer->y += $vector->y;
|
||||
$pointer->z += $vector->z;
|
||||
$pointerX += $vector->x;
|
||||
$pointerY += $vector->y;
|
||||
$pointerZ += $vector->z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -225,13 +225,35 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @return string
|
||||
*/
|
||||
public static function chunkHash($x, $z){
|
||||
return $x . ":" . $z;
|
||||
return PHP_INT_SIZE === 8 ? (($x & 0xFFFFFFFF) << 32) | ($z & 0xFFFFFFFF) : $x . ":" . $z;
|
||||
}
|
||||
|
||||
public static function blockHash($x, $y, $z){
|
||||
return PHP_INT_SIZE === 8 ? (($x & 0xFFFFFFF) << 35) | (($y & 0x7f) << 28) | ($z & 0xFFFFFFF) : $x . ":" . $y .":". $z;
|
||||
}
|
||||
|
||||
public static function getBlockXYZ($hash, &$x, &$y, &$z){
|
||||
if(PHP_INT_SIZE === 8){
|
||||
$x = ($hash >> 35) << 36 >> 36;
|
||||
$y = (($hash >> 28) & 0x7f);// << 57 >> 57; //it's always positive
|
||||
$z = ($hash & 0xFFFFFFF) << 36 >> 36;
|
||||
}else{
|
||||
$hash = explode(":", $hash);
|
||||
$x = (int) $hash[0];
|
||||
$y = (int) $hash[1];
|
||||
$z = (int) $hash[2];
|
||||
}
|
||||
}
|
||||
|
||||
public static function getXZ($hash, &$x, &$z){
|
||||
list($x, $z) = explode(":", $hash);
|
||||
$x = (int) $x;
|
||||
$z = (int) $z;
|
||||
if(PHP_INT_SIZE === 8){
|
||||
$x = ($hash >> 32) << 32 >> 32;
|
||||
$z = ($hash & 0xFFFFFFFF) << 32 >> 32;
|
||||
}else{
|
||||
$hash = explode(":", $hash);
|
||||
$x = (int) $hash[0];
|
||||
$z = (int) $hash[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -393,7 +415,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @return Player[]
|
||||
*/
|
||||
public function getUsingChunk($X, $Z){
|
||||
return isset($this->usedChunks[$index = "$X:$Z"]) ? $this->usedChunks[$index] : [];
|
||||
return isset($this->usedChunks[$index = Level::chunkHash($X, $Z)]) ? $this->usedChunks[$index] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -474,7 +496,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
$this->timings->doTickPending->startTiming();
|
||||
while($this->updateQueue->count() > 0 and $this->updateQueue->current()["priority"] <= $currentTick){
|
||||
$block = $this->getBlock($this->updateQueue->extract()["data"]);
|
||||
unset($this->updateQueueIndex["{$block->x}:{$block->y}:{$block->z}"]);
|
||||
unset($this->updateQueueIndex[Level::blockHash($block->x, $block->y, $block->z)]);
|
||||
$block->onUpdate(self::BLOCK_UPDATE_SCHEDULED);
|
||||
}
|
||||
$this->timings->doTickPending->stopTiming();
|
||||
@ -698,10 +720,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param Vector3 $pos
|
||||
*/
|
||||
public function updateAround(Vector3 $pos){
|
||||
$block = $this->getBlock($pos);
|
||||
|
||||
for($side = 0; $side <= 5; ++$side){
|
||||
$this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($block->getSide($side)));
|
||||
$this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->getBlock($pos->getSide($side))));
|
||||
if(!$ev->isCancelled()){
|
||||
$ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
@ -713,8 +733,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param int $delay
|
||||
*/
|
||||
public function scheduleUpdate(Vector3 $pos, $delay){
|
||||
$index = "{$pos->x}:{$pos->y}:{$pos->z}";
|
||||
if(isset($this->updateQueueIndex[$index]) and $this->updateQueueIndex[$index] <= $delay){
|
||||
if(isset($this->updateQueueIndex[$index = Level::blockHash($pos->x, $pos->y, $pos->z)]) and $this->updateQueueIndex[$index] <= $delay){
|
||||
return;
|
||||
}
|
||||
$this->updateQueueIndex[$index] = $delay;
|
||||
@ -912,7 +931,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
*/
|
||||
public function getBlock(Vector3 $pos, $cached = true){
|
||||
$fullState = 0;
|
||||
$index = PHP_INT_SIZE === 8 ? (($pos->x & 0xFFFFFFF) << 35) | (($pos->y & 0x7f) << 28) | ($pos->z & 0xFFFFFFF) : "{$pos->x}:{$pos->y}:{$pos->z}";
|
||||
$index = Level::blockHash($pos->x, $pos->y, $pos->z);
|
||||
if($cached and isset($this->blockCache[$index])){
|
||||
return $this->blockCache[$index];
|
||||
}elseif($pos->y >= 0 and $pos->y < 128 and ($chunk = $this->getChunk($pos->x >> 4, $pos->z >> 4, false)) !== null){
|
||||
@ -1053,7 +1072,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
return false;
|
||||
}
|
||||
|
||||
unset($this->blockCache["{$pos->x}:{$pos->y}:{$pos->z}"]);
|
||||
unset($this->blockCache[Level::blockHash($pos->x, $pos->y, $pos->z)]);
|
||||
|
||||
if($this->getChunk($pos->x >> 4, $pos->z >> 4, true)->setBlock($pos->x & 0x0f, $pos->y & 0x7f, $pos->z & 0x0f, $block->getId(), $block->getDamage())){
|
||||
if(!($pos instanceof Position)){
|
||||
@ -1094,7 +1113,6 @@ class Level implements ChunkManager, Metadatable{
|
||||
if($update === true){
|
||||
$this->updateAllLight($block);
|
||||
|
||||
$this->updateAround($pos);
|
||||
$this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($block));
|
||||
if(!$ev->isCancelled()){
|
||||
$ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
|
||||
@ -1102,6 +1120,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
$entity->scheduleUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
$this->updateAround($pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2067,22 +2087,24 @@ class Level implements ChunkManager, Metadatable{
|
||||
}
|
||||
if($spawn instanceof Vector3){
|
||||
$v = $spawn->floor();
|
||||
for(; $v->y > 0; --$v->y){
|
||||
$b = $this->getBlock($v);
|
||||
if($b === null){
|
||||
return $spawn;
|
||||
}elseif($b->isSolid()){
|
||||
$v->y++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(; $v->y < 128; ++$v->y){
|
||||
if(!$this->getBlock($v->getSide(1))->isSolid()){
|
||||
if(!$this->getBlock($v)->isSolid()){
|
||||
return new Position($spawn->x, $v->y === Math::floorFloat($spawn->y) ? $spawn->y : $v->y, $spawn->z, $this);
|
||||
$chunk = $this->getChunk($v->x >> 4, $v->z >> 4, false);
|
||||
$x = $v->x & 0x0f;
|
||||
$z = $v->z & 0x0f;
|
||||
if($chunk !== null){
|
||||
for(; $v->y > 0; --$v->y){
|
||||
if(Block::$solid[$chunk->getBlockId($x, $v->y & 0x7f, $z)]){
|
||||
$v->y++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(; $v->y < 128; ++$v->y){
|
||||
if(!Block::$solid[$chunk->getBlockId($x, $v->y + 1, $z)]){
|
||||
if(!Block::$solid[$chunk->getBlockId($x, $v->y, $z)]){
|
||||
return new Position($spawn->x, $v->y === Math::floorFloat($spawn->y) ? $spawn->y : $v->y, $spawn->z, $this);
|
||||
}
|
||||
}else{
|
||||
++$v->y;
|
||||
}
|
||||
}else{
|
||||
++$v->y;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,9 +76,7 @@ class Anvil extends McRegion{
|
||||
* @return RegionLoader
|
||||
*/
|
||||
protected function getRegion($x, $z){
|
||||
$index = $x . ":" . $z;
|
||||
|
||||
return isset($this->regions[$index]) ? $this->regions[$index] : null;
|
||||
return isset($this->regions[$index = Level::chunkHash($x, $z)]) ? $this->regions[$index] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,8 +124,7 @@ class Anvil extends McRegion{
|
||||
}
|
||||
|
||||
protected function loadRegion($x, $z){
|
||||
$index = $x . ":" . $z;
|
||||
if(isset($this->regions[$index])){
|
||||
if(isset($this->regions[$index = Level::chunkHash($x, $z)])){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -216,9 +216,7 @@ class McRegion extends BaseLevelProvider{
|
||||
* @return RegionLoader
|
||||
*/
|
||||
protected function getRegion($x, $z){
|
||||
$index = $x . ":" . $z;
|
||||
|
||||
return isset($this->regions[$index]) ? $this->regions[$index] : null;
|
||||
return isset($this->regions[$index = Level::chunkHash($x, $z)]) ? $this->regions[$index] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -282,8 +280,7 @@ class McRegion extends BaseLevelProvider{
|
||||
}
|
||||
|
||||
protected function loadRegion($x, $z){
|
||||
$index = $x . ":" . $z;
|
||||
if(isset($this->regions[$index])){
|
||||
if(isset($this->regions[$index = Level::chunkHash($x, $z)])){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user