InputRemovalType enum

Пакет: com.hypixel.hytale.builtin.crafting.component

Файл: com/hypixel/hytale/builtin/crafting/component/CraftingManager.java

Поля (1)

МодификаторыТипИмя
NORMAL, ORDERED

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.builtin.crafting.component;

class="kw">import com.google.gson.JsonArray;
class="kw">import com.hypixel.hytale.builtin.adventure.memories.MemoriesPlugin;
class="kw">import com.hypixel.hytale.builtin.crafting.CraftingPlugin;
class="kw">import com.hypixel.hytale.builtin.crafting.window.BenchWindow;
class="kw">import com.hypixel.hytale.builtin.crafting.window.CraftingWindow;
class="kw">import com.hypixel.hytale.component.Component;
class="kw">import com.hypixel.hytale.component.ComponentAccessor;
class="kw">import com.hypixel.hytale.component.ComponentType;
class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.component.Store;
class="kw">import com.hypixel.hytale.component.spatial.SpatialResource;
class="kw">import com.hypixel.hytale.event.IEventDispatcher;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.math.shape.Box;
class="kw">import com.hypixel.hytale.math.util.ChunkUtil;
class="kw">import com.hypixel.hytale.protocol.BenchRequirement;
class="kw">import com.hypixel.hytale.protocol.BenchType;
class="kw">import com.hypixel.hytale.protocol.GameMode;
class="kw">import com.hypixel.hytale.protocol.ItemQuantity;
class="kw">import com.hypixel.hytale.protocol.ItemResourceType;
class="kw">import com.hypixel.hytale.protocol.SoundCategory;
class="kw">import com.hypixel.hytale.protocol.packets.interface_.NotificationStyle;
class="kw">import com.hypixel.hytale.server.core.HytaleServer;
class="kw">import com.hypixel.hytale.server.core.Message;
class="kw">import com.hypixel.hytale.server.core.asset.type.blockhitbox.BlockBoundingBoxes;
class="kw">import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
class="kw">import com.hypixel.hytale.server.core.asset.type.blocktype.config.bench.Bench;
class="kw">import com.hypixel.hytale.server.core.asset.type.blocktype.config.bench.BenchTierLevel;
class="kw">import com.hypixel.hytale.server.core.asset.type.blocktype.config.bench.BenchUpgradeRequirement;
class="kw">import com.hypixel.hytale.server.core.asset.type.item.config.CraftingRecipe;
class="kw">import com.hypixel.hytale.server.core.asset.type.item.config.Item;
class="kw">import com.hypixel.hytale.server.core.entity.EntityUtils;
class="kw">import com.hypixel.hytale.server.core.entity.entities.Player;
class="kw">import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerConfigData;
class="kw">import com.hypixel.hytale.server.core.entity.entities.player.windows.MaterialExtraResourcesSection;
class="kw">import com.hypixel.hytale.server.core.event.events.ecs.CraftRecipeEvent;
class="kw">import com.hypixel.hytale.server.core.event.events.player.PlayerCraftEvent;
class="kw">import com.hypixel.hytale.server.core.inventory.InventoryComponent;
class="kw">import com.hypixel.hytale.server.core.inventory.InventoryUtils;
class="kw">import com.hypixel.hytale.server.core.inventory.ItemStack;
class="kw">import com.hypixel.hytale.server.core.inventory.MaterialQuantity;
class="kw">import com.hypixel.hytale.server.core.inventory.container.CombinedItemContainer;
class="kw">import com.hypixel.hytale.server.core.inventory.container.DelegateItemContainer;
class="kw">import com.hypixel.hytale.server.core.inventory.container.EmptyItemContainer;
class="kw">import com.hypixel.hytale.server.core.inventory.container.ItemContainer;
class="kw">import com.hypixel.hytale.server.core.inventory.container.SimpleItemContainer;
class="kw">import com.hypixel.hytale.server.core.inventory.container.filter.FilterType;
class="kw">import com.hypixel.hytale.server.core.inventory.transaction.ListTransaction;
class="kw">import com.hypixel.hytale.server.core.inventory.transaction.MaterialSlotTransaction;
class="kw">import com.hypixel.hytale.server.core.inventory.transaction.MaterialTransaction;
class="kw">import com.hypixel.hytale.server.core.modules.block.BlockModule;
class="kw">import com.hypixel.hytale.server.core.modules.block.components.ItemContainerBlock;
class="kw">import com.hypixel.hytale.server.core.modules.entity.player.PlayerSettings;
class="kw">import com.hypixel.hytale.server.core.universe.PlayerRef;
class="kw">import com.hypixel.hytale.server.core.universe.world.SoundUtil;
class="kw">import com.hypixel.hytale.server.core.universe.world.World;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.BlockOperations;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
class="kw">import com.hypixel.hytale.server.core.util.NotificationUtil;
class="kw">import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
class="kw">import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectArrayList;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectList;
class="kw">import java.util.Collections;
class="kw">import java.util.List;
class="kw">import java.util.Map;
class="kw">import java.util.Objects;
class="kw">import java.util.Set;
class="kw">import java.util.concurrent.BlockingQueue;
class="kw">import java.util.concurrent.LinkedBlockingQueue;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import org.joml.Vector3d;
class="kw">import org.joml.Vector3i;

class="kw">public class CraftingManager class="kw">implements Component<EntityStore> {
   @Nonnull
   class="kw">private class="kw">static class="kw">final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
   class="kw">private class="kw">static class="kw">final int QUEUED_CRAFTING_JOBS_MAX_CAPACITY = 32;
   @Nonnull
   class="kw">private class="kw">final BlockingQueue<CraftingManager.CraftingJob> queuedCraftingJobs = new LinkedBlockingQueue<>(32);
   @Nullable
   class="kw">private CraftingManager.BenchUpgradingJob upgradingJob;
   class="kw">private int x;
   class="kw">private int y;
   class="kw">private int z;
   @Nullable
   class="kw">private BlockType blockType;

