From 987d647b76c299e5aaa875f764e46a612c7d6b9e Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Thu, 6 Nov 2014 12:12:31 +0100 Subject: [PATCH 1/5] Return proper BlockIterator index, throw more exceptions, improved blockQueue performance --- src/pocketmine/utils/BlockIterator.php | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/pocketmine/utils/BlockIterator.php b/src/pocketmine/utils/BlockIterator.php index cc777115b..64c48e2ed 100644 --- a/src/pocketmine/utils/BlockIterator.php +++ b/src/pocketmine/utils/BlockIterator.php @@ -38,9 +38,11 @@ class BlockIterator implements \Iterator{ private $end = false; - /** @var Block[] */ - private $blockQueue = [null, null, null]; + /** @var \SplFixedArray[3] */ + private $blockQueue; private $currentBlock = 0; + /** @var Block */ + private $currentBlockObject = null; private $currentDistance = 0; private $maxDistanceInt = 0; @@ -57,6 +59,7 @@ class BlockIterator implements \Iterator{ public function __construct(Level $level, Vector3 $start, Vector3 $direction, $yOffset = 0, $maxDistance = 0){ $this->level = $level; $this->maxDistance = (int) $maxDistance; + $this->blockQueue = new \SplFixedArray(3); $startClone = new Vector3($start->x, $start->y, $start->z); $startClone->y += $yOffset; @@ -219,20 +222,28 @@ class BlockIterator implements \Iterator{ if($this->currentBlock <= -1){ throw new \OutOfBoundsException; }else{ - --$this->currentBlock; + $this->currentBlockObject = $this->blockQueue[$this->currentBlock--]; } } + /** + * @return Block + * + * @throws \OutOfBoundsException + */ public function current(){ - return $this->blockQueue[$this->currentBlock]; + if($this->currentBlockObject === null){ + throw new \OutOfBoundsException; + } + return $this->currentBlockObject; } public function rewind(){ - + throw new \InvalidStateException("BlockIterator doesn't support rewind()"); } public function key(){ - return $this->currentBlock; + return $this->currentBlock - 1; } public function valid(){ From 263bff01c871130fab8bc54dcffb75217e16f27c Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Thu, 6 Nov 2014 12:16:12 +0100 Subject: [PATCH 2/5] Change RuntimeException to InvalidStateException on BlockIterator --- src/pocketmine/utils/BlockIterator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pocketmine/utils/BlockIterator.php b/src/pocketmine/utils/BlockIterator.php index 64c48e2ed..9cbe30357 100644 --- a/src/pocketmine/utils/BlockIterator.php +++ b/src/pocketmine/utils/BlockIterator.php @@ -166,7 +166,7 @@ class BlockIterator implements \Iterator{ } if(!$startBlockFound){ - throw new \RuntimeException("Start block missed in BlockIterator"); + throw new \InvalidStateException("Start block missed in BlockIterator"); } $this->maxDistanceInt = round($maxDistance / (sqrt($mainDirection ** 2 + $secondDirection ** 2 + $thirdDirection ** 2) / $mainDirection)); From 3b9a9bcd5daff567481a1c368b5230ca99a1596f Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Thu, 6 Nov 2014 12:23:45 +0100 Subject: [PATCH 3/5] Use proper indexes on Living->getLineOfSight() when a max length is set --- src/pocketmine/entity/Living.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index bc8af8bac..e89d3dd05 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -197,15 +197,18 @@ abstract class Living extends Entity implements Damageable{ } $blocks = []; + $nextIndex = 0; + $itr = new BlockIterator($this->level, $this->getPosition(), $this->getDirectionVector(), $this->getEyeHeight(), $maxDistance); while($itr->valid()){ $itr->next(); $block = $itr->current(); - $blocks[] = $block; + $blocks[$nextIndex++] = $block; if($maxLength !== 0 and count($blocks) > $maxLength){ array_shift($blocks); + --$nextIndex; } $id = $block->getID(); From f1519e6d13e8ea9a9e4a18731714cecf6a2092d3 Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Thu, 6 Nov 2014 12:34:33 +0100 Subject: [PATCH 4/5] Improved Level->getTile() to a direct lookup instead of linear search --- src/pocketmine/level/Level.php | 11 ++++------- src/pocketmine/level/format/FullChunk.php | 7 +++++++ src/pocketmine/level/format/generic/BaseFullChunk.php | 10 ++++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 332d8abdc..bbbc8edd1 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -1366,13 +1366,10 @@ class Level implements ChunkManager, Metadatable{ if($pos instanceof Position and $pos->getLevel() !== $this){ return null; } - $tiles = $this->getChunkTiles($pos->x >> 4, $pos->z >> 4); - if(count($tiles) > 0){ - foreach($tiles as $tile){ - if($tile->x === (int) $pos->x and $tile->y === (int) $pos->y and $tile->z === (int) $pos->z){ - return $tile; - } - } + $chunk = $this->getChunk($pos->x >> 4, $pos->z >> 4); + + if($chunk instanceof FullChunk){ + return $chunk->getTile($pos->x & 0x0f, $pos->y & 0x7f, $pos->z & 0x0f); } return null; diff --git a/src/pocketmine/level/format/FullChunk.php b/src/pocketmine/level/format/FullChunk.php index b489e269f..bc040114e 100644 --- a/src/pocketmine/level/format/FullChunk.php +++ b/src/pocketmine/level/format/FullChunk.php @@ -226,6 +226,13 @@ interface FullChunk{ */ public function getTiles(); + /** + * @param int $x 0-15 + * @param int $y 0-127 + * @param int $z 0-15 + */ + public function getTile($x, $y, $z); + /** * @return bool */ diff --git a/src/pocketmine/level/format/generic/BaseFullChunk.php b/src/pocketmine/level/format/generic/BaseFullChunk.php index 3878fd868..f50df4702 100644 --- a/src/pocketmine/level/format/generic/BaseFullChunk.php +++ b/src/pocketmine/level/format/generic/BaseFullChunk.php @@ -37,6 +37,9 @@ abstract class BaseFullChunk implements FullChunk{ /** @var Tile[] */ protected $tiles = []; + /** @var Tile[] */ + protected $tileList = []; + /** @var string */ protected $biomeIds; @@ -234,11 +237,13 @@ abstract class BaseFullChunk implements FullChunk{ public function addTile(Tile $tile){ $this->tiles[$tile->getID()] = $tile; + $this->tiles[(($tile->z & 0x0f) << 8) | (($tile->x & 0x0f) << 4) | ($tile->y & 0x7f)] = $tile; $this->hasChanged = true; } public function removeTile(Tile $tile){ unset($this->tiles[$tile->getID()]); + unset($this->tiles[(($tile->z & 0x0f) << 8) | (($tile->x & 0x0f) << 4) | ($tile->y & 0x7f)]); $this->hasChanged = true; } @@ -250,6 +255,11 @@ abstract class BaseFullChunk implements FullChunk{ return $this->tiles; } + public function getTile($x, $y, $z){ + $index = ($z << 8) | ($x << 4) | $y; + return isset($this->tileList[$index]) ? $this->tileList[$index] : null; + } + public function isLoaded(){ return $this->getProvider() === null ? false : $this->getProvider()->isChunkLoaded($this->getX(), $this->getZ()); } From 7e1095e28daf50a4275ea426f5c712cf27da4d6f Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Thu, 6 Nov 2014 12:57:17 +0100 Subject: [PATCH 5/5] Reenabled collision against entities on move --- src/pocketmine/entity/Entity.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 49fc6eec7..7df739a2f 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -874,7 +874,7 @@ abstract class Entity extends Location implements Metadatable{ //TODO: big messy loop }*/ - $list = $this->level->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox($dx, $dy, $dz), false); + $list = $this->level->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox($dx, $dy, $dz)); foreach($list as $bb){