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\tile\Spawnable;
use pocketmine\block\tile\Tile;
use pocketmine\block\tile\TileFactory;
use pocketmine\block\UnknownBlock;
use pocketmine\block\VanillaBlocks;
use pocketmine\data\bedrock\BiomeIds;
use pocketmine\entity\Entity;
use pocketmine\entity\EntityFactory;
use pocketmine\entity\Location;
use pocketmine\entity\object\ExperienceOrb;
use pocketmine\entity\object\ItemEntity;
@ -54,6 +56,8 @@ use pocketmine\item\ItemUseResult;
use pocketmine\item\LegacyStringToItemParser;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
use pocketmine\network\mcpe\protocol\ClientboundPacket;
@ -2245,7 +2249,7 @@ class World implements ChunkManager{
$this->chunks[$chunkHash] = $chunk;
unset($this->blockCache[$chunkHash]);
$chunk->initChunk($this);
$this->initChunk($chunk);
(new ChunkLoadEvent($this, $chunk, !$chunk->isGenerated()))->call();
@ -2262,6 +2266,52 @@ class World implements ChunkManager{
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{
$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\tile\Tile;
use pocketmine\block\tile\TileFactory;
use pocketmine\data\bedrock\BiomeIds;
use pocketmine\entity\Entity;
use pocketmine\entity\EntityFactory;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\player\Player;
use pocketmine\world\World;
use function array_fill;
use function array_filter;
use function array_map;
@ -84,10 +79,10 @@ class Chunk{
protected $biomeIds;
/** @var CompoundTag[]|null */
protected $NBTtiles;
public $NBTtiles;
/** @var CompoundTag[]|null */
protected $NBTentities;
public $NBTentities;
/**
* @param SubChunk[] $subChunks
@ -345,55 +340,6 @@ class Chunk{
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{
return $this->biomeIds->getData();
}