   @Nonnull
   class="kw">public class="kw">static ComponentType<EntityStore, CraftingManager> getComponentType() {
      class="kw">return CraftingPlugin.get().getCraftingManagerComponentType();
   }

   class="kw">public CraftingManager() {
   }

   class="kw">private CraftingManager(@Nonnull CraftingManager var1) {
      this.x = var1.x;
      this.y = var1.y;
      this.z = var1.z;
      this.blockType = var1.blockType;
      this.queuedCraftingJobs.addAll(var1.queuedCraftingJobs);
      this.upgradingJob = var1.upgradingJob;
   }

   class="kw">public boolean hasBenchSet() {
      class="kw">return this.blockType != null;
   }

   class="kw">public void setBench(int var1, int var2, int var3, @Nonnull BlockType var4) {
      Bench var5 = var4.getBench();
      Objects.requireNonNull(var5, "blockType isn't a bench!");
      if (var5.getType() != BenchType.Crafting
         && var5.getType() != BenchType.DiagramCrafting
         && var5.getType() != BenchType.StructuralCrafting
         && var5.getType() != BenchType.Processing) {
         throw new IllegalArgumentException("blockType isn't a crafting bench!");
      }

      if (this.blockType != null) {
         throw new IllegalArgumentException("Bench blockType is already set! Must be cleared (close UI).");
      }

      if (!this.queuedCraftingJobs.isEmpty()) {
         throw new IllegalArgumentException("Queue already has jobs!");
      }

      if (this.upgradingJob != null) {
         throw new IllegalArgumentException("Upgrading job is already set!");
      }

      this.x = var1;
      this.y = var2;
      this.z = var3;
      this.blockType = var4;
   }

   class="kw">public boolean clearBench(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2) {
      boolean var3 = this.cancelAllCrafting(var1, var2);
      this.x = 0;
      this.y = 0;
      this.z = 0;
      this.blockType = null;
      this.upgradingJob = null;
      class="kw">return var3;
   }

   class="kw">public boolean craftItem(
      @Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2, @Nonnull CraftingRecipe var3, int var4, @Nonnull ItemContainer var5
   ) {
      if (this.upgradingJob != null) {
         class="kw">return false;
      }

      Objects.requireNonNull(var3, "Recipe can't be null");
      int var6 = this.resolveCraftQuantity(var1, var2, var3, var5, var4);
      if (var6 < 1) {
         class="kw">return false;
      }

      CraftRecipeEvent.Pre var7 = new CraftRecipeEvent.Pre(var3, var6);
      var2.invoke(var1, var7);
      if (var7.isCancelled()) {
         class="kw">return false;
      }

      if (!this.isValidBenchForRecipe(var1, var2, var3)) {
         class="kw">return false;
      }

      World var8 = var2.getExternalData().getWorld();
      Player var9 = var2.getComponent(var1, Player.getComponentType());
      assert var9 != null;
      if (var9.getGameMode() != GameMode.Creative && !removeInputFromInventory(var5, var3, var6)) {
         PlayerRef var12 = var2.getComponent(var1, PlayerRef.getComponentType());
         assert var12 != null;
         String var13 = getRecipeOutputTranslationKey(var3);
         if (var13 != null) {
            NotificationUtil.sendNotification(
               var12.getPacketHandler(),
               Message.translation("server.general.crafting.missingIngredient").param("item", Message.translation(var13)),
               NotificationStyle.Danger
            );
         }

         LOGGER.at(Level.FINE).log("Missing items required to craft the item: %s", var3);
         class="kw">return false;
      } else {
         CraftRecipeEvent.Post var10 = new CraftRecipeEvent.Post(var3, var6);
         var2.invoke(var1, var10);
         if (var10.isCancelled()) {
            class="kw">return true;
         }

         giveOutput(var1, var2, var3, var6);
         IEventDispatcher var11 = HytaleServer.get().getEventBus().dispatchFor(PlayerCraftEvent.class, var8.getName());
         if (var11.hasListener()) {
            var11.dispatch(new PlayerCraftEvent(var1, var9, var3, var6));
         }

         class="kw">return true;
      }
   }

   @Nullable
   class="kw">private class="kw">static String getRecipeOutputTranslationKey(@Nonnull CraftingRecipe var0) {
      MaterialQuantity var1 = var0.getPrimaryOutput();
      if (var1 == null) {
         class="kw">return null;
      }

      String var2 = var1.getItemId();
      if (var2 == null) {
         class="kw">return null;
      }

      Item var3 = Item.getAssetMap().getAsset(var2);
      class="kw">return var3 != null ? var3.getTranslationKey() : null;
   }

   class="kw">public boolean queueCraft(
      @Nonnull Ref<EntityStore> var1,
      @Nonnull ComponentAccessor<EntityStore> var2,
      @Nonnull CraftingWindow var3,
      int var4,
      @Nonnull CraftingRecipe var5,
      int var6,
      @Nonnull ItemContainer var7,
      @Nonnull CraftingManager.InputRemovalType var8
   ) {
      if (this.upgradingJob != null) {
         class="kw">return false;
      }

      Objects.requireNonNull(var5, "Recipe can't be null");
      if (!this.isValidBenchForRecipe(var1, var2, var5)) {
         class="kw">return false;
      }

      int var9 = this.resolveCraftQuantity(var1, var2, var5, var7, var6);
      if (var9 < 1) {
         class="kw">return false;
      }

      CraftRecipeEvent.Pre var10 = new CraftRecipeEvent.Pre(var5, var9);
      var2.invoke(var1, var10);
      if (var10.isCancelled()) {
         class="kw">return false;
      }

      float var11 = var5.getTimeSeconds();
      if (var11 > 0.0F) {
         int var12 = this.getBenchTierLevel(var2);
         if (var12 > 1) {
            BenchTierLevel var13 = this.getBenchTierLevelData(var12 - 1);
            if (var13 != null) {
               var11 -= var11 * var13.getCraftingTimeReductionModifier();
            }
         }
      }

      boolean var14 = this.queuedCraftingJobs.offer(new CraftingManager.CraftingJob(var3, var4, var5, var9, var11, var7, var8));
      if (!var14) {
         LOGGER.at(Level.WARNING)
            .log(
               "Rejecting crafting job for %s (%s) due to lack of queue capacity (%d, %d, %d) (%d entries)",
               EntityUtils.getEntityName(var1, var2),
               var5.getId(),
               this.x,
               this.y,
               this.z,
               this.queuedCraftingJobs.size()
            );
         class="kw">return false;
      } else {
         class="kw">return true;
      }
   }

