From 6246ad19c4c177630a91aa8c380a49d5dd4c8b2a Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Sun, 12 Oct 2014 16:16:19 +0200 Subject: [PATCH] Added global block cache --- src/pocketmine/Player.php | 11 ++-- src/pocketmine/entity/Entity.php | 37 +++++------- src/pocketmine/level/Level.php | 99 ++++++++++++++++++-------------- 3 files changed, 75 insertions(+), 72 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 34f8de51e..b3c4a04bb 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -175,7 +175,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ /** @var Vector3 */ protected $newPosition; - private $viewDistance; + protected $viewDistance; + protected $chunksPerTick; /** @var null|Position */ private $spawnPosition = null; private $inAction = false; @@ -424,6 +425,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ $this->setLevel($this->server->getDefaultLevel(), true); $this->viewDistance = $this->server->getViewDistance(); $this->newPosition = new Vector3(0, 0, 0); + $this->chunksPerTick = (int) $this->server->getProperty("chunk-sending.per-tick", 4); } /** @@ -608,10 +610,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ if(count($this->loadQueue) === 0){ $this->chunkLoadTask->setNextRun($this->chunkLoadTask->getNextRun() + 30); }else{ - $count = 0; - $limit = (int) $this->server->getProperty("chunk-sending.per-tick", 4); + $count = 0;; foreach($this->loadQueue as $index => $distance){ - if($count >= $limit){ + if($count >= $this->chunksPerTick){ break; } ++$count; @@ -648,7 +649,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ } } - if($spawned < 48){ + if($spawned < 56){ return; } diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index b69e59a42..9b615ee7d 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -477,6 +477,8 @@ abstract class Entity extends Position implements Metadatable{ return false; }elseif($this->dead === true){ $this->despawnFromAll(); + Timings::$tickEntityTimer->stopTiming(); + return false; } $hasUpdate = false; @@ -749,23 +751,12 @@ abstract class Entity extends Position implements Metadatable{ } public function isInsideOfSolid(){ - $blocks = []; - for($i = 0; $i < 8; ++$i){ - $x = (($i % 2) - 0.5) * $this->width * 0.8; - $y = ((($i >> 1) % 2) - 0.5) * 0.1; - $z = ((($i >> 2) % 2) - 0.5) * $this->width * 0.8; - $v = (new Vector3($this->x + $x, $this->y + $this->getEyeHeight() + $y, $this->z + $z))->floor(); - $blocks["{$v->x}:{$v->y}:{$v->z}"] = $v; - } + $block = $this->getLevel()->getBlock($pos = (new Vector3($this->x, $y = ($this->y + $this->getEyeHeight()), $this->z))->floor()); - foreach($blocks as $vector){ - $block = $this->getLevel()->getBlock($vector); + $bb = $block->getBoundingBox(); - $bb = $block->getBoundingBox(); - - if($bb !== null and $block->isSolid and !$block->isTransparent and $bb->intersectsWith($this->getBoundingBox())){ - return true; - } + if($bb !== null and $block->isSolid and !$block->isTransparent and $bb->intersectsWith($this->getBoundingBox())){ + return true; } return false; } @@ -998,20 +989,20 @@ abstract class Entity extends Position implements Metadatable{ } protected function checkBlockCollision(){ - $minX = Math::floorFloat($this->boundingBox->minX - 0.001); - $minY = Math::floorFloat($this->boundingBox->minY - 0.001); - $minZ = Math::floorFloat($this->boundingBox->minZ - 0.001); - $maxX = Math::floorFloat($this->boundingBox->maxX + 0.001); - $maxY = Math::floorFloat($this->boundingBox->maxY + 0.001); - $maxZ = Math::floorFloat($this->boundingBox->maxZ + 0.001); + $minX = Math::floorFloat($this->boundingBox->minX + 0.001); + $minY = Math::floorFloat($this->boundingBox->minY + 0.001); + $minZ = Math::floorFloat($this->boundingBox->minZ + 0.001); + $maxX = Math::floorFloat($this->boundingBox->maxX - 0.001); + $maxY = Math::floorFloat($this->boundingBox->maxY - 0.001); + $maxZ = Math::floorFloat($this->boundingBox->maxZ - 0.001); $vector = new Vector3(0, 0, 0); for($z = $minZ; $z <= $maxZ; ++$z){ for($x = $minX; $x <= $maxX; ++$x){ for($y = $minY; $y <= $maxY; ++$y){ - $block = $this->getLevel()->getBlock(new Vector3($x, $y, $z)); - if($block !== null and $block->getID() > 0 and $block->hasEntityCollision){ + $block = $this->level->getBlock(new Vector3($x, $y, $z)); + if($block !== null and $block->hasEntityCollision){ $block->onEntityCollide($this); if(!($this instanceof Player)){ $block->addVelocityToEntity($this, $vector); diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 53e4ca325..e7ffd0004 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -128,6 +128,8 @@ class Level implements ChunkManager, Metadatable{ /** @var Tile[] */ public $updateTiles = []; + protected $blockCache = []; + /** @var Server */ protected $server; @@ -456,6 +458,52 @@ class Level implements ChunkManager, Metadatable{ $this->unloadChunks(); + $X = null; + $Z = null; + + //Do block updates + $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}"]); + $block->onUpdate(self::BLOCK_UPDATE_SCHEDULED); + } + $this->timings->doTickPending->stopTiming(); + + $this->timings->entityTick->startTiming(); + //Update entities that need update + //if(count($this->updateEntities) > 0){ + Timings::$tickEntityTimer->startTiming(); + foreach($this->entities as $id => $entity){ + if(!$entity->closed){ + $entity->onUpdate(); + } + } + Timings::$tickEntityTimer->stopTiming(); + //} + $this->timings->entityTick->stopTiming(); + + $this->timings->tileEntityTick->startTiming(); + //Update tiles that need update + if(count($this->updateTiles) > 0){ + //Timings::$tickTileEntityTimer->startTiming(); + foreach($this->updateTiles as $id => $tile){ + if($tile->onUpdate() !== true){ + unset($this->updateTiles[$id]); + } + } + //Timings::$tickTileEntityTimer->stopTiming(); + } + $this->timings->tileEntityTick->stopTiming(); + + $this->timings->doTickTiles->startTiming(); + $this->tickChunks(); + $this->timings->doTickTiles->stopTiming(); + + if(($currentTick % 20) === 0){ + $this->blockCache = []; + } + if(count($this->changedCount) > 0){ if(count($this->players) > 0){ foreach($this->changedCount as $index => $mini){ @@ -503,48 +551,6 @@ class Level implements ChunkManager, Metadatable{ } - $X = null; - $Z = null; - - //Do block updates - $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}"]); - $block->onUpdate(self::BLOCK_UPDATE_SCHEDULED); - } - $this->timings->doTickPending->stopTiming(); - - $this->timings->entityTick->startTiming(); - //Update entities that need update - //if(count($this->updateEntities) > 0){ - Timings::$tickEntityTimer->startTiming(); - foreach($this->entities as $id => $entity){ - if(!$entity->closed){ - $entity->onUpdate(); - } - } - Timings::$tickEntityTimer->stopTiming(); - //} - $this->timings->entityTick->stopTiming(); - - $this->timings->tileEntityTick->startTiming(); - //Update tiles that need update - if(count($this->updateTiles) > 0){ - //Timings::$tickTileEntityTimer->startTiming(); - foreach($this->updateTiles as $id => $tile){ - if($tile->onUpdate() !== true){ - unset($this->updateTiles[$id]); - } - } - //Timings::$tickTileEntityTimer->stopTiming(); - } - $this->timings->tileEntityTick->stopTiming(); - - $this->timings->doTickTiles->startTiming(); - $this->tickChunks(); - $this->timings->doTickTiles->stopTiming(); - $this->processChunkRequest(); $this->timings->doTick->stopTiming(); @@ -872,7 +878,10 @@ class Level implements ChunkManager, Metadatable{ public function getBlock(Vector3 $pos){ $blockId = 0; $meta = 0; - if($pos->y >= 0 and $pos->y < 128 and ($chunk = $this->getChunk($pos->x >> 4, $pos->z >> 4, true)) !== null){ + $index = "{$pos->x}:{$pos->y}:{$pos->z}"; + if(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, true)) !== null){ $chunk->getBlock($pos->x & 0x0f, $pos->y & 0x7f, $pos->z & 0x0f, $blockId, $meta); } @@ -885,7 +894,7 @@ class Level implements ChunkManager, Metadatable{ return $air; } - return Block::get($blockId, $meta, new Position($pos->x, $pos->y, $pos->z, $this)); + return $this->blockCache[$index] = Block::get($blockId, $meta, new Position($pos->x, $pos->y, $pos->z, $this)); } /** @@ -911,6 +920,8 @@ class Level implements ChunkManager, Metadatable{ return false; } + unset($this->blockCache["{$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)){ $pos = new Position($pos->x, $pos->y, $pos->z, $this);