relocate some world-specific logic from Chunk to World

This commit is contained in:
Dylan K. Taylor 2020-11-05 14:28:36 +00:00
parent 8762d44506
commit 058a3b3fa6
2 changed files with 53 additions and 57 deletions

View File

@ -32,10 +32,12 @@ use pocketmine\block\BlockFactory;
use pocketmine\block\BlockLegacyIds; use pocketmine\block\BlockLegacyIds;
use pocketmine\block\tile\Spawnable; use pocketmine\block\tile\Spawnable;
use pocketmine\block\tile\Tile; use pocketmine\block\tile\Tile;
use pocketmine\block\tile\TileFactory;
use pocketmine\block\UnknownBlock; use pocketmine\block\UnknownBlock;
use pocketmine\block\VanillaBlocks; use pocketmine\block\VanillaBlocks;
use pocketmine\data\bedrock\BiomeIds; use pocketmine\data\bedrock\BiomeIds;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
use pocketmine\entity\EntityFactory;
use pocketmine\entity\Location; use pocketmine\entity\Location;
use pocketmine\entity\object\ExperienceOrb; use pocketmine\entity\object\ExperienceOrb;
use pocketmine\entity\object\ItemEntity; use pocketmine\entity\object\ItemEntity;
@ -54,6 +56,8 @@ use pocketmine\item\ItemUseResult;
use pocketmine\item\LegacyStringToItemParser; use pocketmine\item\LegacyStringToItemParser;
use pocketmine\math\AxisAlignedBB; use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\convert\RuntimeBlockMapping; use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
use pocketmine\network\mcpe\protocol\BlockActorDataPacket; use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
use pocketmine\network\mcpe\protocol\ClientboundPacket; use pocketmine\network\mcpe\protocol\ClientboundPacket;
@ -2245,7 +2249,7 @@ class World implements ChunkManager{
$this->chunks[$chunkHash] = $chunk; $this->chunks[$chunkHash] = $chunk;
unset($this->blockCache[$chunkHash]); unset($this->blockCache[$chunkHash]);
$chunk->initChunk($this); $this->initChunk($chunk);
(new ChunkLoadEvent($this, $chunk, !$chunk->isGenerated()))->call(); (new ChunkLoadEvent($this, $chunk, !$chunk->isGenerated()))->call();
@ -2262,6 +2266,52 @@ class World implements ChunkManager{
return true; return true;
} }
private function initChunk(Chunk $chunk) : void{
if($chunk->NBTentities !== null){
$chunk->setDirtyFlag(Chunk::DIRTY_FLAG_ENTITIES, true);
$this->timings->syncChunkLoadEntitiesTimer->startTiming();
$entityFactory = EntityFactory::getInstance();
foreach($chunk->NBTentities as $nbt){
try{
$entity = $entityFactory->createFromData($this, $nbt);
if(!($entity instanceof Entity)){
$saveIdTag = $nbt->getTag("id") ?? $nbt->getTag("identifier");
$saveId = "<unknown>";
if($saveIdTag instanceof StringTag){
$saveId = $saveIdTag->getValue();
}elseif($saveIdTag instanceof IntTag){ //legacy MCPE format
$saveId = "legacy(" . $saveIdTag->getValue() . ")";
}
$this->getLogger()->warning("Chunk " . $chunk->getX() . " " . $chunk->getZ() . ": Deleted unknown entity type $saveId");
continue;
}
}catch(\Exception $t){ //TODO: this shouldn't be here
$this->getLogger()->logException($t);
continue;
}
}
$chunk->NBTentities = null;
$this->timings->syncChunkLoadEntitiesTimer->stopTiming();
}
if($chunk->NBTtiles !== null){
$chunk->setDirtyFlag(Chunk::DIRTY_FLAG_TILES, true);
$this->timings->syncChunkLoadTileEntitiesTimer->startTiming();
$tileFactory = TileFactory::getInstance();
foreach($chunk->NBTtiles as $nbt){
if(($tile = $tileFactory->createFromData($this, $nbt)) !== null){
$this->addTile($tile);
}else{
$this->getLogger()->warning("Chunk " . $chunk->getX() . " " . $chunk->getZ() . ": Deleted unknown tile entity type " . $nbt->getString("id", "<unknown>"));
continue;
}
}
$chunk->NBTtiles = null;
$this->timings->syncChunkLoadTileEntitiesTimer->stopTiming();
}
}
private function queueUnloadChunk(int $x, int $z) : void{ private function queueUnloadChunk(int $x, int $z) : void{
$this->unloadQueue[World::chunkHash($x, $z)] = microtime(true); $this->unloadQueue[World::chunkHash($x, $z)] = microtime(true);
} }