   class="kw">private int resolveCraftQuantity(
      @Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2, @Nonnull CraftingRecipe var3, @Nonnull ItemContainer var4, int var5
   ) {
      Player var6 = var2.getComponent(var1, Player.getComponentType());
      boolean var7 = var6 != null && var6.getGameMode() == GameMode.Creative;
      if (!var7) {
         int var8 = getMaterialCraftLimit(var3, var4);
         if (var5 > var8) {
            LOGGER.at(Level.WARNING)
               .log(
                  "Crafting quantity mismatch for %s: asked for %d of %s but %d are craftable", EntityUtils.getEntityName(var1, var2), var5, var3.getId(), var8
               );
         }
      }

      class="kw">return Math.min(var5, getOutputCraftCeiling(var1, var2, var3));
   }

   class="kw">public int getRemainingQueueSize() {
      int var1 = 0;

      for (CraftingManager.CraftingJob var3 : this.queuedCraftingJobs) {
         var1 += var3.quantity - var3.quantityCompleted;
      }

      class="kw">return var1;
   }

   class="kw">public void tick(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2, float var3) {
      if (this.upgradingJob != null) {
         if (var3 > 0.0F) {
            this.upgradingJob.timeSecondsCompleted += var3;
         }

         this.upgradingJob.window.updateBenchUpgradeJob(this.upgradingJob.computeLoadingPercent());
         if (this.upgradingJob.timeSecondsCompleted >= this.upgradingJob.timeSeconds) {
            this.upgradingJob.window.updateBenchTierLevel(this.finishTierUpgrade(var1, var2));
            this.upgradingJob = null;
         }
      } else {
         Player var4 = var2.getComponent(var1, Player.getComponentType());
         assert var4 != null;
         PlayerRef var5 = var2.getComponent(var1, PlayerRef.getComponentType());
         assert var5 != null;

         while (var3 > 0.0F && !this.queuedCraftingJobs.isEmpty()) {
            CraftingManager.CraftingJob var6 = this.queuedCraftingJobs.peek();
            boolean var7 = var4.getGameMode() == GameMode.Creative;
            if (var6 != null && var6.quantityStarted < var6.quantity && var6.quantityStarted <= var6.quantityCompleted) {
               LOGGER.at(Level.FINE).log("Removing Items for next quantity: %s", var6);
               int var8 = var6.quantityStarted++;
               if (!var7 && !removeInputFromInventory(var6, var8)) {
                  String var9 = getRecipeOutputTranslationKey(var6.recipe);
                  if (var9 != null) {
                     NotificationUtil.sendNotification(
                        var5.getPacketHandler(),
                        Message.translation("server.general.crafting.missingIngredient").param("item", Message.translation(var9)),
                        NotificationStyle.Danger
                     );
                  }

                  LOGGER.at(Level.FINE).log("Missing items required to craft the item: %s", var6);
                  this.queuedCraftingJobs.poll();
                  var6.window.updateQueueSize(this.getRemainingQueueSize());
                  if (this.queuedCraftingJobs.isEmpty()) {
                     var6.window.setBlockInteractionState("class="kw">default", var2.getExternalData().getWorld());
                  }

                  var6 = null;
               }

               if (!var7 && var6 != null && var6.quantityStarted < var6.quantity && var6.quantityStarted <= var6.quantityCompleted) {
                  NotificationUtil.sendNotification(
                     var5.getPacketHandler(), Message.translation("server.general.crafting.failedTakingCorrectQuantity"), NotificationStyle.Danger
                  );
                  LOGGER.at(Level.SEVERE).log("Failed to remove the correct quantity of input, removing crafting job %s", var6);
                  this.queuedCraftingJobs.poll();
                  var6.window.updateQueueSize(this.getRemainingQueueSize());
                  if (this.queuedCraftingJobs.isEmpty()) {
                     var6.window.setBlockInteractionState("class="kw">default", var2.getExternalData().getWorld());
                  }

                  var6 = null;
               }
            }

            if (var6 != null) {
               var6.timeSecondsCompleted += var3;
               float var11 = var6.timeSeconds <= 0.0F ? 1.0F : var6.timeSecondsCompleted / var6.timeSeconds;
               if (var11 > 1.0F) {
                  var11 = 1.0F;
               }

               var6.window.updateCraftingJob(var11);
               LOGGER.at(Level.FINEST).log("Update time: %s", var6);
               var3 = 0.0F;
               if (var6.timeSecondsCompleted >= var6.timeSeconds) {
                  var3 = var6.timeSecondsCompleted - var6.timeSeconds;
                  int var12 = var6.quantityCompleted++;
                  var6.timeSecondsCompleted = 0.0F;
                  LOGGER.at(Level.FINE).log("Crafted 1 Quantity: %s", var6);
                  CraftRecipeEvent.Post var10 = new CraftRecipeEvent.Post(var6.recipe, var6.quantity);
                  var2.invoke(var1, var10);
                  if (var6.quantityCompleted == var6.quantity) {
                     if (!var10.isCancelled()) {
                        giveOutput(var1, var2, var6, var12);
                     }

                     LOGGER.at(Level.FINE).log("Crafting Finished: %s", var6);
                     this.queuedCraftingJobs.poll();
                  } else {
                     if (var6.quantityCompleted > var6.quantity) {
                        this.queuedCraftingJobs.poll();
                        throw new RuntimeException("QuantityCompleted is greater than the Quality! " + var6);
                     }

                     if (!var10.isCancelled()) {
                        giveOutput(var1, var2, var6, var12);
                     }
                  }

                  var6.window.updateQueueSize(this.getRemainingQueueSize());
                  if (this.queuedCraftingJobs.isEmpty()) {
                     var6.window.setBlockInteractionState("class="kw">default", var2.getExternalData().getWorld());
                  }
               }
            }
         }
      }
   }

