From 14114f6eaf1c5939286afb2eec0beda2ac4e96ff Mon Sep 17 00:00:00 2001 From: "Asfadavy Aulia A." <67502532+DavyCraft648@users.noreply.github.com> Date: Tue, 14 Oct 2025 20:19:57 +0700 Subject: [PATCH] Implement Cactus Flower (#6838) --- src/block/BlockTypeIds.php | 3 +- src/block/Cactus.php | 64 +++++++++++++------ src/block/CactusFlower.php | 46 +++++++++++++ src/block/VanillaBlocks.php | 2 + .../block/convert/VanillaBlockMappings.php | 2 + src/item/StringToItemParser.php | 1 + tests/phpstan/configs/actual-problems.neon | 18 ------ .../block_factory_consistency_check.json | 1 + 8 files changed, 100 insertions(+), 37 deletions(-) create mode 100644 src/block/CactusFlower.php diff --git a/src/block/BlockTypeIds.php b/src/block/BlockTypeIds.php index 7bda65963..827a95edc 100644 --- a/src/block/BlockTypeIds.php +++ b/src/block/BlockTypeIds.php @@ -826,8 +826,9 @@ final class BlockTypeIds{ public const COPPER_CHAIN = 10796; public const COPPER_LANTERN = 10797; public const COPPER_TORCH = 10798; + public const CACTUS_FLOWER = 10799; - public const FIRST_UNUSED_BLOCK_ID = 10799; + public const FIRST_UNUSED_BLOCK_ID = 10800; private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID; diff --git a/src/block/Cactus.php b/src/block/Cactus.php index 51c98786b..525614096 100644 --- a/src/block/Cactus.php +++ b/src/block/Cactus.php @@ -33,12 +33,14 @@ use pocketmine\event\entity\EntityDamageByBlockEvent; use pocketmine\event\entity\EntityDamageEvent; use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; +use function mt_rand; class Cactus extends Transparent implements Ageable{ use AgeableTrait; use StaticSupportTrait; public const MAX_AGE = 15; + public const MAX_HEIGHT = 3; public function hasEntityCollision() : bool{ return true; @@ -78,26 +80,52 @@ class Cactus extends Transparent implements Ageable{ } public function onRandomTick() : void{ - if(!$this->getSide(Facing::DOWN)->hasSameTypeId($this)){ - $world = $this->position->getWorld(); - if($this->age === self::MAX_AGE){ - for($y = 1; $y < 3; ++$y){ - if(!$world->isInWorld($this->position->x, $this->position->y + $y, $this->position->z)){ - break; - } - $b = $world->getBlockAt($this->position->x, $this->position->y + $y, $this->position->z); - if($b->getTypeId() === BlockTypeIds::AIR){ - BlockEventHelper::grow($b, VanillaBlocks::CACTUS(), null); - }else{ - break; - } + $up = $this->getSide(Facing::UP); + if($up->getTypeId() !== BlockTypeIds::AIR){ + return; + } + + $world = $this->position->getWorld(); + + if(!$world->isInWorld($up->position->x, $up->position->y, $up->position->z)){ + return; + } + + $height = 1; + while($height < self::MAX_HEIGHT && $this->getSide(Facing::DOWN, $height)->hasSameTypeId($this)){ + $height++; + } + + if($this->age === 9){ + $canGrowFlower = true; + foreach(Facing::HORIZONTAL as $side){ + if($up->getSide($side)->isSolid()){ + $canGrowFlower = false; + break; + } + } + + if($canGrowFlower){ + $chance = $height >= self::MAX_HEIGHT ? 25 : 10; + if(mt_rand(1, 100) <= $chance){ + if(BlockEventHelper::grow($up, VanillaBlocks::CACTUS_FLOWER(), null)){ + $this->age = 0; + $world->setBlock($this->position, $this, update: false); + } + return; } - $this->age = 0; - $world->setBlock($this->position, $this, update: false); - }else{ - ++$this->age; - $world->setBlock($this->position, $this, update: false); } } + + if($this->age === self::MAX_AGE){ + $this->age = 0; + + if($height < self::MAX_HEIGHT){ + BlockEventHelper::grow($up, VanillaBlocks::CACTUS(), null); + } + }else{ + ++$this->age; + } + $world->setBlock($this->position, $this, update: false); } } diff --git a/src/block/CactusFlower.php b/src/block/CactusFlower.php new file mode 100644 index 000000000..b46d9c9d4 --- /dev/null +++ b/src/block/CactusFlower.php @@ -0,0 +1,46 @@ +getSide(Facing::DOWN); + return + $supportBlock->getSupportType(Facing::UP)->hasCenterSupport() || + $supportBlock->getTypeId() === BlockTypeIds::CACTUS; + } + + public function getFlameEncouragement() : int{ + return 60; + } + + public function getFlammability() : int{ + return 100; + } +} diff --git a/src/block/VanillaBlocks.php b/src/block/VanillaBlocks.php index 8569d8c1c..fe3bbc254 100644 --- a/src/block/VanillaBlocks.php +++ b/src/block/VanillaBlocks.php @@ -162,6 +162,7 @@ use function strtolower; * @method static BrownMushroomBlock BROWN_MUSHROOM_BLOCK() * @method static BuddingAmethyst BUDDING_AMETHYST() * @method static Cactus CACTUS() + * @method static CactusFlower CACTUS_FLOWER() * @method static Cake CAKE() * @method static CakeWithCandle CAKE_WITH_CANDLE() * @method static CakeWithDyedCandle CAKE_WITH_DYED_CANDLE() @@ -1378,6 +1379,7 @@ final class VanillaBlocks{ return []; } }); + self::register("cactus_flower", fn(BID $id) => new CactusFlower($id, "Cactus Flower", new Info(BreakInfo::instant()))); self::registerBlocksR13(); self::registerBlocksR14(); diff --git a/src/data/bedrock/block/convert/VanillaBlockMappings.php b/src/data/bedrock/block/convert/VanillaBlockMappings.php index b1780e8c9..fa5116bd1 100644 --- a/src/data/bedrock/block/convert/VanillaBlockMappings.php +++ b/src/data/bedrock/block/convert/VanillaBlockMappings.php @@ -459,6 +459,8 @@ final class VanillaBlockMappings{ $reg->mapSimple(Blocks::PINK_TULIP(), Ids::PINK_TULIP); $reg->mapSimple(Blocks::RED_TULIP(), Ids::RED_TULIP); $reg->mapSimple(Blocks::WHITE_TULIP(), Ids::WHITE_TULIP); + + $reg->mapSimple(Blocks::CACTUS_FLOWER(), Ids::CACTUS_FLOWER); } private static function registerColoredMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{ diff --git a/src/item/StringToItemParser.php b/src/item/StringToItemParser.php index e222fc098..976d84100 100644 --- a/src/item/StringToItemParser.php +++ b/src/item/StringToItemParser.php @@ -211,6 +211,7 @@ final class StringToItemParser extends StringToTParser{ $result->registerBlock("burning_furnace", fn() => Blocks::FURNACE()); $result->registerBlock("bush", fn() => Blocks::DEAD_BUSH()); $result->registerBlock("cactus", fn() => Blocks::CACTUS()); + $result->registerBlock("cactus_flower", fn() => Blocks::CACTUS_FLOWER()); $result->registerBlock("cake", fn() => Blocks::CAKE()); $result->registerBlock("cake_block", fn() => Blocks::CAKE()); $result->registerBlock("calcite", fn() => Blocks::CALCITE()); diff --git a/tests/phpstan/configs/actual-problems.neon b/tests/phpstan/configs/actual-problems.neon index fa513de78..d16485695 100644 --- a/tests/phpstan/configs/actual-problems.neon +++ b/tests/phpstan/configs/actual-problems.neon @@ -90,36 +90,18 @@ parameters: count: 3 path: ../../../src/block/Block.php - - - message: '#^Parameter \#1 \$x of method pocketmine\\world\\World\:\:getBlockAt\(\) expects int, float\|int given\.$#' - identifier: argument.type - count: 1 - path: ../../../src/block/Cactus.php - - message: '#^Parameter \#1 \$x of method pocketmine\\world\\World\:\:isInWorld\(\) expects int, float\|int given\.$#' identifier: argument.type count: 1 path: ../../../src/block/Cactus.php - - - message: '#^Parameter \#2 \$y of method pocketmine\\world\\World\:\:getBlockAt\(\) expects int, float\|int given\.$#' - identifier: argument.type - count: 1 - path: ../../../src/block/Cactus.php - - message: '#^Parameter \#2 \$y of method pocketmine\\world\\World\:\:isInWorld\(\) expects int, float\|int given\.$#' identifier: argument.type count: 1 path: ../../../src/block/Cactus.php - - - message: '#^Parameter \#3 \$z of method pocketmine\\world\\World\:\:getBlockAt\(\) expects int, float\|int given\.$#' - identifier: argument.type - count: 1 - path: ../../../src/block/Cactus.php - - message: '#^Parameter \#3 \$z of method pocketmine\\world\\World\:\:isInWorld\(\) expects int, float\|int given\.$#' identifier: argument.type diff --git a/tests/phpunit/block/block_factory_consistency_check.json b/tests/phpunit/block/block_factory_consistency_check.json index 356d6adfb..507b4bfdc 100644 --- a/tests/phpunit/block/block_factory_consistency_check.json +++ b/tests/phpunit/block/block_factory_consistency_check.json @@ -82,6 +82,7 @@ "BROWN_MUSHROOM_BLOCK": 11, "BUDDING_AMETHYST": 1, "CACTUS": 16, + "CACTUS_FLOWER": 1, "CAKE": 7, "CAKE_WITH_CANDLE": 2, "CAKE_WITH_DYED_CANDLE": 32,