mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 00:33:59 +00:00
feat: Implement Brewing (#4413)
The following API constants have been added: - tile\BrewingStand::BREW_TIME_TICKS The following public API methods have been added: - utils\BrewingStandSlot->getSlotNumber() : int - CraftingManager->getPotionTypeRecipes() : array<string, array<string, PotionTypeRecipe>> - CraftingManager->getPotionContainerChangeRecipes() : array<int, array<string, PotionContainerChangeRecipe>> - CraftingManager->registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void - CraftingManager->registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void The following classes have been added: - BrewingRecipe - PotionTypeRecipe - PotionContainerChangeRecipe - BrewItemEvent - BrewingFuelUseEvent - PotionFinishBrewingSound
This commit is contained in:
parent
b2630a0920
commit
e0da99a973
@ -125,6 +125,24 @@ class BrewingStand extends Transparent{
|
||||
}
|
||||
|
||||
public function onScheduledUpdate() : void{
|
||||
//TODO
|
||||
$brewing = $this->position->getWorld()->getTile($this->position);
|
||||
if($brewing instanceof TileBrewingStand){
|
||||
if($brewing->onUpdate()){
|
||||
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1);
|
||||
}
|
||||
|
||||
$changed = false;
|
||||
foreach(BrewingStandSlot::getAll() as $slot){
|
||||
$occupied = !$brewing->getInventory()->isSlotEmpty($slot->getSlotNumber());
|
||||
if($occupied !== $this->hasSlot($slot)){
|
||||
$this->setSlot($slot, $occupied);
|
||||
$changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if($changed){
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,16 +24,29 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block\tile;
|
||||
|
||||
use pocketmine\block\inventory\BrewingStandInventory;
|
||||
use pocketmine\crafting\BrewingRecipe;
|
||||
use pocketmine\event\block\BrewingFuelUseEvent;
|
||||
use pocketmine\event\block\BrewItemEvent;
|
||||
use pocketmine\inventory\CallbackInventoryListener;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\network\mcpe\protocol\ContainerSetDataPacket;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\sound\PotionFinishBrewingSound;
|
||||
use pocketmine\world\World;
|
||||
use function array_map;
|
||||
use function count;
|
||||
|
||||
class BrewingStand extends Spawnable implements Container, Nameable{
|
||||
|
||||
use NameableTrait {
|
||||
addAdditionalSpawnData as addNameSpawnData;
|
||||
}
|
||||
use ContainerTrait;
|
||||
use NameableTrait;
|
||||
|
||||
public const BREW_TIME_TICKS = 400; // Brew time in ticks
|
||||
|
||||
private const TAG_BREW_TIME = "BrewTime"; //TAG_Short
|
||||
private const TAG_BREW_TIME_PE = "CookTime"; //TAG_Short
|
||||
@ -41,15 +54,11 @@ class BrewingStand extends Spawnable implements Container, Nameable{
|
||||
private const TAG_REMAINING_FUEL_TIME = "Fuel"; //TAG_Byte
|
||||
private const TAG_REMAINING_FUEL_TIME_PE = "FuelAmount"; //TAG_Short
|
||||
|
||||
/** @var BrewingStandInventory */
|
||||
private $inventory;
|
||||
private BrewingStandInventory $inventory;
|
||||
|
||||
/** @var int */
|
||||
private $brewTime = 0;
|
||||
/** @var int */
|
||||
private $maxFuelTime = 0;
|
||||
/** @var int */
|
||||
private $remainingFuelTime = 0;
|
||||
private int $brewTime = 0;
|
||||
private int $maxFuelTime = 0;
|
||||
private int $remainingFuelTime = 0;
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
parent::__construct($world, $pos);
|
||||
@ -83,6 +92,14 @@ class BrewingStand extends Spawnable implements Container, Nameable{
|
||||
$nbt->setShort(self::TAG_REMAINING_FUEL_TIME_PE, $this->remainingFuelTime);
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
$this->addNameSpawnData($nbt);
|
||||
|
||||
$nbt->setShort(self::TAG_BREW_TIME_PE, $this->brewTime);
|
||||
$nbt->setShort(self::TAG_MAX_FUEL_TIME, $this->maxFuelTime);
|
||||
$nbt->setShort(self::TAG_REMAINING_FUEL_TIME_PE, $this->remainingFuelTime);
|
||||
}
|
||||
|
||||
public function getDefaultName() : string{
|
||||
return "Brewing Stand";
|
||||
}
|
||||
@ -108,4 +125,135 @@ class BrewingStand extends Spawnable implements Container, Nameable{
|
||||
public function getRealInventory(){
|
||||
return $this->inventory;
|
||||
}
|
||||
|
||||
private function checkFuel(Item $item) : void{
|
||||
$ev = new BrewingFuelUseEvent($this);
|
||||
if(!$item->equals(VanillaItems::BLAZE_POWDER(), true, false)){
|
||||
$ev->cancel();
|
||||
}
|
||||
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
return;
|
||||
}
|
||||
|
||||
$item->pop();
|
||||
$this->inventory->setItem(BrewingStandInventory::SLOT_FUEL, $item);
|
||||
|
||||
$this->maxFuelTime = $this->remainingFuelTime = $ev->getFuelTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BrewingRecipe[]
|
||||
* @phpstan-return array<int, BrewingRecipe>
|
||||
*/
|
||||
private function getBrewableRecipes() : array{
|
||||
if($this->inventory->getItem(BrewingStandInventory::SLOT_INGREDIENT)->isNull()){
|
||||
return [];
|
||||
}
|
||||
|
||||
$recipes = [];
|
||||
foreach([BrewingStandInventory::SLOT_BOTTLE_LEFT, BrewingStandInventory::SLOT_BOTTLE_MIDDLE, BrewingStandInventory::SLOT_BOTTLE_RIGHT] as $slot){
|
||||
$input = $this->inventory->getItem($slot);
|
||||
if($input->isNull()){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(($recipe = $this->position->getWorld()->getServer()->getCraftingManager()->matchBrewingRecipe($input, $this->inventory->getItem(BrewingStandInventory::SLOT_INGREDIENT))) !== null){
|
||||
$recipes[$slot] = $recipe;
|
||||
}
|
||||
}
|
||||
|
||||
return $recipes;
|
||||
}
|
||||
|
||||
public function onUpdate() : bool{
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
$prevBrewTime = $this->brewTime;
|
||||
$prevRemainingFuelTime = $this->remainingFuelTime;
|
||||
$prevMaxFuelTime = $this->maxFuelTime;
|
||||
|
||||
$ret = false;
|
||||
|
||||
$fuel = $this->inventory->getItem(BrewingStandInventory::SLOT_FUEL);
|
||||
$ingredient = $this->inventory->getItem(BrewingStandInventory::SLOT_INGREDIENT);
|
||||
|
||||
$recipes = $this->getBrewableRecipes();
|
||||
$canBrew = count($recipes) !== 0;
|
||||
|
||||
if($this->remainingFuelTime <= 0 && $canBrew){
|
||||
$this->checkFuel($fuel);
|
||||
}
|
||||
|
||||
if($this->remainingFuelTime > 0){
|
||||
if($canBrew){
|
||||
if($this->brewTime === 0){
|
||||
$this->brewTime = self::BREW_TIME_TICKS;
|
||||
--$this->remainingFuelTime;
|
||||
}
|
||||
|
||||
--$this->brewTime;
|
||||
|
||||
if($this->brewTime <= 0){
|
||||
$anythingBrewed = false;
|
||||
foreach($recipes as $slot => $recipe){
|
||||
$input = $this->inventory->getItem($slot);
|
||||
$output = $recipe->getResultFor($input);
|
||||
if($output === null){
|
||||
continue;
|
||||
}
|
||||
|
||||
$ev = new BrewItemEvent($this, $slot, $input, $output, $recipe);
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->inventory->setItem($slot, $ev->getResult());
|
||||
$anythingBrewed = true;
|
||||
}
|
||||
|
||||
if($anythingBrewed){
|
||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new PotionFinishBrewingSound());
|
||||
}
|
||||
|
||||
$ingredient->pop();
|
||||
$this->inventory->setItem(BrewingStandInventory::SLOT_INGREDIENT, $ingredient);
|
||||
|
||||
$this->brewTime = 0;
|
||||
}else{
|
||||
$ret = true;
|
||||
}
|
||||
}else{
|
||||
$this->brewTime = 0;
|
||||
}
|
||||
}else{
|
||||
$this->brewTime = $this->remainingFuelTime = $this->maxFuelTime = 0;
|
||||
}
|
||||
|
||||
$viewers = array_map(fn(Player $p) => $p->getNetworkSession()->getInvManager(), $this->inventory->getViewers());
|
||||
foreach($viewers as $v){
|
||||
if($v === null){
|
||||
continue;
|
||||
}
|
||||
if($prevBrewTime !== $this->brewTime){
|
||||
$v->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_BREWING_STAND_BREW_TIME, $this->brewTime);
|
||||
}
|
||||
if($prevRemainingFuelTime !== $this->remainingFuelTime){
|
||||
$v->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_BREWING_STAND_FUEL_AMOUNT, $this->remainingFuelTime);
|
||||
}
|
||||
if($prevMaxFuelTime !== $this->maxFuelTime){
|
||||
$v->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_BREWING_STAND_FUEL_TOTAL, $this->maxFuelTime);
|
||||
}
|
||||
}
|
||||
|
||||
$this->timings->stopTiming();
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\utils;
|
||||
|
||||
use pocketmine\block\inventory\BrewingStandInventory;
|
||||
use pocketmine\utils\EnumTrait;
|
||||
|
||||
/**
|
||||
@ -36,13 +37,24 @@ use pocketmine\utils\EnumTrait;
|
||||
* @method static BrewingStandSlot SOUTHWEST()
|
||||
*/
|
||||
final class BrewingStandSlot{
|
||||
use EnumTrait;
|
||||
use EnumTrait {
|
||||
__construct as Enum___construct;
|
||||
}
|
||||
|
||||
protected static function setup() : void{
|
||||
self::registerAll(
|
||||
new self("east"),
|
||||
new self("northwest"),
|
||||
new self("southwest")
|
||||
new self("east", BrewingStandInventory::SLOT_BOTTLE_LEFT),
|
||||
new self("northwest", BrewingStandInventory::SLOT_BOTTLE_MIDDLE),
|
||||
new self("southwest", BrewingStandInventory::SLOT_BOTTLE_RIGHT)
|
||||
);
|
||||
}
|
||||
|
||||
private function __construct(string $enumName, private int $slotNumber){
|
||||
$this->Enum___construct($enumName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the brewing stand inventory slot number associated with this visual slot.
|
||||
*/
|
||||
public function getSlotNumber() : int{ return $this->slotNumber; }
|
||||
}
|
||||
|
30
src/crafting/BrewingRecipe.php
Normal file
30
src/crafting/BrewingRecipe.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?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\crafting;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
||||
interface BrewingRecipe{
|
||||
public function getResultFor(Item $input) : ?Item;
|
||||
}
|
@ -45,6 +45,18 @@ class CraftingManager{
|
||||
*/
|
||||
protected $furnaceRecipeManagers;
|
||||
|
||||
/**
|
||||
* @var PotionTypeRecipe[][]
|
||||
* @phpstan-var array<string, array<string, PotionTypeRecipe>>
|
||||
*/
|
||||
protected $potionTypeRecipes = [];
|
||||
|
||||
/**
|
||||
* @var PotionContainerChangeRecipe[][]
|
||||
* @phpstan-var array<int, array<string, PotionContainerChangeRecipe>>
|
||||
*/
|
||||
protected $potionContainerChangeRecipes = [];
|
||||
|
||||
/**
|
||||
* @var ObjectSet
|
||||
* @phpstan-var ObjectSet<\Closure() : void>
|
||||
@ -140,6 +152,22 @@ class CraftingManager{
|
||||
return $this->furnaceRecipeManagers[$furnaceType->id()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PotionTypeRecipe[][]
|
||||
* @phpstan-return array<string, array<string, PotionTypeRecipe>>
|
||||
*/
|
||||
public function getPotionTypeRecipes() : array{
|
||||
return $this->potionTypeRecipes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PotionContainerChangeRecipe[][]
|
||||
* @phpstan-return array<int, array<string, PotionContainerChangeRecipe>>
|
||||
*/
|
||||
public function getPotionContainerChangeRecipes() : array{
|
||||
return $this->potionContainerChangeRecipes;
|
||||
}
|
||||
|
||||
public function registerShapedRecipe(ShapedRecipe $recipe) : void{
|
||||
$this->shapedRecipes[self::hashOutputs($recipe->getResults())][] = $recipe;
|
||||
|
||||
@ -156,6 +184,25 @@ class CraftingManager{
|
||||
}
|
||||
}
|
||||
|
||||
public function registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void{
|
||||
$input = $recipe->getInput();
|
||||
$ingredient = $recipe->getIngredient();
|
||||
$this->potionTypeRecipes[$input->getId() . ":" . $input->getMeta()][$ingredient->getId() . ":" . ($ingredient->hasAnyDamageValue() ? "?" : $ingredient->getMeta())] = $recipe;
|
||||
|
||||
foreach($this->recipeRegisteredCallbacks as $callback){
|
||||
$callback();
|
||||
}
|
||||
}
|
||||
|
||||
public function registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void{
|
||||
$ingredient = $recipe->getIngredient();
|
||||
$this->potionContainerChangeRecipes[$recipe->getInputItemId()][$ingredient->getId() . ":" . ($ingredient->hasAnyDamageValue() ? "?" : $ingredient->getMeta())] = $recipe;
|
||||
|
||||
foreach($this->recipeRegisteredCallbacks as $callback){
|
||||
$callback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item[] $outputs
|
||||
*/
|
||||
@ -206,4 +253,11 @@ class CraftingManager{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function matchBrewingRecipe(Item $input, Item $ingredient) : ?BrewingRecipe{
|
||||
return $this->potionTypeRecipes[$input->getId() . ":" . $input->getMeta()][$ingredient->getId() . ":" . $ingredient->getMeta()] ??
|
||||
$this->potionTypeRecipes[$input->getId() . ":" . $input->getMeta()][$ingredient->getId() . ":?"] ??
|
||||
$this->potionContainerChangeRecipes[$input->getId()][$ingredient->getId() . ":" . $ingredient->getMeta()] ??
|
||||
$this->potionContainerChangeRecipes[$input->getId()][$ingredient->getId() . ":?"] ?? null;
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,20 @@ final class CraftingManagerFromDataHelper{
|
||||
Item::jsonDeserialize($recipe["input"]))
|
||||
);
|
||||
}
|
||||
foreach($recipes["potion_type"] as $recipe){
|
||||
$result->registerPotionTypeRecipe(new PotionTypeRecipe(
|
||||
Item::jsonDeserialize($recipe["input"]),
|
||||
Item::jsonDeserialize($recipe["ingredient"]),
|
||||
Item::jsonDeserialize($recipe["output"])
|
||||
));
|
||||
}
|
||||
foreach($recipes["potion_container_change"] as $recipe){
|
||||
$result->registerPotionContainerChangeRecipe(new PotionContainerChangeRecipe(
|
||||
$recipe["input_item_id"],
|
||||
Item::jsonDeserialize($recipe["ingredient"]),
|
||||
$recipe["output_item_id"]
|
||||
));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
54
src/crafting/PotionContainerChangeRecipe.php
Normal file
54
src/crafting/PotionContainerChangeRecipe.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?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\crafting;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
|
||||
class PotionContainerChangeRecipe implements BrewingRecipe{
|
||||
|
||||
public function __construct(
|
||||
private int $inputItemId,
|
||||
private Item $ingredient,
|
||||
private int $outputItemId
|
||||
){
|
||||
$this->ingredient = clone $ingredient;
|
||||
}
|
||||
|
||||
public function getInputItemId() : int{
|
||||
return $this->inputItemId;
|
||||
}
|
||||
|
||||
public function getIngredient() : Item{
|
||||
return clone $this->ingredient;
|
||||
}
|
||||
|
||||
public function getOutputItemId() : int{
|
||||
return $this->outputItemId;
|
||||
}
|
||||
|
||||
public function getResultFor(Item $input) : ?Item{
|
||||
return $input->getId() === $this->getInputItemId() ? ItemFactory::getInstance()->get($this->getOutputItemId(), $input->getMeta()) : null;
|
||||
}
|
||||
}
|
55
src/crafting/PotionTypeRecipe.php
Normal file
55
src/crafting/PotionTypeRecipe.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?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\crafting;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
||||
class PotionTypeRecipe implements BrewingRecipe{
|
||||
|
||||
public function __construct(
|
||||
private Item $input,
|
||||
private Item $ingredient,
|
||||
private Item $output
|
||||
){
|
||||
$this->input = clone $input;
|
||||
$this->ingredient = clone $ingredient;
|
||||
$this->output = clone $output;
|
||||
}
|
||||
|
||||
public function getInput() : Item{
|
||||
return clone $this->input;
|
||||
}
|
||||
|
||||
public function getIngredient() : Item{
|
||||
return clone $this->ingredient;
|
||||
}
|
||||
|
||||
public function getOutput() : Item{
|
||||
return clone $this->output;
|
||||
}
|
||||
|
||||
public function getResultFor(Item $input) : ?Item{
|
||||
return $input->equals($this->input, true, false) ? $this->getOutput() : null;
|
||||
}
|
||||
}
|
71
src/event/block/BrewItemEvent.php
Normal file
71
src/event/block/BrewItemEvent.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?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\event\block;
|
||||
|
||||
use pocketmine\block\tile\BrewingStand;
|
||||
use pocketmine\crafting\BrewingRecipe;
|
||||
use pocketmine\event\Cancellable;
|
||||
use pocketmine\event\CancellableTrait;
|
||||
use pocketmine\item\Item;
|
||||
|
||||
class BrewItemEvent extends BlockEvent implements Cancellable{
|
||||
use CancellableTrait;
|
||||
|
||||
public function __construct(
|
||||
private BrewingStand $brewingStand,
|
||||
private int $slot,
|
||||
private Item $input,
|
||||
private Item $result,
|
||||
private BrewingRecipe $recipe
|
||||
){
|
||||
parent::__construct($brewingStand->getBlock());
|
||||
}
|
||||
|
||||
public function getBrewingStand() : BrewingStand{
|
||||
return $this->brewingStand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns which slot of the brewing stand's inventory the potion is in.
|
||||
*/
|
||||
public function getSlot() : int{
|
||||
return $this->slot;
|
||||
}
|
||||
|
||||
public function getInput() : Item{
|
||||
return clone $this->input;
|
||||
}
|
||||
|
||||
public function getResult() : Item{
|
||||
return clone $this->result;
|
||||
}
|
||||
|
||||
public function setResult(Item $result) : void{
|
||||
$this->result = clone $result;
|
||||
}
|
||||
|
||||
public function getRecipe() : BrewingRecipe{
|
||||
return $this->recipe;
|
||||
}
|
||||
}
|
64
src/event/block/BrewingFuelUseEvent.php
Normal file
64
src/event/block/BrewingFuelUseEvent.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?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\event\block;
|
||||
|
||||
use pocketmine\block\tile\BrewingStand;
|
||||
use pocketmine\event\Cancellable;
|
||||
use pocketmine\event\CancellableTrait;
|
||||
|
||||
/**
|
||||
* Called when a brewing stand consumes a new fuel item.
|
||||
*/
|
||||
class BrewingFuelUseEvent extends BlockEvent implements Cancellable{
|
||||
use CancellableTrait;
|
||||
|
||||
private int $fuelTime = 20;
|
||||
|
||||
public function __construct(
|
||||
private BrewingStand $brewingStand
|
||||
){
|
||||
parent::__construct($brewingStand->getBlock());
|
||||
}
|
||||
|
||||
public function getBrewingStand() : BrewingStand{
|
||||
return $this->brewingStand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many times the fuel can be used for potion brewing before it runs out.
|
||||
*/
|
||||
public function getFuelTime() : int{
|
||||
return $this->fuelTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets how many times the fuel can be used for potion brewing before it runs out.
|
||||
*/
|
||||
public function setFuelTime(int $fuelTime) : void{
|
||||
if($fuelTime <= 0){
|
||||
throw new \InvalidArgumentException("Fuel time must be positive");
|
||||
}
|
||||
$this->fuelTime = $fuelTime;
|
||||
}
|
||||
}
|
37
src/network/mcpe/cache/CraftingDataCache.php
vendored
37
src/network/mcpe/cache/CraftingDataCache.php
vendored
@ -26,12 +26,15 @@ namespace pocketmine\network\mcpe\cache;
|
||||
use pocketmine\crafting\CraftingManager;
|
||||
use pocketmine\crafting\FurnaceType;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\network\mcpe\convert\ItemTranslator;
|
||||
use pocketmine\network\mcpe\convert\TypeConverter;
|
||||
use pocketmine\network\mcpe\protocol\CraftingDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
||||
use pocketmine\network\mcpe\protocol\types\recipe\CraftingRecipeBlockName;
|
||||
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipe as ProtocolFurnaceRecipe;
|
||||
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipeBlockName;
|
||||
use pocketmine\network\mcpe\protocol\types\recipe\PotionContainerChangeRecipe as ProtocolPotionContainerChangeRecipe;
|
||||
use pocketmine\network\mcpe\protocol\types\recipe\PotionTypeRecipe as ProtocolPotionTypeRecipe;
|
||||
use pocketmine\network\mcpe\protocol\types\recipe\RecipeIngredient;
|
||||
use pocketmine\network\mcpe\protocol\types\recipe\ShapedRecipe as ProtocolShapedRecipe;
|
||||
use pocketmine\network\mcpe\protocol\types\recipe\ShapelessRecipe as ProtocolShapelessRecipe;
|
||||
@ -137,7 +140,39 @@ final class CraftingDataCache{
|
||||
}
|
||||
}
|
||||
|
||||
$potionTypeRecipes = [];
|
||||
foreach($manager->getPotionTypeRecipes() as $recipes){
|
||||
foreach($recipes as $recipe){
|
||||
$input = $converter->coreItemStackToNet($recipe->getInput());
|
||||
$ingredient = $converter->coreItemStackToNet($recipe->getIngredient());
|
||||
$output = $converter->coreItemStackToNet($recipe->getOutput());
|
||||
$potionTypeRecipes[] = new ProtocolPotionTypeRecipe(
|
||||
$input->getId(),
|
||||
$input->getMeta(),
|
||||
$ingredient->getId(),
|
||||
$ingredient->getMeta(),
|
||||
$output->getId(),
|
||||
$output->getMeta()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$potionContainerChangeRecipes = [];
|
||||
$itemTranslator = ItemTranslator::getInstance();
|
||||
foreach($manager->getPotionContainerChangeRecipes() as $recipes){
|
||||
foreach($recipes as $recipe){
|
||||
$input = $itemTranslator->toNetworkId($recipe->getInputItemId(), 0);
|
||||
$ingredient = $itemTranslator->toNetworkId($recipe->getIngredient()->getId(), 0);
|
||||
$output = $itemTranslator->toNetworkId($recipe->getOutputItemId(), 0);
|
||||
$potionContainerChangeRecipes[] = new ProtocolPotionContainerChangeRecipe(
|
||||
$input[0],
|
||||
$ingredient[0],
|
||||
$output[0]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Timings::$craftingDataCacheRebuild->stopTiming();
|
||||
return CraftingDataPacket::create($recipesWithTypeIds, [], [], [], true);
|
||||
return CraftingDataPacket::create($recipesWithTypeIds, $potionTypeRecipes, $potionContainerChangeRecipes, [], true);
|
||||
}
|
||||
}
|
||||
|
35
src/world/sound/PotionFinishBrewingSound.php
Normal file
35
src/world/sound/PotionFinishBrewingSound.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\LevelSoundEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelSoundEvent;
|
||||
|
||||
final class PotionFinishBrewingSound implements Sound{
|
||||
|
||||
public function encode(Vector3 $pos) : array{
|
||||
return [LevelSoundEventPacket::nonActorSound(LevelSoundEvent::POTION_BREWED, $pos, false)];
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user