PocketMine-MP/src/block/tile/Cauldron.php
Dylan T c1acf44337
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).
2022-07-20 16:12:58 +01:00

136 lines
5.4 KiB
PHP

<?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 [];
}
}