   class="kw">public boolean cancelAllCrafting(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2) {
      LOGGER.at(Level.FINE).log("Cancel Crafting!");
      ObjectList var3 = new ObjectArrayList(this.queuedCraftingJobs.size());
      this.queuedCraftingJobs.drainTo(var3);
      if (!var3.isEmpty()) {
         CraftingManager.CraftingJob var4 = (CraftingManager.CraftingJob)var3.getFirst();
         LOGGER.at(Level.FINE).log("Refunding Items for: %s", var4);
         refundInputToInventory(var1, var2, var4, var4.quantityStarted - 1);
         class="kw">return true;
      } else {
         class="kw">return false;
      }
   }

   class="kw">private boolean isValidBenchForRecipe(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2, @Nonnull CraftingRecipe var3) {
      Player var4 = var2.getComponent(var1, Player.getComponentType());
      assert var4 != null;
      PlayerConfigData var5 = var4.getPlayerConfigData();
      MaterialQuantity var6 = var3.getPrimaryOutput();
      String var7 = var6 != null ? var6.getItemId() : null;
      if (!var3.isKnowledgeRequired() || var7 != null && var5.getKnownRecipes().contains(var7)) {
         World var8 = var2.getExternalData().getWorld();
         if (var3.getRequiredMemoriesLevel() > 1 && MemoriesPlugin.get().getMemoriesLevel(var8.getGameplayConfig()) < var3.getRequiredMemoriesLevel()) {
            LOGGER.at(Level.WARNING).log("Attempted to craft %s but doesn't have the required world memories level!", var3.getId());
            class="kw">return false;
         }

         BenchType var9 = this.blockType != null ? this.blockType.getBench().getType() : BenchType.Crafting;
         String var10 = this.blockType != null ? this.blockType.getBench().getId() : "Fieldcraft";
         boolean var11 = false;
         int var12 = this.getBenchTierLevel(var2);
         BenchRequirement[] var13 = var3.getBenchRequirement();
         if (var13 != null) {
            for (BenchRequirement var17 : var13) {
               if (var17.type == var9 && var10.equals(var17.id) && var17.requiredTierLevel <= var12 && this.benchHasRequiredAugmentTags(var2, var17)) {
                  var11 = true;
                  break;
               }
            }
         }

         if (!var11) {
            LOGGER.at(Level.WARNING).log("Attempted to craft %s using %s, %s but requires bench %s but a bench is NOT set!", var3.getId(), var9, var10, var13);
            class="kw">return false;
         } else if (var9 == BenchType.Crafting && !"Fieldcraft".equals(var10)) {
            CraftingManager.CraftingJob var18 = this.queuedCraftingJobs.peek();
            class="kw">return var18 == null || var18.recipe.getId().equals(var3.getId());
         } else {
            class="kw">return true;
         }
      } else {
         LOGGER.at(Level.WARNING).log("Attempted to craft %s but doesn't know the recipe!", var3.getId());
         class="kw">return false;
      }
   }

   class="kw">private class="kw">static void giveOutput(
      @Nonnull Ref<EntityStore> var0, @Nonnull ComponentAccessor<EntityStore> var1, @Nonnull CraftingManager.CraftingJob var2, int var3
   ) {
      var2.removedItems.remove(var3);
      String var4 = var2.recipe.getId();
      CraftingRecipe var5 = CraftingRecipe.getAssetMap().getAsset(var4);
      if (var5 == null) {
         throw new RuntimeException("A non-existent item ID was provided! " + var4);
      }

      giveOutput(var0, var1, var5, 1);
   }

   class="kw">private class="kw">static void giveOutput(@Nonnull Ref<EntityStore> var0, @Nonnull ComponentAccessor<EntityStore> var1, @Nonnull CraftingRecipe var2, int var3) {
      Player var4 = var1.getComponent(var0, Player.getComponentType());
      if (var4 == null) {
         LOGGER.at(Level.WARNING).log("Attempted to give output to a non-player entity: %s", var0);
      } else {
         List var5 = getOutputItemStacks(var2, var3);
         PlayerSettings var6 = var1.getComponent(var0, PlayerSettings.getComponentType());
         if (var6 == null) {
            var6 = PlayerSettings.defaults();
         }

         for (ItemStack var8 : var5) {
            if (!ItemStack.isEmpty(var8)) {
               ItemContainer var9 = InventoryUtils.getContainerForItemPickup(var0, var8.getItem(), var6, var1);
               SimpleItemContainer.addOrDropItemStack(var1, var0, var9, var8);
            }
         }
      }
   }

   class="kw">private class="kw">static boolean removeInputFromInventory(@Nonnull CraftingManager.CraftingJob var0, int var1) {
      Objects.requireNonNull(var0, "Job can't be null!");
      CraftingRecipe var2 = var0.recipe;
      Objects.requireNonNull(var2, "CraftingRecipe can't be null!");
      List var3 = getInputMaterials(var2);
      if (var3.isEmpty()) {
         class="kw">return true;
      }

      LOGGER.at(Level.FINEST).log("Removing Materials: %s - %s", var0, var3);
      ObjectList var4 = new ObjectArrayList();

      boolean var5 = class="kw">switch (var0.inputRemovalType) {
         case NORMAL -> {
            ListTransaction var11 = var0.inputItemContainer.removeMaterials(var3, true, true, true);

            for (MaterialTransaction var13 : var11.getList()) {
               for (MaterialSlotTransaction var10 : var13.getList()) {
                  if (!ItemStack.isEmpty(var10.getOutput())) {
                     var4.add(var10.getOutput());
                  }
               }
            }

            yield var11.succeeded();
         }
         case ORDERED -> {
            ListTransaction var6 = var0.inputItemContainer.removeMaterialsOrdered(var3, true, true, true);

            for (MaterialSlotTransaction var8 : var6.getList()) {
               if (!ItemStack.isEmpty(var8.getOutput())) {
                  var4.add(var8.getOutput());
               }
            }

            yield var6.succeeded();
         }
         class="kw">default -> throw new IllegalArgumentException("Unknown enum: " + var0.inputRemovalType);
      };
      var0.removedItems.put(var1, var4);
      var0.window.invalidateExtraResources();
      class="kw">return var5;
   }

