PocketMine-MP 5.33.2 git-919492bdcad8510eb6606439eb77e1c604f1d1ea
Loading...
Searching...
No Matches
WaterCauldron.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\block;
25
26use pocketmine\block\tile\Cauldron as TileCauldron;
27use pocketmine\block\utils\DyeColor;
49use function array_pop;
50use function assert;
51use function count;
52
53final class WaterCauldron extends FillableCauldron{
54
55 public const WATER_BOTTLE_FILL_AMOUNT = 2;
56
57 public const DYE_ARMOR_USE_AMOUNT = 1;
58 public const CLEAN_ARMOR_USE_AMOUNT = 1;
59 public const CLEAN_BANNER_USE_AMOUNT = 1;
60 public const CLEAN_SHULKER_BOX_USE_AMOUNT = 1;
61
62 //TODO: I'm not sure if this was intended to be 2 (to match java) but in Bedrock you can extinguish yourself 6 times ...
63 public const ENTITY_EXTINGUISH_USE_AMOUNT = 1;
64
65 private ?Color $customWaterColor = null;
66
67 public function readStateFromWorld() : Block{
68 $result = parent::readStateFromWorld();
69 if($result !== $this){
70 return $result;
71 }
72
73 $tile = $this->position->getWorld()->getTile($this->position);
74
75 $potionItem = $tile instanceof TileCauldron ? $tile->getPotionItem() : null;
76 if($potionItem !== null){
77 //TODO: HACK! we keep potion cauldrons as a separate block type due to different behaviour, but in the
78 //blockstate they are typically indistinguishable from water cauldrons. This hack converts cauldrons into
79 //their appropriate type.
80 return VanillaBlocks::POTION_CAULDRON()->setFillLevel($this->getFillLevel())->setPotionItem($potionItem);
81 }
82
83 $this->customWaterColor = $tile instanceof TileCauldron ? $tile->getCustomWaterColor() : null;
84
85 return $this;
86 }
87
88 public function writeStateToWorld() : void{
89 parent::writeStateToWorld();
90 $tile = $this->position->getWorld()->getTile($this->position);
91 assert($tile instanceof TileCauldron);
92 $tile->setCustomWaterColor($this->customWaterColor);
93 $tile->setPotionItem(null);
94 }
95
96 public function getCustomWaterColor() : ?Color{ return $this->customWaterColor; }
97
99 public function setCustomWaterColor(?Color $customWaterColor) : self{
100 $this->customWaterColor = $customWaterColor;
101 return $this;
102 }
103
104 public function getFillSound() : Sound{
105 return new CauldronFillWaterSound();
106 }
107
108 public function getEmptySound() : Sound{
109 return new CauldronEmptyWaterSound();
110 }
111
112 public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
113 $world = $this->position->getWorld();
114 if(($dyeColor = match($item->getTypeId()){
115 ItemTypeIds::LAPIS_LAZULI => DyeColor::BLUE,
116 ItemTypeIds::INK_SAC => DyeColor::BLACK,
117 ItemTypeIds::COCOA_BEANS => DyeColor::BROWN,
118 ItemTypeIds::BONE_MEAL => DyeColor::WHITE,
119 ItemTypeIds::DYE => $item instanceof Dye ? $item->getColor() : null,
120 default => null
121 }) !== null && ($newColor = $dyeColor->getRgbValue())->toRGBA() !== $this->customWaterColor?->toRGBA()
122 ){
123 $world->setBlock($this->position, $this->setCustomWaterColor($this->customWaterColor === null ? $newColor : Color::mix($this->customWaterColor, $newColor)));
124 $world->addSound($this->position->add(0.5, 0.5, 0.5), new CauldronAddDyeSound());
125
126 $item->pop();
127 }elseif($item instanceof Potion || $item instanceof SplashPotion){ //TODO: lingering potion
128 if($item->getType() === PotionType::WATER){
129 $this->setCustomWaterColor(null)->addFillLevels(self::WATER_BOTTLE_FILL_AMOUNT, $item, VanillaItems::GLASS_BOTTLE(), $returnedItems);
130 }else{
131 $this->mix($item, VanillaItems::GLASS_BOTTLE(), $returnedItems);
132 }
133 }elseif($item instanceof Armor){
134 if($this->customWaterColor !== null){
135 if(match($item->getTypeId()){ //TODO: a DyeableArmor class would probably be a better idea, since not all types of armor are dyeable
136 ItemTypeIds::LEATHER_CAP,
137 ItemTypeIds::LEATHER_TUNIC,
138 ItemTypeIds::LEATHER_PANTS,
139 ItemTypeIds::LEATHER_BOOTS => true,
140 default => false
141 } && $item->getCustomColor()?->toRGBA() !== $this->customWaterColor->toRGBA()){
142 $item->setCustomColor($this->customWaterColor);
143 $world->setBlock($this->position, $this->withFillLevel($this->getFillLevel() - self::DYE_ARMOR_USE_AMOUNT));
144 $world->addSound($this->position->add(0.5, 0.5, 0.5), new CauldronDyeItemSound());
145 }
146 }elseif($item->getCustomColor() !== null){
147 $item->clearCustomColor();
148 $world->setBlock($this->position, $this->withFillLevel($this->getFillLevel() - self::CLEAN_ARMOR_USE_AMOUNT));
149 $world->addSound($this->position->add(0.5, 0.5, 0.5), new CauldronCleanItemSound());
150 }
151 }elseif($item instanceof Banner){
152 $patterns = $item->getPatterns();
153 if(count($patterns) > 0 && $this->customWaterColor === null){
154 array_pop($patterns);
155 $item->setPatterns($patterns);
156
157 $world->setBlock($this->position, $this->withFillLevel($this->getFillLevel() - self::CLEAN_BANNER_USE_AMOUNT));
158 $world->addSound($this->position->add(0.5, 0.5, 0.5), new CauldronCleanItemSound());
159 }
160 }elseif(ItemTypeIds::toBlockTypeId($item->getTypeId()) === BlockTypeIds::DYED_SHULKER_BOX){
161 if($this->customWaterColor === null){
162 $newItem = VanillaBlocks::SHULKER_BOX()->asItem();
163 $newItem->setNamedTag($item->getNamedTag());
164
165 $item->pop();
166 $returnedItems[] = $newItem;
167
168 $world->setBlock($this->position, $this->withFillLevel($this->getFillLevel() - self::CLEAN_SHULKER_BOX_USE_AMOUNT));
169 $world->addSound($this->position->add(0.5, 0.5, 0.5), new CauldronCleanItemSound());
170 }
171 }else{
172 match($item->getTypeId()){
173 ItemTypeIds::WATER_BUCKET => $this->setCustomWaterColor(null)->addFillLevels(self::MAX_FILL_LEVEL, $item, VanillaItems::BUCKET(), $returnedItems),
174 ItemTypeIds::BUCKET => $this->removeFillLevels(self::MAX_FILL_LEVEL, $item, VanillaItems::WATER_BUCKET(), $returnedItems),
175 ItemTypeIds::GLASS_BOTTLE => $this->removeFillLevels(self::WATER_BOTTLE_FILL_AMOUNT, $item, VanillaItems::POTION()->setType(PotionType::WATER), $returnedItems),
176 ItemTypeIds::LAVA_BUCKET, ItemTypeIds::POWDER_SNOW_BUCKET => $this->mix($item, VanillaItems::BUCKET(), $returnedItems),
177 default => null
178 };
179 }
180
181 return true;
182 }
183
184 public function hasEntityCollision() : bool{ return true; }
185
186 public function onEntityInside(Entity $entity) : bool{
187 if($entity->isOnFire()){
188 $entity->extinguish(EntityExtinguishEvent::CAUSE_WATER_CAULDRON);
189 //TODO: particles
190
191 $this->position->getWorld()->setBlock($this->position, $this->withFillLevel($this->getFillLevel() - self::ENTITY_EXTINGUISH_USE_AMOUNT));
192 }
193
194 return true;
195 }
196
197 public function onNearbyBlockChange() : void{
198 $hasCustomWaterColor = $this->customWaterColor !== null;
199 if($this->getFillLevel() < self::MAX_FILL_LEVEL || $hasCustomWaterColor){
200 $world = $this->position->getWorld();
201 if($world->getBlock($this->position->up())->getTypeId() === BlockTypeIds::WATER){
202 if($hasCustomWaterColor){
203 //TODO: particles
204 }
205 $world->setBlock($this->position, $this->setCustomWaterColor(null)->setFillLevel(FillableCauldron::MAX_FILL_LEVEL));
206 $world->addSound($this->position->add(0.5, 0.5, 0.5), $this->getFillSound());
207 }
208 }
209 }
210}
setCustomWaterColor(?Color $customWaterColor)
onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player=null, array &$returnedItems=[])
pop(int $count=1)
Definition Item.php:435