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