   class="kw">private class="kw">static boolean removeInputFromInventory(@Nonnull ItemContainer var0, @Nonnull CraftingRecipe var1, int var2) {
      List var3 = getInputMaterials(var1, var2);
      if (var3.isEmpty()) {
         class="kw">return true;
      }

      LOGGER.at(Level.FINEST).log("Removing Materials: %s - %s", var1, var3);
      ListTransaction var4 = var0.removeMaterials(var3, true, true, true);
      class="kw">return var4.succeeded();
   }

   class="kw">private class="kw">static void refundInputToInventory(
      @Nonnull Ref<EntityStore> var0, @Nonnull ComponentAccessor<EntityStore> var1, @Nonnull CraftingManager.CraftingJob var2, int var3
   ) {
      Objects.requireNonNull(var2, "Job can't be null!");
      List var4 = (List<ItemStack>)var2.removedItems.get(var3);
      if (var4 != null) {
         CombinedItemContainer var5 = InventoryComponent.getCombined(var1, var0, InventoryComponent.HOTBAR_FIRST);
         SimpleItemContainer.addOrDropItemStacks(var1, var0, var5, var4);
      }
   }

   @Nonnull
   class="kw">public class="kw">static List<ItemStack> getOutputItemStacks(@Nonnull CraftingRecipe var0) {
      class="kw">return getOutputItemStacks(var0, 1);
   }

   @Nonnull
   class="kw">public class="kw">static List<ItemStack> getOutputItemStacks(@Nonnull CraftingRecipe var0, int var1) {
      Objects.requireNonNull(var0);
      MaterialQuantity[] var2 = var0.getOutputs();
      if (var2 == null) {
         class="kw">return List.of();
      }

      ObjectList var3 = new ObjectArrayList();

      for (MaterialQuantity var7 : var2) {
         ItemStack var8 = getOutputItemStack(var7, var1);
         if (var8 != null) {
            var3.add(var8);
         }
      }

      class="kw">return var3;
   }

   @Nullable
   class="kw">public class="kw">static ItemStack getOutputItemStack(@Nonnull MaterialQuantity var0, @Nonnull String var1) {
      class="kw">return getOutputItemStack(var0, 1);
   }

   @Nullable
   class="kw">public class="kw">static ItemStack getOutputItemStack(@Nonnull MaterialQuantity var0, int var1) {
      String var2 = var0.getItemId();
      if (var2 == null) {
         class="kw">return null;
      }

      int var3 = var0.getQuantity() <= 0 ? 1 : var0.getQuantity();
      class="kw">return new ItemStack(var2, var3 * var1, var0.getMetadata());
   }

   @Nonnull
   class="kw">public class="kw">static List<MaterialQuantity> getInputMaterials(@Nonnull CraftingRecipe var0) {
      class="kw">return getInputMaterials(var0, 1);
   }

   @Nonnull
   class="kw">private class="kw">static List<MaterialQuantity> getInputMaterials(@Nonnull MaterialQuantity[] var0) {
      class="kw">return getInputMaterials(var0, 1);
   }

   @Nonnull
   class="kw">public class="kw">static List<MaterialQuantity> getInputMaterials(@Nonnull CraftingRecipe var0, int var1) {
      Objects.requireNonNull(var0);
      class="kw">return var0.getInput() == null ? Collections.emptyList() : getInputMaterials(var0.getInput(), var1);
   }

   @Nonnull
   class="kw">private class="kw">static List<MaterialQuantity> getInputMaterials(@Nonnull MaterialQuantity[] var0, int var1) {
      ObjectList var2 = new ObjectArrayList();

      for (MaterialQuantity var6 : var0) {
         var2.add(var6.clone(var6.getQuantity() * var1));
      }

      class="kw">return var2;
   }

   class="kw">public class="kw">static boolean matches(@Nonnull MaterialQuantity var0, @Nonnull ItemStack var1) {
      String var2 = var0.getItemId();
      if (var2 != null) {
         class="kw">return var2.equals(var1.getItemId());
      }

      if (var0.isItemExcluded(var1.getItemId())) {
         class="kw">return false;
      }

      String var3 = var0.getResourceTypeId();
      if (var3 != null && var1.getItem().getResourceTypes() != null) {
         for (ItemResourceType var7 : var1.getItem().getResourceTypes()) {
            if (var3.equals(var7.id)) {
               class="kw">return true;
            }
         }
      }

      class="kw">return false;
   }

   @Nonnull
   class="kw">public class="kw">static JsonArray generateInventoryHints(@Nonnull List<CraftingRecipe> var0, int var1, @Nonnull ItemContainer var2) {
      JsonArray var3 = new JsonArray();
      short var4 = 0;

      for (short var5 = var2.getCapacity(); var4 < var5; var4++) {
         ItemStack var6 = var2.getItemStack(var4);
         if (var6 != null && !var6.isEmpty() && matchesAnyRecipe(var0, var1, var6)) {
            var3.add(var4);
         }
      }

      class="kw">return var3;
   }

   class="kw">public class="kw">static boolean matchesAnyRecipe(@Nonnull List<CraftingRecipe> var0, int var1, @Nonnull ItemStack var2) {
      for (CraftingRecipe var4 : var0) {
         MaterialQuantity[] var5 = var4.getInput();
         if (var1 < var5.length && matches(var5[var1], var2)) {
            class="kw">return true;
         }
      }

      class="kw">return false;
   }

