From c21197ef176166b1c2c19b091cf84664aa878c00 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Tue, 21 Feb 2017 17:03:45 +0000 Subject: [PATCH] Removed entanglement between chunks and providers. WARNING: BREAKING API CHANGES. - All entity and tile constructors now require a \pocketmine\level\Level instead of a \pocketmine\level\format\Chunk. - Chunk->getProvider() and Chunk->setProvider() have been removed. - Chunk::__construct() has had the $provider parameter removed. - Chunk->unload() has had the unused $save parameter removed. - ChunkEvents now take a Level parameter instead of going through the Chunk API bump to 3.0.0-ALPHA4 --- src/pocketmine/Player.php | 6 +- src/pocketmine/PocketMine.php | 2 +- src/pocketmine/block/BurningFurnace.php | 4 +- src/pocketmine/block/Chest.php | 4 +- src/pocketmine/block/EnchantingTable.php | 2 +- src/pocketmine/block/Fallable.php | 2 +- src/pocketmine/block/FlowerPot.php | 2 +- src/pocketmine/block/ItemFrame.php | 4 +- src/pocketmine/block/MobHead.php | 2 +- src/pocketmine/block/SignPost.php | 2 +- src/pocketmine/block/TNT.php | 2 +- src/pocketmine/entity/Arrow.php | 6 +- src/pocketmine/entity/Entity.php | 20 +++--- src/pocketmine/entity/Projectile.php | 6 +- src/pocketmine/entity/Snowball.php | 6 +- src/pocketmine/event/level/ChunkEvent.php | 17 +++-- src/pocketmine/event/level/ChunkLoadEvent.php | 12 ++-- src/pocketmine/item/SpawnEgg.php | 10 +-- src/pocketmine/level/Explosion.php | 2 +- src/pocketmine/level/Level.php | 25 +++---- src/pocketmine/level/format/Chunk.php | 70 ++++++------------- .../level/format/io/leveldb/LevelDB.php | 7 +- .../level/format/io/region/Anvil.php | 1 - .../level/format/io/region/McRegion.php | 8 +-- .../level/format/io/region/PMAnvil.php | 1 - .../level/generator/GenerationTask.php | 2 +- .../level/generator/LightPopulationTask.php | 2 +- .../level/generator/PopulationTask.php | 4 +- src/pocketmine/tile/Chest.php | 6 +- src/pocketmine/tile/FlowerPot.php | 6 +- src/pocketmine/tile/Furnace.php | 6 +- src/pocketmine/tile/ItemFrame.php | 6 +- src/pocketmine/tile/Sign.php | 6 +- src/pocketmine/tile/Skull.php | 6 +- src/pocketmine/tile/Spawnable.php | 6 +- src/pocketmine/tile/Tile.php | 18 ++--- tests/plugins/PocketMine-DevTools | 2 +- 37 files changed, 123 insertions(+), 170 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 4ee1d7a5b..1635632cd 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -1726,7 +1726,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->server->saveOfflinePlayerData($this->username, $nbt, true); } - parent::__construct($this->level->getChunk($nbt["Pos"][0] >> 4, $nbt["Pos"][2] >> 4, true), $nbt); + parent::__construct($this->level, $nbt); $this->loggedIn = true; $this->server->addOnlinePlayer($this); @@ -2115,7 +2115,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade ]); $f = 1.5; - $snowball = Entity::createEntity("Snowball", $this->chunk, $nbt, $this); + $snowball = Entity::createEntity("Snowball", $this->getLevel(), $nbt, $this); $snowball->setMotion($snowball->getMotion()->multiply($f)); if($this->isSurvival()){ $item->setCount($item->getCount() - 1); @@ -2200,7 +2200,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $diff = ($this->server->getTick() - $this->startAction); $p = $diff / 20; $f = min((($p ** 2) + $p * 2) / 3, 1) * 2; - $ev = new EntityShootBowEvent($this, $bow, Entity::createEntity("Arrow", $this->chunk, $nbt, $this, $f == 2 ? true : false), $f); + $ev = new EntityShootBowEvent($this, $bow, Entity::createEntity("Arrow", $this->getLevel(), $nbt, $this, $f == 2 ? true : false), $f); if($f < 0.1 or $diff < 5){ $ev->setCancelled(); diff --git a/src/pocketmine/PocketMine.php b/src/pocketmine/PocketMine.php index 8e569d790..38ceaa33c 100644 --- a/src/pocketmine/PocketMine.php +++ b/src/pocketmine/PocketMine.php @@ -74,7 +74,7 @@ namespace pocketmine { use raklib\RakLib; const VERSION = "1.6.2dev"; - const API_VERSION = "3.0.0-ALPHA3"; + const API_VERSION = "3.0.0-ALPHA4"; const CODENAME = "Unleashed"; /* diff --git a/src/pocketmine/block/BurningFurnace.php b/src/pocketmine/block/BurningFurnace.php index 6c056165c..2945379e9 100644 --- a/src/pocketmine/block/BurningFurnace.php +++ b/src/pocketmine/block/BurningFurnace.php @@ -88,7 +88,7 @@ class BurningFurnace extends Solid{ } } - Tile::createTile("Furnace", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt); + Tile::createTile("Furnace", $this->getLevel(), $nbt); return true; } @@ -111,7 +111,7 @@ class BurningFurnace extends Solid{ new IntTag("z", $this->z) ]); $nbt->Items->setTagType(NBT::TAG_Compound); - $furnace = Tile::createTile("Furnace", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt); + $furnace = Tile::createTile("Furnace", $this->getLevel(), $nbt); } if(isset($furnace->namedtag->Lock) and $furnace->namedtag->Lock instanceof StringTag){ diff --git a/src/pocketmine/block/Chest.php b/src/pocketmine/block/Chest.php index 2019dbd66..6ab84125f 100644 --- a/src/pocketmine/block/Chest.php +++ b/src/pocketmine/block/Chest.php @@ -115,7 +115,7 @@ class Chest extends Transparent{ } } - $tile = Tile::createTile("Chest", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt); + $tile = Tile::createTile("Chest", $this->getLevel(), $nbt); if($chest instanceof TileChest and $tile instanceof TileChest){ $chest->pairWith($tile); @@ -155,7 +155,7 @@ class Chest extends Transparent{ new IntTag("z", $this->z) ]); $nbt->Items->setTagType(NBT::TAG_Compound); - $chest = Tile::createTile("Chest", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt); + $chest = Tile::createTile("Chest", $this->getLevel(), $nbt); } if(isset($chest->namedtag->Lock) and $chest->namedtag->Lock instanceof StringTag){ diff --git a/src/pocketmine/block/EnchantingTable.php b/src/pocketmine/block/EnchantingTable.php index 432be61f8..7f5aecb30 100644 --- a/src/pocketmine/block/EnchantingTable.php +++ b/src/pocketmine/block/EnchantingTable.php @@ -57,7 +57,7 @@ class EnchantingTable extends Transparent{ } } - Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt); + Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel(), $nbt); return true; } diff --git a/src/pocketmine/block/Fallable.php b/src/pocketmine/block/Fallable.php index 8119a235a..bd5898164 100644 --- a/src/pocketmine/block/Fallable.php +++ b/src/pocketmine/block/Fallable.php @@ -37,7 +37,7 @@ abstract class Fallable extends Solid{ if($type === Level::BLOCK_UPDATE_NORMAL){ $down = $this->getSide(Vector3::SIDE_DOWN); if($down->getId() === self::AIR or ($down instanceof Liquid)){ - $fall = Entity::createEntity("FallingSand", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new CompoundTag("", [ + $fall = Entity::createEntity("FallingSand", $this->getLevel(), new CompoundTag("", [ "Pos" => new ListTag("Pos", [ new DoubleTag("", $this->x + 0.5), new DoubleTag("", $this->y), diff --git a/src/pocketmine/block/FlowerPot.php b/src/pocketmine/block/FlowerPot.php index a888d295e..1e7a23ceb 100644 --- a/src/pocketmine/block/FlowerPot.php +++ b/src/pocketmine/block/FlowerPot.php @@ -85,7 +85,7 @@ class FlowerPot extends Flowable{ } } - Tile::createTile(Tile::FLOWER_POT, $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt); + Tile::createTile(Tile::FLOWER_POT, $this->getLevel(), $nbt); return true; } diff --git a/src/pocketmine/block/ItemFrame.php b/src/pocketmine/block/ItemFrame.php index b78ad8fa8..397dc5964 100644 --- a/src/pocketmine/block/ItemFrame.php +++ b/src/pocketmine/block/ItemFrame.php @@ -56,7 +56,7 @@ class ItemFrame extends Flowable{ new FloatTag("ItemDropChance", 1.0), new ByteTag("ItemRotation", 0) ]); - $tile = Tile::createTile(Tile::ITEM_FRAME, $this->level->getChunk($this->x >> 4, $this->z >> 4), $nbt); + $tile = Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), $nbt); } if($tile->hasItem()){ @@ -133,7 +133,7 @@ class ItemFrame extends Flowable{ } } - Tile::createTile(Tile::ITEM_FRAME, $this->level->getChunk($this->x >> 4, $this->z >> 4), $nbt); + Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), $nbt); return true; diff --git a/src/pocketmine/block/MobHead.php b/src/pocketmine/block/MobHead.php index 0aafffa5a..ff3d758e2 100644 --- a/src/pocketmine/block/MobHead.php +++ b/src/pocketmine/block/MobHead.php @@ -81,7 +81,7 @@ class MobHead extends Flowable{ $nbt->CustomName = new StringTag("CustomName", $item->getCustomName()); } /** @var Spawnable $tile */ - Tile::createTile("Skull", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt); + Tile::createTile("Skull", $this->getLevel(), $nbt); return true; } return false; diff --git a/src/pocketmine/block/SignPost.php b/src/pocketmine/block/SignPost.php index aa0c9f5f9..3df18271d 100644 --- a/src/pocketmine/block/SignPost.php +++ b/src/pocketmine/block/SignPost.php @@ -87,7 +87,7 @@ class SignPost extends Transparent{ $this->getLevel()->setBlock($block, new WallSign($this->meta), true); } - Tile::createTile(Tile::SIGN, $this->getLevel()->getChunk($block->x >> 4, $block->z >> 4), $nbt); + Tile::createTile(Tile::SIGN, $this->getLevel(), $nbt); return true; } diff --git a/src/pocketmine/block/TNT.php b/src/pocketmine/block/TNT.php index fc87276a5..5b93b2d3a 100644 --- a/src/pocketmine/block/TNT.php +++ b/src/pocketmine/block/TNT.php @@ -57,7 +57,7 @@ class TNT extends Solid{ $this->getLevel()->setBlock($this, new Air(), true); $mot = (new Random())->nextSignedFloat() * M_PI * 2; - $tnt = Entity::createEntity("PrimedTNT", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new CompoundTag("", [ + $tnt = Entity::createEntity("PrimedTNT", $this->getLevel(), new CompoundTag("", [ "Pos" => new ListTag("Pos", [ new DoubleTag("", $this->x + 0.5), new DoubleTag("", $this->y), diff --git a/src/pocketmine/entity/Arrow.php b/src/pocketmine/entity/Arrow.php index 3d0c2102a..969021323 100644 --- a/src/pocketmine/entity/Arrow.php +++ b/src/pocketmine/entity/Arrow.php @@ -21,7 +21,7 @@ namespace pocketmine\entity; -use pocketmine\level\format\Chunk; +use pocketmine\level\Level; use pocketmine\level\particle\CriticalParticle; use pocketmine\nbt\tag\CompoundTag; use pocketmine\network\protocol\AddEntityPacket; @@ -41,9 +41,9 @@ class Arrow extends Projectile{ protected $isCritical; - public function __construct(Chunk $chunk, CompoundTag $nbt, Entity $shootingEntity = null, $critical = false){ + public function __construct(Level $level, CompoundTag $nbt, Entity $shootingEntity = null, $critical = false){ $this->isCritical = (bool) $critical; - parent::__construct($chunk, $nbt, $shootingEntity); + parent::__construct($level, $nbt, $shootingEntity); } public function onUpdate($currentTick){ diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 8f154b3df..e0a19f54e 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -269,10 +269,7 @@ abstract class Entity extends Location implements Metadatable{ protected $isPlayer = false; - public function __construct(Chunk $chunk, CompoundTag $nbt){ - - assert($chunk !== null and $chunk->getProvider() !== null); - + public function __construct(Level $level, CompoundTag $nbt){ $this->timings = Timings::getEntityTimings($this); $this->isPlayer = $this instanceof Player; @@ -287,9 +284,10 @@ abstract class Entity extends Location implements Metadatable{ $this->justCreated = true; $this->namedtag = $nbt; - $this->chunk = $chunk; - $this->setLevel($chunk->getProvider()->getLevel()); - $this->server = $chunk->getProvider()->getLevel()->getServer(); + $this->chunk = $level->getChunk($this->namedtag["Pos"][0] >> 4, $this->namedtag["Pos"][2] >> 4); + assert($this->chunk !== null); + $this->setLevel($level); + $this->server = $level->getServer(); $this->boundingBox = new AxisAlignedBB(0, 0, 0, 0, 0, 0); $this->setPositionAndRotation( @@ -301,6 +299,8 @@ abstract class Entity extends Location implements Metadatable{ $this->namedtag->Rotation[0], $this->namedtag->Rotation[1] ); + + $this->setMotion($this->temporalVector->setComponents($this->namedtag["Motion"][0], $this->namedtag["Motion"][1], $this->namedtag["Motion"][2])); assert(!is_nan($this->x) and !is_infinite($this->x) and !is_nan($this->y) and !is_infinite($this->y) and !is_nan($this->z) and !is_infinite($this->z)); @@ -515,16 +515,16 @@ abstract class Entity extends Location implements Metadatable{ /** * @param int|string $type - * @param Chunk $chunk + * @param Level $level * @param CompoundTag $nbt * @param $args * * @return Entity */ - public static function createEntity($type, Chunk $chunk, CompoundTag $nbt, ...$args){ + public static function createEntity($type, Level $level, CompoundTag $nbt, ...$args){ if(isset(self::$knownEntities[$type])){ $class = self::$knownEntities[$type]; - return new $class($chunk, $nbt, ...$args); + return new $class($level, $nbt, ...$args); } return null; diff --git a/src/pocketmine/entity/Projectile.php b/src/pocketmine/entity/Projectile.php index 3ed192c12..fc21eb32e 100644 --- a/src/pocketmine/entity/Projectile.php +++ b/src/pocketmine/entity/Projectile.php @@ -26,7 +26,7 @@ use pocketmine\event\entity\EntityDamageByChildEntityEvent; use pocketmine\event\entity\EntityDamageByEntityEvent; use pocketmine\event\entity\EntityDamageEvent; use pocketmine\event\entity\ProjectileHitEvent; -use pocketmine\level\format\Chunk; +use pocketmine\level\Level; use pocketmine\level\MovingObjectPosition; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; @@ -42,12 +42,12 @@ abstract class Projectile extends Entity{ public $hadCollision = false; - public function __construct(Chunk $chunk, CompoundTag $nbt, Entity $shootingEntity = null){ + public function __construct(Level $level, CompoundTag $nbt, Entity $shootingEntity = null){ $this->shootingEntity = $shootingEntity; if($shootingEntity !== null){ $this->setDataProperty(self::DATA_SHOOTER_ID, self::DATA_TYPE_LONG, $shootingEntity->getId()); } - parent::__construct($chunk, $nbt); + parent::__construct($level, $nbt); } public function attack($damage, EntityDamageEvent $source){ diff --git a/src/pocketmine/entity/Snowball.php b/src/pocketmine/entity/Snowball.php index 77dac72f5..cc9b1aabf 100644 --- a/src/pocketmine/entity/Snowball.php +++ b/src/pocketmine/entity/Snowball.php @@ -21,7 +21,7 @@ namespace pocketmine\entity; -use pocketmine\level\format\Chunk; +use pocketmine\level\Level; use pocketmine\nbt\tag\CompoundTag; use pocketmine\network\protocol\AddEntityPacket; use pocketmine\Player; @@ -36,8 +36,8 @@ class Snowball extends Projectile{ protected $gravity = 0.03; protected $drag = 0.01; - public function __construct(Chunk $chunk, CompoundTag $nbt, Entity $shootingEntity = null){ - parent::__construct($chunk, $nbt, $shootingEntity); + public function __construct(Level $level, CompoundTag $nbt, Entity $shootingEntity = null){ + parent::__construct($level, $nbt, $shootingEntity); } public function onUpdate($currentTick){ diff --git a/src/pocketmine/event/level/ChunkEvent.php b/src/pocketmine/event/level/ChunkEvent.php index 15deb6e69..510335086 100644 --- a/src/pocketmine/event/level/ChunkEvent.php +++ b/src/pocketmine/event/level/ChunkEvent.php @@ -14,27 +14,30 @@ * (at your option) any later version. * * @author PocketMine Team - * @link http://www.pocketmine.net/ + * @link http://www.pocketmine.net/ * * - */ +*/ + -/** - * Level related events - */ namespace pocketmine\event\level; +use pocketmine\level\Level; use pocketmine\level\format\Chunk; +/** + * Chunk-related events + */ abstract class ChunkEvent extends LevelEvent{ /** @var Chunk */ private $chunk; /** + * @param Level $level * @param Chunk $chunk */ - public function __construct(Chunk $chunk){ - parent::__construct($chunk->getProvider()->getLevel()); + public function __construct(Level $level, Chunk $chunk){ + parent::__construct($level); $this->chunk = $chunk; } diff --git a/src/pocketmine/event/level/ChunkLoadEvent.php b/src/pocketmine/event/level/ChunkLoadEvent.php index a7d0eb6a2..c0508defa 100644 --- a/src/pocketmine/event/level/ChunkLoadEvent.php +++ b/src/pocketmine/event/level/ChunkLoadEvent.php @@ -14,13 +14,15 @@ * (at your option) any later version. * * @author PocketMine Team - * @link http://www.pocketmine.net/ + * @link http://www.pocketmine.net/ * * - */ +*/ + namespace pocketmine\event\level; +use pocketmine\level\Level; use pocketmine\level\format\Chunk; /** @@ -31,9 +33,9 @@ class ChunkLoadEvent extends ChunkEvent{ private $newChunk; - public function __construct(Chunk $chunk, $newChunk){ - parent::__construct($chunk); - $this->newChunk = (bool) $newChunk; + public function __construct(Level $level, Chunk $chunk, bool $newChunk){ + parent::__construct($level, $chunk); + $this->newChunk = $newChunk; } /** diff --git a/src/pocketmine/item/SpawnEgg.php b/src/pocketmine/item/SpawnEgg.php index a6727625f..6343f5f6f 100644 --- a/src/pocketmine/item/SpawnEgg.php +++ b/src/pocketmine/item/SpawnEgg.php @@ -24,7 +24,6 @@ namespace pocketmine\item; use pocketmine\block\Block; use pocketmine\entity\Entity; -use pocketmine\level\format\Chunk; use pocketmine\level\Level; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\DoubleTag; @@ -43,13 +42,6 @@ class SpawnEgg extends Item{ } public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){ - $entity = null; - $chunk = $level->getChunk($block->getX() >> 4, $block->getZ() >> 4); - - if(!($chunk instanceof Chunk)){ - return false; - } - $nbt = new CompoundTag("", [ "Pos" => new ListTag("Pos", [ new DoubleTag("", $block->getX() + 0.5), @@ -71,7 +63,7 @@ class SpawnEgg extends Item{ $nbt->CustomName = new StringTag("CustomName", $this->getCustomName()); } - $entity = Entity::createEntity($this->meta, $chunk, $nbt); + $entity = Entity::createEntity($this->meta, $level, $nbt); if($entity instanceof Entity){ if($player->isSurvival()){ diff --git a/src/pocketmine/level/Explosion.php b/src/pocketmine/level/Explosion.php index 94e93fc79..301c52808 100644 --- a/src/pocketmine/level/Explosion.php +++ b/src/pocketmine/level/Explosion.php @@ -173,7 +173,7 @@ class Explosion{ foreach($this->affectedBlocks as $block){ if($block->getId() === Block::TNT){ $mot = (new Random())->nextSignedFloat() * M_PI * 2; - $tnt = Entity::createEntity("PrimedTNT", $this->level->getChunk($block->x >> 4, $block->z >> 4), new CompoundTag("", [ + $tnt = Entity::createEntity("PrimedTNT", $this->level, new CompoundTag("", [ "Pos" => new ListTag("Pos", [ new DoubleTag("", $block->x + 0.5), new DoubleTag("", $block->y), diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index ee2abdf08..59716c599 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -1452,7 +1452,7 @@ class Level implements ChunkManager, Metadatable{ $itemTag->setName("Item"); if($item->getId() > 0 and $item->getCount() > 0){ - $itemEntity = Entity::createEntity("Item", $this->getChunk($source->getX() >> 4, $source->getZ() >> 4, true), new CompoundTag("", [ + $itemEntity = Entity::createEntity("Item", $this, new CompoundTag("", [ "Pos" => new ListTag("Pos", [ new DoubleTag("", $source->getX()), new DoubleTag("", $source->getY()), @@ -2126,11 +2126,10 @@ class Level implements ChunkManager, Metadatable{ } } unset($this->chunkPopulationQueue[$index]); - $chunk->setProvider($this->provider); $this->setChunk($x, $z, $chunk, false); $chunk = $this->getChunk($x, $z, false); - if($chunk !== null and ($oldChunk === null or $oldChunk->isPopulated() === false) and $chunk->isPopulated() and $chunk->getProvider() !== null){ - $this->server->getPluginManager()->callEvent(new ChunkPopulateEvent($chunk)); + if($chunk !== null and ($oldChunk === null or $oldChunk->isPopulated() === false) and $chunk->isPopulated()){ + $this->server->getPluginManager()->callEvent(new ChunkPopulateEvent($this, $chunk)); foreach($this->getChunkLoaders($x, $z) as $loader){ $loader->onChunkPopulated($chunk); @@ -2139,10 +2138,8 @@ class Level implements ChunkManager, Metadatable{ }elseif(isset($this->chunkGenerationQueue[$index]) or isset($this->chunkPopulationLock[$index])){ unset($this->chunkGenerationQueue[$index]); unset($this->chunkPopulationLock[$index]); - $chunk->setProvider($this->provider); $this->setChunk($x, $z, $chunk, false); }else{ - $chunk->setProvider($this->provider); $this->setChunk($x, $z, $chunk, false); } Timings::$generationCallbackTimer->stopTiming(); @@ -2435,15 +2432,9 @@ class Level implements ChunkManager, Metadatable{ } $this->chunks[$index] = $chunk; - $chunk->initChunk(); + $chunk->initChunk($this); - if($chunk->getProvider() !== null){ - $this->server->getPluginManager()->callEvent(new ChunkLoadEvent($chunk, !$chunk->isGenerated())); - }else{ - $this->unloadChunk($x, $z, false); - $this->timings->syncChunkLoadTimer->stopTiming(); - return false; - } + $this->server->getPluginManager()->callEvent(new ChunkLoadEvent($this, $chunk, !$chunk->isGenerated())); if(!$chunk->isLightPopulated() and $chunk->isPopulated() and $this->getServer()->getProperty("chunk-ticking.light-updates", false)){ $this->getServer()->getScheduler()->scheduleAsyncTask(new LightPopulationTask($this, $chunk)); @@ -2494,10 +2485,10 @@ class Level implements ChunkManager, Metadatable{ $index = Level::chunkHash($x, $z); - $chunk = $this->getChunk($x, $z); + $chunk = $this->chunks[$index] ?? null; - if($chunk !== null and $chunk->getProvider() !== null){ - $this->server->getPluginManager()->callEvent($ev = new ChunkUnloadEvent($chunk)); + if($chunk !== null){ + $this->server->getPluginManager()->callEvent($ev = new ChunkUnloadEvent($this, $chunk)); if($ev->isCancelled()){ $this->timings->doChunkUnload->stopTiming(); return false; diff --git a/src/pocketmine/level/format/Chunk.php b/src/pocketmine/level/format/Chunk.php index f03666216..52684896c 100644 --- a/src/pocketmine/level/format/Chunk.php +++ b/src/pocketmine/level/format/Chunk.php @@ -29,7 +29,7 @@ namespace pocketmine\level\format; use pocketmine\block\Block; use pocketmine\entity\Entity; use pocketmine\level\format\io\ChunkException; -use pocketmine\level\format\io\LevelProvider; +use pocketmine\level\Level; use pocketmine\nbt\NBT; use pocketmine\nbt\tag\CompoundTag; use pocketmine\Player; @@ -41,9 +41,6 @@ class Chunk{ const MAX_SUBCHUNKS = 16; - /** @var LevelProvider */ - protected $provider; - protected $x; protected $z; @@ -85,7 +82,6 @@ class Chunk{ protected $NBTentities = []; /** - * @param LevelProvider $provider * @param int $chunkX * @param int $chunkZ * @param SubChunk[] $subChunks @@ -94,12 +90,11 @@ class Chunk{ * @param string $biomeIds * @param int[] $heightMap */ - public function __construct($provider, int $chunkX, int $chunkZ, array $subChunks = [], array $entities = [], array $tiles = [], string $biomeIds = "", array $heightMap = []){ - $this->provider = $provider; + public function __construct(int $chunkX, int $chunkZ, array $subChunks = [], array $entities = [], array $tiles = [], string $biomeIds = "", array $heightMap = []){ $this->x = $chunkX; $this->z = $chunkZ; - $this->height = $provider !== null ? ($provider->getWorldHeight() >> 4) : 16; + $this->height = Chunk::MAX_SUBCHUNKS; //TODO: add a way of changing this $this->emptySubChunk = new EmptySubChunk(); @@ -164,20 +159,6 @@ class Chunk{ $this->z = $z; } - /** - * @return LevelProvider|null - */ - public function getProvider(){ - return $this->provider; - } - - /** - * @param LevelProvider $provider - */ - public function setProvider(LevelProvider $provider){ - $this->provider = $provider; - } - /** * Returns the chunk height in count of subchunks. * @@ -661,20 +642,12 @@ class Chunk{ /** * Unloads the chunk, closing entities and tiles. * - * @param bool $save * @param bool $safe Whether to check if there are still players using this chunk * * @return bool */ - public function unload(bool $save = true, bool $safe = true) : bool{ - $level = $this->getProvider(); - if($level === null){ - return true; - } - if($save === true and $this->hasChanged){ - $level->saveChunk($this->getX(), $this->getZ()); - } - if($safe === true){ + public function unload(bool $safe = true) : bool{ + if($safe){ foreach($this->getEntities() as $entity){ if($entity instanceof Player){ return false; @@ -688,22 +661,24 @@ class Chunk{ } $entity->close(); } + foreach($this->getTiles() as $tile){ $tile->close(); } - $this->provider = null; + return true; } /** * Deserializes tiles and entities from NBT - * TODO: remove this + * + * @param Level $level */ - public function initChunk(){ - if($this->getProvider() instanceof LevelProvider and !$this->isInit){ + public function initChunk(Level $level){ + if(!$this->isInit){ $changed = false; if($this->NBTentities !== null){ - $this->getProvider()->getLevel()->timings->syncChunkLoadEntitiesTimer->startTiming(); + $level->timings->syncChunkLoadEntitiesTimer->startTiming(); foreach($this->NBTentities as $nbt){ if($nbt instanceof CompoundTag){ if(!isset($nbt->id)){ @@ -716,7 +691,7 @@ class Chunk{ continue; //Fixes entities allocated in wrong chunks. } - if(($entity = Entity::createEntity($nbt["id"], $this, $nbt)) instanceof Entity){ + if(($entity = Entity::createEntity($nbt["id"], $level, $nbt)) instanceof Entity){ $entity->spawnToAll(); }else{ $changed = true; @@ -724,9 +699,9 @@ class Chunk{ } } } - $this->getProvider()->getLevel()->timings->syncChunkLoadEntitiesTimer->stopTiming(); + $level->timings->syncChunkLoadEntitiesTimer->stopTiming(); - $this->getProvider()->getLevel()->timings->syncChunkLoadTileEntitiesTimer->startTiming(); + $level->timings->syncChunkLoadTileEntitiesTimer->startTiming(); foreach($this->NBTtiles as $nbt){ if($nbt instanceof CompoundTag){ if(!isset($nbt->id)){ @@ -739,14 +714,14 @@ class Chunk{ continue; //Fixes tiles allocated in wrong chunks. } - if(Tile::createTile($nbt["id"], $this, $nbt) === null){ + if(Tile::createTile($nbt["id"], $level, $nbt) === null){ $changed = true; continue; } } } - $this->getProvider()->getLevel()->timings->syncChunkLoadTileEntitiesTimer->stopTiming(); + $level->timings->syncChunkLoadTileEntitiesTimer->stopTiming(); $this->NBTentities = null; $this->NBTtiles = null; @@ -954,12 +929,11 @@ class Chunk{ /** * Deserializes a fast-serialized chunk * - * @param string $data - * @param LevelProvider|null $provider + * @param string $data * * @return Chunk */ - public static function fastDeserialize(string $data, LevelProvider $provider = null){ + public static function fastDeserialize(string $data){ $stream = new BinaryStream(); $stream->setBuffer($data); $data = null; @@ -973,7 +947,7 @@ class Chunk{ $heightMap = array_values(unpack("C*", $stream->get(256))); $biomeIds = $stream->get(256); - $chunk = new Chunk($provider, $x, $z, $subChunks, [], [], $biomeIds, $heightMap); + $chunk = new Chunk($x, $z, $subChunks, [], [], $biomeIds, $heightMap); $flags = $stream->getByte(); $chunk->lightPopulated = (bool) ($flags & 4); $chunk->terrainPopulated = (bool) ($flags & 2); @@ -982,8 +956,8 @@ class Chunk{ } //TODO: get rid of this - public static function getEmptyChunk(int $x, int $z, LevelProvider $provider = null) : Chunk{ - return new Chunk($provider, $x, $z); + public static function getEmptyChunk(int $x, int $z) : Chunk{ + return new Chunk($x, $z); } /** diff --git a/src/pocketmine/level/format/io/leveldb/LevelDB.php b/src/pocketmine/level/format/io/leveldb/LevelDB.php index cd81336a6..fadfddede 100644 --- a/src/pocketmine/level/format/io/leveldb/LevelDB.php +++ b/src/pocketmine/level/format/io/leveldb/LevelDB.php @@ -258,7 +258,7 @@ class LevelDB extends BaseLevelProvider{ $this->level->timings->syncChunkLoadDataTimer->startTiming(); $chunk = $this->readChunk($chunkX, $chunkZ); if($chunk === null and $create){ - $chunk = Chunk::getEmptyChunk($chunkX, $chunkZ, $this); + $chunk = Chunk::getEmptyChunk($chunkX, $chunkZ); } $this->level->timings->syncChunkLoadDataTimer->stopTiming(); @@ -392,7 +392,6 @@ class LevelDB extends BaseLevelProvider{ }*/ //TODO $chunk = new Chunk( - $this, $chunkX, $chunkZ, $subChunks, @@ -469,7 +468,7 @@ class LevelDB extends BaseLevelProvider{ public function unloadChunk(int $x, int $z, bool $safe = true) : bool{ $chunk = $this->chunks[$index = Level::chunkHash($x, $z)] ?? null; - if($chunk instanceof Chunk and $chunk->unload(false, $safe)){ + if($chunk instanceof Chunk and $chunk->unload($safe)){ unset($this->chunks[$index]); return true; @@ -514,8 +513,6 @@ class LevelDB extends BaseLevelProvider{ } public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk){ - $chunk->setProvider($this); - $chunk->setX($chunkX); $chunk->setZ($chunkZ); diff --git a/src/pocketmine/level/format/io/region/Anvil.php b/src/pocketmine/level/format/io/region/Anvil.php index 111c7f6a0..9b48a2830 100644 --- a/src/pocketmine/level/format/io/region/Anvil.php +++ b/src/pocketmine/level/format/io/region/Anvil.php @@ -134,7 +134,6 @@ class Anvil extends McRegion{ } $result = new Chunk( - $this, $chunk["xPos"], $chunk["zPos"], $subChunks, diff --git a/src/pocketmine/level/format/io/region/McRegion.php b/src/pocketmine/level/format/io/region/McRegion.php index 7f5981f3a..cdb57f0cc 100644 --- a/src/pocketmine/level/format/io/region/McRegion.php +++ b/src/pocketmine/level/format/io/region/McRegion.php @@ -188,7 +188,6 @@ class McRegion extends BaseLevelProvider{ } $result = new Chunk( - $this, $chunk["xPos"], $chunk["zPos"], $subChunks, @@ -294,9 +293,6 @@ class McRegion extends BaseLevelProvider{ } public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk){ - - $chunk->setProvider($this); - self::getRegionIndex($chunkX, $chunkZ, $regionX, $regionZ); $this->loadRegion($regionX, $regionZ); @@ -354,7 +350,7 @@ class McRegion extends BaseLevelProvider{ public function unloadChunk(int $chunkX, int $chunkZ, bool $safe = true) : bool{ $chunk = $this->chunks[$index = Level::chunkHash($chunkX, $chunkZ)] ?? null; - if($chunk instanceof Chunk and $chunk->unload(false, $safe)){ + if($chunk instanceof Chunk and $chunk->unload($safe)){ unset($this->chunks[$index]); return true; } @@ -422,7 +418,7 @@ class McRegion extends BaseLevelProvider{ * @return Chunk */ public function getEmptyChunk(int $chunkX, int $chunkZ){ - return Chunk::getEmptyChunk($chunkX, $chunkZ, $this); + return Chunk::getEmptyChunk($chunkX, $chunkZ); } /** diff --git a/src/pocketmine/level/format/io/region/PMAnvil.php b/src/pocketmine/level/format/io/region/PMAnvil.php index da79808c2..cb28cb17f 100644 --- a/src/pocketmine/level/format/io/region/PMAnvil.php +++ b/src/pocketmine/level/format/io/region/PMAnvil.php @@ -129,7 +129,6 @@ class PMAnvil extends Anvil{ } $result = new Chunk( - $this, $chunk["xPos"], $chunk["zPos"], $subChunks, diff --git a/src/pocketmine/level/generator/GenerationTask.php b/src/pocketmine/level/generator/GenerationTask.php index aea200912..3ffe1320f 100644 --- a/src/pocketmine/level/generator/GenerationTask.php +++ b/src/pocketmine/level/generator/GenerationTask.php @@ -75,7 +75,7 @@ class GenerationTask extends AsyncTask{ return; } /** @var Chunk $chunk */ - $chunk = Chunk::fastDeserialize($this->chunk, $level->getProvider()); + $chunk = Chunk::fastDeserialize($this->chunk); if($chunk === null){ //TODO error return; diff --git a/src/pocketmine/level/generator/LightPopulationTask.php b/src/pocketmine/level/generator/LightPopulationTask.php index 6010776bc..6515fd2ce 100644 --- a/src/pocketmine/level/generator/LightPopulationTask.php +++ b/src/pocketmine/level/generator/LightPopulationTask.php @@ -55,7 +55,7 @@ class LightPopulationTask extends AsyncTask{ $level = $server->getLevel($this->levelId); if($level !== null){ /** @var Chunk $chunk */ - $chunk = Chunk::fastDeserialize($this->chunk, $level->getProvider()); + $chunk = Chunk::fastDeserialize($this->chunk); if($chunk === null){ //TODO error return; diff --git a/src/pocketmine/level/generator/PopulationTask.php b/src/pocketmine/level/generator/PopulationTask.php index 562a41c8b..c40b31378 100644 --- a/src/pocketmine/level/generator/PopulationTask.php +++ b/src/pocketmine/level/generator/PopulationTask.php @@ -152,7 +152,7 @@ class PopulationTask extends AsyncTask{ return; } - $chunk = Chunk::fastDeserialize($this->chunk, $level->getProvider()); + $chunk = Chunk::fastDeserialize($this->chunk); if($chunk === null){ //TODO error @@ -165,7 +165,7 @@ class PopulationTask extends AsyncTask{ } $c = $this->{"chunk$i"}; if($c !== null){ - $c = Chunk::fastDeserialize($c, $level->getProvider()); + $c = Chunk::fastDeserialize($c); $level->generateChunkCallback($c->getX(), $c->getZ(), $c); } } diff --git a/src/pocketmine/tile/Chest.php b/src/pocketmine/tile/Chest.php index b055ad899..8d6abae94 100644 --- a/src/pocketmine/tile/Chest.php +++ b/src/pocketmine/tile/Chest.php @@ -25,7 +25,7 @@ use pocketmine\inventory\ChestInventory; use pocketmine\inventory\DoubleChestInventory; use pocketmine\inventory\InventoryHolder; use pocketmine\item\Item; -use pocketmine\level\format\Chunk; +use pocketmine\level\Level; use pocketmine\math\Vector3; use pocketmine\nbt\NBT; use pocketmine\nbt\tag\CompoundTag; @@ -40,8 +40,8 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{ /** @var DoubleChestInventory */ protected $doubleInventory = null; - public function __construct(Chunk $chunk, CompoundTag $nbt){ - parent::__construct($chunk, $nbt); + public function __construct(Level $level, CompoundTag $nbt){ + parent::__construct($level, $nbt); $this->inventory = new ChestInventory($this); if(!isset($this->namedtag->Items) or !($this->namedtag->Items instanceof ListTag)){ diff --git a/src/pocketmine/tile/FlowerPot.php b/src/pocketmine/tile/FlowerPot.php index 82deffec6..fa802bc61 100644 --- a/src/pocketmine/tile/FlowerPot.php +++ b/src/pocketmine/tile/FlowerPot.php @@ -22,7 +22,7 @@ namespace pocketmine\tile; use pocketmine\item\Item; -use pocketmine\level\format\Chunk; +use pocketmine\level\Level; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\ShortTag; @@ -30,14 +30,14 @@ use pocketmine\nbt\tag\StringTag; class FlowerPot extends Spawnable{ - public function __construct(Chunk $chunk, CompoundTag $nbt){ + public function __construct(Level $level, CompoundTag $nbt){ if(!isset($nbt->item)){ $nbt->item = new ShortTag("item", 0); } if(!isset($nbt->mData)){ $nbt->mData = new IntTag("mData", 0); } - parent::__construct($chunk, $nbt); + parent::__construct($level, $nbt); } public function canAddItem(Item $item): bool{ diff --git a/src/pocketmine/tile/Furnace.php b/src/pocketmine/tile/Furnace.php index badf8bf0e..b97b95adb 100644 --- a/src/pocketmine/tile/Furnace.php +++ b/src/pocketmine/tile/Furnace.php @@ -28,7 +28,7 @@ use pocketmine\inventory\FurnaceInventory; use pocketmine\inventory\FurnaceRecipe; use pocketmine\inventory\InventoryHolder; use pocketmine\item\Item; -use pocketmine\level\format\Chunk; +use pocketmine\level\Level; use pocketmine\nbt\NBT; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; @@ -41,7 +41,7 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ /** @var FurnaceInventory */ protected $inventory; - public function __construct(Chunk $chunk, CompoundTag $nbt){ + public function __construct(Level $level, CompoundTag $nbt){ if(!isset($nbt->BurnTime) or $nbt["BurnTime"] < 0){ $nbt->BurnTime = new ShortTag("BurnTime", 0); } @@ -53,7 +53,7 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ $nbt->BurnTicks = new ShortTag("BurnTicks", 0); } - parent::__construct($chunk, $nbt); + parent::__construct($level, $nbt); $this->inventory = new FurnaceInventory($this); if(!isset($this->namedtag->Items) or !($this->namedtag->Items instanceof ListTag)){ diff --git a/src/pocketmine/tile/ItemFrame.php b/src/pocketmine/tile/ItemFrame.php index 052b8c6bf..0f4a62a90 100644 --- a/src/pocketmine/tile/ItemFrame.php +++ b/src/pocketmine/tile/ItemFrame.php @@ -22,7 +22,7 @@ namespace pocketmine\tile; use pocketmine\item\Item; -use pocketmine\level\format\Chunk; +use pocketmine\level\Level; use pocketmine\nbt\tag\ByteTag; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\FloatTag; @@ -31,7 +31,7 @@ use pocketmine\nbt\tag\StringTag; class ItemFrame extends Spawnable{ - public function __construct(Chunk $chunk, CompoundTag $nbt){ + public function __construct(Level $level, CompoundTag $nbt){ if(!isset($nbt->ItemRotation)){ $nbt->ItemRotation = new ByteTag("ItemRotation", 0); } @@ -40,7 +40,7 @@ class ItemFrame extends Spawnable{ $nbt->ItemDropChance = new FloatTag("ItemDropChance", 1.0); } - parent::__construct($chunk, $nbt); + parent::__construct($level, $nbt); } public function hasItem() : bool{ diff --git a/src/pocketmine/tile/Sign.php b/src/pocketmine/tile/Sign.php index fc11b0628..e69d653e3 100644 --- a/src/pocketmine/tile/Sign.php +++ b/src/pocketmine/tile/Sign.php @@ -22,7 +22,7 @@ namespace pocketmine\tile; use pocketmine\event\block\SignChangeEvent; -use pocketmine\level\format\Chunk; +use pocketmine\level\Level; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\StringTag; @@ -31,7 +31,7 @@ use pocketmine\utils\TextFormat; class Sign extends Spawnable{ - public function __construct(Chunk $chunk, CompoundTag $nbt){ + public function __construct(Level $level, CompoundTag $nbt){ if(!isset($nbt->Text1)){ $nbt->Text1 = new StringTag("Text1", ""); } @@ -45,7 +45,7 @@ class Sign extends Spawnable{ $nbt->Text4 = new StringTag("Text4", ""); } - parent::__construct($chunk, $nbt); + parent::__construct($level, $nbt); } public function saveNBT(){ diff --git a/src/pocketmine/tile/Skull.php b/src/pocketmine/tile/Skull.php index 4cc874861..91be14c0f 100644 --- a/src/pocketmine/tile/Skull.php +++ b/src/pocketmine/tile/Skull.php @@ -21,7 +21,7 @@ namespace pocketmine\tile; -use pocketmine\level\format\Chunk; +use pocketmine\level\Level; use pocketmine\nbt\tag\ByteTag; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; @@ -35,14 +35,14 @@ class Skull extends Spawnable{ const TYPE_CREEPER = 4; const TYPE_DRAGON = 5; - public function __construct(Chunk $chunk, CompoundTag $nbt){ + public function __construct(Level $level, CompoundTag $nbt){ if(!isset($nbt->SkullType)){ $nbt->SkullType = new ByteTag("SkullType", 0); } if(!isset($nbt->Rot)){ $nbt->Rot = new ByteTag("Rot", 0); } - parent::__construct($chunk, $nbt); + parent::__construct($level, $nbt); } public function setType(int $type){ diff --git a/src/pocketmine/tile/Spawnable.php b/src/pocketmine/tile/Spawnable.php index 825d04c3d..07f0ffaa4 100644 --- a/src/pocketmine/tile/Spawnable.php +++ b/src/pocketmine/tile/Spawnable.php @@ -21,7 +21,7 @@ namespace pocketmine\tile; -use pocketmine\level\format\Chunk; +use pocketmine\level\Level; use pocketmine\nbt\NBT; use pocketmine\nbt\tag\CompoundTag; use pocketmine\network\protocol\BlockEntityDataPacket; @@ -46,8 +46,8 @@ abstract class Spawnable extends Tile{ return true; } - public function __construct(Chunk $chunk, CompoundTag $nbt){ - parent::__construct($chunk, $nbt); + public function __construct(Level $level, CompoundTag $nbt){ + parent::__construct($level, $nbt); $this->spawnToAll(); } diff --git a/src/pocketmine/tile/Tile.php b/src/pocketmine/tile/Tile.php index 88452791b..3c51ca6b5 100644 --- a/src/pocketmine/tile/Tile.php +++ b/src/pocketmine/tile/Tile.php @@ -76,16 +76,16 @@ abstract class Tile extends Position{ /** * @param string $type - * @param Chunk $chunk + * @param Level $level * @param CompoundTag $nbt * @param $args * * @return Tile */ - public static function createTile($type, Chunk $chunk, CompoundTag $nbt, ...$args){ + public static function createTile($type, Level $level, CompoundTag $nbt, ...$args){ if(isset(self::$knownTiles[$type])){ $class = self::$knownTiles[$type]; - return new $class($chunk, $nbt, ...$args); + return new $class($level, $nbt, ...$args); } return null; @@ -116,15 +116,15 @@ abstract class Tile extends Position{ return self::$shortNames[static::class]; } - public function __construct(Chunk $chunk, CompoundTag $nbt){ - assert($chunk !== null and $chunk->getProvider() !== null); - + public function __construct(Level $level, CompoundTag $nbt){ $this->timings = Timings::getTileEntityTimings($this); - $this->server = $chunk->getProvider()->getLevel()->getServer(); - $this->chunk = $chunk; - $this->setLevel($chunk->getProvider()->getLevel()); $this->namedtag = $nbt; + $this->server = $level->getServer(); + $this->setLevel($level); + $this->chunk = $level->getChunk($this->namedtag["x"] >> 4, $this->namedtag["z"] >> 4, false); + assert($this->chunk !== null); + $this->name = ""; $this->lastUpdate = microtime(true); $this->id = Tile::$tileCount++; diff --git a/tests/plugins/PocketMine-DevTools b/tests/plugins/PocketMine-DevTools index eb1b7e1c3..db894896e 160000 --- a/tests/plugins/PocketMine-DevTools +++ b/tests/plugins/PocketMine-DevTools @@ -1 +1 @@ -Subproject commit eb1b7e1c32e440fae216bc46d47ae4f94201de99 +Subproject commit db894896ee4932a86f8655ca9f8cabef726787b3