mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-06 11:57:10 +00:00
Implemented sweet berries (#4164)
this doesn't implement the server-side logic for the "stickiness" (slowdown) because we don't have the system needed for it yet. It also doesn't have parity with vanilla on the damage.
This commit is contained in:
parent
f64ef50ce3
commit
309bed414f
@ -585,7 +585,7 @@ class BlockFactory{
|
||||
//TODO: minecraft:sticky_piston
|
||||
//TODO: minecraft:stonecutter_block
|
||||
//TODO: minecraft:structure_block
|
||||
//TODO: minecraft:sweet_berry_bush
|
||||
$this->register(new SweetBerryBush(new BID(Ids::SWEET_BERRY_BUSH, 0, ItemIds::SWEET_BERRIES), "Sweet Berry Bush", BlockBreakInfo::instant()));
|
||||
//TODO: minecraft:turtle_egg
|
||||
//endregion
|
||||
|
||||
|
161
src/block/SweetBerryBush.php
Normal file
161
src/block/SweetBerryBush.php
Normal file
@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function mt_rand;
|
||||
|
||||
class SweetBerryBush extends Flowable{
|
||||
public const STAGE_SAPLING = 0;
|
||||
public const STAGE_BUSH_NO_BERRIES = 1;
|
||||
public const STAGE_BUSH_SOME_BERRIES = 2;
|
||||
public const STAGE_MATURE = 3;
|
||||
|
||||
protected int $age = self::STAGE_SAPLING;
|
||||
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->age;
|
||||
}
|
||||
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->age = BlockDataSerializer::readBoundedInt("stage", $stateMeta, self::STAGE_SAPLING, self::STAGE_MATURE);
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b111;
|
||||
}
|
||||
|
||||
public function getAge() : int{ return $this->age; }
|
||||
|
||||
/** @return $this */
|
||||
public function setAge(int $age) : self{
|
||||
if($age < self::STAGE_SAPLING || $age > self::STAGE_MATURE){
|
||||
throw new \InvalidArgumentException("Age must be in range 0-3");
|
||||
}
|
||||
$this->age = $age;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBerryDropAmount() : int{
|
||||
if($this->age === self::STAGE_MATURE){
|
||||
return mt_rand(2, 3);
|
||||
}elseif($this->age >= self::STAGE_BUSH_SOME_BERRIES){
|
||||
return mt_rand(1, 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function canBeSupportedBy(Block $block) : bool{
|
||||
$id = $block->getId();
|
||||
return $id === BlockLegacyIds::GRASS || $id === BlockLegacyIds::DIRT || $id === BlockLegacyIds::PODZOL;
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
|
||||
return false;
|
||||
}
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($this->age < self::STAGE_MATURE && $item instanceof Fertilizer){
|
||||
$block = clone $this;
|
||||
$block->age++;
|
||||
|
||||
$ev = new BlockGrowEvent($this, $block);
|
||||
$ev->call();
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
$this->pos->getWorld()->setBlock($this->pos, $ev->getNewState());
|
||||
}
|
||||
|
||||
$item->pop();
|
||||
}elseif(($dropAmount = $this->getBerryDropAmount()) > 0){
|
||||
$this->pos->getWorld()->setBlock($this->pos, $this->setAge(self::STAGE_BUSH_NO_BERRIES));
|
||||
$this->pos->getWorld()->dropItem($this->pos, $this->asItem()->setCount($dropAmount));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return VanillaItems::SWEET_BERRIES();
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if(($dropAmount = $this->getBerryDropAmount()) > 0){
|
||||
return [
|
||||
$this->asItem()->setCount($dropAmount)
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
|
||||
$this->pos->getWorld()->useBreakOn($this->pos);
|
||||
}
|
||||
}
|
||||
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if($this->age < self::STAGE_MATURE and mt_rand(0, 2) === 1){
|
||||
$block = clone $this;
|
||||
++$block->age;
|
||||
$ev = new BlockGrowEvent($this, $block);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->pos->getWorld()->setBlock($this->pos, $ev->getNewState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function hasEntityCollision() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onEntityInside(Entity $entity) : bool{
|
||||
//TODO: in MCPE, this only triggers if moving while inside the bush block - we don't have the system to deal
|
||||
//with that reliably right now
|
||||
if($this->age >= self::STAGE_BUSH_NO_BERRIES && $entity instanceof Living){
|
||||
$entity->attack(new EntityDamageByBlockEvent($this, $entity, EntityDamageByBlockEvent::CAUSE_CONTACT, 1));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -545,6 +545,7 @@ use function assert;
|
||||
* @method static Wood STRIPPED_SPRUCE_WOOD()
|
||||
* @method static Sugarcane SUGARCANE()
|
||||
* @method static DoublePlant SUNFLOWER()
|
||||
* @method static SweetBerryBush SWEET_BERRY_BUSH()
|
||||
* @method static TallGrass TALL_GRASS()
|
||||
* @method static TNT TNT()
|
||||
* @method static Torch TORCH()
|
||||
@ -1107,6 +1108,7 @@ final class VanillaBlocks{
|
||||
self::register("stripped_spruce_wood", $factory->get(467, 9));
|
||||
self::register("sugarcane", $factory->get(83, 0));
|
||||
self::register("sunflower", $factory->get(175, 0));
|
||||
self::register("sweet_berry_bush", $factory->get(462, 0));
|
||||
self::register("tall_grass", $factory->get(31, 1));
|
||||
self::register("tnt", $factory->get(46, 0));
|
||||
self::register("torch", $factory->get(50, 5));
|
||||
|
@ -326,7 +326,7 @@ class ItemFactory{
|
||||
//TODO: minecraft:shield
|
||||
//TODO: minecraft:sparkler
|
||||
//TODO: minecraft:spawn_egg
|
||||
//TODO: minecraft:sweet_berries
|
||||
$this->register(new SweetBerries(new ItemIdentifier(ItemIds::SWEET_BERRIES, 0), "Sweet Berries"));
|
||||
//TODO: minecraft:tnt_minecart
|
||||
//TODO: minecraft:trident
|
||||
//TODO: minecraft:turtle_helmet
|
||||
|
42
src/item/SweetBerries.php
Normal file
42
src/item/SweetBerries.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\item;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\VanillaBlocks;
|
||||
|
||||
class SweetBerries extends Food{
|
||||
|
||||
public function getFoodRestore() : int{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getSaturationRestore() : float{
|
||||
return 1.2;
|
||||
}
|
||||
|
||||
public function getBlock(?int $clickedFace = null) : Block{
|
||||
return VanillaBlocks::SWEET_BERRY_BUSH();
|
||||
}
|
||||
}
|
@ -334,6 +334,7 @@ use function assert;
|
||||
* @method static Potion STRONG_TURTLE_MASTER_POTION()
|
||||
* @method static SplashPotion STRONG_TURTLE_MASTER_SPLASH_POTION()
|
||||
* @method static Item SUGAR()
|
||||
* @method static SweetBerries SWEET_BERRIES()
|
||||
* @method static Potion SWIFTNESS_POTION()
|
||||
* @method static SplashPotion SWIFTNESS_SPLASH_POTION()
|
||||
* @method static Potion THICK_POTION()
|
||||
@ -700,6 +701,7 @@ final class VanillaItems{
|
||||
self::register("strong_turtle_master_potion", $factory->get(373, 39));
|
||||
self::register("strong_turtle_master_splash_potion", $factory->get(438, 39));
|
||||
self::register("sugar", $factory->get(353));
|
||||
self::register("sweet_berries", $factory->get(477));
|
||||
self::register("swiftness_potion", $factory->get(373, 14));
|
||||
self::register("swiftness_splash_potion", $factory->get(438, 14));
|
||||
self::register("thick_potion", $factory->get(373, 3));
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user