From d2bf92c3ede19b8672c8498dbf47d1a4cb237006 Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Sun, 22 Mar 2015 02:44:39 +0100 Subject: [PATCH] New batched UpdateBlockPacket, added Level->sendBlocks() --- src/pocketmine/Player.php | 25 +---- src/pocketmine/level/Level.php | 102 ++++++------------ .../network/protocol/UpdateBlockPacket.php | 27 +++-- 3 files changed, 52 insertions(+), 102 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 8eb32c06c..452b998f3 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -105,7 +105,6 @@ use pocketmine\network\protocol\SetSpawnPositionPacket; use pocketmine\network\protocol\SetTimePacket; use pocketmine\network\protocol\StartGamePacket; use pocketmine\network\protocol\TakeItemEntityPacket; -use pocketmine\network\protocol\UpdateBlockPacket; use pocketmine\network\SourceInterface; use pocketmine\permission\PermissibleBase; use pocketmine\permission\PermissionAttachment; @@ -1715,21 +1714,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ $target = $this->level->getBlock($blockVector); $block = $target->getSide($packet->face); - $pk = new UpdateBlockPacket(); - $pk->x = $target->x; - $pk->y = $target->y; - $pk->z = $target->z; - $pk->block = $target->getId(); - $pk->meta = $target->getDamage(); - $this->dataPacket($pk); - - $pk = new UpdateBlockPacket(); - $pk->x = $block->x; - $pk->y = $block->y; - $pk->z = $block->z; - $pk->block = $block->getId(); - $pk->meta = $block->getDamage(); - $this->dataPacket($pk); + $this->level->sendBlocks([$this], [$target, $block]); break; }elseif($packet->face === 0xff){ if($this->isCreative()){ @@ -1906,13 +1891,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ $target = $this->level->getBlock($vector); $tile = $this->level->getTile($vector); - $pk = new UpdateBlockPacket(); - $pk->x = $target->x; - $pk->y = $target->y; - $pk->z = $target->z; - $pk->block = $target->getId(); - $pk->meta = $target->getDamage(); - $this->dataPacket($pk); + $this->level->sendBlocks([$this], [$target]); if($tile instanceof Spawnable){ $tile->spawnTo($this); diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 677dfba86..84cf4813b 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -163,7 +163,6 @@ class Level implements ChunkManager, Metadatable{ /** @var Block[][] */ protected $changedBlocks = []; - protected $changedCount = []; /** @var ReversePriorityQueue */ private $updateQueue; @@ -583,52 +582,22 @@ class Level implements ChunkManager, Metadatable{ $this->tickChunks(); $this->timings->doTickTiles->stopTiming(); - if(count($this->changedCount) > 0){ + if(count($this->changedBlocks) > 0){ if(count($this->players) > 0){ - foreach($this->changedCount as $index => $mini){ - for($Y = 0; $Y < 8; ++$Y){ - if(($mini & (1 << $Y)) === 0){ - continue; - } - if(count($this->changedBlocks[$index][$Y]) < 256){ - continue; - }else{ - $X = null; - $Z = null; - Level::getXZ($index, $X, $Z); - foreach($this->getUsingChunk($X, $Z) as $p){ - $p->unloadChunk($X, $Z); - } - unset($this->changedBlocks[$index][$Y]); + foreach($this->changedBlocks as $index => $blocks){ + if(count($blocks) > 512){ + Level::getXZ($index, $X, $Z); + foreach($this->getUsingChunk($X, $Z) as $p){ + $p->unloadChunk($X, $Z); } + }else{ + $this->sendBlocks($this->getUsingChunk($pos->x >> 4, $pos->z >> 4), $blocks); } } - $this->changedCount = []; - if(count($this->changedBlocks) > 0){ - foreach($this->changedBlocks as $index => $mini){ - foreach($mini as $blocks){ - /** @var Block $b */ - foreach($blocks as $b){ - if(!($b instanceof Block)){ - $b = $this->getBlock($b); - } - $pk = new UpdateBlockPacket(); - $pk->x = $b->x; - $pk->y = $b->y; - $pk->z = $b->z; - $pk->block = $b->getId(); - $pk->meta = $b->getDamage(); - Server::broadcastPacket($this->getUsingChunk($b->x >> 4, $b->z >> 4), $pk); - } - } - } - $this->changedBlocks = []; - } - }else{ - $this->changedCount = []; - $this->changedBlocks = []; } + $this->changedBlocks = []; + } $this->processChunkRequest(); @@ -638,6 +607,23 @@ class Level implements ChunkManager, Metadatable{ $this->timings->doTick->stopTiming(); } + /** + * @param Player[] $target + * @param Block[] $blocks + * @param int $flags + */ + public function sendBlocks(array $target, array $blocks, $flags = UpdateBlockPacket::FLAG_NONE){ + $pk = new UpdateBlockPacket(); + foreach($blocks as $b){ + if($b === null){ + continue; + } + + $pk->records[] = [$b->x, $b->z, $b->y, $b->getId(), $b->getDamage(), $flags]; + } + Server::broadcastPacket($target, $pk); + } + public function clearCache(){ $this->blockCache = []; } @@ -1146,7 +1132,7 @@ class Level implements ChunkManager, Metadatable{ * * @param Vector3 $pos * @param Block $block - * @param bool $direct + * @param bool $direct @deprecated * @param bool $update * * @return bool Whether the block has been updated or not @@ -1169,14 +1155,7 @@ class Level implements ChunkManager, Metadatable{ } if($direct === true){ - $pk = new UpdateBlockPacket(); - $pk->x = $pos->x; - $pk->y = $pos->y; - $pk->z = $pos->z; - $pk->block = $block->getId(); - $pk->meta = $block->getDamage(); - - Server::broadcastPacket($this->getUsingChunk($pos->x >> 4, $pos->z >> 4), $pk); + $this->sendBlocks($this->getUsingChunk($pos->x >> 4, $pos->z >> 4), [$block], UpdateBlockPacket::FLAG_ALL_PRIORITY); }else{ if(!($pos instanceof Position)){ $pos = $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z); @@ -1184,14 +1163,9 @@ class Level implements ChunkManager, Metadatable{ $block->position($pos); if(!isset($this->changedBlocks[$index])){ $this->changedBlocks[$index] = []; - $this->changedCount[$index] = 0; } - $Y = $pos->y >> 4; - if(!isset($this->changedBlocks[$index][$Y])){ - $this->changedBlocks[$index][$Y] = []; - $this->changedCount[$index] |= 1 << $Y; - } - $this->changedBlocks[$index][$Y][Level::blockHash($block->x, $block->y, $block->z)] = clone $block; + + $this->changedBlocks[$index][Level::blockHash($block->x, $block->y, $block->z)] = clone $block; } if($update === true){ @@ -1663,13 +1637,8 @@ class Level implements ChunkManager, Metadatable{ if(!isset($this->changedBlocks[$index = Level::chunkHash($x >> 4, $z >> 4)])){ $this->changedBlocks[$index] = []; - $this->changedCount[$index] = 0; } - if(!isset($this->changedBlocks[$index][$Y = $y >> 4])){ - $this->changedBlocks[$index][$Y] = []; - $this->changedCount[$index] |= 1 << $Y; - } - $this->changedBlocks[$index][$Y][Level::blockHash($x, $y, $z)] = new Vector3($x, $y, $z); + $this->changedBlocks[$index][Level::blockHash($x, $y, $z)] = new Vector3($x, $y, $z); } /** @@ -1699,13 +1668,8 @@ class Level implements ChunkManager, Metadatable{ if(!isset($this->changedBlocks[$index = Level::chunkHash($x >> 4, $z >> 4)])){ $this->changedBlocks[$index] = []; - $this->changedCount[$index] = 0; } - if(!isset($this->changedBlocks[$index][$Y = $y >> 4])){ - $this->changedBlocks[$index][$Y] = []; - $this->changedCount[$index] |= 1 << $Y; - } - $this->changedBlocks[$index][$Y][Level::blockHash($x, $y, $z)] = new Vector3($x, $y, $z); + $this->changedBlocks[$index][Level::blockHash($x, $y, $z)] = new Vector3($x, $y, $z); } /** diff --git a/src/pocketmine/network/protocol/UpdateBlockPacket.php b/src/pocketmine/network/protocol/UpdateBlockPacket.php index 68d6743aa..d42c8d129 100644 --- a/src/pocketmine/network/protocol/UpdateBlockPacket.php +++ b/src/pocketmine/network/protocol/UpdateBlockPacket.php @@ -28,11 +28,15 @@ class UpdateBlockPacket extends DataPacket{ public static $pool = []; public static $next = 0; - public $x; - public $z; - public $y; - public $block; - public $meta; + const FLAG_NONE = 0b0; + const FLAG_NEIGHBORS = 0b1; + const FLAG_NOGRAPHIC = 0b100; + const FLAG_PRIORITY = 0b1000; + + const FLAG_ALL = self::FLAG_NEIGHBORS; + const FLAG_ALL_PRIORITY = self::FLAG_NEIGHBORS | self::FLAG_PRIORITY; + + public $records = []; //x, z, y, blockId, blockData, flags public function pid(){ return Info::UPDATE_BLOCK_PACKET; @@ -44,11 +48,14 @@ class UpdateBlockPacket extends DataPacket{ public function encode(){ $this->reset(); - $this->putInt($this->x); - $this->putInt($this->z); - $this->putByte($this->y); - $this->putByte($this->block); - $this->putByte($this->meta); + $this->putInt(count($this->records)); + foreach($this->records as $r){ + $this->putInt($r[0]); + $this->putInt($r[1]); + $this->putByte($r[2]); + $this->putByte($r[3]); + $this->putByte(($r[5] << 4) | $r[4]); + } } } \ No newline at end of file