From 83d11c7429a9bc961c052e6d0a10a0ea9638b154 Mon Sep 17 00:00:00 2001 From: ipad54 <63200545+ipad54@users.noreply.github.com> Date: Mon, 17 Jul 2023 18:30:52 +0300 Subject: [PATCH] Implemented Big & Small dripleaf (#5835) --- build/generate-runtime-enum-serializers.php | 2 + src/block/BaseBigDripleaf.php | 136 ++++++++++++++ src/block/BigDripleafHead.php | 132 ++++++++++++++ src/block/BigDripleafStem.php | 41 +++++ src/block/BlockTypeIds.php | 5 +- src/block/SmallDripleaf.php | 170 ++++++++++++++++++ src/block/VanillaBlocks.php | 7 + src/block/utils/DripleafState.php | 65 +++++++ .../convert/BlockObjectToStateSerializer.php | 27 +++ .../BlockStateToObjectDeserializer.php | 22 +++ src/data/runtime/RuntimeEnumDescriber.php | 2 + .../runtime/RuntimeEnumDeserializerTrait.php | 10 ++ .../runtime/RuntimeEnumSerializerTrait.php | 10 ++ .../RuntimeEnumSizeCalculatorTrait.php | 4 + src/item/StringToItemParser.php | 2 + src/world/sound/DripleafTiltDownSound.php | 35 ++++ src/world/sound/DripleafTiltUpSound.php | 35 ++++ .../block_factory_consistency_check.json | 2 +- 18 files changed, 705 insertions(+), 2 deletions(-) create mode 100644 src/block/BaseBigDripleaf.php create mode 100644 src/block/BigDripleafHead.php create mode 100644 src/block/BigDripleafStem.php create mode 100644 src/block/SmallDripleaf.php create mode 100644 src/block/utils/DripleafState.php create mode 100644 src/world/sound/DripleafTiltDownSound.php create mode 100644 src/world/sound/DripleafTiltUpSound.php diff --git a/build/generate-runtime-enum-serializers.php b/build/generate-runtime-enum-serializers.php index 1273e26f8..805ed18e1 100644 --- a/build/generate-runtime-enum-serializers.php +++ b/build/generate-runtime-enum-serializers.php @@ -27,6 +27,7 @@ use pocketmine\block\utils\BellAttachmentType; use pocketmine\block\utils\CopperOxidation; use pocketmine\block\utils\CoralType; use pocketmine\block\utils\DirtType; +use pocketmine\block\utils\DripleafState; use pocketmine\block\utils\DyeColor; use pocketmine\block\utils\FroglightType; use pocketmine\block\utils\LeverFacing; @@ -145,6 +146,7 @@ $enumsUsed = [ CopperOxidation::getAll(), CoralType::getAll(), DirtType::getAll(), + DripleafState::getAll(), DyeColor::getAll(), FroglightType::getAll(), LeverFacing::getAll(), diff --git a/src/block/BaseBigDripleaf.php b/src/block/BaseBigDripleaf.php new file mode 100644 index 000000000..dcd81af0a --- /dev/null +++ b/src/block/BaseBigDripleaf.php @@ -0,0 +1,136 @@ +isHead() === $head) || + $block->getTypeId() === BlockTypeIds::CLAY || + $block->hasTypeTag(BlockTypeTags::DIRT) || + $block->hasTypeTag(BlockTypeTags::MUD); + } + + public function onNearbyBlockChange() : void{ + if( + (!$this->isHead() && !$this->getSide(Facing::UP) instanceof BaseBigDripleaf) || + !$this->canBeSupportedBy($this->getSide(Facing::DOWN), false) + ){ + $this->position->getWorld()->useBreakOn($this->position); + } + } + + public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ + $block = $blockReplace->getSide(Facing::DOWN); + if(!$this->canBeSupportedBy($block, true)){ + return false; + } + if($player !== null){ + $this->facing = Facing::opposite($player->getHorizontalFacing()); + } + if($block instanceof BaseBigDripleaf){ + $this->facing = $block->getFacing(); + $tx->addBlock($block->getPosition(), VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($this->facing)); + } + return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); + } + + public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{ + if($item instanceof Fertilizer && $this->grow($player)){ + $item->pop(); + return true; + } + return false; + } + + private function seekToHead() : ?BaseBigDripleaf{ + if($this->isHead()){ + return $this; + } + $step = 1; + while(($next = $this->getSide(Facing::UP, $step)) instanceof BaseBigDripleaf){ + if($next->isHead()){ + return $next; + } + $step++; + } + return null; + } + + private function grow(?Player $player) : bool{ + $head = $this->seekToHead(); + if($head === null){ + return false; + } + $pos = $head->getPosition(); + $up = $pos->up(); + $world = $pos->getWorld(); + if( + !$world->isInWorld($up->getFloorX(), $up->getFloorY(), $up->getFloorZ()) || + $world->getBlock($up)->getTypeId() !== BlockTypeIds::AIR + ){ + return false; + } + + $tx = new BlockTransaction($world); + + $tx->addBlock($pos, VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($head->getFacing())); + $tx->addBlock($up, VanillaBlocks::BIG_DRIPLEAF_HEAD()->setFacing($head->getFacing())); + + $ev = new StructureGrowEvent($head, $tx, $player); + $ev->call(); + + if(!$ev->isCancelled()){ + return $tx->apply(); + } + return false; + } + + public function getFlameEncouragement() : int{ + return 15; + } + + public function getFlammability() : int{ + return 100; + } + + public function getSupportType(int $facing) : SupportType{ + return SupportType::NONE(); + } +} diff --git a/src/block/BigDripleafHead.php b/src/block/BigDripleafHead.php new file mode 100644 index 000000000..d5bd226ca --- /dev/null +++ b/src/block/BigDripleafHead.php @@ -0,0 +1,132 @@ +leafState = DripleafState::STABLE(); + parent::__construct($idInfo, $name, $typeInfo); + } + + protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{ + parent::describeBlockOnlyState($w); + $w->dripleafState($this->leafState); + } + + protected function isHead() : bool{ + return true; + } + + public function getLeafState() : DripleafState{ + return $this->leafState; + } + + /** @return $this */ + public function setLeafState(DripleafState $leafState) : self{ + $this->leafState = $leafState; + return $this; + } + + public function hasEntityCollision() : bool{ + return true; + } + + private function setTiltAndScheduleTick(DripleafState $tilt) : void{ + $this->position->getWorld()->setBlock($this->position, $this->setLeafState($tilt)); + $delay = $tilt->getScheduledUpdateDelayTicks(); + if($delay !== null){ + $this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, $delay); + } + } + + private function getLeafTopOffset() : float{ + return match($this->leafState){ + DripleafState::STABLE(), DripleafState::UNSTABLE() => 1 / 16, + DripleafState::PARTIAL_TILT() => 3 / 16, + default => 0 + }; + } + + public function onEntityInside(Entity $entity) : bool{ + if(!$entity instanceof Projectile && $this->leafState->equals(DripleafState::STABLE())){ + //the entity must be standing on top of the leaf - do not collapse if the entity is standing underneath + $intersection = AxisAlignedBB::one() + ->offset($this->position->x, $this->position->y, $this->position->z) + ->trim(Facing::DOWN, 1 - $this->getLeafTopOffset()); + if($entity->getBoundingBox()->intersectsWith($intersection)){ + $this->setTiltAndScheduleTick(DripleafState::UNSTABLE()); + return false; + } + } + return true; + } + + public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{ + if(!$this->leafState->equals(DripleafState::FULL_TILT())){ + $this->setTiltAndScheduleTick(DripleafState::FULL_TILT()); + $this->position->getWorld()->addSound($this->position, new DripleafTiltDownSound()); + } + } + + public function onScheduledUpdate() : void{ + if(!$this->leafState->equals(DripleafState::STABLE())){ + if($this->leafState->equals(DripleafState::FULL_TILT())){ + $this->position->getWorld()->setBlock($this->position, $this->setLeafState(DripleafState::STABLE())); + $this->position->getWorld()->addSound($this->position, new DripleafTiltUpSound()); + }else{ + $this->setTiltAndScheduleTick(match($this->leafState->id()){ + DripleafState::UNSTABLE()->id() => DripleafState::PARTIAL_TILT(), + DripleafState::PARTIAL_TILT()->id() => DripleafState::FULL_TILT(), + default => throw new AssumptionFailedError("All types should be covered") + }); + $this->position->getWorld()->addSound($this->position, new DripleafTiltDownSound()); + } + } + } + + protected function recalculateCollisionBoxes() : array{ + if(!$this->leafState->equals(DripleafState::FULL_TILT())){ + return [ + AxisAlignedBB::one() + ->trim(Facing::DOWN, 11 / 16) + ->trim(Facing::UP, $this->getLeafTopOffset()) + ]; + } + return []; + } +} diff --git a/src/block/BigDripleafStem.php b/src/block/BigDripleafStem.php new file mode 100644 index 000000000..d44c47ccb --- /dev/null +++ b/src/block/BigDripleafStem.php @@ -0,0 +1,41 @@ +asItem(); + } +} diff --git a/src/block/BlockTypeIds.php b/src/block/BlockTypeIds.php index b48a1ed03..fe2101e1f 100644 --- a/src/block/BlockTypeIds.php +++ b/src/block/BlockTypeIds.php @@ -733,8 +733,11 @@ final class BlockTypeIds{ public const CHERRY_TRAPDOOR = 10703; public const CHERRY_WALL_SIGN = 10704; public const CHERRY_WOOD = 10705; + public const SMALL_DRIPLEAF = 10706; + public const BIG_DRIPLEAF_HEAD = 10707; + public const BIG_DRIPLEAF_STEM = 10708; - public const FIRST_UNUSED_BLOCK_ID = 10706; + public const FIRST_UNUSED_BLOCK_ID = 10709; private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID; diff --git a/src/block/SmallDripleaf.php b/src/block/SmallDripleaf.php new file mode 100644 index 000000000..e08e6f6e9 --- /dev/null +++ b/src/block/SmallDripleaf.php @@ -0,0 +1,170 @@ +horizontalFacing($this->facing); + $w->bool($this->top); + } + + public function isTop() : bool{ + return $this->top; + } + + /** @return $this */ + public function setTop(bool $top) : self{ + $this->top = $top; + return $this; + } + + private function canBeSupportedBy(Block $block) : bool{ + //TODO: Moss + //TODO: Small Dripleaf also can be placed on dirt, coarse dirt, farmland, grass blocks, + // podzol, rooted dirt, mycelium, and mud if these blocks are underwater (needs waterlogging) + return $block->getTypeId() === BlockTypeIds::CLAY; + } + + public function onNearbyBlockChange() : void{ + if(!$this->top && !$this->canBeSupportedBy($this->getSide(Facing::DOWN))){ + $this->position->getWorld()->useBreakOn($this->position); + return; + } + $face = $this->top ? Facing::DOWN : Facing::UP; + if(!$this->getSide($face)->hasSameTypeId($this)){ + $this->position->getWorld()->useBreakOn($this->position); + } + } + + public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ + $block = $blockReplace->getSide(Facing::UP); + if($block->getTypeId() !== BlockTypeIds::AIR || !$this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){ + return false; + } + if($player !== null){ + $this->facing = Facing::opposite($player->getHorizontalFacing()); + } + + $tx->addBlock($block->getPosition(), VanillaBlocks::SMALL_DRIPLEAF() + ->setFacing($this->facing) + ->setTop(true) + ); + return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); + } + + public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{ + if($item instanceof Fertilizer && $this->grow($player)){ + $item->pop(); + return true; + } + return false; + } + + private function canGrowTo(Position $pos) : bool{ + $world = $pos->getWorld(); + if(!$world->isInWorld($pos->getFloorX(), $pos->getFloorY(), $pos->getFloorZ())){ + return false; + } + $block = $world->getBlock($pos); + return $block->hasSameTypeId($this) || $block->getTypeId() === BlockTypeIds::AIR; + } + + private function grow(?Player $player) : bool{ + $bottomBlock = $this->top ? $this->getSide(Facing::DOWN) : $this; + if(!$this->hasSameTypeId($bottomBlock)){ + return false; + } + $world = $this->position->getWorld(); + $tx = new BlockTransaction($world); + $height = mt_rand(2, 5); + $grown = 0; + for($i = 0; $i < $height; $i++){ + $pos = $bottomBlock->getSide(Facing::UP, $i)->getPosition(); + if(!$this->canGrowTo($pos)){ + break; + } + $block = ++$grown < $height && $this->canGrowTo($pos->getSide(Facing::UP)) ? + VanillaBlocks::BIG_DRIPLEAF_STEM() : + VanillaBlocks::BIG_DRIPLEAF_HEAD(); + $tx->addBlock($pos, $block->setFacing($this->facing)); + } + if($grown > 1){ + $ev = new StructureGrowEvent($bottomBlock, $tx, $player); + $ev->call(); + if(!$ev->isCancelled()){ + return $tx->apply(); + } + } + + return false; + } + + public function getAffectedBlocks() : array{ + $other = $this->getSide($this->top ? Facing::DOWN : Facing::UP); + if($other->hasSameTypeId($this)){ + return [$this, $other]; + } + return parent::getAffectedBlocks(); + } + + public function getDropsForCompatibleTool(Item $item) : array{ + if(!$this->top){ + return [$this->asItem()]; + } + return []; + } + + public function getFlameEncouragement() : int{ + return 15; + } + + public function getFlammability() : int{ + return 100; + } + + public function getSupportType(int $facing) : SupportType{ + return SupportType::NONE(); + } + + protected function recalculateCollisionBoxes() : array{ + return []; + } +} diff --git a/src/block/VanillaBlocks.php b/src/block/VanillaBlocks.php index a45e18a1e..9f2996abd 100644 --- a/src/block/VanillaBlocks.php +++ b/src/block/VanillaBlocks.php @@ -113,6 +113,8 @@ use function mb_strtolower; * @method static Bedrock BEDROCK() * @method static Beetroot BEETROOTS() * @method static Bell BELL() + * @method static BigDripleafHead BIG_DRIPLEAF_HEAD() + * @method static BigDripleafStem BIG_DRIPLEAF_STEM() * @method static WoodenButton BIRCH_BUTTON() * @method static WoodenDoor BIRCH_DOOR() * @method static WoodenFence BIRCH_FENCE() @@ -658,6 +660,7 @@ use function mb_strtolower; * @method static Opaque SHROOMLIGHT() * @method static ShulkerBox SHULKER_BOX() * @method static Slime SLIME() + * @method static SmallDripleaf SMALL_DRIPLEAF() * @method static SmithingTable SMITHING_TABLE() * @method static Furnace SMOKER() * @method static Opaque SMOOTH_BASALT() @@ -1598,6 +1601,10 @@ final class VanillaBlocks{ self::register("hanging_roots", new HangingRoots(new BID(Ids::HANGING_ROOTS), "Hanging Roots", new Info(BreakInfo::instant(ToolType::SHEARS, 1)))); self::register("cave_vines", new CaveVines(new BID(Ids::CAVE_VINES), "Cave Vines", new Info(BreakInfo::instant()))); + + self::register("small_dripleaf", new SmallDripleaf(new BID(Ids::SMALL_DRIPLEAF), "Small Dripleaf", new Info(BreakInfo::instant(BlockToolType::SHEARS, toolHarvestLevel: 1)))); + self::register("big_dripleaf_head", new BigDripleafHead(new BID(Ids::BIG_DRIPLEAF_HEAD), "Big Dripleaf", new Info(BreakInfo::instant()))); + self::register("big_dripleaf_stem", new BigDripleafStem(new BID(Ids::BIG_DRIPLEAF_STEM), "Big Dripleaf Stem", new Info(BreakInfo::instant()))); } private static function registerBlocksR18() : void{ diff --git a/src/block/utils/DripleafState.php b/src/block/utils/DripleafState.php new file mode 100644 index 000000000..3c2e20a13 --- /dev/null +++ b/src/block/utils/DripleafState.php @@ -0,0 +1,65 @@ +Enum___construct($enumName); + } + + public function getScheduledUpdateDelayTicks() : ?int{ + return $this->scheduledUpdateDelayTicks; + } + +} diff --git a/src/data/bedrock/block/convert/BlockObjectToStateSerializer.php b/src/data/bedrock/block/convert/BlockObjectToStateSerializer.php index 0ba6496dd..8ec9a1ddc 100644 --- a/src/data/bedrock/block/convert/BlockObjectToStateSerializer.php +++ b/src/data/bedrock/block/convert/BlockObjectToStateSerializer.php @@ -31,6 +31,8 @@ use pocketmine\block\Barrel; use pocketmine\block\Bed; use pocketmine\block\Beetroot; use pocketmine\block\Bell; +use pocketmine\block\BigDripleafHead; +use pocketmine\block\BigDripleafStem; use pocketmine\block\Block; use pocketmine\block\BoneBlock; use pocketmine\block\BrewingStand; @@ -115,6 +117,7 @@ use pocketmine\block\SeaPickle; use pocketmine\block\SimplePillar; use pocketmine\block\SimplePressurePlate; use pocketmine\block\Slab; +use pocketmine\block\SmallDripleaf; use pocketmine\block\SnowLayer; use pocketmine\block\Sponge; use pocketmine\block\StainedGlass; @@ -138,6 +141,7 @@ use pocketmine\block\UnderwaterTorch; use pocketmine\block\utils\BrewingStandSlot; use pocketmine\block\utils\CoralType; use pocketmine\block\utils\DirtType; +use pocketmine\block\utils\DripleafState; use pocketmine\block\utils\DyeColor; use pocketmine\block\utils\FroglightType; use pocketmine\block\utils\LeverFacing; @@ -958,6 +962,24 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{ ->writeLegacyHorizontalFacing($block->getFacing()); }); + $this->map(Blocks::BIG_DRIPLEAF_HEAD(), function(BigDripleafHead $block) : Writer{ + return Writer::create(Ids::BIG_DRIPLEAF) + ->writeLegacyHorizontalFacing($block->getFacing()) + ->writeString(StateNames::BIG_DRIPLEAF_TILT, match($block->getLeafState()->id()){ + DripleafState::STABLE()->id() => StringValues::BIG_DRIPLEAF_TILT_NONE, + DripleafState::UNSTABLE()->id() => StringValues::BIG_DRIPLEAF_TILT_UNSTABLE, + DripleafState::PARTIAL_TILT()->id() => StringValues::BIG_DRIPLEAF_TILT_PARTIAL_TILT, + DripleafState::FULL_TILT()->id() => StringValues::BIG_DRIPLEAF_TILT_FULL_TILT, + default => throw new BlockStateSerializeException("Invalid Dripleaf tilt type " . $block->getLeafState()->name()) + }) + ->writeBool(StateNames::BIG_DRIPLEAF_HEAD, true); + }); + $this->map(Blocks::BIG_DRIPLEAF_STEM(), function(BigDripleafStem $block) : Writer{ + return Writer::create(Ids::BIG_DRIPLEAF) + ->writeLegacyHorizontalFacing($block->getFacing()) + ->writeString(StateNames::BIG_DRIPLEAF_TILT, StringValues::BIG_DRIPLEAF_TILT_NONE) + ->writeBool(StateNames::BIG_DRIPLEAF_HEAD, false); + }); $this->map(Blocks::BIRCH_SAPLING(), fn(Sapling $block) => Helper::encodeSapling($block, StringValues::SAPLING_TYPE_BIRCH)); $this->mapSlab(Blocks::BLACKSTONE_SLAB(), Ids::BLACKSTONE_SLAB, Ids::BLACKSTONE_DOUBLE_SLAB); $this->mapStairs(Blocks::BLACKSTONE_STAIRS(), Ids::BLACKSTONE_STAIRS); @@ -1454,6 +1476,11 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{ ->writeBool(StateNames::DEAD_BIT, !$block->isUnderwater()) ->writeInt(StateNames::CLUSTER_COUNT, $block->getCount() - 1); }); + $this->map(Blocks::SMALL_DRIPLEAF(), function(SmallDripleaf $block) : Writer{ + return Writer::create(Ids::SMALL_DRIPLEAF_BLOCK) + ->writeLegacyHorizontalFacing($block->getFacing()) + ->writeBool(StateNames::UPPER_BLOCK_BIT, $block->isTop()); + }); $this->map(Blocks::SMOKER(), fn(Furnace $block) => Helper::encodeFurnace($block, Ids::SMOKER, Ids::LIT_SMOKER)); $this->map(Blocks::SMOOTH_QUARTZ(), fn() => Helper::encodeQuartz(StringValues::CHISEL_TYPE_SMOOTH, Axis::Y)); $this->map(Blocks::SMOOTH_QUARTZ_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_SMOOTH_QUARTZ)); diff --git a/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php b/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php index 65b896523..08c9b5914 100644 --- a/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php +++ b/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php @@ -35,6 +35,7 @@ use pocketmine\block\utils\BrewingStandSlot; use pocketmine\block\utils\CopperOxidation; use pocketmine\block\utils\CoralType; use pocketmine\block\utils\DirtType; +use pocketmine\block\utils\DripleafState; use pocketmine\block\utils\DyeColor; use pocketmine\block\utils\FroglightType; use pocketmine\block\utils\LeverFacing; @@ -826,6 +827,22 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{ ->setFacing($in->readLegacyHorizontalFacing()) ->setAttachmentType($in->readBellAttachmentType()); }); + $this->map(Ids::BIG_DRIPLEAF, function(Reader $in) : Block{ + if($in->readBool(StateNames::BIG_DRIPLEAF_HEAD)){ + return Blocks::BIG_DRIPLEAF_HEAD() + ->setFacing($in->readLegacyHorizontalFacing()) + ->setLeafState(match($type = $in->readString(StateNames::BIG_DRIPLEAF_TILT)){ + StringValues::BIG_DRIPLEAF_TILT_NONE => DripleafState::STABLE(), + StringValues::BIG_DRIPLEAF_TILT_UNSTABLE => DripleafState::UNSTABLE(), + StringValues::BIG_DRIPLEAF_TILT_PARTIAL_TILT => DripleafState::PARTIAL_TILT(), + StringValues::BIG_DRIPLEAF_TILT_FULL_TILT => DripleafState::FULL_TILT(), + default => throw $in->badValueException(StateNames::BIG_DRIPLEAF_TILT, $type), + }); + }else{ + $in->ignored(StateNames::BIG_DRIPLEAF_TILT); + return Blocks::BIG_DRIPLEAF_STEM()->setFacing($in->readLegacyHorizontalFacing()); + } + }); $this->mapSlab(Ids::BLACKSTONE_SLAB, Ids::BLACKSTONE_DOUBLE_SLAB, fn() => Blocks::BLACKSTONE_SLAB()); $this->mapStairs(Ids::BLACKSTONE_STAIRS, fn() => Blocks::BLACKSTONE_STAIRS()); $this->map(Ids::BLACKSTONE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::BLACKSTONE_WALL(), $in)); @@ -1332,6 +1349,11 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{ ->setFacing($in->readHorizontalFacing()) ->setLit(false); }); + $this->map(Ids::SMALL_DRIPLEAF_BLOCK, function(Reader $in) : Block{ + return Blocks::SMALL_DRIPLEAF() + ->setFacing($in->readLegacyHorizontalFacing()) + ->setTop($in->readBool(StateNames::UPPER_BLOCK_BIT)); + }); $this->mapStairs(Ids::SMOOTH_QUARTZ_STAIRS, fn() => Blocks::SMOOTH_QUARTZ_STAIRS()); $this->mapStairs(Ids::SMOOTH_RED_SANDSTONE_STAIRS, fn() => Blocks::SMOOTH_RED_SANDSTONE_STAIRS()); $this->mapStairs(Ids::SMOOTH_SANDSTONE_STAIRS, fn() => Blocks::SMOOTH_SANDSTONE_STAIRS()); diff --git a/src/data/runtime/RuntimeEnumDescriber.php b/src/data/runtime/RuntimeEnumDescriber.php index 643ecd301..7103017f7 100644 --- a/src/data/runtime/RuntimeEnumDescriber.php +++ b/src/data/runtime/RuntimeEnumDescriber.php @@ -37,6 +37,8 @@ interface RuntimeEnumDescriber{ public function dirtType(\pocketmine\block\utils\DirtType &$value) : void; + public function dripleafState(\pocketmine\block\utils\DripleafState &$value) : void; + public function dyeColor(\pocketmine\block\utils\DyeColor &$value) : void; public function froglightType(\pocketmine\block\utils\FroglightType &$value) : void; diff --git a/src/data/runtime/RuntimeEnumDeserializerTrait.php b/src/data/runtime/RuntimeEnumDeserializerTrait.php index 4774304a9..7d80a6f54 100644 --- a/src/data/runtime/RuntimeEnumDeserializerTrait.php +++ b/src/data/runtime/RuntimeEnumDeserializerTrait.php @@ -71,6 +71,16 @@ trait RuntimeEnumDeserializerTrait{ }; } + public function dripleafState(\pocketmine\block\utils\DripleafState &$value) : void{ + $value = match($this->readInt(2)){ + 0 => \pocketmine\block\utils\DripleafState::FULL_TILT(), + 1 => \pocketmine\block\utils\DripleafState::PARTIAL_TILT(), + 2 => \pocketmine\block\utils\DripleafState::STABLE(), + 3 => \pocketmine\block\utils\DripleafState::UNSTABLE(), + default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for DripleafState") + }; + } + public function dyeColor(\pocketmine\block\utils\DyeColor &$value) : void{ $value = match($this->readInt(4)){ 0 => \pocketmine\block\utils\DyeColor::BLACK(), diff --git a/src/data/runtime/RuntimeEnumSerializerTrait.php b/src/data/runtime/RuntimeEnumSerializerTrait.php index c570046c6..8c3d67118 100644 --- a/src/data/runtime/RuntimeEnumSerializerTrait.php +++ b/src/data/runtime/RuntimeEnumSerializerTrait.php @@ -71,6 +71,16 @@ trait RuntimeEnumSerializerTrait{ }); } + public function dripleafState(\pocketmine\block\utils\DripleafState &$value) : void{ + $this->writeInt(2, match($value){ + \pocketmine\block\utils\DripleafState::FULL_TILT() => 0, + \pocketmine\block\utils\DripleafState::PARTIAL_TILT() => 1, + \pocketmine\block\utils\DripleafState::STABLE() => 2, + \pocketmine\block\utils\DripleafState::UNSTABLE() => 3, + default => throw new \pocketmine\utils\AssumptionFailedError("All DripleafState cases should be covered") + }); + } + public function dyeColor(\pocketmine\block\utils\DyeColor &$value) : void{ $this->writeInt(4, match($value){ \pocketmine\block\utils\DyeColor::BLACK() => 0, diff --git a/src/data/runtime/RuntimeEnumSizeCalculatorTrait.php b/src/data/runtime/RuntimeEnumSizeCalculatorTrait.php index 3c8d189e1..2ab62f03e 100644 --- a/src/data/runtime/RuntimeEnumSizeCalculatorTrait.php +++ b/src/data/runtime/RuntimeEnumSizeCalculatorTrait.php @@ -47,6 +47,10 @@ trait RuntimeEnumSizeCalculatorTrait{ $this->addBits(2); } + public function dripleafState(\pocketmine\block\utils\DripleafState &$value) : void{ + $this->addBits(2); + } + public function dyeColor(\pocketmine\block\utils\DyeColor &$value) : void{ $this->addBits(4); } diff --git a/src/item/StringToItemParser.php b/src/item/StringToItemParser.php index e5e5252e1..ea9923c21 100644 --- a/src/item/StringToItemParser.php +++ b/src/item/StringToItemParser.php @@ -155,6 +155,7 @@ final class StringToItemParser extends StringToTParser{ $result->registerBlock("beetroot_block", fn() => Blocks::BEETROOTS()); $result->registerBlock("beetroots", fn() => Blocks::BEETROOTS()); $result->registerBlock("bell", fn() => Blocks::BELL()); + $result->registerBlock("big_dripleaf", fn() => Blocks::BIG_DRIPLEAF_HEAD()); $result->registerBlock("birch_button", fn() => Blocks::BIRCH_BUTTON()); $result->registerBlock("birch_door", fn() => Blocks::BIRCH_DOOR()); $result->registerBlock("birch_door_block", fn() => Blocks::BIRCH_DOOR()); @@ -972,6 +973,7 @@ final class StringToItemParser extends StringToTParser{ $result->registerBlock("slabs", fn() => Blocks::SMOOTH_STONE_SLAB()); $result->registerBlock("slime", fn() => Blocks::SLIME()); $result->registerBlock("slime_block", fn() => Blocks::SLIME()); + $result->registerBlock("small_dripleaf", fn() => Blocks::SMALL_DRIPLEAF()); $result->registerBlock("smoker", fn() => Blocks::SMOKER()); $result->registerBlock("smooth_basalt", fn() => Blocks::SMOOTH_BASALT()); $result->registerBlock("smooth_quartz", fn() => Blocks::SMOOTH_QUARTZ()); diff --git a/src/world/sound/DripleafTiltDownSound.php b/src/world/sound/DripleafTiltDownSound.php new file mode 100644 index 000000000..1366f1b71 --- /dev/null +++ b/src/world/sound/DripleafTiltDownSound.php @@ -0,0 +1,35 @@ +