From 790c2cd4b74267b229c183b9b640ed5438797dc5 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 30 May 2019 19:26:16 +0100 Subject: [PATCH] added missing Monster Spawner tile --- src/pocketmine/block/BlockFactory.php | 3 +- src/pocketmine/block/tile/MonsterSpawner.php | 156 +++++++++++++++++++ src/pocketmine/block/tile/TileFactory.php | 2 +- 3 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 src/pocketmine/block/tile/MonsterSpawner.php diff --git a/src/pocketmine/block/BlockFactory.php b/src/pocketmine/block/BlockFactory.php index 86b5bccb7..8881f923e 100644 --- a/src/pocketmine/block/BlockFactory.php +++ b/src/pocketmine/block/BlockFactory.php @@ -37,6 +37,7 @@ use pocketmine\block\tile\EnderChest as TileEnderChest; use pocketmine\block\tile\FlowerPot as TileFlowerPot; use pocketmine\block\tile\Furnace as TileFurnace; use pocketmine\block\tile\ItemFrame as TileItemFrame; +use pocketmine\block\tile\MonsterSpawner as TileMonsterSpawner; use pocketmine\block\tile\Note as TileNote; use pocketmine\block\tile\Sign as TileSign; use pocketmine\block\tile\Skull as TileSkull; @@ -228,7 +229,7 @@ class BlockFactory{ self::register(new Magma(new BID(Ids::MAGMA), "Magma Block")); self::register(new Melon(new BID(Ids::MELON_BLOCK), "Melon Block")); self::register(new MelonStem(new BID(Ids::MELON_STEM, 0, ItemIds::MELON_SEEDS), "Melon Stem")); - self::register(new MonsterSpawner(new BID(Ids::MOB_SPAWNER), "Monster Spawner")); + self::register(new MonsterSpawner(new BID(Ids::MOB_SPAWNER, 0, null, TileMonsterSpawner::class), "Monster Spawner")); self::register(new Mycelium(new BID(Ids::MYCELIUM), "Mycelium")); $netherBrickBreakInfo = new BlockBreakInfo(2.0, BlockToolType::TYPE_PICKAXE, TieredTool::TIER_WOODEN, 30.0); diff --git a/src/pocketmine/block/tile/MonsterSpawner.php b/src/pocketmine/block/tile/MonsterSpawner.php new file mode 100644 index 000000000..e698b2c07 --- /dev/null +++ b/src/pocketmine/block/tile/MonsterSpawner.php @@ -0,0 +1,156 @@ + + private const TAG_SPAWN_DATA = "SpawnData"; //TAG_Compound + private const TAG_MIN_SPAWN_DELAY = "MinSpawnDelay"; //TAG_Short + private const TAG_MAX_SPAWN_DELAY = "MaxSpawnDelay"; //TAG_Short + private const TAG_SPAWN_PER_ATTEMPT = "SpawnCount"; //TAG_Short + private const TAG_MAX_NEARBY_ENTITIES = "MaxNearbyEntities"; //TAG_Short + private const TAG_REQUIRED_PLAYER_RANGE = "RequiredPlayerRange"; //TAG_Short + private const TAG_SPAWN_RANGE = "SpawnRange"; //TAG_Short + private const TAG_ENTITY_WIDTH = "DisplayEntityWidth"; //TAG_Float + private const TAG_ENTITY_HEIGHT = "DisplayEntityHeight"; //TAG_Float + private const TAG_ENTITY_SCALE = "DisplayEntityScale"; //TAG_Float + + public const DEFAULT_MIN_SPAWN_DELAY = 200; //ticks + public const DEFAULT_MAX_SPAWN_DELAY = 800; + + public const DEFAULT_MAX_NEARBY_ENTITIES = 6; + public const DEFAULT_SPAWN_RANGE = 4; //blocks + public const DEFAULT_REQUIRED_PLAYER_RANGE = 16; + + /** + * @var string + * TODO: replace this with a cached entity or something of that nature + */ + private $entityTypeId = ":"; + /** + * @var ListTag|null + * TODO: deserialize this properly and drop the NBT (PC and PE formats are different, just for fun) + */ + private $spawnPotentials = null; + /** + * @var CompoundTag|null + * TODO: deserialize this properly and drop the NBT (PC and PE formats are different, just for fun) + */ + private $spawnData = null; + + /** @var float */ + private $displayEntityWidth = 1; + /** @var float */ + private $displayEntityHeight = 1; + /** @var float */ + private $displayEntityScale = 1; + + /** @var int */ + private $spawnDelay = self::DEFAULT_MIN_SPAWN_DELAY; + /** @var int */ + private $minSpawnDelay = self::DEFAULT_MIN_SPAWN_DELAY; + /** @var int */ + private $maxSpawnDelay = self::DEFAULT_MAX_SPAWN_DELAY; + /** @var int */ + private $spawnPerAttempt = 1; + /** @var int */ + private $maxNearbyEntities = self::DEFAULT_MAX_NEARBY_ENTITIES; + /** @var int */ + private $spawnRange = self::DEFAULT_SPAWN_RANGE; + /** @var int */ + private $requiredPlayerRange = self::DEFAULT_REQUIRED_PLAYER_RANGE; + + public function readSaveData(CompoundTag $nbt) : void{ + if($nbt->hasTag(self::TAG_LEGACY_ENTITY_TYPE_ID, IntTag::class)){ + //TODO: this will cause unexpected results when there's no mapping for the entity + $this->entityTypeId = AddEntityPacket::LEGACY_ID_MAP_BC[$nbt->getInt(self::TAG_LEGACY_ENTITY_TYPE_ID)] ?? ":"; + }elseif($nbt->hasTag(self::TAG_ENTITY_TYPE_ID, StringTag::class)){ + $this->entityTypeId = $nbt->getString(self::TAG_ENTITY_TYPE_ID); + }else{ + $this->entityTypeId = ":"; //default - TODO: replace this with a constant + } + + $this->spawnData = $nbt->getCompoundTag(self::TAG_SPAWN_DATA); + $this->spawnPotentials = $nbt->getListTag(self::TAG_SPAWN_POTENTIALS); + + $this->spawnDelay = $nbt->getShort(self::TAG_SPAWN_DELAY, self::DEFAULT_MIN_SPAWN_DELAY); + $this->minSpawnDelay = $nbt->getShort(self::TAG_MIN_SPAWN_DELAY, self::DEFAULT_MIN_SPAWN_DELAY); + $this->maxSpawnDelay = $nbt->getShort(self::TAG_MAX_SPAWN_DELAY, self::DEFAULT_MAX_SPAWN_DELAY); + $this->spawnPerAttempt = $nbt->getShort(self::TAG_SPAWN_PER_ATTEMPT, 1); + $this->maxNearbyEntities = $nbt->getShort(self::TAG_MAX_NEARBY_ENTITIES, self::DEFAULT_MAX_NEARBY_ENTITIES); + $this->requiredPlayerRange = $nbt->getShort(self::TAG_REQUIRED_PLAYER_RANGE, self::DEFAULT_REQUIRED_PLAYER_RANGE); + $this->spawnRange = $nbt->getShort(self::TAG_SPAWN_RANGE, self::DEFAULT_SPAWN_RANGE); + + $this->displayEntityWidth = $nbt->getFloat(self::TAG_ENTITY_WIDTH, 1.0); + $this->displayEntityHeight = $nbt->getFloat(self::TAG_ENTITY_HEIGHT, 1.0); + $this->displayEntityScale = $nbt->getFloat(self::TAG_ENTITY_SCALE, 1.0); + } + + protected function writeSaveData(CompoundTag $nbt) : void{ + $nbt->setString(self::TAG_ENTITY_TYPE_ID, $this->entityTypeId); + if($this->spawnData !== null){ + $nbt->setTag(self::TAG_SPAWN_DATA, clone $this->spawnData); + } + if($this->spawnPotentials !== null){ + $nbt->setTag(self::TAG_SPAWN_POTENTIALS, clone $this->spawnPotentials); + } + + $nbt->setShort(self::TAG_SPAWN_DELAY, $this->spawnDelay); + $nbt->setShort(self::TAG_MIN_SPAWN_DELAY, $this->minSpawnDelay); + $nbt->setShort(self::TAG_MAX_SPAWN_DELAY, $this->maxSpawnDelay); + $nbt->setShort(self::TAG_SPAWN_PER_ATTEMPT, $this->spawnPerAttempt); + $nbt->setShort(self::TAG_MAX_NEARBY_ENTITIES, $this->maxNearbyEntities); + $nbt->setShort(self::TAG_REQUIRED_PLAYER_RANGE, $this->requiredPlayerRange); + $nbt->setShort(self::TAG_SPAWN_RANGE, $this->spawnRange); + + $nbt->setFloat(self::TAG_ENTITY_WIDTH, $this->displayEntityWidth); + $nbt->setFloat(self::TAG_ENTITY_HEIGHT, $this->displayEntityHeight); + $nbt->setFloat(self::TAG_ENTITY_SCALE, $this->displayEntityScale); + } + + protected function addAdditionalSpawnData(CompoundTag $nbt) : void{ + $nbt->setString(self::TAG_ENTITY_TYPE_ID, $this->entityTypeId); + + //TODO: we can't set SpawnData here because it might crash the client if it's from a PC world (we need to implement full deserialization) + + $nbt->setFloat(self::TAG_ENTITY_SCALE, $this->displayEntityScale); + } + + public function onUpdate() : bool{ + return false; //TODO + } +} diff --git a/src/pocketmine/block/tile/TileFactory.php b/src/pocketmine/block/tile/TileFactory.php index 811dd719f..a6c5217aa 100644 --- a/src/pocketmine/block/tile/TileFactory.php +++ b/src/pocketmine/block/tile/TileFactory.php @@ -56,6 +56,7 @@ final class TileFactory{ self::register(FlowerPot::class, ["FlowerPot", "minecraft:flower_pot"]); self::register(Furnace::class, ["Furnace", "minecraft:furnace"]); self::register(ItemFrame::class, ["ItemFrame"]); //this is an entity in PC + self::register(MonsterSpawner::class, ["MobSpawner", "minecraft:mob_spawner"]); self::register(Note::class, ["Music", "minecraft:noteblock"]); self::register(Sign::class, ["Sign", "minecraft:sign"]); self::register(Skull::class, ["Skull", "minecraft:skull"]); @@ -79,7 +80,6 @@ final class TileFactory{ //TODO: JigsawBlock //TODO: Jukebox //TODO: Lectern - //TODO: MobSpawner //TODO: MovingBlock //TODO: NetherReactor //TODO: PistonArm