   class="kw">private class="kw">static int getMaterialCraftLimit(@Nonnull CraftingRecipe var0, @Nonnull ItemContainer var1) {
      MaterialQuantity[] var2 = var0.getInput();
      if (var2 != null && var2.length != 0) {
         int var3 = Integer.MAX_VALUE;
         boolean var4 = false;

         for (MaterialQuantity var8 : var2) {
            int var9 = var8.getQuantity();
            if (var9 > 0) {
               var4 = true;
               var3 = Math.min(var3, var1.countRemovableMaterial(var8) / var9);
               if (var3 == 0) {
                  break;
               }
            }
         }

         class="kw">return var4 ? var3 : 1;
      } else {
         class="kw">return 1;
      }
   }

   class="kw">private class="kw">static int getOutputCraftCeiling(@Nonnull Ref<EntityStore> var0, @Nonnull ComponentAccessor<EntityStore> var1, @Nonnull CraftingRecipe var2) {
      MaterialQuantity var3 = var2.getPrimaryOutput();
      String var4 = var3 != null ? var3.getItemId() : null;
      if (var4 == null) {
         class="kw">return 1;
      }

      int var5 = Math.max(1, var3.getQuantity());
      Item var6 = Item.getAssetMap().getAsset(var4);
      int var7 = var6 != null ? Math.max(1, var6.getMaxStack()) : 1;
      CombinedItemContainer var8 = InventoryComponent.getCombined(var1, var0, InventoryComponent.BACKPACK_STORAGE_HOTBAR);
      long var9 = (long)var8.getCapacity() * var7;
      class="kw">return (int)Math.max(1L, Math.min(var9 / var5, 2147483647L));
   }

   class="kw">public boolean startTierUpgrade(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2, @Nonnull BenchWindow var3) {
      if (this.upgradingJob != null) {
         class="kw">return false;
      }

      BenchUpgradeRequirement var4 = this.getBenchUpgradeRequirement(this.getBenchTierLevel(var2));
      if (var4 == null) {
         class="kw">return false;
      }

      List var5 = getInputMaterials(var4.getInput());
      if (var5.isEmpty()) {
         class="kw">return false;
      }

      Player var6 = var2.getComponent(var1, Player.getComponentType());
      assert var6 != null;
      if (var6.getGameMode() != GameMode.Creative) {
         CombinedItemContainer var7 = InventoryComponent.getCombined(var2, var1, InventoryComponent.BACKPACK_STORAGE_HOTBAR);
         CombinedItemContainer var8 = new CombinedItemContainer(var7, var3.getExtraResourcesSection().getItemContainer());
         if (!var8.canRemoveMaterials(var5)) {
            class="kw">return false;
         }
      }

      this.upgradingJob = new CraftingManager.BenchUpgradingJob(var3, var4.getTimeSeconds());
      this.cancelAllCrafting(var1, var2);
      class="kw">return true;
   }

   class="kw">private int finishTierUpgrade(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2) {
      if (this.upgradingJob == null) {
         class="kw">return 0;
      }

      World var3 = var2.getExternalData().getWorld();
      ChunkStore var4 = var3.getChunkStore();
      Ref var5 = var4.getChunkSectionReferenceAtBlock(this.x, this.y, this.z);
      if (var5 != null && var5.isValid()) {
         Ref var6 = BlockModule.getBlockEntity(var4.getStore(), var5, this.x, this.y, this.z);
         if (var6 == null) {
            class="kw">return 0;
         }

         BlockModule.BlockStateInfo var7 = var4.getStore().getComponent(var6, BlockModule.BlockStateInfo.getComponentType());
         if (var7 == null) {
            class="kw">return 0;
         }

         BenchBlock var8 = var4.getStore().getComponent(var6, BenchBlock.getComponentType());
         if (var8 != null && var8.getTierLevel() != 0) {
            BenchUpgradeRequirement var9 = this.getBenchUpgradeRequirement(var8.getTierLevel());
            if (var9 == null) {
               class="kw">return var8.getTierLevel();
            }

            List var10 = getInputMaterials(var9.getInput());
            if (var10.isEmpty()) {
               class="kw">return var8.getTierLevel();
            }

            Player var11 = var2.getComponent(var1, Player.getComponentType());
            assert var11 != null;
            boolean var12 = var11.getGameMode() == GameMode.Creative;
            if (!var12) {
               CombinedItemContainer var13 = InventoryComponent.getCombined(var2, var1, InventoryComponent.BACKPACK_STORAGE_HOTBAR);
               CombinedItemContainer var14 = new CombinedItemContainer(var13, this.upgradingJob.window.getExtraResourcesSection().getItemContainer());
               ListTransaction var15 = var14.removeMaterials(var10);
               if (var15.succeeded()) {
                  List var16 = new ObjectArrayList();

                  for (MaterialTransaction var18 : var15.getList()) {
                     for (MaterialSlotTransaction var20 : var18.getList()) {
                        var16.add(var20.getOutput());
                     }
                  }

                  var8.addUpgradeItems(var16);
                  var7.markNeedsSaving();
                  var12 = true;
               }
            }

            if (var12) {
               var8.setTierLevel(var8.getTierLevel() + 1);
               var7.markNeedsSaving();
               BlockSection var21 = var4.getStore().getComponent(var5, BlockSection.getComponentType());
               assert var21 != null;
               BlockType var22 = BenchBlock.getBaseBlockType(this.blockType);
               BlockOperations.setBlockInteractionState(var4, var5, this.x, this.y, this.z, var22, var8.getTierStateName(), true);
               ProcessingBenchBlock var23 = var4.getStore().getComponent(var6, ProcessingBenchBlock.getComponentType());
               if (var23 != null) {
                  int var24 = var21.getRotationIndex(this.x, this.y, this.z);
                  var23.setupSlots(var3, var8, var7, this.x, this.y, this.z, this.blockType, var24);
               }

               int var25 = var21.get(this.x, this.y, this.z);
               BlockType var26 = BlockType.getAssetMap().getAsset(var25);
               if (var26 != null && var26.getBench().getBenchUpgradeCompletedSoundEventIndex() != 0) {
                  SoundUtil.playSoundEvent3d(
                     var26.getBench().getBenchUpgradeCompletedSoundEventIndex(), SoundCategory.SFX, this.x + 0.5, this.y + 0.5, this.z + 0.5, var2
                  );
               }
            }

            class="kw">return var8.getTierLevel();
         } else {
            class="kw">return 0;
         }
      } else {
         class="kw">return 0;
      }
   }

