mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-06 20:07:09 +00:00
Implement cauldrons (#5163)
the following things are currently not implemented: - particle/sound effects when an entity extinguishes itself - particle/sound effects when mixing different stuff in a cauldron - powder snow cauldron both of these things are contingent on #5169, but for the time being, the PR is functionally complete and I want to move on to something else without being stalled by the particle+sound problem (which I haven't yet decided how to solve).
This commit is contained in:
parent
466307a43f
commit
c1acf44337
@ -694,6 +694,11 @@ final class BlockTypeIds{
|
||||
public const SMITHING_TABLE = 10667;
|
||||
public const NETHERITE = 10668;
|
||||
public const SPORE_BLOSSOM = 10669;
|
||||
public const CAULDRON = 10670;
|
||||
public const WATER_CAULDRON = 10671;
|
||||
public const LAVA_CAULDRON = 10672;
|
||||
public const POTION_CAULDRON = 10673;
|
||||
public const POWDER_SNOW_CAULDRON = 10674;
|
||||
|
||||
public const FIRST_UNUSED_BLOCK_ID = 10670;
|
||||
public const FIRST_UNUSED_BLOCK_ID = 10675;
|
||||
}
|
||||
|
104
src/block/Cauldron.php
Normal file
104
src/block/Cauldron.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?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\tile\Cauldron as TileCauldron;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemTypeIds;
|
||||
use pocketmine\item\Potion;
|
||||
use pocketmine\item\PotionType;
|
||||
use pocketmine\item\SplashPotion;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use function assert;
|
||||
|
||||
final class Cauldron extends Transparent{
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
parent::writeStateToWorld();
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
assert($tile instanceof TileCauldron);
|
||||
|
||||
//empty cauldrons don't use this information
|
||||
$tile->setCustomWaterColor(null);
|
||||
$tile->setPotionItem(null);
|
||||
}
|
||||
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
$result = [
|
||||
AxisAlignedBB::one()->trim(Facing::UP, 11 / 16) //bottom of the cauldron
|
||||
];
|
||||
|
||||
foreach(Facing::HORIZONTAL as $f){ //add the frame parts around the bowl
|
||||
$result[] = AxisAlignedBB::one()->trim($f, 14 / 16);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return $facing === Facing::UP ? SupportType::EDGE() : SupportType::NONE();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item[] &$returnedItems
|
||||
*/
|
||||
private function fill(int $amount, FillableCauldron $result, Item $usedItem, Item $returnedItem, array &$returnedItems) : void{
|
||||
$this->position->getWorld()->setBlock($this->position, $result->setFillLevel($amount));
|
||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), $result->getFillSound());
|
||||
|
||||
$usedItem->pop();
|
||||
$returnedItems[] = $returnedItem;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item->getTypeId() === ItemTypeIds::WATER_BUCKET){
|
||||
$this->fill(FillableCauldron::MAX_FILL_LEVEL, VanillaBlocks::WATER_CAULDRON(), $item, VanillaItems::BUCKET(), $returnedItems);
|
||||
}elseif($item->getTypeId() === ItemTypeIds::LAVA_BUCKET){
|
||||
$this->fill(FillableCauldron::MAX_FILL_LEVEL, VanillaBlocks::LAVA_CAULDRON(), $item, VanillaItems::BUCKET(), $returnedItems);
|
||||
}elseif($item->getTypeId() === ItemTypeIds::POWDER_SNOW_BUCKET){
|
||||
//TODO: powder snow cauldron
|
||||
}elseif($item instanceof Potion || $item instanceof SplashPotion){ //TODO: lingering potion
|
||||
if($item->getType()->equals(PotionType::WATER())){
|
||||
$this->fill(WaterCauldron::WATER_BOTTLE_FILL_AMOUNT, VanillaBlocks::WATER_CAULDRON(), $item, VanillaItems::GLASS_BOTTLE(), $returnedItems);
|
||||
}else{
|
||||
$this->fill(PotionCauldron::POTION_FILL_AMOUNT, VanillaBlocks::POTION_CAULDRON()->setPotionItem($item), $item, VanillaItems::GLASS_BOTTLE(), $returnedItems);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$world = $this->position->getWorld();
|
||||
if($world->getBlock($this->position->up())->getTypeId() === BlockTypeIds::WATER){
|
||||
$cauldron = VanillaBlocks::WATER_CAULDRON()->setFillLevel(FillableCauldron::MAX_FILL_LEVEL);
|
||||
$world->setBlock($this->position, $cauldron);
|
||||
$world->addSound($this->position->add(0.5, 0.5, 0.5), $cauldron->getFillSound());
|
||||
}
|
||||
}
|
||||
}
|
132
src/block/FillableCauldron.php
Normal file
132
src/block/FillableCauldron.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?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\SupportType;
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\world\sound\Sound;
|
||||
use function min;
|
||||
|
||||
abstract class FillableCauldron extends Transparent{
|
||||
public const MIN_FILL_LEVEL = 1;
|
||||
public const MAX_FILL_LEVEL = 6;
|
||||
|
||||
private int $fillLevel = self::MIN_FILL_LEVEL;
|
||||
|
||||
public function getRequiredStateDataBits() : int{
|
||||
return 3;
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->boundedInt(3, self::MIN_FILL_LEVEL, self::MAX_FILL_LEVEL, $this->fillLevel);
|
||||
}
|
||||
|
||||
public function getFillLevel() : int{ return $this->fillLevel; }
|
||||
|
||||
/** @return $this */
|
||||
public function setFillLevel(int $fillLevel) : self{
|
||||
if($fillLevel < self::MIN_FILL_LEVEL || $fillLevel > self::MAX_FILL_LEVEL){
|
||||
throw new \InvalidArgumentException("Fill level must be in range " . self::MIN_FILL_LEVEL . " ... " . self::MAX_FILL_LEVEL);
|
||||
}
|
||||
$this->fillLevel = $fillLevel;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
$result = [
|
||||
AxisAlignedBB::one()->trim(Facing::UP, 11 / 16) //bottom of the cauldron
|
||||
];
|
||||
|
||||
foreach(Facing::HORIZONTAL as $f){ //add the frame parts around the bowl
|
||||
$result[] = AxisAlignedBB::one()->trim($f, 14 / 16);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return $facing === Facing::UP ? SupportType::EDGE() : SupportType::NONE();
|
||||
}
|
||||
|
||||
protected function withFillLevel(int $fillLevel) : Block{
|
||||
return $fillLevel === 0 ? VanillaBlocks::CAULDRON() : $this->setFillLevel(min(self::MAX_FILL_LEVEL, $fillLevel));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item[] &$returnedItems
|
||||
*/
|
||||
protected function addFillLevels(int $amount, Item $usedItem, Item $returnedItem, array &$returnedItems) : void{
|
||||
if($this->fillLevel >= self::MAX_FILL_LEVEL){
|
||||
return;
|
||||
}
|
||||
$this->position->getWorld()->setBlock($this->position, $this->withFillLevel($this->fillLevel + $amount));
|
||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), $this->getFillSound());
|
||||
|
||||
$usedItem->pop();
|
||||
$returnedItems[] = $returnedItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item[] &$returnedItems
|
||||
*/
|
||||
protected function removeFillLevels(int $amount, Item $usedItem, Item $returnedItem, array &$returnedItems) : void{
|
||||
if($this->fillLevel < $amount){
|
||||
return;
|
||||
}
|
||||
|
||||
$this->position->getWorld()->setBlock($this->position, $this->withFillLevel($this->fillLevel - $amount));
|
||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), $this->getEmptySound());
|
||||
|
||||
$usedItem->pop();
|
||||
$returnedItems[] = $returnedItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound played when adding levels to the cauldron liquid.
|
||||
*/
|
||||
abstract public function getFillSound() : Sound;
|
||||
|
||||
/**
|
||||
* Returns the sound played when removing levels from the cauldron liquid.
|
||||
*/
|
||||
abstract public function getEmptySound() : Sound;
|
||||
|
||||
/**
|
||||
* @param Item[] &$returnedItems
|
||||
*/
|
||||
protected function mix(Item $usedItem, Item $returnedItem, array &$returnedItems) : void{
|
||||
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::CAULDRON());
|
||||
//TODO: sounds and particles
|
||||
|
||||
$usedItem->pop();
|
||||
$returnedItems[] = $returnedItem;
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return VanillaBlocks::CAULDRON()->asItem();
|
||||
}
|
||||
}
|
88
src/block/LavaCauldron.php
Normal file
88
src/block/LavaCauldron.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?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\tile\Cauldron as TileCauldron;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\event\entity\EntityCombustByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemTypeIds;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\sound\CauldronEmptyLavaSound;
|
||||
use pocketmine\world\sound\CauldronFillLavaSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
use function assert;
|
||||
|
||||
final class LavaCauldron extends FillableCauldron{
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
parent::writeStateToWorld();
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
assert($tile instanceof TileCauldron);
|
||||
|
||||
$tile->setCustomWaterColor(null);
|
||||
$tile->setPotionItem(null);
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return 15;
|
||||
}
|
||||
|
||||
public function getFillSound() : Sound{
|
||||
return new CauldronFillLavaSound();
|
||||
}
|
||||
|
||||
public function getEmptySound() : Sound{
|
||||
return new CauldronEmptyLavaSound();
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
match($item->getTypeId()){
|
||||
ItemTypeIds::BUCKET => $this->removeFillLevels(self::MAX_FILL_LEVEL, $item, VanillaItems::LAVA_BUCKET(), $returnedItems),
|
||||
ItemTypeIds::POWDER_SNOW_BUCKET, ItemTypeIds::WATER_BUCKET => $this->mix($item, VanillaItems::BUCKET(), $returnedItems),
|
||||
ItemTypeIds::LINGERING_POTION, ItemTypeIds::POTION, ItemTypeIds::SPLASH_POTION => $this->mix($item, VanillaItems::GLASS_BOTTLE(), $returnedItems),
|
||||
default => null
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
public function hasEntityCollision() : bool{ return true; }
|
||||
|
||||
public function onEntityInside(Entity $entity) : bool{
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_LAVA, 4);
|
||||
$entity->attack($ev);
|
||||
|
||||
$ev = new EntityCombustByBlockEvent($this, $entity, 8);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->setOnFire($ev->getDuration());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
108
src/block/PotionCauldron.php
Normal file
108
src/block/PotionCauldron.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?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\tile\Cauldron as TileCauldron;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemTypeIds;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\sound\CauldronEmptyPotionSound;
|
||||
use pocketmine\world\sound\CauldronFillPotionSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
use function assert;
|
||||
|
||||
final class PotionCauldron extends FillableCauldron{
|
||||
public const POTION_FILL_AMOUNT = 2;
|
||||
|
||||
private ?Item $potionItem = null;
|
||||
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
||||
parent::__construct($idInfo, $name, $breakInfo);
|
||||
}
|
||||
|
||||
public function readStateFromWorld() : Block{
|
||||
parent::readStateFromWorld();
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
$this->potionItem = $tile instanceof TileCauldron ? $tile->getPotionItem() : null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
parent::writeStateToWorld();
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
assert($tile instanceof TileCauldron);
|
||||
$tile->setCustomWaterColor(null);
|
||||
$tile->setPotionItem($this->potionItem);
|
||||
}
|
||||
|
||||
public function getPotionItem() : ?Item{ return $this->potionItem === null ? null : clone $this->potionItem; }
|
||||
|
||||
/** @return $this */
|
||||
public function setPotionItem(?Item $potionItem) : self{
|
||||
$this->potionItem = $potionItem !== null ? (clone $potionItem)->setCount(1) : null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFillSound() : Sound{
|
||||
return new CauldronFillPotionSound();
|
||||
}
|
||||
|
||||
public function getEmptySound() : Sound{
|
||||
return new CauldronEmptyPotionSound();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item[] &$returnedItems
|
||||
*/
|
||||
protected function addFillLevelsOrMix(int $amount, Item $usedItem, Item $returnedItem, array &$returnedItems) : void{
|
||||
if($this->potionItem !== null && !$usedItem->equals($this->potionItem, true, false)){
|
||||
$this->mix($usedItem, $returnedItem, $returnedItems);
|
||||
}else{
|
||||
$this->addFillLevels($amount, $usedItem, $returnedItem, $returnedItems);
|
||||
}
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
match($item->getTypeId()){
|
||||
ItemTypeIds::LINGERING_POTION, ItemTypeIds::POTION, ItemTypeIds::SPLASH_POTION => $this->addFillLevelsOrMix(self::POTION_FILL_AMOUNT, $item, VanillaItems::GLASS_BOTTLE(), $returnedItems),
|
||||
ItemTypeIds::GLASS_BOTTLE => $this->potionItem === null ? null : $this->removeFillLevels(self::POTION_FILL_AMOUNT, $item, clone $this->potionItem, $returnedItems),
|
||||
ItemTypeIds::LAVA_BUCKET, ItemTypeIds::POWDER_SNOW_BUCKET, ItemTypeIds::WATER_BUCKET => $this->mix($item, VanillaItems::BUCKET(), $returnedItems),
|
||||
//TODO: tipped arrows
|
||||
default => null
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$world = $this->position->getWorld();
|
||||
if($world->getBlock($this->position->up())->getTypeId() === BlockTypeIds::WATER){
|
||||
$cauldron = VanillaBlocks::WATER_CAULDRON()->setFillLevel(FillableCauldron::MAX_FILL_LEVEL);
|
||||
$world->setBlock($this->position, $cauldron);
|
||||
$world->addSound($this->position->add(0.5, 0.5, 0.5), $cauldron->getFillSound());
|
||||
}
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ use pocketmine\block\tile\Bed as TileBed;
|
||||
use pocketmine\block\tile\Bell as TileBell;
|
||||
use pocketmine\block\tile\BlastFurnace as TileBlastFurnace;
|
||||
use pocketmine\block\tile\BrewingStand as TileBrewingStand;
|
||||
use pocketmine\block\tile\Cauldron as TileCauldron;
|
||||
use pocketmine\block\tile\Chest as TileChest;
|
||||
use pocketmine\block\tile\Comparator as TileComparator;
|
||||
use pocketmine\block\tile\DaylightSensor as TileDaylightSensor;
|
||||
@ -143,6 +144,7 @@ use function mb_strtolower;
|
||||
* @method static Carrot CARROTS()
|
||||
* @method static CartographyTable CARTOGRAPHY_TABLE()
|
||||
* @method static CarvedPumpkin CARVED_PUMPKIN()
|
||||
* @method static Cauldron CAULDRON()
|
||||
* @method static ChemicalHeat CHEMICAL_HEAT()
|
||||
* @method static Chest CHEST()
|
||||
* @method static Opaque CHISELED_DEEPSLATE()
|
||||
@ -453,6 +455,7 @@ use function mb_strtolower;
|
||||
* @method static LapisOre LAPIS_LAZULI_ORE()
|
||||
* @method static DoubleTallGrass LARGE_FERN()
|
||||
* @method static Lava LAVA()
|
||||
* @method static LavaCauldron LAVA_CAULDRON()
|
||||
* @method static Lectern LECTERN()
|
||||
* @method static Opaque LEGACY_STONECUTTER()
|
||||
* @method static Lever LEVER()
|
||||
@ -558,6 +561,7 @@ use function mb_strtolower;
|
||||
* @method static Stair POLISHED_GRANITE_STAIRS()
|
||||
* @method static Flower POPPY()
|
||||
* @method static Potato POTATOES()
|
||||
* @method static PotionCauldron POTION_CAULDRON()
|
||||
* @method static PoweredRail POWERED_RAIL()
|
||||
* @method static Opaque PRISMARINE()
|
||||
* @method static Opaque PRISMARINE_BRICKS()
|
||||
@ -697,6 +701,7 @@ use function mb_strtolower;
|
||||
* @method static WallSign WARPED_WALL_SIGN()
|
||||
* @method static Opaque WARPED_WART_BLOCK()
|
||||
* @method static Water WATER()
|
||||
* @method static WaterCauldron WATER_CAULDRON()
|
||||
* @method static WeightedPressurePlateHeavy WEIGHTED_PRESSURE_PLATE_HEAVY()
|
||||
* @method static WeightedPressurePlateLight WEIGHTED_PRESSURE_PLATE_LIGHT()
|
||||
* @method static Wheat WHEAT()
|
||||
@ -1166,6 +1171,7 @@ final class VanillaBlocks{
|
||||
self::registerCraftingTables();
|
||||
self::registerOres();
|
||||
self::registerWoodenBlocks();
|
||||
self::registerCauldronBlocks();
|
||||
}
|
||||
|
||||
private static function registerWoodenBlocks() : void{
|
||||
@ -1513,4 +1519,12 @@ final class VanillaBlocks{
|
||||
self::register("mud_brick_wall", new Wall(new BID(Ids::MUD_BRICK_WALL), "Mud Brick Wall", $mudBricksBreakInfo));
|
||||
}
|
||||
|
||||
private static function registerCauldronBlocks() : void{
|
||||
$cauldronBreakInfo = new BreakInfo(2, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel());
|
||||
|
||||
self::register("cauldron", new Cauldron(new BID(Ids::CAULDRON, TileCauldron::class), "Cauldron", $cauldronBreakInfo));
|
||||
self::register("water_cauldron", new WaterCauldron(new BID(Ids::WATER_CAULDRON, TileCauldron::class), "Water Cauldron", $cauldronBreakInfo));
|
||||
self::register("lava_cauldron", new LavaCauldron(new BID(Ids::LAVA_CAULDRON, TileCauldron::class), "Lava Cauldron", $cauldronBreakInfo));
|
||||
self::register("potion_cauldron", new PotionCauldron(new BID(Ids::POTION_CAULDRON, TileCauldron::class), "Potion Cauldron", $cauldronBreakInfo));
|
||||
}
|
||||
}
|
||||
|
209
src/block/WaterCauldron.php
Normal file
209
src/block/WaterCauldron.php
Normal file
@ -0,0 +1,209 @@
|
||||
<?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\tile\Cauldron as TileCauldron;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\color\Color;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\item\Armor;
|
||||
use pocketmine\item\Banner;
|
||||
use pocketmine\item\Dye;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemBlock;
|
||||
use pocketmine\item\ItemTypeIds;
|
||||
use pocketmine\item\Potion;
|
||||
use pocketmine\item\PotionType;
|
||||
use pocketmine\item\SplashPotion;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\sound\CauldronAddDyeSound;
|
||||
use pocketmine\world\sound\CauldronCleanItemSound;
|
||||
use pocketmine\world\sound\CauldronDyeItemSound;
|
||||
use pocketmine\world\sound\CauldronEmptyWaterSound;
|
||||
use pocketmine\world\sound\CauldronFillWaterSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
use function array_pop;
|
||||
use function assert;
|
||||
use function count;
|
||||
|
||||
final class WaterCauldron extends FillableCauldron{
|
||||
|
||||
public const WATER_BOTTLE_FILL_AMOUNT = 2;
|
||||
|
||||
public const DYE_ARMOR_USE_AMOUNT = 1;
|
||||
public const CLEAN_ARMOR_USE_AMOUNT = 1;
|
||||
public const CLEAN_BANNER_USE_AMOUNT = 1;
|
||||
public const CLEAN_SHULKER_BOX_USE_AMOUNT = 1;
|
||||
|
||||
//TODO: I'm not sure if this was intended to be 2 (to match java) but in Bedrock you can extinguish yourself 6 times ...
|
||||
public const ENTITY_EXTINGUISH_USE_AMOUNT = 1;
|
||||
|
||||
private ?Color $customWaterColor = null;
|
||||
|
||||
public function readStateFromWorld() : Block{
|
||||
$result = parent::readStateFromWorld();
|
||||
if($result !== $this){
|
||||
return $result;
|
||||
}
|
||||
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
|
||||
$potionItem = $tile instanceof TileCauldron ? $tile->getPotionItem() : null;
|
||||
if($potionItem !== null){
|
||||
//TODO: HACK! we keep potion cauldrons as a separate block type due to different behaviour, but in the
|
||||
//blockstate they are typically indistinguishable from water cauldrons. This hack converts cauldrons into
|
||||
//their appropriate type.
|
||||
return VanillaBlocks::POTION_CAULDRON()->setFillLevel($this->getFillLevel())->setPotionItem($potionItem);
|
||||
}
|
||||
|
||||
$this->customWaterColor = $tile instanceof TileCauldron ? $tile->getCustomWaterColor() : null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
parent::writeStateToWorld();
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
assert($tile instanceof TileCauldron);
|
||||
$tile->setCustomWaterColor($this->customWaterColor);
|
||||
$tile->setPotionItem(null);
|
||||
}
|
||||
|
||||
/** @return Color|null */
|
||||
public function getCustomWaterColor() : ?Color{ return $this->customWaterColor; }
|
||||
|
||||
/** @return $this */
|
||||
public function setCustomWaterColor(?Color $customWaterColor) : self{
|
||||
$this->customWaterColor = $customWaterColor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFillSound() : Sound{
|
||||
return new CauldronFillWaterSound();
|
||||
}
|
||||
|
||||
public function getEmptySound() : Sound{
|
||||
return new CauldronEmptyWaterSound();
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if(($newColor = match($item->getTypeId()){
|
||||
ItemTypeIds::LAPIS_LAZULI => DyeColor::BLUE()->getRgbValue(),
|
||||
ItemTypeIds::INK_SAC => DyeColor::BLACK()->getRgbValue(),
|
||||
ItemTypeIds::COCOA_BEANS => DyeColor::BROWN()->getRgbValue(),
|
||||
ItemTypeIds::BONE_MEAL => DyeColor::WHITE()->getRgbValue(),
|
||||
ItemTypeIds::DYE => $item instanceof Dye ? $item->getColor()->getRgbValue() : null,
|
||||
default => null
|
||||
}) !== null && $newColor->toRGBA() !== $this->customWaterColor?->toRGBA()
|
||||
){
|
||||
$this->position->getWorld()->setBlock($this->position, $this->setCustomWaterColor($this->customWaterColor === null ? $newColor : Color::mix($this->customWaterColor, $newColor)));
|
||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new CauldronAddDyeSound());
|
||||
|
||||
$item->pop();
|
||||
}elseif($item instanceof Potion || $item instanceof SplashPotion){ //TODO: lingering potion
|
||||
if($item->getType()->equals(PotionType::WATER())){
|
||||
$this->addFillLevels(self::WATER_BOTTLE_FILL_AMOUNT, $item, VanillaItems::GLASS_BOTTLE(), $returnedItems);
|
||||
}else{
|
||||
$this->mix($item, VanillaItems::GLASS_BOTTLE(), $returnedItems);
|
||||
}
|
||||
}elseif($item instanceof Armor){
|
||||
if($this->customWaterColor !== null){
|
||||
if(match($item->getTypeId()){ //TODO: a DyeableArmor class would probably be a better idea, since not all types of armor are dyeable
|
||||
ItemTypeIds::LEATHER_CAP,
|
||||
ItemTypeIds::LEATHER_TUNIC,
|
||||
ItemTypeIds::LEATHER_PANTS,
|
||||
ItemTypeIds::LEATHER_BOOTS => true,
|
||||
default => false
|
||||
} && $item->getCustomColor()?->toRGBA() !== $this->customWaterColor->toRGBA()){
|
||||
$item->setCustomColor($this->customWaterColor);
|
||||
$this->position->getWorld()->setBlock($this->position, $this->withFillLevel($this->getFillLevel() - self::DYE_ARMOR_USE_AMOUNT));
|
||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new CauldronDyeItemSound());
|
||||
}
|
||||
}elseif($item->getCustomColor() !== null){
|
||||
$item->clearCustomColor();
|
||||
$this->position->getWorld()->setBlock($this->position, $this->withFillLevel($this->getFillLevel() - self::CLEAN_ARMOR_USE_AMOUNT));
|
||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new CauldronCleanItemSound());
|
||||
}
|
||||
}elseif($item instanceof Banner){
|
||||
$patterns = $item->getPatterns();
|
||||
if(count($patterns) > 0 && $this->customWaterColor === null){
|
||||
array_pop($patterns);
|
||||
$item->setPatterns($patterns);
|
||||
|
||||
$this->position->getWorld()->setBlock($this->position, $this->withFillLevel($this->getFillLevel() - self::CLEAN_BANNER_USE_AMOUNT));
|
||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new CauldronCleanItemSound());
|
||||
}
|
||||
}elseif($item instanceof ItemBlock && $item->getBlock()->getTypeId() === BlockTypeIds::DYED_SHULKER_BOX){
|
||||
if($this->customWaterColor === null){
|
||||
$newItem = VanillaBlocks::SHULKER_BOX()->asItem();
|
||||
$newItem->setNamedTag($item->getNamedTag());
|
||||
|
||||
$item->pop();
|
||||
$returnedItems[] = $newItem;
|
||||
|
||||
$this->position->getWorld()->setBlock($this->position, $this->withFillLevel($this->getFillLevel() - self::CLEAN_SHULKER_BOX_USE_AMOUNT));
|
||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new CauldronCleanItemSound());
|
||||
}
|
||||
}else{
|
||||
match($item->getTypeId()){
|
||||
ItemTypeIds::WATER_BUCKET => $this->addFillLevels(self::MAX_FILL_LEVEL, $item, VanillaItems::BUCKET(), $returnedItems),
|
||||
ItemTypeIds::BUCKET => $this->removeFillLevels(self::MAX_FILL_LEVEL, $item, VanillaItems::WATER_BUCKET(), $returnedItems),
|
||||
ItemTypeIds::GLASS_BOTTLE => $this->removeFillLevels(self::WATER_BOTTLE_FILL_AMOUNT, $item, VanillaItems::POTION()->setType(PotionType::WATER()), $returnedItems),
|
||||
ItemTypeIds::LAVA_BUCKET, ItemTypeIds::POWDER_SNOW_BUCKET => $this->mix($item, VanillaItems::BUCKET(), $returnedItems),
|
||||
default => null
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function hasEntityCollision() : bool{ return true; }
|
||||
|
||||
public function onEntityInside(Entity $entity) : bool{
|
||||
if($entity->isOnFire()){
|
||||
$entity->extinguish();
|
||||
//TODO: particles
|
||||
|
||||
$this->position->getWorld()->setBlock($this->position, $this->withFillLevel($this->getFillLevel() - self::ENTITY_EXTINGUISH_USE_AMOUNT));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$hasCustomWaterColor = $this->customWaterColor !== null;
|
||||
if($this->getFillLevel() < self::MAX_FILL_LEVEL || $hasCustomWaterColor){
|
||||
$world = $this->position->getWorld();
|
||||
if($world->getBlock($this->position->up())->getTypeId() === BlockTypeIds::WATER){
|
||||
if($hasCustomWaterColor){
|
||||
//TODO: particles
|
||||
}
|
||||
$world->setBlock($this->position, $this->setCustomWaterColor(null)->setFillLevel(FillableCauldron::MAX_FILL_LEVEL));
|
||||
$world->addSound($this->position->add(0.5, 0.5, 0.5), $this->getFillSound());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
135
src/block/tile/Cauldron.php
Normal file
135
src/block/tile/Cauldron.php
Normal file
@ -0,0 +1,135 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\FillableCauldron;
|
||||
use pocketmine\color\Color;
|
||||
use pocketmine\data\bedrock\block\BlockStateNames;
|
||||
use pocketmine\data\bedrock\PotionTypeIdMap;
|
||||
use pocketmine\data\SavedDataLoadingException;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemTypeIds;
|
||||
use pocketmine\item\Potion;
|
||||
use pocketmine\item\SplashPotion;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Binary;
|
||||
|
||||
final class Cauldron extends Spawnable{
|
||||
|
||||
private const POTION_CONTAINER_TYPE_NONE = -1;
|
||||
private const POTION_CONTAINER_TYPE_NORMAL = 0;
|
||||
private const POTION_CONTAINER_TYPE_SPLASH = 1;
|
||||
private const POTION_CONTAINER_TYPE_LINGERING = 2;
|
||||
|
||||
private const POTION_ID_NONE = -1;
|
||||
|
||||
private const TAG_POTION_ID = "PotionId"; //TAG_Short
|
||||
private const TAG_POTION_CONTAINER_TYPE = "PotionType"; //TAG_Short
|
||||
private const TAG_CUSTOM_COLOR = "CustomColor"; //TAG_Int
|
||||
|
||||
private ?Item $potionItem = null;
|
||||
private ?Color $customWaterColor = null;
|
||||
|
||||
public function getPotionItem() : ?Item{ return $this->potionItem; }
|
||||
|
||||
public function setPotionItem(?Item $potionItem) : void{
|
||||
$this->potionItem = $potionItem;
|
||||
}
|
||||
|
||||
public function getCustomWaterColor() : ?Color{ return $this->customWaterColor; }
|
||||
|
||||
public function setCustomWaterColor(?Color $customWaterColor) : void{
|
||||
$this->customWaterColor = $customWaterColor;
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
$nbt->setShort(self::TAG_POTION_CONTAINER_TYPE, match($this->potionItem?->getTypeId()){
|
||||
ItemTypeIds::POTION => self::POTION_CONTAINER_TYPE_NORMAL,
|
||||
ItemTypeIds::SPLASH_POTION => self::POTION_CONTAINER_TYPE_SPLASH,
|
||||
ItemTypeIds::LINGERING_POTION => self::POTION_CONTAINER_TYPE_LINGERING,
|
||||
null => self::POTION_CONTAINER_TYPE_NONE,
|
||||
default => throw new AssumptionFailedError("Unexpected potion item type")
|
||||
});
|
||||
|
||||
//TODO: lingering potion
|
||||
$type = $this->potionItem instanceof Potion || $this->potionItem instanceof SplashPotion ? $this->potionItem->getType() : null;
|
||||
$nbt->setShort(self::TAG_POTION_ID, $type === null ? self::POTION_ID_NONE : PotionTypeIdMap::getInstance()->toId($type));
|
||||
|
||||
if($this->customWaterColor !== null){
|
||||
$nbt->setInt(self::TAG_CUSTOM_COLOR, Binary::signInt($this->customWaterColor->toARGB()));
|
||||
}
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
$containerType = $nbt->getShort(self::TAG_POTION_CONTAINER_TYPE, self::POTION_CONTAINER_TYPE_NONE);
|
||||
$potionId = $nbt->getShort(self::TAG_POTION_ID, self::POTION_ID_NONE);
|
||||
if($containerType !== self::POTION_CONTAINER_TYPE_NONE && $potionId !== self::POTION_ID_NONE){
|
||||
$potionType = PotionTypeIdMap::getInstance()->fromId($potionId);
|
||||
if($potionType === null){
|
||||
throw new SavedDataLoadingException("Unknown potion type ID $potionId");
|
||||
}
|
||||
$this->potionItem = match($containerType){
|
||||
self::POTION_CONTAINER_TYPE_NORMAL => VanillaItems::POTION()->setType($potionType),
|
||||
self::POTION_CONTAINER_TYPE_SPLASH => VanillaItems::SPLASH_POTION()->setType($potionType),
|
||||
self::POTION_CONTAINER_TYPE_LINGERING => throw new SavedDataLoadingException("Not implemented"),
|
||||
default => throw new SavedDataLoadingException("Invalid potion container type ID $containerType")
|
||||
};
|
||||
}else{
|
||||
$this->potionItem = null;
|
||||
}
|
||||
|
||||
$this->customWaterColor = ($customColorTag = $nbt->getTag(self::TAG_CUSTOM_COLOR)) instanceof IntTag ? Color::fromARGB(Binary::unsignInt($customColorTag->getValue())) : null;
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setShort(self::TAG_POTION_CONTAINER_TYPE, match($this->potionItem?->getTypeId()){
|
||||
ItemTypeIds::POTION => self::POTION_CONTAINER_TYPE_NORMAL,
|
||||
ItemTypeIds::SPLASH_POTION => self::POTION_CONTAINER_TYPE_SPLASH,
|
||||
ItemTypeIds::LINGERING_POTION => self::POTION_CONTAINER_TYPE_LINGERING,
|
||||
null => self::POTION_CONTAINER_TYPE_NONE,
|
||||
default => throw new AssumptionFailedError("Unexpected potion item type")
|
||||
});
|
||||
|
||||
//TODO: lingering potion
|
||||
$type = $this->potionItem instanceof Potion || $this->potionItem instanceof SplashPotion ? $this->potionItem->getType() : null;
|
||||
$nbt->setShort(self::TAG_POTION_ID, $type === null ? self::POTION_ID_NONE : PotionTypeIdMap::getInstance()->toId($type));
|
||||
|
||||
if($this->customWaterColor !== null){
|
||||
$nbt->setInt(self::TAG_CUSTOM_COLOR, Binary::signInt($this->customWaterColor->toARGB()));
|
||||
}
|
||||
}
|
||||
|
||||
public function getRenderUpdateBugWorkaroundStateProperties(Block $block) : array{
|
||||
if($block instanceof FillableCauldron){
|
||||
$realFillLevel = $block->getFillLevel();
|
||||
return [BlockStateNames::FILL_LEVEL => new IntTag($realFillLevel === FillableCauldron::MAX_FILL_LEVEL ? FillableCauldron::MIN_FILL_LEVEL : $realFillLevel + 1)];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -57,6 +57,7 @@ final class TileFactory{
|
||||
$this->register(Bell::class, ["Bell", "minecraft:bell"]);
|
||||
$this->register(BlastFurnace::class, ["BlastFurnace", "minecraft:blast_furnace"]);
|
||||
$this->register(BrewingStand::class, ["BrewingStand", "minecraft:brewing_stand"]);
|
||||
$this->register(Cauldron::class, ["Cauldron", "minecraft:cauldron"]);
|
||||
$this->register(Chest::class, ["Chest", "minecraft:chest"]);
|
||||
$this->register(Comparator::class, ["Comparator", "minecraft:comparator"]);
|
||||
$this->register(DaylightSensor::class, ["DaylightDetector", "minecraft:daylight_detector"]);
|
||||
|
@ -68,6 +68,7 @@ use pocketmine\block\EndPortalFrame;
|
||||
use pocketmine\block\EndRod;
|
||||
use pocketmine\block\Farmland;
|
||||
use pocketmine\block\FenceGate;
|
||||
use pocketmine\block\FillableCauldron;
|
||||
use pocketmine\block\Fire;
|
||||
use pocketmine\block\FloorBanner;
|
||||
use pocketmine\block\FloorCoralFan;
|
||||
@ -176,6 +177,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
|
||||
|
||||
public function __construct(){
|
||||
$this->registerCandleSerializers();
|
||||
$this->registerCauldronSerializers();
|
||||
$this->registerSimpleSerializers();
|
||||
$this->registerSerializers();
|
||||
}
|
||||
@ -292,6 +294,14 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
|
||||
})->writeBool(StateNames::LIT, $block->isLit()));
|
||||
}
|
||||
|
||||
private function registerCauldronSerializers() : void{
|
||||
$this->map(Blocks::CAULDRON(), fn() => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_WATER, 0, new Writer(Ids::CAULDRON)));
|
||||
$this->map(Blocks::LAVA_CAULDRON(), fn(FillableCauldron $b) => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_LAVA, $b->getFillLevel(), new Writer(Ids::LAVA_CAULDRON)));
|
||||
//potion cauldrons store their real information in the block actor data
|
||||
$this->map(Blocks::POTION_CAULDRON(), fn(FillableCauldron $b) => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_WATER, $b->getFillLevel(), new Writer(Ids::CAULDRON)));
|
||||
$this->map(Blocks::WATER_CAULDRON(), fn(FillableCauldron $b) => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_WATER, $b->getFillLevel(), new Writer(Ids::CAULDRON)));
|
||||
}
|
||||
|
||||
private function registerSimpleSerializers() : void{
|
||||
$this->mapSimple(Blocks::AIR(), Ids::AIR);
|
||||
$this->mapSimple(Blocks::AMETHYST(), Ids::AMETHYST_BLOCK);
|
||||
|
@ -91,6 +91,12 @@ final class BlockStateSerializerHelper{
|
||||
->writeTorchFacing($block->getFacing());
|
||||
}
|
||||
|
||||
public static function encodeCauldron(string $liquid, int $fillLevel, BlockStateWriter $out) : BlockStateWriter{
|
||||
return $out
|
||||
->writeString(BlockStateNames::CAULDRON_LIQUID, $liquid)
|
||||
->writeInt(BlockStateNames::FILL_LEVEL, $fillLevel);
|
||||
}
|
||||
|
||||
public static function selectCopperId(CopperOxidation $oxidation, string $noneId, string $exposedId, string $weatheredId, string $oxidizedId) : string{
|
||||
return match($oxidation){
|
||||
CopperOxidation::NONE() => $noneId,
|
||||
|
@ -60,6 +60,7 @@ final class BlockStateToBlockObjectDeserializer implements BlockStateDeserialize
|
||||
|
||||
public function __construct(){
|
||||
$this->registerCandleDeserializers();
|
||||
$this->registerCauldronDeserializers();
|
||||
$this->registerSimpleDeserializers();
|
||||
$this->registerDeserializers();
|
||||
}
|
||||
@ -136,6 +137,25 @@ final class BlockStateToBlockObjectDeserializer implements BlockStateDeserialize
|
||||
$this->map(Ids::YELLOW_CANDLE_CAKE, $cakeWithDyedCandleDeserializer(DyeColor::YELLOW()));
|
||||
}
|
||||
|
||||
private function registerCauldronDeserializers() : void{
|
||||
$deserializer = function(Reader $in) : Block{
|
||||
$level = $in->readBoundedInt(StateNames::FILL_LEVEL, 0, 6);
|
||||
if($level === 0){
|
||||
$in->ignored(StateNames::CAULDRON_LIQUID);
|
||||
return Blocks::CAULDRON();
|
||||
}
|
||||
|
||||
return (match($liquid = $in->readString(StateNames::CAULDRON_LIQUID)){
|
||||
StringValues::CAULDRON_LIQUID_WATER => Blocks::WATER_CAULDRON(),
|
||||
StringValues::CAULDRON_LIQUID_LAVA => Blocks::LAVA_CAULDRON(),
|
||||
StringValues::CAULDRON_LIQUID_POWDER_SNOW => throw new UnsupportedBlockStateException("Powder snow is not supported yet"),
|
||||
default => throw $in->badValueException(StateNames::CAULDRON_LIQUID, $liquid)
|
||||
})->setFillLevel($level);
|
||||
};
|
||||
$this->map(Ids::CAULDRON, $deserializer);
|
||||
$this->map(Ids::LAVA_CAULDRON, $deserializer);
|
||||
}
|
||||
|
||||
private function registerSimpleDeserializers() : void{
|
||||
$this->map(Ids::AIR, fn() => Blocks::AIR());
|
||||
$this->map(Ids::AMETHYST_BLOCK, fn() => Blocks::AMETHYST());
|
||||
|
@ -198,7 +198,7 @@ final class ItemDeserializer{
|
||||
$this->map(Ids::CARROT, fn() => Items::CARROT());
|
||||
//TODO: minecraft:carrot_on_a_stick
|
||||
//TODO: minecraft:cat_spawn_egg
|
||||
//TODO: minecraft:cauldron
|
||||
$this->map(Ids::CAULDRON, fn() => Blocks::CAULDRON()->asItem());
|
||||
//TODO: minecraft:cave_spider_spawn_egg
|
||||
//TODO: minecraft:chain
|
||||
$this->map(Ids::CHAINMAIL_BOOTS, fn() => Items::CHAINMAIL_BOOTS());
|
||||
|
@ -229,6 +229,7 @@ final class ItemSerializer{
|
||||
$this->mapBlock(Blocks::BIRCH_DOOR(), self::id(Ids::BIRCH_DOOR));
|
||||
$this->mapBlock(Blocks::BREWING_STAND(), self::id(Ids::BREWING_STAND));
|
||||
$this->mapBlock(Blocks::CAKE(), self::id(Ids::CAKE));
|
||||
$this->mapBlock(Blocks::CAULDRON(), self::id(Ids::CAULDRON));
|
||||
$this->mapBlock(Blocks::CRIMSON_DOOR(), self::id(Ids::CRIMSON_DOOR));
|
||||
$this->mapBlock(Blocks::DARK_OAK_DOOR(), self::id(Ids::DARK_OAK_DOOR));
|
||||
$this->mapBlock(Blocks::FLOWER_POT(), self::id(Ids::FLOWER_POT));
|
||||
|
@ -294,6 +294,8 @@ final class ItemTypeIds{
|
||||
public const RAW_GOLD = 20255;
|
||||
public const SPYGLASS = 20256;
|
||||
public const NETHERITE_SCRAP = 20257;
|
||||
public const POWDER_SNOW_BUCKET = 20258;
|
||||
public const LINGERING_POTION = 20259;
|
||||
|
||||
public const FIRST_UNUSED_ITEM_ID = 20258;
|
||||
public const FIRST_UNUSED_ITEM_ID = 20260;
|
||||
}
|
||||
|
@ -197,6 +197,7 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->registerBlock("carrot_block", fn() => Blocks::CARROTS());
|
||||
$result->registerBlock("carrots", fn() => Blocks::CARROTS());
|
||||
$result->registerBlock("carved_pumpkin", fn() => Blocks::CARVED_PUMPKIN());
|
||||
$result->registerBlock("cauldron", fn() => Blocks::CAULDRON());
|
||||
$result->registerBlock("chemical_heat", fn() => Blocks::CHEMICAL_HEAT());
|
||||
$result->registerBlock("chemistry_table", fn() => Blocks::COMPOUND_CREATOR());
|
||||
$result->registerBlock("chest", fn() => Blocks::CHEST());
|
||||
|
35
src/world/sound/CauldronAddDyeSound.php
Normal file
35
src/world/sound/CauldronAddDyeSound.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\world\sound;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||
|
||||
final class CauldronAddDyeSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelEventPacket::create(LevelEvent::CAULDRON_ADD_DYE, 0, $pos)];
|
||||
}
|
||||
}
|
35
src/world/sound/CauldronCleanItemSound.php
Normal file
35
src/world/sound/CauldronCleanItemSound.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\world\sound;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||
|
||||
final class CauldronCleanItemSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelEventPacket::create(LevelEvent::CAULDRON_CLEAN_ARMOR, 0, $pos)];
|
||||
}
|
||||
}
|
35
src/world/sound/CauldronDyeItemSound.php
Normal file
35
src/world/sound/CauldronDyeItemSound.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\world\sound;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||
|
||||
final class CauldronDyeItemSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelEventPacket::create(LevelEvent::CAULDRON_DYE_ARMOR, 0, $pos)];
|
||||
}
|
||||
}
|
35
src/world/sound/CauldronEmptyLavaSound.php
Normal file
35
src/world/sound/CauldronEmptyLavaSound.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\world\sound;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||
|
||||
final class CauldronEmptyLavaSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelEventPacket::create(LevelEvent::SOUND_CAULDRON_TAKE_LAVA, 0, $pos)];
|
||||
}
|
||||
}
|
35
src/world/sound/CauldronEmptyPotionSound.php
Normal file
35
src/world/sound/CauldronEmptyPotionSound.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\world\sound;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||
|
||||
final class CauldronEmptyPotionSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelEventPacket::create(LevelEvent::CAULDRON_TAKE_POTION, 0, $pos)];
|
||||
}
|
||||
}
|
35
src/world/sound/CauldronEmptyPowderSnowSound.php
Normal file
35
src/world/sound/CauldronEmptyPowderSnowSound.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\world\sound;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||
|
||||
final class CauldronEmptyPowderSnowSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelEventPacket::create(LevelEvent::SOUND_CAULDRON_TAKE_POWDER_SNOW, 0, $pos)];
|
||||
}
|
||||
}
|
35
src/world/sound/CauldronEmptyWaterSound.php
Normal file
35
src/world/sound/CauldronEmptyWaterSound.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\world\sound;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||
|
||||
final class CauldronEmptyWaterSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelEventPacket::create(LevelEvent::CAULDRON_TAKE_WATER, 0, $pos)];
|
||||
}
|
||||
}
|
35
src/world/sound/CauldronFillLavaSound.php
Normal file
35
src/world/sound/CauldronFillLavaSound.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\world\sound;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||
|
||||
final class CauldronFillLavaSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelEventPacket::create(LevelEvent::SOUND_CAULDRON_FILL_LAVA, 0, $pos)];
|
||||
}
|
||||
}
|
35
src/world/sound/CauldronFillPotionSound.php
Normal file
35
src/world/sound/CauldronFillPotionSound.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\world\sound;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||
|
||||
final class CauldronFillPotionSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelEventPacket::create(LevelEvent::CAULDRON_FILL_POTION, 0, $pos)];
|
||||
}
|
||||
}
|
35
src/world/sound/CauldronFillPowderSnowSound.php
Normal file
35
src/world/sound/CauldronFillPowderSnowSound.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\world\sound;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||
|
||||
final class CauldronFillPowderSnowSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelEventPacket::create(LevelEvent::SOUND_CAULDRON_FILL_POWDER_SNOW, 0, $pos)];
|
||||
}
|
||||
}
|
35
src/world/sound/CauldronFillWaterSound.php
Normal file
35
src/world/sound/CauldronFillWaterSound.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\world\sound;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelEvent;
|
||||
|
||||
final class CauldronFillWaterSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelEventPacket::create(LevelEvent::CAULDRON_FILL_WATER, 0, $pos)];
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -27,6 +27,7 @@ use PHPUnit\Framework\TestCase;
|
||||
use pocketmine\block\BaseBanner;
|
||||
use pocketmine\block\Bed;
|
||||
use pocketmine\block\BlockFactory;
|
||||
use pocketmine\block\BlockTypeIds;
|
||||
use pocketmine\block\Skull;
|
||||
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
|
||||
use pocketmine\data\bedrock\block\BlockStateSerializeException;
|
||||
@ -54,6 +55,11 @@ final class BlockSerializerDeserializerTest extends TestCase{
|
||||
self::fail($e->getMessage());
|
||||
}
|
||||
|
||||
if($block->getTypeId() === BlockTypeIds::POTION_CAULDRON){
|
||||
//this pretends to be a water cauldron in the blockstate, and stores its actual data in the blockentity
|
||||
continue;
|
||||
}
|
||||
|
||||
//The following are workarounds for differences in blockstate representation in Bedrock vs PM
|
||||
//In these cases, some properties are not stored in the blockstate (but rather in the block entity NBT), but
|
||||
//they do form part of the internal blockstate hash in PM. This leads to inconsistencies when serializing
|
||||
|
Loading…
x
Reference in New Issue
Block a user