View File

@ -28,15 +28,10 @@ namespace pocketmine\world\format;
use pocketmine\block\BlockLegacyIds; use pocketmine\block\BlockLegacyIds;
use pocketmine\block\tile\Tile; use pocketmine\block\tile\Tile;
use pocketmine\block\tile\TileFactory;
use pocketmine\data\bedrock\BiomeIds; use pocketmine\data\bedrock\BiomeIds;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
use pocketmine\entity\EntityFactory;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\player\Player; use pocketmine\player\Player;
use pocketmine\world\World;
use function array_fill; use function array_fill;
use function array_filter; use function array_filter;
use function array_map; use function array_map;
@ -84,10 +79,10 @@ class Chunk{
protected $biomeIds; protected $biomeIds;
/** @var CompoundTag[]|null */ /** @var CompoundTag[]|null */
protected $NBTtiles; public $NBTtiles;
/** @var CompoundTag[]|null */ /** @var CompoundTag[]|null */
protected $NBTentities; public $NBTentities;
/** /**
* @param SubChunk[] $subChunks * @param SubChunk[] $subChunks
@ -345,55 +340,6 @@ class Chunk{
return $this->NBTentities ?? array_map(function(Entity $entity) : CompoundTag{ return $entity->saveNBT(); }, $this->getSavableEntities()); return $this->NBTentities ?? array_map(function(Entity $entity) : CompoundTag{ return $entity->saveNBT(); }, $this->getSavableEntities());
} }
/**
* Deserializes tiles and entities from NBT
*/
public function initChunk(World $world) : void{
if($this->NBTentities !== null){
$this->dirtyFlags |= self::DIRTY_FLAG_ENTITIES;
$world->timings->syncChunkLoadEntitiesTimer->startTiming();
$entityFactory = EntityFactory::getInstance();
foreach($this->NBTentities as $nbt){
try{
$entity = $entityFactory->createFromData($world, $nbt);
if(!($entity instanceof Entity)){
$saveIdTag = $nbt->getTag("id") ?? $nbt->getTag("identifier");
$saveId = "<unknown>";
if($saveIdTag instanceof StringTag){
$saveId = $saveIdTag->getValue();
}elseif($saveIdTag instanceof IntTag){ //legacy MCPE format
$saveId = "legacy(" . $saveIdTag->getValue() . ")";
}
$world->getLogger()->warning("Chunk $this->x $this->z: Deleted unknown entity type $saveId");
continue;
}
}catch(\Exception $t){ //TODO: this shouldn't be here
$world->getLogger()->logException($t);
continue;
}
}
$this->NBTentities = null;
$world->timings->syncChunkLoadEntitiesTimer->stopTiming();
}
if($this->NBTtiles !== null){
$this->dirtyFlags |= self::DIRTY_FLAG_TILES;
$world->timings->syncChunkLoadTileEntitiesTimer->startTiming();
$tileFactory = TileFactory::getInstance();
foreach($this->NBTtiles as $nbt){
if(($tile = $tileFactory->createFromData($world, $nbt)) !== null){
$world->addTile($tile);
}else{
$world->getLogger()->warning("Chunk $this->x $this->z: Deleted unknown tile entity type " . $nbt->getString("id", "<unknown>"));
continue;
}
}
$this->NBTtiles = null;
$world->timings->syncChunkLoadTileEntitiesTimer->stopTiming();
}
}
public function getBiomeIdArray() : string{ public function getBiomeIdArray() : string{
return $this->biomeIds->getData(); return $this->biomeIds->getData();
} }