From be2d134994d53a8b63e6d2643173c0f27d909d9f Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 11 Oct 2017 16:09:08 +0100 Subject: [PATCH] Added API to allow flagging an entity not to be saved to disk when its chunk is saved (#1452) --- src/pocketmine/Player.php | 8 ++++ src/pocketmine/entity/Entity.php | 21 ++++++++++ .../level/format/io/leveldb/LevelDB.php | 40 +++++++++++-------- .../level/format/io/region/Anvil.php | 2 +- .../level/format/io/region/McRegion.php | 2 +- .../level/format/io/region/PMAnvil.php | 2 +- 6 files changed, 55 insertions(+), 20 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 5e7b9dd506..a91e432047 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -3415,6 +3415,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ return []; } + public function canSaveWithChunk() : bool{ + return false; + } + + public function setCanSaveWithChunk(bool $value) : void{ + throw new \BadMethodCallException("Players can't be saved with chunks"); + } + /** * Handles player data saving * diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 4be957e29e..e1744243e3 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -337,6 +337,9 @@ abstract class Entity extends Location implements Metadatable{ /** @var bool */ protected $isStatic = false; + /** @var bool */ + private $savedWithChunk = true; + /** @var bool */ public $isCollided = false; /** @var bool */ @@ -764,6 +767,24 @@ abstract class Entity extends Location implements Metadatable{ return false; } + /** + * Returns whether this entity will be saved when its chunk is unloaded. + * @return bool + */ + public function canSaveWithChunk() : bool{ + return $this->savedWithChunk; + } + + /** + * Sets whether this entity will be saved when its chunk is unloaded. This can be used to prevent the entity being + * saved to disk. + * + * @param bool $value + */ + public function setCanSaveWithChunk(bool $value) : void{ + $this->savedWithChunk = $value; + } + /** * Returns the short save name * diff --git a/src/pocketmine/level/format/io/leveldb/LevelDB.php b/src/pocketmine/level/format/io/leveldb/LevelDB.php index d0c4340367..eea526e71a 100644 --- a/src/pocketmine/level/format/io/leveldb/LevelDB.php +++ b/src/pocketmine/level/format/io/leveldb/LevelDB.php @@ -509,32 +509,38 @@ class LevelDB extends BaseLevelProvider{ //TODO: use this properly $this->db->put($index . self::TAG_STATE_FINALISATION, chr(self::FINALISATION_DONE)); - $this->writeTags($chunk->getTiles(), $index . self::TAG_BLOCK_ENTITY); - $this->writeTags(array_filter($chunk->getEntities(), function(Entity $entity) : bool{ - return !($entity instanceof Player); - }), $index . self::TAG_ENTITY); + /** @var CompoundTag[] $tiles */ + $tiles = []; + foreach($chunk->getTiles() as $tile){ + if(!$tile->isClosed()){ + $tile->saveNBT(); + $tiles[] = $tile->namedtag; + } + } + $this->writeTags($tiles, $index . self::TAG_BLOCK_ENTITY); + + /** @var CompoundTag[] $entities */ + $entities = []; + foreach($chunk->getEntities() as $entity){ + if($entity->canSaveWithChunk() and !$entity->isClosed()){ + $entity->saveNBT(); + $entities[] = $entity->namedtag; + } + } + $this->writeTags($entities, $index . self::TAG_ENTITY); $this->db->delete($index . self::TAG_DATA_2D_LEGACY); $this->db->delete($index . self::TAG_LEGACY_TERRAIN); } /** - * @param Entity[]|Tile[] $targets - * @param string $index + * @param CompoundTag[] $targets + * @param string $index */ private function writeTags(array $targets, string $index){ - $nbt = new NBT(NBT::LITTLE_ENDIAN); - $out = []; - /** @var Entity|Tile $target */ - foreach($targets as $target){ - if(!$target->isClosed()){ - $target->saveNBT(); - $out[] = $target->namedtag; - } - } - if(!empty($targets)){ - $nbt->setData($out); + $nbt = new NBT(NBT::LITTLE_ENDIAN); + $nbt->setData($targets); $this->db->put($index, $nbt->write()); }else{ $this->db->delete($index); diff --git a/src/pocketmine/level/format/io/region/Anvil.php b/src/pocketmine/level/format/io/region/Anvil.php index a9d83741e3..7536f3f334 100644 --- a/src/pocketmine/level/format/io/region/Anvil.php +++ b/src/pocketmine/level/format/io/region/Anvil.php @@ -70,7 +70,7 @@ class Anvil extends McRegion{ $entities = []; foreach($chunk->getEntities() as $entity){ - if(!($entity instanceof Player) and !$entity->isClosed()){ + if($entity->canSaveWithChunk() and !$entity->isClosed()){ $entity->saveNBT(); $entities[] = $entity->namedtag; } diff --git a/src/pocketmine/level/format/io/region/McRegion.php b/src/pocketmine/level/format/io/region/McRegion.php index b3c7391080..df2394542b 100644 --- a/src/pocketmine/level/format/io/region/McRegion.php +++ b/src/pocketmine/level/format/io/region/McRegion.php @@ -89,7 +89,7 @@ class McRegion extends BaseLevelProvider{ $entities = []; foreach($chunk->getEntities() as $entity){ - if(!($entity instanceof Player) and !$entity->isClosed()){ + if($entity->canSaveWithChunk() and !$entity->isClosed()){ $entity->saveNBT(); $entities[] = $entity->namedtag; } diff --git a/src/pocketmine/level/format/io/region/PMAnvil.php b/src/pocketmine/level/format/io/region/PMAnvil.php index b6fe2728b0..9a8a2951a3 100644 --- a/src/pocketmine/level/format/io/region/PMAnvil.php +++ b/src/pocketmine/level/format/io/region/PMAnvil.php @@ -74,7 +74,7 @@ class PMAnvil extends Anvil{ $entities = []; foreach($chunk->getEntities() as $entity){ - if(!($entity instanceof Player) and !$entity->isClosed()){ + if($entity->canSaveWithChunk() and !$entity->isClosed()){ $entity->saveNBT(); $entities[] = $entity->namedtag; }