50    public const BREW_TIME_TICKS = 400; 
 
   52    private const TAG_BREW_TIME = 
"BrewTime"; 
 
   53    private const TAG_BREW_TIME_PE = 
"CookTime"; 
 
   54    private const TAG_MAX_FUEL_TIME = 
"FuelTotal"; 
 
   55    private const TAG_REMAINING_FUEL_TIME = 
"Fuel"; 
 
   56    private const TAG_REMAINING_FUEL_TIME_PE = 
"FuelAmount"; 
 
   60    private int $brewTime = 0;
 
   61    private int $maxFuelTime = 0;
 
   62    private int $remainingFuelTime = 0;
 
   65        parent::__construct($world, $pos);
 
   67        $this->inventory->getListeners()->add(CallbackInventoryListener::onAnyChange(
static function(
Inventory $unused) use ($world, $pos) : 
void{
 
   72    public function readSaveData(
CompoundTag $nbt) : 
void{
 
   73        $this->loadName($nbt);
 
   74        $this->loadItems($nbt);
 
   76        $this->brewTime = $nbt->getShort(self::TAG_BREW_TIME, $nbt->getShort(self::TAG_BREW_TIME_PE, 0));
 
   77        $this->maxFuelTime = $nbt->getShort(self::TAG_MAX_FUEL_TIME, 0);
 
   78        $this->remainingFuelTime = $nbt->getByte(self::TAG_REMAINING_FUEL_TIME, $nbt->getShort(self::TAG_REMAINING_FUEL_TIME_PE, 0));
 
   79        if($this->maxFuelTime === 0){
 
   80            $this->maxFuelTime = $this->remainingFuelTime;
 
   82        if($this->remainingFuelTime === 0){
 
   83            $this->maxFuelTime = $this->remainingFuelTime = $this->brewTime = 0;
 
   88        $this->saveName($nbt);
 
   89        $this->saveItems($nbt);
 
   91        $nbt->
setShort(self::TAG_BREW_TIME_PE, $this->brewTime);
 
   92        $nbt->
setShort(self::TAG_MAX_FUEL_TIME, $this->maxFuelTime);
 
   93        $nbt->
setShort(self::TAG_REMAINING_FUEL_TIME_PE, $this->remainingFuelTime);
 
 
   97        $this->addNameSpawnData($nbt);
 
   99        $nbt->
setShort(self::TAG_BREW_TIME_PE, $this->brewTime);
 
  100        $nbt->
setShort(self::TAG_MAX_FUEL_TIME, $this->maxFuelTime);
 
  101        $nbt->
setShort(self::TAG_REMAINING_FUEL_TIME_PE, $this->remainingFuelTime);
 
 
  104    public function getDefaultName() : string{
 
  105        return 
"Brewing Stand";
 
  108    public function close() : void{
 
  110            $this->inventory->removeAllWindows();
 
  116    public function getInventory() : Inventory{
 
  117        return $this->inventory;
 
  120    public function getRealInventory() : Inventory{
 
  121        return $this->inventory;
 
  124    private function checkFuel(Item $item) : void{
 
  125        $ev = new BrewingFuelUseEvent($this);
 
  126        if(!$item->equals(VanillaItems::BLAZE_POWDER(), 
true, 
false)){
 
  131        if($ev->isCancelled()){
 
  136        $this->inventory->setItem(BrewingStandInventoryWindow::SLOT_FUEL, $item);
 
  138        $this->maxFuelTime = $this->remainingFuelTime = $ev->getFuelTime();
 
  145    private function getBrewableRecipes() : array{
 
  146        $ingredient = $this->inventory->getItem(BrewingStandInventoryWindow::SLOT_INGREDIENT);
 
  147        if($ingredient->isNull()){
 
  152        $craftingManager = $this->position->getWorld()->getServer()->getCraftingManager();
 
  153        foreach([BrewingStandInventoryWindow::SLOT_BOTTLE_LEFT, BrewingStandInventoryWindow::SLOT_BOTTLE_MIDDLE, BrewingStandInventoryWindow::SLOT_BOTTLE_RIGHT] as $slot){
 
  154            $input = $this->inventory->getItem($slot);
 
  155            if($input->isNull()){
 
  159            if(($recipe = $craftingManager->matchBrewingRecipe($input, $ingredient)) !== 
null){
 
  160                $recipes[$slot] = $recipe;
 
  167    public function onUpdate() : bool{
 
  172        $this->timings->startTiming();
 
  174        $prevBrewTime = $this->brewTime;
 
  175        $prevRemainingFuelTime = $this->remainingFuelTime;
 
  176        $prevMaxFuelTime = $this->maxFuelTime;
 
  180        $fuel = $this->inventory->getItem(BrewingStandInventoryWindow::SLOT_FUEL);
 
  181        $ingredient = $this->inventory->getItem(BrewingStandInventoryWindow::SLOT_INGREDIENT);
 
  183        $recipes = $this->getBrewableRecipes();
 
  184        $canBrew = count($recipes) !== 0;
 
  186        if($this->remainingFuelTime <= 0 && $canBrew){
 
  187            $this->checkFuel($fuel);
 
  190        if($this->remainingFuelTime > 0){
 
  192                if($this->brewTime === 0){
 
  193                    $this->brewTime = self::BREW_TIME_TICKS;
 
  194                    --$this->remainingFuelTime;
 
  199                if($this->brewTime <= 0){
 
  200                    $anythingBrewed = 
false;
 
  201                    foreach($recipes as $slot => $recipe){
 
  202                        $input = $this->inventory->getItem($slot);
 
  203                        $output = $recipe->getResultFor($input);
 
  204                        if($output === 
null){
 
  208                        $ev = 
new BrewItemEvent($this, $slot, $input, $output, $recipe);
 
  210                        if($ev->isCancelled()){
 
  214                        $this->inventory->setItem($slot, $ev->getResult());
 
  215                        $anythingBrewed = 
true;
 
  219                        $this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), 
new PotionFinishBrewingSound());
 
  223                    $this->inventory->setItem(BrewingStandInventoryWindow::SLOT_INGREDIENT, $ingredient);
 
  233            $this->brewTime = $this->remainingFuelTime = $this->maxFuelTime = 0;
 
  236        $viewers = array_map(fn(Player $p) => $p->getNetworkSession()->getInvManager(), $this->inventory->getViewers());
 
  237        foreach($viewers as $v){
 
  241            if($prevBrewTime !== $this->brewTime){
 
  242                $v->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_BREWING_STAND_BREW_TIME, $this->brewTime);
 
  244            if($prevRemainingFuelTime !== $this->remainingFuelTime){
 
  245                $v->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_BREWING_STAND_FUEL_AMOUNT, $this->remainingFuelTime);
 
  247            if($prevMaxFuelTime !== $this->maxFuelTime){
 
  248                $v->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_BREWING_STAND_FUEL_TOTAL, $this->maxFuelTime);
 
  252        $this->timings->stopTiming();