   @Nullable
   class="kw">private BenchTierLevel getBenchTierLevelData(int var1) {
      if (this.blockType == null) {
         class="kw">return null;
      }

      Bench var2 = this.blockType.getBench();
      class="kw">return var2 == null ? null : var2.getTierLevel(var1);
   }

   @Nullable
   class="kw">private BenchUpgradeRequirement getBenchUpgradeRequirement(int var1) {
      BenchTierLevel var2 = this.getBenchTierLevelData(var1);
      class="kw">return var2 == null ? null : var2.getUpgradeRequirement();
   }

   class="kw">private int getBenchTierLevel(@Nonnull ComponentAccessor<EntityStore> var1) {
      World var2 = var1.getExternalData().getWorld();
      ChunkStore var3 = var2.getChunkStore();
      Ref var4 = BlockModule.getBlockEntity(var2, this.x, this.y, this.z);
      if (var4 == null) {
         class="kw">return 0;
      }

      BenchBlock var5 = var3.getStore().getComponent(var4, BenchBlock.getComponentType());
      class="kw">return var5 != null && var5.getTierLevel() != 0 ? var5.getTierLevel() : 0;
   }

   class="kw">private boolean benchHasRequiredAugmentTags(@Nonnull ComponentAccessor<EntityStore> var1, @Nonnull BenchRequirement var2) {
      String[] var3 = var2.requiredAugmentTags;
      if (var3 != null && var3.length != 0) {
         Set var4 = this.getBenchGrantedAugmentTags(var1);

         for (String var8 : var3) {
            if (!var4.contains(var8)) {
               class="kw">return false;
            }
         }

         class="kw">return true;
      } else {
         class="kw">return true;
      }
   }

   @Nonnull
   class="kw">private Set<String> getBenchGrantedAugmentTags(@Nonnull ComponentAccessor<EntityStore> var1) {
      World var2 = var1.getExternalData().getWorld();
      ChunkStore var3 = var2.getChunkStore();
      Ref var4 = BlockModule.getBlockEntity(var2, this.x, this.y, this.z);
      if (var4 == null) {
         class="kw">return Set.of();
      }

      BenchBlock var5 = var3.getStore().getComponent(var4, BenchBlock.getComponentType());
      if (var5 == null) {
         class="kw">return Set.of();
      }

      BenchBlock.refreshGrantedAugmentTags(var3.getStore(), var4, new Vector3i(this.x, this.y, this.z));
      class="kw">return var5.getGrantedAugmentTags();
   }

   class="kw">public class="kw">static int feedExtraResourcesSection(
      @Nonnull World var0,
      int var1,
      int var2,
      int var3,
      @Nonnull BlockType var4,
      int var5,
      @Nonnull Bench var6,
      int var7,
      @Nonnull MaterialExtraResourcesSection var8
   ) {
      CraftingManager.ChestLookupResult var9 = getContainersAroundBench(var0, var1, var2, var3, var4, var5);
      List var10 = var9.containers;
      List var11 = var9.states;
      ItemContainer var12 = EmptyItemContainer.INSTANCE;
      if (!var10.isEmpty()) {
         var12 = new CombinedItemContainer(var10.stream().map(var0x -> {
            DelegateItemContainer var1 = new DelegateItemContainer<>(var0x);
            var1.setGlobalFilter(FilterType.ALLOW_OUTPUT_ONLY);
            class="kw">return var1;
         }).toArray(ItemContainer[]::new));
      }

      Map var13 = new Object2ObjectOpenHashMap();

      for (ItemContainer var15 : var10) {
         var15.forEach((var3x, var4x) -> {
            if (CraftingPlugin.isValidUpgradeMaterialForBench(var6, var7, var4x) || CraftingPlugin.isValidCraftingMaterialForBench(var6, var4x)) {
               ItemQuantity var10000 = var13.computeIfAbsent(var4x.getItemId(), var1x -> new ItemQuantity(var4x.getItemId(), 0));
               var10000.quantity = var10000.quantity + var4x.getQuantity();
            }
         });
      }

      var8.setItemContainer(var12);
      var8.setExtraMaterials(var13.values().toArray(new ItemQuantity[0]));
      var8.setValid(true);
      class="kw">return var11.size();
   }

