From a407c067af280a276b84e8f6fa2aa75f4e7e146c Mon Sep 17 00:00:00 2001
From: ybw0014
Date: Sun, 7 Jan 2024 22:10:26 -0500
Subject: [PATCH] refactor: cache (#28)
---
.../fastmachines/core/recipes/IRecipe.java | 2 +-
.../fastmachines/core/recipes/RawRecipe.java | 8 +
.../abstracts/AbstractFastMachine.java | 419 ------------------
.../{abstracts => generic}/AFastMachine.java | 8 +-
.../AInfinityMachine.java | 8 +-
.../machines/generic/AbstractFastMachine.java | 180 ++++++++
.../machines/generic/FastMachineCache.java | 273 ++++++++++++
.../FastInfinityWorkbench.java | 2 +-
.../slimeframe/FastSlimeFrameFoundry.java | 2 +-
.../machines/slimefun/FastArmorForge.java | 2 +-
.../machines/slimefun/FastComposter.java | 2 +-
.../machines/slimefun/FastCompressor.java | 2 +-
.../slimefun/FastEnhancedCraftingTable.java | 2 +-
.../machines/slimefun/FastGrindStone.java | 2 +-
.../items/machines/slimefun/FastJuicer.java | 2 +-
.../machines/slimefun/FastMagicWorkbench.java | 2 +-
.../machines/slimefun/FastOreCrusher.java | 2 +-
.../machines/slimefun/FastOreWasher.java | 2 +-
.../machines/slimefun/FastPanningMachine.java | 2 +-
.../slimefun/FastPressureChamber.java | 2 +-
.../items/machines/slimefun/FastSmeltery.java | 2 +-
.../items/machines/slimefun/FastTableSaw.java | 2 +-
.../machines/vanilla/FastCraftingTable.java | 2 +-
.../items/machines/vanilla/FastFurnace.java | 2 +-
.../fastmachines/utils/RecipeUtils.java | 15 +-
25 files changed, 500 insertions(+), 447 deletions(-)
delete mode 100644 src/main/java/net/guizhanss/fastmachines/items/machines/abstracts/AbstractFastMachine.java
rename src/main/java/net/guizhanss/fastmachines/items/machines/{abstracts => generic}/AFastMachine.java (83%)
rename src/main/java/net/guizhanss/fastmachines/items/machines/{abstracts => generic}/AInfinityMachine.java (83%)
create mode 100644 src/main/java/net/guizhanss/fastmachines/items/machines/generic/AbstractFastMachine.java
create mode 100644 src/main/java/net/guizhanss/fastmachines/items/machines/generic/FastMachineCache.java
diff --git a/src/main/java/net/guizhanss/fastmachines/core/recipes/IRecipe.java b/src/main/java/net/guizhanss/fastmachines/core/recipes/IRecipe.java
index 97a63cc..52ed8b9 100644
--- a/src/main/java/net/guizhanss/fastmachines/core/recipes/IRecipe.java
+++ b/src/main/java/net/guizhanss/fastmachines/core/recipes/IRecipe.java
@@ -7,7 +7,7 @@
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
-import net.guizhanss.fastmachines.items.machines.abstracts.AbstractFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AbstractFastMachine;
/**
* This interface represents a recipe used by a {@link AbstractFastMachine}.
diff --git a/src/main/java/net/guizhanss/fastmachines/core/recipes/RawRecipe.java b/src/main/java/net/guizhanss/fastmachines/core/recipes/RawRecipe.java
index ddd417e..1fc794a 100644
--- a/src/main/java/net/guizhanss/fastmachines/core/recipes/RawRecipe.java
+++ b/src/main/java/net/guizhanss/fastmachines/core/recipes/RawRecipe.java
@@ -4,6 +4,14 @@
import org.bukkit.inventory.ItemStack;
+/**
+ * A temporary class used to store a pair of input and output. This class is used before registering recipes.
+ *
+ * @param input
+ * The input {@link ItemStack}s.
+ * @param output
+ * The output {@link ItemStack}s.
+ */
public record RawRecipe(ItemStack[] input, ItemStack[] output) {
@Override
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/abstracts/AbstractFastMachine.java b/src/main/java/net/guizhanss/fastmachines/items/machines/abstracts/AbstractFastMachine.java
deleted file mode 100644
index a1375a3..0000000
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/abstracts/AbstractFastMachine.java
+++ /dev/null
@@ -1,419 +0,0 @@
-package net.guizhanss.fastmachines.items.machines.abstracts;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-import com.google.common.base.Preconditions;
-
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.entity.Player;
-import org.bukkit.event.block.BlockBreakEvent;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.ItemMeta;
-
-import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
-import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
-import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
-import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
-import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.blocks.BlockPosition;
-import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;
-import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
-import io.github.thebusybiscuit.slimefun4.utils.LoreBuilder;
-
-import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
-import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
-
-import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.core.recipes.IRecipe;
-import net.guizhanss.fastmachines.core.recipes.RandomRecipe;
-import net.guizhanss.fastmachines.setup.Groups;
-import net.guizhanss.fastmachines.utils.BlockStorageUtils;
-import net.guizhanss.fastmachines.utils.Heads;
-import net.guizhanss.fastmachines.utils.Keys;
-import net.guizhanss.fastmachines.utils.MachineUtils;
-import net.guizhanss.guizhanlib.minecraft.utils.ItemUtil;
-import net.guizhanss.guizhanlib.slimefun.machines.TickingMenuBlock;
-
-/**
- * A fast machine is a basic machine but uses energy to fast craft from the given materials.
- *
- * Idea from FinalTECH.
- *
- * @author Final_ROOT
- * @author ybw0014
- */
-@SuppressWarnings("ConstantConditions")
-public abstract class AbstractFastMachine extends TickingMenuBlock implements EnergyNetComponent {
-
- // slots
- protected static final int[] INPUT_SLOTS = new int[] {
- 0, 1, 2, 3, 4, 5, 6, 7, 8,
- 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, 31, 32, 33, 34, 35
- };
- protected static final int[] OUTPUT_SLOTS = new int[] {
- 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 0, 1, 2, 3, 4, 5, 6, 7, 8,
- };
- protected static final int[] PREVIEW_SLOTS = new int[] {
- 36, 37, 38, 39, 40, 41,
- 45, 46, 47, 48, 49, 50
- };
- protected static final int SCROLL_UP_SLOT = 42;
- protected static final int SCROLL_DOWN_SLOT = 51;
- protected static final int CHOICE_SLOT = 52;
- protected static final int CRAFT_SLOT = 53;
- protected static final int CHOICE_INDICATOR_SLOT = 43;
- protected static final int INFO_SLOT = 44;
-
- // constants
- protected static final int ITEMS_PER_PAGE = PREVIEW_SLOTS.length;
- protected static final String KEY_CHOICE = "choice";
-
- // menu items
- protected static final ItemStack SCROLL_UP_ITEM = FastMachines.getLocalization().getItem(
- "SCROLL_UP", Heads.ARROW_UP.getTexture());
- protected static final ItemStack SCROLL_DOWN_ITEM = FastMachines.getLocalization().getItem(
- "SCROLL_DOWN", Heads.ARROW_DOWN.getTexture());
- protected static final ItemStack CHOICE_INDICATOR_ITEM = FastMachines.getLocalization().getItem(
- "CHOICE_INDICATOR", Material.YELLOW_STAINED_GLASS_PANE);
- protected static final ItemStack INFO_ITEM = FastMachines.getLocalization().getItem(
- "INFO", Heads.INFO.getTexture());
- protected static final ItemStack NO_ITEM = FastMachines.getLocalization().getItem(
- "NO_ITEM", Material.BARRIER);
-
- // outputs map
- protected static final Map> OUTPUTS_MAP = new HashMap<>();
-
- protected final List recipes = new ArrayList<>();
-
- @ParametersAreNonnullByDefault
- protected AbstractFastMachine(SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
- super(Groups.MACHINES, item, recipeType, recipe);
- }
-
- @Nonnull
- @Override
- public EnergyNetComponentType getEnergyComponentType() {
- return EnergyNetComponentType.CONSUMER;
- }
-
- // Also getCapacity() which is already defined.
- public abstract int getEnergyPerUse();
-
- @Override
- protected void setup(@Nonnull BlockMenuPreset preset) {
- for (int slot : PREVIEW_SLOTS) {
- preset.addItem(slot, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
- }
- preset.addItem(CHOICE_INDICATOR_SLOT, CHOICE_INDICATOR_ITEM, ChestMenuUtils.getEmptyClickHandler());
- preset.addItem(INFO_SLOT, INFO_ITEM, ChestMenuUtils.getEmptyClickHandler());
- preset.addItem(CHOICE_SLOT, NO_ITEM, ChestMenuUtils.getEmptyClickHandler());
- preset.addItem(SCROLL_UP_SLOT, SCROLL_UP_ITEM, ChestMenuUtils.getEmptyClickHandler());
- preset.addItem(SCROLL_DOWN_SLOT, SCROLL_DOWN_ITEM, ChestMenuUtils.getEmptyClickHandler());
-
- ItemStack craftItem = ItemUtil.appendLore(
- getCraftItem(),
- "",
- LoreBuilder.power(getEnergyPerUse(), FastMachines.getLocalization().getString("lores.per-craft"))
- );
- preset.addItem(CRAFT_SLOT, craftItem, ChestMenuUtils.getEmptyClickHandler());
- }
-
- @Override
- @ParametersAreNonnullByDefault
- protected void onNewInstance(BlockMenu blockMenu, Block block) {
- BlockPosition pos = new BlockPosition(block);
- blockMenu.addMenuClickHandler(SCROLL_UP_SLOT, (player, i, itemStack, clickAction) -> {
- int currentPage = BlockStorageUtils.getInt(pos, "page", 1);
- BlockStorageUtils.setInt(pos, "page", currentPage - 1);
- updateMenu(blockMenu);
- return false;
- });
- blockMenu.addMenuClickHandler(SCROLL_DOWN_SLOT, (player, i, itemStack, clickAction) -> {
- int currentPage = BlockStorageUtils.getInt(pos, "page", 1);
- BlockStorageUtils.setInt(pos, "page", currentPage + 1);
- updateMenu(blockMenu);
- return false;
- });
- blockMenu.addMenuClickHandler(CRAFT_SLOT, (player, i, itemStack, clickAction) -> {
- if (clickAction.isShiftClicked()) {
- if (clickAction.isRightClicked()) {
- craft(blockMenu, player, Integer.MAX_VALUE);
- } else {
- craft(blockMenu, player, 64);
- }
- } else {
- if (clickAction.isRightClicked()) {
- craft(blockMenu, player, 16);
- } else {
- craft(blockMenu, player, 1);
- }
- }
- return false;
- });
- }
-
- @Override
- @ParametersAreNonnullByDefault
- protected void tick(Block block, BlockMenu blockMenu) {
- if (blockMenu.hasViewer() && FastMachines.getSlimefunTickCount() % 2 == 0) {
- // Calculate machine inputs
- findAvailableOutputs(blockMenu);
- // Display available outputs
- updateMenu(blockMenu);
- }
- }
-
- @Override
- public int[] getInputSlots() {
- return INPUT_SLOTS;
- }
-
- @Override
- public int[] getOutputSlots() {
- // Basic machines should not support cargo access
- return new int[0];
- }
-
- @Override
- public void register(@Nonnull SlimefunAddon addon) {
- super.register(addon);
- FastMachines.getScheduler().run(2, this::registerRecipes);
- }
-
- @Override
- @ParametersAreNonnullByDefault
- protected void onBreak(BlockBreakEvent e, BlockMenu menu) {
- super.onBreak(e, menu);
- Location l = menu.getLocation();
- menu.dropItems(l, INPUT_SLOTS);
- }
-
- @Nonnull
- protected Map getMachineOutputs(@Nonnull BlockMenu menu) {
- BlockPosition pos = new BlockPosition(menu.getLocation());
- var outputs = OUTPUTS_MAP.getOrDefault(pos, new LinkedHashMap<>());
- OUTPUTS_MAP.put(pos, outputs);
- return outputs;
- }
-
- /**
- * Find all the available outputs based on the given inputs.
- *
- * @param blockMenu
- * The {@link BlockMenu} of this machine.
- */
- @ParametersAreNonnullByDefault
- protected void findAvailableOutputs(BlockMenu blockMenu) {
- BlockPosition pos = new BlockPosition(blockMenu.getLocation());
- Map machineInputs = MachineUtils.getMachineInputAmount(blockMenu, INPUT_SLOTS);
- var outputs = getMachineOutputs(blockMenu);
- outputs.clear();
-
- if (machineInputs.isEmpty()) {
- return;
- }
-
- FastMachines.debug("current machine: {0}, location: {1}", getClass().getSimpleName(), pos);
- FastMachines.debug("machine inputs: {0}", machineInputs);
-
- // Fetch available recipes based on inputs
- for (var recipe : recipes) {
- if (recipe.isDisabledInWorld(pos.getWorld())) {
- continue;
- }
-
- FastMachines.debug("checking recipe: {0}", recipe);
-
- // stores the possible maximum output amount
- int outputAmount = Integer.MAX_VALUE;
-
- for (var recipeInputEntry : recipe.getInput().entrySet()) {
-
- // if the current recipe input isn't in the machine input, just ignore this
- if (!machineInputs.containsKey(recipeInputEntry.getKey())) {
- outputAmount = 0;
- break;
- }
-
- FastMachines.debug("input: {0}, machine amount: {1}", recipeInputEntry.getKey(),
- machineInputs.get(recipeInputEntry.getKey()));
- FastMachines.debug("recipe amount: {0}", recipeInputEntry.getValue());
-
- // check the maximum possible output amount based on inputs
- int inputAmount = machineInputs.get(recipeInputEntry.getKey());
- int recipeAmount = recipeInputEntry.getValue();
- outputAmount = Math.min(outputAmount, inputAmount / recipeAmount);
-
- FastMachines.debug("result amount: {0}", inputAmount / recipeAmount);
- }
-
- // this recipe is available
- if (outputAmount > 0) {
- FastMachines.debug("recipe is available, output amount: {0}", outputAmount);
- outputs.put(recipe, outputAmount);
- }
- }
-
- FastMachines.debug("outputs: " + outputs);
- }
-
- @ParametersAreNonnullByDefault
- protected void updateMenu(BlockMenu blockMenu) {
- BlockPosition pos = new BlockPosition(blockMenu.getLocation());
- var outputs = getMachineOutputs(blockMenu);
- ItemStack[] outputItems =
- outputs.keySet().stream().map(recipe -> recipe.getOutput(pos.getWorld())).toArray(ItemStack[]::new);
- int currentPage = BlockStorageUtils.getInt(pos, "page", 1);
- int totalPages = (int) Math.ceil(outputs.size() * 1.0 / ITEMS_PER_PAGE);
- // limit the page in range
- if (currentPage < 1) {
- currentPage = 1;
- BlockStorageUtils.setInt(pos, "page", 1);
- }
- if (currentPage > totalPages) {
- currentPage = totalPages;
- BlockStorageUtils.setInt(pos, "page", totalPages);
- }
-
- for (int i = 0; i < ITEMS_PER_PAGE; i++) {
- int index = (currentPage - 1) * ITEMS_PER_PAGE + i;
- if (totalPages == 0 || index >= outputs.size()) {
- blockMenu.replaceExistingItem(PREVIEW_SLOTS[i], ChestMenuUtils.getBackground());
- blockMenu.addMenuClickHandler(PREVIEW_SLOTS[i], ChestMenuUtils.getEmptyClickHandler());
- continue;
- }
- ItemStack output = getDisplayItem(outputItems[index]);
- blockMenu.replaceExistingItem(PREVIEW_SLOTS[i], output);
- blockMenu.addMenuClickHandler(PREVIEW_SLOTS[i], ((player, slot, itemStack, clickAction) -> {
- BlockStorageUtils.setInt(pos, KEY_CHOICE, index);
- updateChoice(blockMenu);
- return false;
- }));
- }
-
- updateChoice(blockMenu);
- }
-
- @ParametersAreNonnullByDefault
- protected void updateChoice(BlockMenu blockMenu) {
- BlockPosition pos = new BlockPosition(blockMenu.getLocation());
- var outputs = getMachineOutputs(blockMenu);
- ItemStack[] outputItems =
- outputs.keySet().stream().map(recipe -> recipe.getOutput(pos.getWorld())).toArray(ItemStack[]::new);
-
- int choice = BlockStorageUtils.getInt(pos, KEY_CHOICE);
- if (choice >= outputs.size()) {
- blockMenu.replaceExistingItem(CHOICE_SLOT, NO_ITEM);
- } else {
- ItemStack output = getDisplayItem(outputItems[choice]);
- blockMenu.replaceExistingItem(CHOICE_SLOT, output);
- }
- }
-
- @ParametersAreNonnullByDefault
- protected void craft(BlockMenu blockMenu, Player p, int amount) {
- Preconditions.checkArgument(amount > 0, "amount must greater than 0");
-
- BlockPosition pos = new BlockPosition(blockMenu.getLocation());
- var outputs = getMachineOutputs(blockMenu);
- var outputRecipes = outputs.entrySet().stream().toList();
-
- int choice = BlockStorageUtils.getInt(pos, KEY_CHOICE);
- // invalid choice, due to previous selection not available anymore
- if (choice >= outputs.size()) {
- return;
- }
- var recipe = outputRecipes.get(choice);
- int maxAmount = recipe.getValue();
- amount = Math.min(maxAmount, amount);
-
- // check if the machine has enough energy
- if (FastMachines.getAddonConfig().getBoolean("fast-machines.use-energy")) {
- int energyNeeded = getEnergyPerUse() * amount;
- int currentEnergy = getCharge(blockMenu.getLocation());
- if (currentEnergy < energyNeeded) {
- FastMachines.getLocalization().sendMessage(p, "not-enough-energy");
- return;
- }
- setCharge(blockMenu.getLocation(), currentEnergy - energyNeeded);
- }
-
- // remove recipe inputs
- for (var inputEntry : recipe.getKey().getInput().entrySet()) {
- int requiredAmount = inputEntry.getValue() * amount;
- var itemAmount = MachineUtils.getItemAmount(blockMenu, INPUT_SLOTS, inputEntry.getKey());
- // total amount is less than required amount, usually shouldn't happen
- if (itemAmount.getSecondValue() < requiredAmount) {
- FastMachines.getLocalization().sendMessage(p, "not-enough-materials");
- return;
- }
- // remove items from machine
- MachineUtils.removeItems(blockMenu, itemAmount.getFirstValue().stream().mapToInt(Integer::intValue).toArray(),
- inputEntry.getKey(), requiredAmount);
- }
-
- // push the product
- if (recipe.getKey() instanceof RandomRecipe randomRecipe) {
- boolean machineFull = false;
- for (int i = 0; i < amount; i++) {
- ItemStack product = randomRecipe.getOutput(pos.getWorld()).clone();
- if (MachineUtils.addItem(p, blockMenu, OUTPUT_SLOTS, product, 1)) {
- machineFull = true;
- }
- }
- if (machineFull) {
- FastMachines.getLocalization().sendMessage(p, "not-enough-space");
- }
- } else {
- ItemStack product = recipe.getKey().getOutput(pos.getWorld()).clone();
- if (MachineUtils.addItem(p, blockMenu, OUTPUT_SLOTS, product, amount)) {
- FastMachines.getLocalization().sendMessage(p, "not-enough-space");
- }
- }
- }
-
- /**
- * Get the {@link ItemStack} that is used to display in the preview slots.
- *
- * @param item
- * The original {@link ItemStack}.
- *
- * @return The new {@link ItemStack} that is used to display.
- */
- @Nonnull
- protected ItemStack getDisplayItem(@Nonnull ItemStack item) {
- ItemStack newItem = item.clone();
- ItemMeta meta = newItem.getItemMeta();
- PersistentDataAPI.setBoolean(meta, Keys.get("display"), true);
- newItem.setItemMeta(meta);
- return newItem;
- }
-
- /**
- * Register available recipes for this machine.
- *
- * Note: this method is called synchronously after server completes loading.
- */
- protected abstract void registerRecipes();
-
- /**
- * Get the item that shows the craft button of this machine.
- *
- * @return the item that shows the craft button of this machine.
- */
- protected abstract ItemStack getCraftItem();
-}
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/abstracts/AFastMachine.java b/src/main/java/net/guizhanss/fastmachines/items/machines/generic/AFastMachine.java
similarity index 83%
rename from src/main/java/net/guizhanss/fastmachines/items/machines/abstracts/AFastMachine.java
rename to src/main/java/net/guizhanss/fastmachines/items/machines/generic/AFastMachine.java
index ec72953..888363d 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/abstracts/AFastMachine.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/generic/AFastMachine.java
@@ -1,4 +1,4 @@
-package net.guizhanss.fastmachines.items.machines.abstracts;
+package net.guizhanss.fastmachines.items.machines.generic;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -8,6 +8,12 @@
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
+/**
+ * General abstract class for Fast Machines.
+ * The default energy per use is 8 and the default capacity is 1024.
+ *
+ * @author ybw0014
+ */
public abstract class AFastMachine extends AbstractFastMachine {
private final IntRangeSetting energyPerUse = new IntRangeSetting(this, "energy-per-use", 0, 8,
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/abstracts/AInfinityMachine.java b/src/main/java/net/guizhanss/fastmachines/items/machines/generic/AInfinityMachine.java
similarity index 83%
rename from src/main/java/net/guizhanss/fastmachines/items/machines/abstracts/AInfinityMachine.java
rename to src/main/java/net/guizhanss/fastmachines/items/machines/generic/AInfinityMachine.java
index 8289e09..bfaad4f 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/abstracts/AInfinityMachine.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/generic/AInfinityMachine.java
@@ -1,4 +1,4 @@
-package net.guizhanss.fastmachines.items.machines.abstracts;
+package net.guizhanss.fastmachines.items.machines.generic;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -8,6 +8,12 @@
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
+/**
+ * General abstract class for Infinity Fast Machines.
+ * The default energy per use is 10m and the default capacity is 100m.
+ *
+ * @author ybw0014
+ */
public abstract class AInfinityMachine extends AbstractFastMachine {
private final IntRangeSetting energyPerUse = new IntRangeSetting(this, "energy-per-use", 0, 10_000_000,
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/generic/AbstractFastMachine.java b/src/main/java/net/guizhanss/fastmachines/items/machines/generic/AbstractFastMachine.java
new file mode 100644
index 0000000..6cc17c1
--- /dev/null
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/generic/AbstractFastMachine.java
@@ -0,0 +1,180 @@
+package net.guizhanss.fastmachines.items.machines.generic;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.inventory.ItemStack;
+
+import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
+import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
+import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
+import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
+import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
+import io.github.thebusybiscuit.slimefun4.libraries.dough.blocks.BlockPosition;
+import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
+import io.github.thebusybiscuit.slimefun4.utils.LoreBuilder;
+
+import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
+import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
+
+import net.guizhanss.fastmachines.FastMachines;
+import net.guizhanss.fastmachines.core.recipes.IRecipe;
+import net.guizhanss.fastmachines.setup.Groups;
+import net.guizhanss.fastmachines.utils.Heads;
+import net.guizhanss.guizhanlib.minecraft.utils.ItemUtil;
+import net.guizhanss.guizhanlib.slimefun.machines.TickingMenuBlock;
+
+import lombok.Getter;
+
+/**
+ * A fast machine is a basic machine but uses energy to fast craft from the given materials.
+ *
+ * Idea from FinalTECH.
+ *
+ * @author Final_ROOT
+ * @author ybw0014
+ */
+@SuppressWarnings("ConstantConditions")
+public abstract class AbstractFastMachine extends TickingMenuBlock implements EnergyNetComponent {
+ // outputs map
+ protected static final Map> OUTPUTS_MAP = new HashMap<>();
+ // slots
+ static final int[] INPUT_SLOTS = new int[] {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35
+ };
+ static final int[] OUTPUT_SLOTS = new int[] {
+ 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ };
+ static final int[] PREVIEW_SLOTS = new int[] {
+ 36, 37, 38, 39, 40, 41,
+ 45, 46, 47, 48, 49, 50
+ };
+ static final int SCROLL_UP_SLOT = 42;
+ static final int SCROLL_DOWN_SLOT = 51;
+ static final int CHOICE_SLOT = 52;
+ static final int CRAFT_SLOT = 53;
+ static final int CHOICE_INDICATOR_SLOT = 43;
+ static final int INFO_SLOT = 44;
+ // constants
+ static final int ITEMS_PER_PAGE = PREVIEW_SLOTS.length;
+ // menu items
+ static final ItemStack NO_ITEM = FastMachines.getLocalization().getItem(
+ "NO_ITEM", Material.BARRIER);
+ static final ItemStack SCROLL_UP_ITEM = FastMachines.getLocalization().getItem(
+ "SCROLL_UP", Heads.ARROW_UP.getTexture());
+ static final ItemStack SCROLL_DOWN_ITEM = FastMachines.getLocalization().getItem(
+ "SCROLL_DOWN", Heads.ARROW_DOWN.getTexture());
+ static final ItemStack CHOICE_INDICATOR_ITEM = FastMachines.getLocalization().getItem(
+ "CHOICE_INDICATOR", Material.YELLOW_STAINED_GLASS_PANE);
+ static final ItemStack INFO_ITEM = FastMachines.getLocalization().getItem(
+ "INFO", Heads.INFO.getTexture());
+
+ @Getter
+ protected final List recipes = new ArrayList<>();
+
+ private final Map CACHES = new HashMap<>();
+
+ @ParametersAreNonnullByDefault
+ protected AbstractFastMachine(SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
+ super(Groups.MACHINES, item, recipeType, recipe);
+ }
+
+ @Nonnull
+ @Override
+ public EnergyNetComponentType getEnergyComponentType() {
+ return EnergyNetComponentType.CONSUMER;
+ }
+
+ // Also getCapacity() which is already defined.
+ public abstract int getEnergyPerUse();
+
+ @Override
+ protected void setup(@Nonnull BlockMenuPreset preset) {
+ for (int slot : PREVIEW_SLOTS) {
+ preset.addItem(slot, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
+ }
+ preset.addItem(CHOICE_INDICATOR_SLOT, CHOICE_INDICATOR_ITEM, ChestMenuUtils.getEmptyClickHandler());
+ preset.addItem(INFO_SLOT, INFO_ITEM, ChestMenuUtils.getEmptyClickHandler());
+ preset.addItem(CHOICE_SLOT, NO_ITEM, ChestMenuUtils.getEmptyClickHandler());
+ preset.addItem(SCROLL_UP_SLOT, SCROLL_UP_ITEM, ChestMenuUtils.getEmptyClickHandler());
+ preset.addItem(SCROLL_DOWN_SLOT, SCROLL_DOWN_ITEM, ChestMenuUtils.getEmptyClickHandler());
+
+ ItemStack craftItem = ItemUtil.appendLore(
+ getCraftItem(),
+ "",
+ LoreBuilder.power(getEnergyPerUse(), FastMachines.getLocalization().getString("lores.per-craft"))
+ );
+ preset.addItem(CRAFT_SLOT, craftItem, ChestMenuUtils.getEmptyClickHandler());
+ }
+
+ @Override
+ @ParametersAreNonnullByDefault
+ protected void onNewInstance(BlockMenu menu, Block block) {
+ BlockPosition pos = new BlockPosition(block);
+ CACHES.put(pos, new FastMachineCache(this, menu));
+ }
+
+ @Override
+ @ParametersAreNonnullByDefault
+ protected void tick(Block b, BlockMenu menu) {
+ BlockPosition pos = new BlockPosition(b);
+ if (menu.hasViewer() && CACHES.containsKey(pos)) {
+ CACHES.get(pos).tick();
+ }
+ }
+
+ @Override
+ public int[] getInputSlots() {
+ return INPUT_SLOTS;
+ }
+
+ @Override
+ public int[] getOutputSlots() {
+ // Basic machines should not support cargo access
+ return new int[0];
+ }
+
+ @Override
+ public void register(@Nonnull SlimefunAddon addon) {
+ super.register(addon);
+ FastMachines.getScheduler().run(2, this::registerRecipes);
+ }
+
+ @Override
+ @ParametersAreNonnullByDefault
+ protected void onBreak(BlockBreakEvent e, BlockMenu menu) {
+ super.onBreak(e, menu);
+ Location l = menu.getLocation();
+ menu.dropItems(l, INPUT_SLOTS);
+ CACHES.remove(new BlockPosition(l));
+ }
+
+ /**
+ * Register available recipes for this machine.
+ *
+ * Note: this method is called synchronously 2 ticks after server completes loading.
+ */
+ protected abstract void registerRecipes();
+
+ /**
+ * Get the item that shows the craft button of this machine.
+ *
+ * @return the item that shows the craft button of this machine.
+ */
+ protected abstract ItemStack getCraftItem();
+}
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/generic/FastMachineCache.java b/src/main/java/net/guizhanss/fastmachines/items/machines/generic/FastMachineCache.java
new file mode 100644
index 0000000..4aea723
--- /dev/null
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/generic/FastMachineCache.java
@@ -0,0 +1,273 @@
+package net.guizhanss.fastmachines.items.machines.generic;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import com.google.common.base.Preconditions;
+
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import io.github.thebusybiscuit.slimefun4.libraries.dough.blocks.BlockPosition;
+import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI;
+import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
+
+import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
+
+import net.guizhanss.fastmachines.FastMachines;
+import net.guizhanss.fastmachines.core.recipes.IRecipe;
+import net.guizhanss.fastmachines.core.recipes.RandomRecipe;
+import net.guizhanss.fastmachines.utils.Keys;
+import net.guizhanss.fastmachines.utils.MachineUtils;
+import net.guizhanss.fastmachines.utils.RecipeUtils;
+
+import static net.guizhanss.fastmachines.items.machines.generic.AbstractFastMachine.CHOICE_SLOT;
+import static net.guizhanss.fastmachines.items.machines.generic.AbstractFastMachine.CRAFT_SLOT;
+import static net.guizhanss.fastmachines.items.machines.generic.AbstractFastMachine.INPUT_SLOTS;
+import static net.guizhanss.fastmachines.items.machines.generic.AbstractFastMachine.ITEMS_PER_PAGE;
+import static net.guizhanss.fastmachines.items.machines.generic.AbstractFastMachine.NO_ITEM;
+import static net.guizhanss.fastmachines.items.machines.generic.AbstractFastMachine.OUTPUT_SLOTS;
+import static net.guizhanss.fastmachines.items.machines.generic.AbstractFastMachine.PREVIEW_SLOTS;
+import static net.guizhanss.fastmachines.items.machines.generic.AbstractFastMachine.SCROLL_DOWN_SLOT;
+import static net.guizhanss.fastmachines.items.machines.generic.AbstractFastMachine.SCROLL_UP_SLOT;
+
+/**
+ * A cache layer to store some of the data of a Fast Machine.
+ */
+public final class FastMachineCache {
+ private final AbstractFastMachine machine;
+ private final BlockMenu menu;
+ private final BlockPosition blockPosition;
+ private final Map outputs = new LinkedHashMap<>();
+ private int page = -1;
+ private ItemStack choice;
+
+ @ParametersAreNonnullByDefault
+ public FastMachineCache(AbstractFastMachine machine, BlockMenu menu) {
+ this.machine = machine;
+ this.menu = menu;
+ this.blockPosition = new BlockPosition(menu.getLocation());
+ init();
+ }
+
+ private void init() {
+ menu.addMenuClickHandler(SCROLL_UP_SLOT, (player, i, itemStack, clickAction) -> {
+ page--;
+ return false;
+ });
+ menu.addMenuClickHandler(SCROLL_DOWN_SLOT, (player, i, itemStack, clickAction) -> {
+ page++;
+ return false;
+ });
+ menu.addMenuClickHandler(CRAFT_SLOT, (player, i, itemStack, clickAction) -> {
+ int amount;
+ if (clickAction.isShiftClicked()) {
+ if (clickAction.isRightClicked()) {
+ amount = Integer.MAX_VALUE;
+ } else {
+ amount = 64;
+ }
+ } else {
+ if (clickAction.isRightClicked()) {
+ amount = 16;
+ } else {
+ amount = 1;
+ }
+ }
+ craft(player, amount);
+ return false;
+ });
+ }
+
+ public void tick() {
+ if (FastMachines.getSlimefunTickCount() % 2 == 0) {
+ findAvailableOutputs();
+ }
+ updateMenu();
+ }
+
+ /**
+ * Find all the available outputs based on the given inputs.
+ */
+ private void findAvailableOutputs() {
+ Map machineInputs = MachineUtils.getMachineInputAmount(menu, INPUT_SLOTS);
+ outputs.clear();
+
+ if (machineInputs.isEmpty()) {
+ return;
+ }
+
+ FastMachines.debug("current machine: {0}, location: {1}", machine.getClass().getSimpleName(), blockPosition);
+ FastMachines.debug("machine inputs: {0}", machineInputs);
+
+ // Fetch available recipes based on inputs
+ for (var recipe : machine.getRecipes()) {
+ if (recipe.isDisabledInWorld(blockPosition.getWorld())) {
+ continue;
+ }
+
+ FastMachines.debug("checking recipe: {0}", recipe);
+
+ // stores the possible maximum output amount
+ int outputAmount = Integer.MAX_VALUE;
+
+ for (var recipeInputEntry : recipe.getInput().entrySet()) {
+
+ // if the current recipe input isn't in the machine input, just ignore this
+ if (!machineInputs.containsKey(recipeInputEntry.getKey())) {
+ outputAmount = 0;
+ break;
+ }
+
+ FastMachines.debug("input: {0}, machine amount: {1}", recipeInputEntry.getKey(),
+ machineInputs.get(recipeInputEntry.getKey()));
+ FastMachines.debug("recipe amount: {0}", recipeInputEntry.getValue());
+
+ // check the maximum possible output amount based on inputs
+ int inputAmount = machineInputs.get(recipeInputEntry.getKey());
+ int recipeAmount = recipeInputEntry.getValue();
+ outputAmount = Math.min(outputAmount, inputAmount / recipeAmount);
+
+ FastMachines.debug("result amount: {0}", inputAmount / recipeAmount);
+ }
+
+ // this recipe is available
+ if (outputAmount > 0) {
+ FastMachines.debug("recipe is available, output amount: {0}", outputAmount);
+ outputs.put(recipe, outputAmount);
+ }
+ }
+
+ FastMachines.debug("outputs: " + outputs);
+ }
+
+ private void updateMenu() {
+ ItemStack[] outputItems =
+ outputs.keySet().stream().map(recipe -> recipe.getOutput(blockPosition.getWorld())).toArray(ItemStack[]::new);
+ int totalPages = (int) Math.ceil(outputs.size() * 1.0 / ITEMS_PER_PAGE);
+ // limit the page in range
+ if (page < 1) {
+ page = 1;
+ }
+ if (page > totalPages) {
+ page = totalPages;
+ }
+
+ for (int i = 0; i < ITEMS_PER_PAGE; i++) {
+ int index = (page - 1) * ITEMS_PER_PAGE + i;
+ if (totalPages == 0 || index >= outputs.size()) {
+ menu.replaceExistingItem(PREVIEW_SLOTS[i], ChestMenuUtils.getBackground());
+ menu.addMenuClickHandler(PREVIEW_SLOTS[i], ChestMenuUtils.getEmptyClickHandler());
+ continue;
+ }
+ ItemStack output = getDisplayItem(outputItems[index]);
+ menu.replaceExistingItem(PREVIEW_SLOTS[i], output);
+ menu.addMenuClickHandler(PREVIEW_SLOTS[i], (player, slot, itemStack, clickAction) -> {
+ choice = itemStack;
+ updateChoice();
+ return false;
+ });
+ }
+
+ updateChoice();
+ }
+
+ private void updateChoice() {
+ ItemStack[] outputItems =
+ outputs.keySet().stream().map(recipe -> recipe.getOutput(blockPosition.getWorld())).toArray(ItemStack[]::new);
+
+ for (ItemStack output : outputItems) {
+ if (RecipeUtils.isItemSimilar(output, choice)) {
+ menu.replaceExistingItem(CHOICE_SLOT, getDisplayItem(choice));
+ return;
+ }
+ }
+ menu.replaceExistingItem(CHOICE_SLOT, NO_ITEM);
+ }
+
+ @ParametersAreNonnullByDefault
+ private void craft(Player p, int amount) {
+ Preconditions.checkArgument(amount > 0, "amount must greater than 0");
+
+ var outputRecipes = outputs.entrySet().stream().toList();
+
+ // invalid choice, due to previous selection not available anymore
+ if (choice == null) {
+ return;
+ }
+ var recipeEntry = outputRecipes.stream().filter(entry ->
+ RecipeUtils.isItemSimilar(entry.getKey().getOutput(blockPosition.getWorld()), choice)
+ ).findFirst();
+ if (recipeEntry.isEmpty()) {
+ return;
+ }
+ var recipe = recipeEntry.get();
+ int maxAmount = recipe.getValue();
+ amount = Math.min(maxAmount, amount);
+
+ // check if the machine has enough energy
+ if (FastMachines.getAddonConfig().getBoolean("fast-machines.use-energy")) {
+ int energyNeeded = machine.getEnergyPerUse() * amount;
+ int currentEnergy = machine.getCharge(blockPosition.toLocation());
+ if (currentEnergy < energyNeeded) {
+ FastMachines.getLocalization().sendMessage(p, "not-enough-energy");
+ return;
+ }
+ machine.setCharge(blockPosition.toLocation(), currentEnergy - energyNeeded);
+ }
+
+ // remove recipe inputs
+ for (var inputEntry : recipe.getKey().getInput().entrySet()) {
+ int requiredAmount = inputEntry.getValue() * amount;
+ var itemAmount = MachineUtils.getItemAmount(menu, INPUT_SLOTS, inputEntry.getKey());
+ // total amount is less than required amount, usually shouldn't happen
+ if (itemAmount.getSecondValue() < requiredAmount) {
+ FastMachines.getLocalization().sendMessage(p, "not-enough-materials");
+ return;
+ }
+ // remove items from machine
+ MachineUtils.removeItems(menu, itemAmount.getFirstValue().stream().mapToInt(Integer::intValue).toArray(),
+ inputEntry.getKey(), requiredAmount);
+ }
+
+ // push the product
+ if (recipe.getKey() instanceof RandomRecipe randomRecipe) {
+ boolean machineFull = false;
+ for (int i = 0; i < amount; i++) {
+ ItemStack product = randomRecipe.getOutput(blockPosition.getWorld()).clone();
+ if (MachineUtils.addItem(p, menu, OUTPUT_SLOTS, product, 1)) {
+ machineFull = true;
+ }
+ }
+ if (machineFull) {
+ FastMachines.getLocalization().sendMessage(p, "not-enough-space");
+ }
+ } else {
+ ItemStack product = recipe.getKey().getOutput(blockPosition.getWorld()).clone();
+ if (MachineUtils.addItem(p, menu, OUTPUT_SLOTS, product, amount)) {
+ FastMachines.getLocalization().sendMessage(p, "not-enough-space");
+ }
+ }
+ }
+
+ /**
+ * Get the {@link ItemStack} that is used to display in the preview slots.
+ *
+ * @param item
+ * The original {@link ItemStack}.
+ *
+ * @return The new {@link ItemStack} that is used to display.
+ */
+ @Nonnull
+ private ItemStack getDisplayItem(@Nonnull ItemStack item) {
+ ItemStack newItem = item.clone();
+ ItemMeta meta = newItem.getItemMeta();
+ PersistentDataAPI.setBoolean(meta, Keys.get("display"), true);
+ newItem.setItemMeta(meta);
+ return newItem;
+ }
+}
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/infinityexpansion/FastInfinityWorkbench.java b/src/main/java/net/guizhanss/fastmachines/items/machines/infinityexpansion/FastInfinityWorkbench.java
index 7983751..17cd47b 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/infinityexpansion/FastInfinityWorkbench.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/infinityexpansion/FastInfinityWorkbench.java
@@ -13,7 +13,7 @@
import net.guizhanss.fastmachines.FastMachines;
import net.guizhanss.fastmachines.core.recipes.RawRecipe;
-import net.guizhanss.fastmachines.items.machines.abstracts.AInfinityMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AInfinityMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastInfinityWorkbench extends AInfinityMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimeframe/FastSlimeFrameFoundry.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimeframe/FastSlimeFrameFoundry.java
index a9869df..54ccfa3 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimeframe/FastSlimeFrameFoundry.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimeframe/FastSlimeFrameFoundry.java
@@ -9,7 +9,7 @@
import me.voper.slimeframe.implementation.SFrameStacks;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public class FastSlimeFrameFoundry extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastArmorForge.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastArmorForge.java
index 0b0e7ed..d937dec 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastArmorForge.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastArmorForge.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastArmorForge extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastComposter.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastComposter.java
index 3779f48..3adf6b2 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastComposter.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastComposter.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastComposter extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastCompressor.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastCompressor.java
index 7417490..f7159ba 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastCompressor.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastCompressor.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastCompressor extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastEnhancedCraftingTable.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastEnhancedCraftingTable.java
index 5f3335a..cccb71a 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastEnhancedCraftingTable.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastEnhancedCraftingTable.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastEnhancedCraftingTable extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastGrindStone.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastGrindStone.java
index 02815e0..7e1c6f2 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastGrindStone.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastGrindStone.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastGrindStone extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastJuicer.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastJuicer.java
index 32a1e5d..f425d68 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastJuicer.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastJuicer.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastJuicer extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastMagicWorkbench.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastMagicWorkbench.java
index ea21038..60423ac 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastMagicWorkbench.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastMagicWorkbench.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastMagicWorkbench extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastOreCrusher.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastOreCrusher.java
index 7fedc79..2e9ea0d 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastOreCrusher.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastOreCrusher.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastOreCrusher extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastOreWasher.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastOreWasher.java
index 08d9a25..31765af 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastOreWasher.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastOreWasher.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastOreWasher extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastPanningMachine.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastPanningMachine.java
index 82966ef..7c841be 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastPanningMachine.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastPanningMachine.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastPanningMachine extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastPressureChamber.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastPressureChamber.java
index 8b7bef7..9bf88ca 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastPressureChamber.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastPressureChamber.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastPressureChamber extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastSmeltery.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastSmeltery.java
index 464fdb3..95264e9 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastSmeltery.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastSmeltery.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastSmeltery extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastTableSaw.java b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastTableSaw.java
index a46387a..d8f170e 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastTableSaw.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/slimefun/FastTableSaw.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastTableSaw extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/vanilla/FastCraftingTable.java b/src/main/java/net/guizhanss/fastmachines/items/machines/vanilla/FastCraftingTable.java
index 0ef9be0..7122321 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/vanilla/FastCraftingTable.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/vanilla/FastCraftingTable.java
@@ -9,7 +9,7 @@
import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastCraftingTable extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/items/machines/vanilla/FastFurnace.java b/src/main/java/net/guizhanss/fastmachines/items/machines/vanilla/FastFurnace.java
index a848156..feabf2a 100644
--- a/src/main/java/net/guizhanss/fastmachines/items/machines/vanilla/FastFurnace.java
+++ b/src/main/java/net/guizhanss/fastmachines/items/machines/vanilla/FastFurnace.java
@@ -8,7 +8,7 @@
import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType;
import net.guizhanss.fastmachines.FastMachines;
-import net.guizhanss.fastmachines.items.machines.abstracts.AFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AFastMachine;
import net.guizhanss.fastmachines.utils.RecipeUtils;
public final class FastFurnace extends AFastMachine {
diff --git a/src/main/java/net/guizhanss/fastmachines/utils/RecipeUtils.java b/src/main/java/net/guizhanss/fastmachines/utils/RecipeUtils.java
index 2048e07..38b186c 100644
--- a/src/main/java/net/guizhanss/fastmachines/utils/RecipeUtils.java
+++ b/src/main/java/net/guizhanss/fastmachines/utils/RecipeUtils.java
@@ -14,6 +14,7 @@
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
+import javax.annotation.ParametersAreNullableByDefault;
import com.google.common.base.Preconditions;
@@ -36,7 +37,7 @@
import net.guizhanss.fastmachines.core.recipes.RandomRecipe;
import net.guizhanss.fastmachines.core.recipes.RawRecipe;
import net.guizhanss.fastmachines.core.recipes.StandardRecipe;
-import net.guizhanss.fastmachines.items.machines.abstracts.AbstractFastMachine;
+import net.guizhanss.fastmachines.items.machines.generic.AbstractFastMachine;
import lombok.experimental.UtilityClass;
@@ -69,13 +70,11 @@ public final class RecipeUtils {
*
* @return Whether the two items are similar.
*/
- @ParametersAreNonnullByDefault
- private static boolean isItemSimilar(ItemStack aItem, ItemStack bItem) {
- if (aItem.getType() == Material.SPAWNER && bItem.getType() == Material.SPAWNER) {
- return SlimefunUtils.isItemSimilar(aItem, bItem, true, true, true);
- } else {
- return SlimefunUtils.isItemSimilar(aItem, bItem, false, true, true);
- }
+ @ParametersAreNullableByDefault
+ public static boolean isItemSimilar(ItemStack aItem, ItemStack bItem) {
+ if (aItem == null || bItem == null) return false;
+ boolean checkLore = aItem.getType() == Material.SPAWNER && bItem.getType() == Material.SPAWNER;
+ return SlimefunUtils.isItemSimilar(aItem, bItem, checkLore, true, true);
}
/**