   @Nonnull
   class="kw">protected class="kw">static CraftingManager.ChestLookupResult getContainersAroundBench(
      @Nonnull World var0, int var1, int var2, int var3, @Nonnull BlockType var4, int var5
   ) {
      List var6 = new ObjectArrayList();
      List var7 = new ObjectArrayList();
      List var8 = new ObjectArrayList();
      Store var9 = var0.getChunkStore().getStore();
      int var10 = var0.getGameplayConfig().getCraftingConfig().getBenchMaterialChestLimit();
      double var11 = var0.getGameplayConfig().getCraftingConfig().getBenchMaterialHorizontalChestSearchRadius();
      double var13 = var0.getGameplayConfig().getCraftingConfig().getBenchMaterialVerticalChestSearchRadius();
      Vector3d var15 = new Vector3d(var1, var2, var3);
      BlockBoundingBoxes var16 = BlockBoundingBoxes.getAssetMap().getAsset(var4.getHitboxTypeIndex());
      BlockBoundingBoxes.RotatedVariantBoxes var17 = var16.get(var5);
      Box var18 = var17.getBoundingBox();
      double var19 = var18.width();
      double var21 = var18.height();
      double var23 = var18.depth();
      double var25 = Math.max(var19, Math.max(var23, var21)) - 1.0;
      SpatialResource var27 = var9.getResource(BlockModule.get().getItemContainerSpatialResourceType());
      List var28 = SpatialResource.getThreadLocalReferenceList();
      var27.getSpatialStructure().ordered3DAxis(var15, var11 + var25, var13 + var25, var11 + var25, var28);
      if (!var28.isEmpty()) {
         int var29 = (int)Math.floor(var18.min.x);
         int var30 = (int)Math.floor(var18.min.y);
         int var31 = (int)Math.floor(var18.min.z);
         int var32 = (int)Math.ceil(var18.max.x) - 1;
         int var33 = (int)Math.ceil(var18.max.y) - 1;
         int var34 = (int)Math.ceil(var18.max.z) - 1;
         double var35 = var15.x + var29 - var11;
         double var37 = var15.y + var30 - var13;
         double var39 = var15.z + var31 - var11;
         double var41 = var15.x + var32 + var11;
         double var43 = var15.y + var33 + var13;
         double var45 = var15.z + var34 + var11;

         for (Ref var48 : var28) {
            if (var48.isValid()) {
               ItemContainerBlock var49 = var9.getComponent(var48, ItemContainerBlock.getComponentType());
               if (var49 != null) {
                  BlockModule.BlockStateInfo var50 = var9.getComponent(var48, BlockModule.BlockStateInfo.getComponentType());
                  if (var50 != null) {
                     ChunkSection var51 = var9.getComponent(var50.getSectionRef(), ChunkSection.getComponentType());
                     if (var51 != null) {
                        int var52 = ChunkUtil.worldCoordFromLocalCoord(var51.getX(), ChunkUtil.xFromIndex(var50.getIndex()));
                        int var53 = ChunkUtil.worldCoordFromLocalCoord(var51.getY(), ChunkUtil.yFromIndex(var50.getIndex()));
                        int var54 = ChunkUtil.worldCoordFromLocalCoord(var51.getZ(), ChunkUtil.zFromIndex(var50.getIndex()));
                        if (var52 >= var35 && var52 <= var41 && var53 >= var37 && var53 <= var43 && var54 >= var39 && var54 <= var45) {
                           var6.add(var49.getItemContainer());
                           var7.add(var49);
                           if (var6.size() >= var10) {
                              break;
                           }
                        } else {
                           var8.add(var49);
                        }
                     }
                  }
               }
            }
         }
      }

      class="kw">return new CraftingManager.ChestLookupResult(var6, var7, var8, var15);
   }

   @Nonnull
   @Override
   class="kw">public String toString() {
      class="kw">return "CraftingManager{queuedCraftingJobs="
         + this.queuedCraftingJobs
         + ", x="
         + this.x
         + ", y="
         + this.y
         + ", z="
         + this.z
         + ", blockType="
         + this.blockType
         + "}";
   }

   @Nonnull
   @Override
   class="kw">public Component<EntityStore> clone() {
      class="kw">return new CraftingManager(this);
   }

   class="kw">private class="kw">static class BenchUpgradingJob {
      @Nonnull
      class="kw">private class="kw">final BenchWindow window;
      class="kw">private class="kw">final float timeSeconds;
      class="kw">private float timeSecondsCompleted;
      class="kw">private float lastSentPercent;

      class="kw">private BenchUpgradingJob(@Nonnull BenchWindow var1, float var2) {
         this.window = var1;
         this.timeSeconds = var2;
      }

      @Nonnull
      @Override
      class="kw">public String toString() {
         class="kw">return "BenchUpgradingJob{window=" + this.window + ", timeSeconds=" + this.timeSeconds + "}";
      }

      class="kw">public float computeLoadingPercent() {
         class="kw">return this.timeSeconds <= 0.0F ? 1.0F : Math.min(this.timeSecondsCompleted / this.timeSeconds, 1.0F);
      }
   }

   class="kw">protected record ChestLookupResult(
      List<ItemContainer> containers, List<ItemContainerBlock> states, List<ItemContainerBlock> filteredOut, Vector3d benchCenteredPos
   ) {
      class="kw">protected ChestLookupResult {
      }
   }

   class="kw">private class="kw">static class CraftingJob {
      @Nonnull
      class="kw">private class="kw">final CraftingWindow window;
      class="kw">private class="kw">final int transactionId;
      @Nonnull
      class="kw">private class="kw">final CraftingRecipe recipe;
      class="kw">private class="kw">final int quantity;
      class="kw">private class="kw">final float timeSeconds;
      @Nonnull
      class="kw">private class="kw">final ItemContainer inputItemContainer;
      @Nonnull
      class="kw">private class="kw">final CraftingManager.InputRemovalType inputRemovalType;
      @Nonnull
      class="kw">private class="kw">final Int2ObjectMap<List<ItemStack>> removedItems = new Int2ObjectOpenHashMap();
      class="kw">private int quantityStarted;
      class="kw">private int quantityCompleted;
      class="kw">private float timeSecondsCompleted;

      class="kw">public CraftingJob(
         @Nonnull CraftingWindow var1,
         int var2,
         @Nonnull CraftingRecipe var3,
         int var4,
         float var5,
         @Nonnull ItemContainer var6,
         @Nonnull CraftingManager.InputRemovalType var7
      ) {
         this.window = var1;
         this.transactionId = var2;
         this.recipe = var3;
         this.quantity = var4;
         this.timeSeconds = var5;
         this.inputItemContainer = var6;
         this.inputRemovalType = var7;
      }

      @Nonnull
      @Override
      class="kw">public String toString() {
         class="kw">return "CraftingJob{window="
            + this.window
            + ", transactionId="
            + this.transactionId
            + ", recipe="
            + this.recipe
            + ", quantity="
            + this.quantity
            + ", timeSeconds="
            + this.timeSeconds
            + ", inputItemContainer="
            + this.inputItemContainer
            + ", inputRemovalType="
            + this.inputRemovalType
            + ", removedItems="
            + this.removedItems
            + ", quantityStarted="
            + this.quantityStarted
            + ", quantityCompleted="
            + this.quantityCompleted
            + ", timeSecondsCompleted="
            + this.timeSecondsCompleted
            + "}";
      }
   }

   class="kw">public enum InputRemovalType {
      NORMAL,
      ORDERED;

      InputRemovalType() {
      }
   }
}