diff --git a/pom.xml b/pom.xml index ec9517ef..8e24ca0f 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ com.github.igotyou FactoryMod jar - 2.5.1 + 2.5.2 FactoryMod https://github.com/Civclassic/FactoryMod @@ -39,7 +39,7 @@ vg.civcraft.mc.civmodcore CivModCore - 1.8.2 + 1.8.4 provided diff --git a/src/main/java/com/github/igotyou/FactoryMod/ConfigParser.java b/src/main/java/com/github/igotyou/FactoryMod/ConfigParser.java index a5cd5038..ae72cc7c 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/ConfigParser.java +++ b/src/main/java/com/github/igotyou/FactoryMod/ConfigParser.java @@ -143,9 +143,14 @@ public void run() { int globalPylonLimit = config.getInt("global_pylon_limit"); PylonRecipe.setGlobalLimit(globalPylonLimit); Map factoryRenames = parseRenames(config.getConfigurationSection("renames")); + int maxInputChests = config.getInt("max_input_chests", 10); + int maxOutputChests = config.getInt("max_output_chests", 10); + int maxFuelChests = config.getInt("max_fuel_chests", 10); + int maxTotalIOFChests = config.getInt("max_iof_chests", 15); manager = new FactoryModManager(plugin, factoryInteractionMaterial, citadelEnabled, nameLayerEnabled, - redstonePowerOn, redstoneRecipeChange, logInventories, factoryRenames); + redstonePowerOn, redstoneRecipeChange, logInventories, maxInputChests, maxOutputChests, maxFuelChests, + maxTotalIOFChests, factoryRenames); upgradeEggs = new HashMap<>(); recipeLists = new HashMap<>(); recipeScalingUpgradeMapping = new HashMap<>(); diff --git a/src/main/java/com/github/igotyou/FactoryMod/FactoryModManager.java b/src/main/java/com/github/igotyou/FactoryMod/FactoryModManager.java index ab631abe..50cc6776 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/FactoryModManager.java +++ b/src/main/java/com/github/igotyou/FactoryMod/FactoryModManager.java @@ -53,17 +53,27 @@ public class FactoryModManager { private boolean logInventories; private int redstonePowerOn; private int redstoneRecipeChange; + private int maxInputChests; + private int maxOutputChests; + private int maxFuelChests; + private int maxTotalIOFChests; private Set compactLore; private Set forceInclude; + private FactoryModPlayerSettings playerSettings; public FactoryModManager(FactoryMod plugin, Material factoryInteractionMaterial, boolean citadelEnabled, boolean nameLayerEnabled, int redstonePowerOn, int redstoneRecipeChange, boolean logInventories, + int maxInputChests, int maxOutputChests, int maxFuelChests, int maxTotalIOFChests, Map factoryRenames) { this.plugin = plugin; this.factoryInteractionMaterial = factoryInteractionMaterial; this.citadelEnabled = citadelEnabled; this.redstonePowerOn = redstonePowerOn; this.redstoneRecipeChange = redstoneRecipeChange; + this.maxInputChests = maxInputChests; + this.maxOutputChests = maxOutputChests; + this.maxFuelChests = maxFuelChests; + this.maxTotalIOFChests = maxTotalIOFChests; this.fileHandler = new FileHandler(this, factoryRenames); factoryCreationRecipes = new HashMap<>(); @@ -76,6 +86,7 @@ public FactoryModManager(FactoryMod plugin, Material factoryInteractionMaterial, recipes = new HashMap<>(); compactLore = new HashSet<>(); forceInclude = new HashSet<>(); + playerSettings = new FactoryModPlayerSettings(plugin); // Normal furnace, craftingtable, chest factories possibleCenterBlocks.add(Material.CRAFTING_TABLE); @@ -149,6 +160,26 @@ public boolean isCitadelEnabled() { return citadelEnabled; } + public int getMaxInputChests() { + return maxInputChests; + } + + public int getMaxOutputChests() { + return maxOutputChests; + } + + public int getMaxFuelChests() { + return maxFuelChests; + } + + /** + * @return The maximum total number of inputs, outputs, and fuel inputs a factory has. A chest with multiple IOF + * settings enabled is counted for each. + */ + public int getMaxTotalIOFChests() { + return maxTotalIOFChests; + } + /** * @return Which material is used to interact with factories, stick by default */ @@ -239,6 +270,8 @@ public void attemptCreation(Block b, Player p) { if (egg != null) { Factory f = egg.hatch(fccs, p); if (f != null) { + // Trigger lazy-initialize default crafting table IOSelector + ((FurnCraftChestFactory)f).getTableIOSelector(); ((Chest) (fccs.getChest().getState())).getInventory().clear(); addFactory(f); p.sendMessage(ChatColor.GREEN + "Successfully created " + f.getName()); @@ -545,4 +578,8 @@ public boolean isForceInclude(String identifier) { public Collection getAllFactoryEggs() { return eggs.values(); } + + public FactoryModPlayerSettings getPlayerSettings() { + return playerSettings; + } } diff --git a/src/main/java/com/github/igotyou/FactoryMod/FactoryModPlayerSettings.java b/src/main/java/com/github/igotyou/FactoryMod/FactoryModPlayerSettings.java new file mode 100644 index 00000000..0ffcaed0 --- /dev/null +++ b/src/main/java/com/github/igotyou/FactoryMod/FactoryModPlayerSettings.java @@ -0,0 +1,69 @@ +package com.github.igotyou.FactoryMod; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import vg.civcraft.mc.civmodcore.playersettings.PlayerSettingAPI; +import vg.civcraft.mc.civmodcore.playersettings.gui.MenuSection; +import vg.civcraft.mc.civmodcore.playersettings.impl.EnumSetting; + +import java.util.UUID; + +public class FactoryModPlayerSettings { + + private final FactoryMod plugin; + EnumSetting ioDirectionSetting; + + public FactoryModPlayerSettings(FactoryMod plugin) { + this.plugin = plugin; + initSettings(); + } + + private void initSettings() { + MenuSection menu = PlayerSettingAPI.getMainMenu().createMenuSection( + "FactoryMod", + "FactoryMod settings", + new ItemStack(Material.FURNACE) + ); + + ioDirectionSetting = new EnumSetting<>( + plugin, + IoConfigDirectionMode.VISUAL_RELATIVE, + "Factory IOConfig Mode", + "ioconfig_visual_mode", + new ItemStack(Material.HOPPER), + "Change how the factory IO config appears", + true, + IoConfigDirectionMode.class + ); + PlayerSettingAPI.registerSetting(ioDirectionSetting, menu); + } + + public IoConfigDirectionMode getIoDirectionMode(UUID id) { + return ioDirectionSetting.getValue(id); + } + + public enum IoConfigDirectionMode { + + VISUAL_RELATIVE( + "Relative Directions", + new String[] { + "The furnace shows the", + "front of the factory." + }), + CARDINAL( + "Cardinal Directions", + new String[] { + "Cardinals (for those too", + "familiar with map mods.)" + }); + + public final String simpleDescription; + public final String[] fullDescription; + + private IoConfigDirectionMode(String simpleDescription, String[] fullDescription) { + this.simpleDescription = simpleDescription; + this.fullDescription = fullDescription; + } + } + +} diff --git a/src/main/java/com/github/igotyou/FactoryMod/factories/Factory.java b/src/main/java/com/github/igotyou/FactoryMod/factories/Factory.java index 1742f6cd..b15875a1 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/factories/Factory.java +++ b/src/main/java/com/github/igotyou/FactoryMod/factories/Factory.java @@ -5,6 +5,7 @@ import com.github.igotyou.FactoryMod.powerManager.IPowerManager; import com.github.igotyou.FactoryMod.repairManager.IRepairManager; import com.github.igotyou.FactoryMod.structures.MultiBlockStructure; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.Furnace; @@ -123,9 +124,13 @@ public void turnFurnaceOn(Block f) { if (f.getType() != Material.FURNACE) { return; } - Furnace furnace = (Furnace) f.getState(); - furnace.setBurnTime(Short.MAX_VALUE); - furnace.update(); + Bukkit.getScheduler().runTask(FactoryMod.getInstance(), () -> { + if (this.isActive()) { + Furnace furnace = (Furnace) f.getState(); + furnace.setBurnTime(Short.MAX_VALUE); + furnace.update(); + } + }); } public String getLogData() { @@ -136,8 +141,19 @@ public void turnFurnaceOff(Block f) { if (f.getType() != Material.FURNACE) { return; } - Furnace furnace = (Furnace) f.getState(); - furnace.setBurnTime((short) 0); - furnace.update(); + FactoryMod fmPlugin = FactoryMod.getInstance(); + if (fmPlugin.isEnabled()) { + Bukkit.getScheduler().runTask(FactoryMod.getInstance(), () -> { + if (!this.isActive()) { + Furnace furnace = (Furnace) f.getState(); + furnace.setBurnTime((short) 0); + furnace.update(); + } + }); + } else if (!this.isActive()) { + Furnace furnace = (Furnace) f.getState(); + furnace.setBurnTime((short) 0); + furnace.update(); + } } } diff --git a/src/main/java/com/github/igotyou/FactoryMod/factories/FurnCraftChestFactory.java b/src/main/java/com/github/igotyou/FactoryMod/factories/FurnCraftChestFactory.java index facad425..0a6ec007 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/factories/FurnCraftChestFactory.java +++ b/src/main/java/com/github/igotyou/FactoryMod/factories/FurnCraftChestFactory.java @@ -5,6 +5,8 @@ import com.github.igotyou.FactoryMod.events.RecipeExecuteEvent; import com.github.igotyou.FactoryMod.interactionManager.IInteractionManager; import com.github.igotyou.FactoryMod.powerManager.FurnacePowerManager; +import com.github.igotyou.FactoryMod.utility.Direction; +import com.github.igotyou.FactoryMod.utility.IIOFInventoryProvider; import com.github.igotyou.FactoryMod.powerManager.IPowerManager; import com.github.igotyou.FactoryMod.recipes.IRecipe; import com.github.igotyou.FactoryMod.recipes.InputRecipe; @@ -15,6 +17,7 @@ import com.github.igotyou.FactoryMod.repairManager.IRepairManager; import com.github.igotyou.FactoryMod.repairManager.PercentageHealthRepairManager; import com.github.igotyou.FactoryMod.structures.FurnCraftChestStructure; +import com.github.igotyou.FactoryMod.utility.IOSelector; import com.github.igotyou.FactoryMod.utility.LoggingUtils; import java.util.ArrayList; import java.util.HashMap; @@ -22,16 +25,21 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.function.Function; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.block.Chest; import org.bukkit.block.Furnace; import org.bukkit.entity.Player; import org.bukkit.inventory.FurnaceInventory; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; import vg.civcraft.mc.citadel.ReinforcementLogic; import vg.civcraft.mc.citadel.model.Reinforcement; import vg.civcraft.mc.civmodcore.inventory.items.ItemUtils; @@ -44,7 +52,7 @@ * which is used as inventory holder * */ -public class FurnCraftChestFactory extends Factory { +public class FurnCraftChestFactory extends Factory implements IIOFInventoryProvider { protected int currentProductionTimer = 0; protected List recipes; protected IRecipe currentRecipe; @@ -53,6 +61,9 @@ public class FurnCraftChestFactory extends Factory { private UUID activator; private double citadelBreakReduction; private boolean autoSelect; + private @Nullable IOSelector furnaceIoSelector; + private @Nullable IOSelector tableIoSelector; + private UiMenuMode uiMenuMode; private static HashSet pylonFactories; @@ -60,12 +71,16 @@ public FurnCraftChestFactory(IInteractionManager im, IRepairManager rm, IPowerMa FurnCraftChestStructure mbs, int updateTime, String name, List recipes, double citadelBreakReduction) { super(im, rm, ipm, mbs, updateTime, name); + if (ipm instanceof FurnacePowerManager) { + ((FurnacePowerManager) ipm).setIofProvider(this); + } this.active = false; this.runCount = new HashMap<>(); this.recipeLevel = new HashMap<>(); this.recipes = new ArrayList<>(); this.citadelBreakReduction = citadelBreakReduction; this.autoSelect = false; + this.uiMenuMode = UiMenuMode.SIMPLE; for (IRecipe rec : recipes) { addRecipe(rec); } @@ -92,6 +107,115 @@ public Inventory getInventory() { return chestBlock.getInventory(); } + public Inventory getInputInventory() { + List invs = new ArrayList<>(12); + getInventoriesForIoType(invs, iosel -> iosel::getInputs); + return new MultiInventoryWrapper(invs); + } + + public Inventory getOutputInventory() { + List invs = new ArrayList<>(12); + getInventoriesForIoType(invs, iosel -> iosel::getOutputs); + return new MultiInventoryWrapper(invs); + } + + public Inventory getFuelInventory() { + if (!getFurnaceIOSelector().hasFuel() && !getTableIOSelector().hasFuel()) { + return getFurnaceInventory(); + } + ArrayList invs = new ArrayList<>(13); + getInventoriesForIoType(invs, iosel -> iosel::getFuel); + invs.add(getFurnaceInventory()); + return new MultiInventoryWrapper(invs); + } + + private void getInventoriesForIoType(List combinedInvList, + Function>> ioTypeFunc) { + FurnCraftChestStructure fccs = (FurnCraftChestStructure) getMultiBlockStructure(); + Block fblock = getFurnace(); + BlockFace facing = getFacing(); + for (BlockFace relativeFace : ioTypeFunc.apply(getFurnaceIOSelector()).apply(facing)) { + Block relBlock = fblock.getRelative(relativeFace); + if (relBlock.getType() == Material.CHEST || relBlock.getType() == Material.TRAPPED_CHEST) { + combinedInvList.add(((Chest) relBlock.getState()).getInventory()); + } + } + Block tblock = fccs.getCraftingTable(); + for (BlockFace relativeFace : ioTypeFunc.apply(getTableIOSelector()).apply(facing)) { + Block relBlock = tblock.getRelative(relativeFace); + if (relBlock.getType() == Material.CHEST || relBlock.getType() == Material.TRAPPED_CHEST) { + combinedInvList.add(((Chest) relBlock.getState()).getInventory()); + } + } + } + + @Override + public int getInputCount() { + return (furnaceIoSelector == null ? 0 : furnaceIoSelector.getInputCount()) + + (tableIoSelector == null ? 0 : tableIoSelector.getInputCount()); + } + + @Override + public int getOutputCount() { + return (furnaceIoSelector == null ? 0 : furnaceIoSelector.getOutputCount()) + + (tableIoSelector == null ? 0 : tableIoSelector.getOutputCount()); + } + + @Override + public int getFuelCount() { + return (furnaceIoSelector == null ? 0 : furnaceIoSelector.getFuelCount()) + + (tableIoSelector == null ? 0 : tableIoSelector.getFuelCount()); + } + + public void setFurnaceIOSelector(IOSelector ioSelector) { + this.furnaceIoSelector = ioSelector; + } + + public IOSelector getFurnaceIOSelector() { + if (furnaceIoSelector == null) { + furnaceIoSelector = new IOSelector(); + } + return furnaceIoSelector; + } + + public void setTableIOSelector(IOSelector ioSelector) { + this.tableIoSelector = ioSelector; + } + + public IOSelector getTableIOSelector() { + if (tableIoSelector == null) { + tableIoSelector = new IOSelector(); + BlockFace front = getFacing(); + BlockFace chestDir = getFurnace().getFace(getCraftingTable()); + if (chestDir != null && front != null) { + Direction defaultDir = Direction.getDirection(front, chestDir); + tableIoSelector.setState(defaultDir, IOSelector.IOState.BOTH); + } + } + return tableIoSelector; + } + + public void setUiMenuMode(UiMenuMode uiMenuMode) { + this.uiMenuMode = uiMenuMode; + } + + public UiMenuMode getUiMenuMode() { + return uiMenuMode; + } + + /** + * @return the direction the furnace (and thus this factory) is facing. + */ + public @Nullable BlockFace getFacing() { + Block fblock = getFurnace(); + if (fblock.getType() != Material.FURNACE) { + return null; + } + Furnace fstate = (Furnace) fblock.getState(); + org.bukkit.block.data.type.Furnace fdata = (org.bukkit.block.data.type.Furnace) fstate.getBlockData(); + return fdata.getFacing(); + } + /** * @return Inventory of the furnace or null if there is no furnace where one * should be @@ -258,6 +382,13 @@ public Block getFurnace() { return ((FurnCraftChestStructure) mbs).getFurnace(); } + /** + * @return The crafting table of this factory + */ + public Block getCraftingTable() { + return ((FurnCraftChestStructure) mbs).getCraftingTable(); + } + /** * @return The chest of this factory */ @@ -362,11 +493,11 @@ public void run() { // this if else might look a bit weird, but because // upgrading changes the current recipe and a lot of // other stuff, this is needed - currentRecipe.applyEffect(getInventory(), this); + currentRecipe.applyEffect(getInputInventory(), getOutputInventory(), this); deactivate(); return; } else { - if (currentRecipe.applyEffect(getInventory(), this)) { + if (currentRecipe.applyEffect(getInputInventory(), getOutputInventory(), this)) { runCount.put(currentRecipe, runCount.get(currentRecipe) + 1); } else { sendActivatorMessage(ChatColor.RED + currentRecipe.getName() + " in " + name + " deactivated because it ran out of storage space"); @@ -402,8 +533,16 @@ public void run() { } } } else { - sendActivatorMessage(ChatColor.GOLD + name + " deactivated, because it ran out of required materials"); - deactivate(); + IRecipe nextOne; + if (isAutoSelect() && (nextOne = getAutoSelectRecipe()) != null) { + sendActivatorMessage(ChatColor.GREEN + name + " automatically switched to recipe " + nextOne.getName() + " and began running it"); + currentRecipe = nextOne; + scheduleUpdate(); + // don't setPowerCounter to 0, fuel has been consumed, let it be used for the new recipe + } else { + sendActivatorMessage(ChatColor.GOLD + name + " deactivated, because it ran out of required materials"); + deactivate(); + } } } else { sendActivatorMessage(ChatColor.GOLD + name + " deactivated, because the factory was destroyed"); @@ -506,12 +645,12 @@ public void setProductionTimer(int timer) { * selected recipe at least once */ public boolean hasInputMaterials() { - return currentRecipe.enoughMaterialAvailable(getInventory()); + return currentRecipe.enoughMaterialAvailable(getInputInventory()); } public IRecipe getAutoSelectRecipe() { for (IRecipe rec : recipes) { - if (rec.enoughMaterialAvailable(getInventory())) { + if (rec.enoughMaterialAvailable(getInputInventory())) { return rec; } } @@ -555,4 +694,17 @@ public void upgrade(String name, List recipes, ItemStack fuel, int fuel public double getCitadelBreakReduction() { return citadelBreakReduction; } + + public enum UiMenuMode { + SIMPLE(Material.PAPER, "Show simple menu"), + IOCONFIG(Material.HOPPER, "Show IO config menu"); + + public final Material uiMaterial; + public final String uiDescription; + + private UiMenuMode(Material uiMaterial, String uiDescription) { + this.uiMaterial = uiMaterial; + this.uiDescription = uiDescription; + } + } } diff --git a/src/main/java/com/github/igotyou/FactoryMod/interactionManager/FurnCraftChestInteractionManager.java b/src/main/java/com/github/igotyou/FactoryMod/interactionManager/FurnCraftChestInteractionManager.java index 84a78a9e..9cd286c7 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/interactionManager/FurnCraftChestInteractionManager.java +++ b/src/main/java/com/github/igotyou/FactoryMod/interactionManager/FurnCraftChestInteractionManager.java @@ -11,12 +11,16 @@ import com.github.igotyou.FactoryMod.structures.MultiBlockStructure; import com.github.igotyou.FactoryMod.utility.FactoryModGUI; import java.text.DecimalFormat; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; + +import com.github.igotyou.FactoryMod.utility.IOConfigSection; +import net.kyori.adventure.text.Component; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; +import org.bukkit.block.Furnace; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockRedstoneEvent; import org.bukkit.inventory.ItemStack; @@ -25,6 +29,11 @@ import vg.civcraft.mc.civmodcore.inventory.items.ItemUtils; import vg.civcraft.mc.civmodcore.inventorygui.Clickable; import vg.civcraft.mc.civmodcore.inventorygui.ClickableInventory; +import vg.civcraft.mc.civmodcore.inventorygui.IClickable; +import vg.civcraft.mc.civmodcore.inventorygui.components.ComponableInventory; +import vg.civcraft.mc.civmodcore.inventorygui.components.Scrollbar; +import vg.civcraft.mc.civmodcore.inventorygui.components.SlotPredicates; +import vg.civcraft.mc.civmodcore.inventorygui.components.StaticDisplaySection; import vg.civcraft.mc.civmodcore.itemHandling.ItemMap; import vg.civcraft.mc.namelayer.NameAPI; import vg.civcraft.mc.namelayer.group.Group; @@ -33,8 +42,7 @@ public class FurnCraftChestInteractionManager implements IInteractionManager { private FurnCraftChestFactory fccf; - private HashMap recipes = new HashMap<>(); - private DecimalFormat decimalFormatting; + private final DecimalFormat decimalFormatting; public FurnCraftChestInteractionManager(FurnCraftChestFactory fccf) { this(); @@ -100,7 +108,7 @@ public void leftClick(Player p, Block b, BlockFace bf) { ClickableInventory ci = new ClickableInventory(54, fccf.getCurrentRecipe().getName()); int index = 4; List inp = ((InputRecipe) fccf.getCurrentRecipe()) - .getInputRepresentation(fccf.getInventory(), fccf); + .getInputRepresentation(fccf.getInputInventory(), fccf); if (inp.size() > 18) { inp = new ItemMap(inp).getLoredItemCountRepresentation(); } @@ -130,7 +138,7 @@ public void clicked(Player arg0) { } index = 49; List outp = ((InputRecipe) fccf.getCurrentRecipe()) - .getOutputRepresentation(fccf.getInventory(), fccf); + .getOutputRepresentation(fccf.getOutputInventory(), fccf); if (outp.size() > 18) { outp = new ItemMap(outp).getLoredItemCountRepresentation(); } @@ -189,88 +197,183 @@ public void clicked(Player arg0) { } if (b.equals(((FurnCraftChestStructure) fccf.getMultiBlockStructure()).getCraftingTable())) { // crafting table // interaction - int rows = ((fccf.getRecipes().size() + 2) / 9) + 1; - if (fccf.getRecipes().size() > 52 || rows > 6) { - p.sendMessage(ChatColor.RED - + "This factory has more than 52 recipes and the GUI for it can't be opened. Either complain to " - + "your admin to have them put less recipes in this factory or complain to /u/maxopoly to add " - + "scrollviews to this"); - return; + ComponableInventory compInv = buildRecipeInventory(p); + compInv.update(); + compInv.updatePlayerView(); + return; + } + if (b.equals(fccf.getFurnace())) { // furnace interaction + if (fccf.isActive()) { + fccf.deactivate(); + p.sendMessage(ChatColor.RED + "Deactivated " + fccf.getName()); + } else { + fccf.attemptToActivate(p, false); } - ClickableInventory ci = new ClickableInventory(rows * 9, "Select a recipe"); - for (IRecipe rec : fccf.getRecipes()) { - InputRecipe recipe = (InputRecipe) (rec); - ItemStack recStack = recipe.getRecipeRepresentation(); - int runcount = fccf.getRunCount(recipe); - ItemUtils.addLore(recStack, "",ChatColor.AQUA + "Ran " + String.valueOf(runcount) + " times"); - if (rec == fccf.getCurrentRecipe()) { - ItemUtils.addLore(recStack, ChatColor.GREEN + "Currently selected"); - ItemUtils.addGlow(recStack); - } - if (recipe instanceof ProductionRecipe) { - ProductionRecipe prod = (ProductionRecipe) recipe; - if (prod.getModifier() != null) { - ItemUtils.addLore(recStack, ChatColor.BOLD + " " + ChatColor.GOLD - + fccf.getRecipeLevel(recipe) + " ★"); - ItemUtils.addLore(recStack, ChatColor.GREEN + "Current output multiplier: " + decimalFormatting - .format(prod.getModifier().getFactor(fccf.getRecipeLevel(recipe), runcount))); - } - } - Clickable c = new Clickable(recStack) { + } + } - @Override - public void clicked(Player p) { - if (fccf.isActive()) { - p.sendMessage(ChatColor.RED + "You can't switch recipes while the factory is running"); - } else { - fccf.setRecipe(recipes.get(this)); - p.sendMessage(ChatColor.GREEN + "Switched recipe to " + recipes.get(this).getName()); - } + private ComponableInventory buildRecipeInventory(Player p) { + ComponableInventory compInv = new ComponableInventory("Select a recipe", 6, p); - } - }; - recipes.put(c, recipe); - ci.addSlot(c); + Clickable autoClick = buildAutoSelectToggle(); + Clickable menuC = buildMenuClickable(); + Clickable menuModeButton = buildMenuModeCycleButton(p); + Clickable[] buddons = new Clickable[] { autoClick, menuC, menuModeButton }; + StaticDisplaySection lowerSection = new StaticDisplaySection(buddons); + + Block fblock = fccf.getFurnace(); + switch (fccf.getUiMenuMode()) { + case IOCONFIG: { + Scrollbar recipeScroller = buildRecipeScrollbar(3); + compInv.addComponent(recipeScroller, SlotPredicates.offsetRectangle(3, 9, 0, 0)); + if (fblock.getType() == Material.FURNACE) { + Furnace fstate = (Furnace) fblock.getState(); + org.bukkit.block.data.type.Furnace fdata = (org.bukkit.block.data.type.Furnace) fstate.getBlockData(); + BlockFace facing = fdata.getFacing(); + IOConfigSection furnaceConfigSection = new IOConfigSection( + p, + fccf.getFurnaceIOSelector(), + Material.FURNACE, + fblock, + facing, + fccf); + IOConfigSection tableConfigSection = new IOConfigSection( + p, + fccf.getTableIOSelector(), + Material.CRAFTING_TABLE, + ((FurnCraftChestStructure) fccf.getMultiBlockStructure()).getCraftingTable(), + facing, + fccf); + compInv.addComponent(furnaceConfigSection, SlotPredicates.offsetRectangle(3, 3, 3, 0)); + compInv.addComponent(tableConfigSection, SlotPredicates.offsetRectangle(3, 3, 3, 4)); + } + compInv.addComponent(lowerSection, SlotPredicates.offsetRectangle(3, 1, 3, 8)); + break; + } + default: { + Scrollbar recipeScroller = buildRecipeScrollbar(5); + compInv.addComponent(recipeScroller, SlotPredicates.offsetRectangle(5, 9, 0, 0)); + compInv.addComponent(lowerSection, SlotPredicates.offsetRectangle(1, 3, 5, 6)); } - ItemStack autoSelectStack = new ItemStack(Material.REDSTONE_BLOCK); - ItemUtils.setDisplayName(autoSelectStack, "Toggle auto select"); - ItemUtils.addLore(autoSelectStack, - ChatColor.GOLD + "Make the factory automatically select any", - ChatColor.GOLD + "recipe it can run whenever you activate it", - ChatColor.AQUA + "Click to turn it " + (fccf.isAutoSelect() ? "off" : "on")); - Clickable autoClick = new Clickable(autoSelectStack) { + } + return compInv; + } - @Override - public void clicked(Player p) { - p.sendMessage(ChatColor.GREEN + "Turned auto select " + (fccf.isAutoSelect() ? "off" : "on") - + " for " + fccf.getName()); - fccf.setAutoSelect(!fccf.isAutoSelect()); + private Scrollbar buildRecipeScrollbar(int rows) { + rows = Math.max(1, Math.min(5, rows)); + List recipeList = fccf.getRecipes(); + List recipeClickList = new ArrayList<>(recipeList.size()); + for (IRecipe rec : fccf.getRecipes()) { + InputRecipe recipe = (InputRecipe) (rec); + ItemStack recStack = recipe.getRecipeRepresentation(); + int runcount = fccf.getRunCount(recipe); + ItemUtils.addLore(recStack, "",ChatColor.AQUA + "Ran " + String.valueOf(runcount) + " times"); + if (rec == fccf.getCurrentRecipe()) { + ItemUtils.addLore(recStack, ChatColor.GREEN + "Currently selected"); + ItemUtils.addGlow(recStack); + } + if (recipe instanceof ProductionRecipe) { + ProductionRecipe prod = (ProductionRecipe) recipe; + if (prod.getModifier() != null) { + ItemUtils.addLore(recStack, ChatColor.BOLD + " " + ChatColor.GOLD + + fccf.getRecipeLevel(recipe) + " ★"); + ItemUtils.addLore(recStack, ChatColor.GREEN + "Current output multiplier: " + decimalFormatting + .format(prod.getModifier().getFactor(fccf.getRecipeLevel(recipe), runcount))); } - }; - ci.setSlot(autoClick, (rows * 9) - 2); - ItemStack menuStack = new ItemStack(Material.PAINTING); - ItemUtils.setDisplayName(menuStack, "Open menu"); - ItemUtils.addLore(menuStack, ChatColor.LIGHT_PURPLE + "Click to open a detailed menu"); - Clickable menuC = new Clickable(menuStack) { + } + Clickable c = new Clickable(recStack) { + @Override public void clicked(Player p) { - FactoryModGUI gui = new FactoryModGUI(p); - gui.showForFactory((FurnCraftChestEgg)FactoryMod.getInstance().getManager().getEgg(fccf.getName())); + if (fccf.isActive()) { + p.sendMessage(ChatColor.RED + "You can't switch recipes while the factory is running"); + } else { + fccf.setRecipe(recipe); + p.sendMessage(ChatColor.GREEN + "Switched recipe to " + recipe.getName()); + } } }; - ci.setSlot(menuC, (rows * 9) - 1); - - ci.showInventory(p); - return; + recipeClickList.add(c); } - if (b.equals(fccf.getFurnace())) { // furnace interaction - if (fccf.isActive()) { - fccf.deactivate(); - p.sendMessage(ChatColor.RED + "Deactivated " + fccf.getName()); - } else { - fccf.attemptToActivate(p, false); + Scrollbar recipeScroller = new Scrollbar(recipeClickList, rows * 9); + recipeScroller.setBackwardsClickSlot(rows == 1 ? 0 : 8); + return recipeScroller; + } + + private Clickable buildAutoSelectToggle() { + ItemStack autoSelectStack = new ItemStack(Material.REDSTONE_BLOCK); + ItemUtils.setDisplayName(autoSelectStack, "Toggle auto select"); + ItemUtils.addLore(autoSelectStack, + ChatColor.GOLD + "Make the factory automatically select any", + ChatColor.GOLD + "recipe it can run whenever you activate it", + ChatColor.AQUA + "Click to turn it " + (fccf.isAutoSelect() ? "off" : "on")); + Clickable autoClick = new Clickable(autoSelectStack) { + + @Override + public void clicked(Player p) { + p.sendMessage(ChatColor.GREEN + "Turned auto select " + (fccf.isAutoSelect() ? "off" : "on") + + " for " + fccf.getName()); + fccf.setAutoSelect(!fccf.isAutoSelect()); } - } + }; + return autoClick; + } + + private Clickable buildMenuClickable() { + ItemStack menuStack = new ItemStack(Material.PAINTING); + ItemUtils.setDisplayName(menuStack, "Open menu"); + ItemUtils.addLore(menuStack, ChatColor.LIGHT_PURPLE + "Click to open a detailed menu"); + Clickable menuC = new Clickable(menuStack) { + @Override + public void clicked(Player p) { + FactoryModGUI gui = new FactoryModGUI(p); + gui.showForFactory((FurnCraftChestEgg)FactoryMod.getInstance().getManager().getEgg(fccf.getName())); + } + }; + return menuC; + } + + private Clickable buildMenuModeCycleButton(Player p) { + FurnCraftChestFactory.UiMenuMode[] modes = FurnCraftChestFactory.UiMenuMode.values(); + FurnCraftChestFactory.UiMenuMode curMode = fccf.getUiMenuMode(); + FurnCraftChestFactory.UiMenuMode nextMode = modes[(curMode.ordinal() + 1) % modes.length]; + ItemStack display = new ItemStack(nextMode.uiMaterial); + ItemUtils.setComponentDisplayName(display, Component.text(nextMode.uiDescription)); + + Clickable menuModeButton = new Clickable(display) { + private ClickableInventory inventory; + private int slot; + + @Override + protected void clicked(Player player) { + cycleMenuMode(); + ComponableInventory compInv = buildRecipeInventory(p); + compInv.update(); + compInv.updatePlayerView(); + } + + @Override + public void addedToInventory(ClickableInventory inv, int slot) { + this.inventory = inv; + this.slot = slot; + } + + private void cycleMenuMode() { + FurnCraftChestFactory.UiMenuMode innerCurMode = fccf.getUiMenuMode(); + innerCurMode = modes[(innerCurMode.ordinal() + 1) % modes.length]; + fccf.setUiMenuMode(innerCurMode); + + ItemStack innerCurStack = getItemStack(); + FurnCraftChestFactory.UiMenuMode innerNextMode = modes[(innerCurMode.ordinal() + 1) % modes.length]; + innerCurStack.setType(innerNextMode.uiMaterial); + ItemUtils.setComponentDisplayName(innerCurStack, Component.text(innerNextMode.uiDescription)); + + if (inventory != null && inventory.getSlot(slot) == this) { + inventory.setSlot(this, slot); + } + } + }; + return menuModeButton; } @Override diff --git a/src/main/java/com/github/igotyou/FactoryMod/listeners/FactoryModListener.java b/src/main/java/com/github/igotyou/FactoryMod/listeners/FactoryModListener.java index 8533aab5..d278663c 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/listeners/FactoryModListener.java +++ b/src/main/java/com/github/igotyou/FactoryMod/listeners/FactoryModListener.java @@ -9,7 +9,10 @@ import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; import org.bukkit.block.Furnace; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -59,14 +62,28 @@ public void blockBreakEvent(BlockBreakEvent e) { } @EventHandler - public void redstoneChange(BlockRedstoneEvent e) { - if (e.getOldCurrent() == e.getNewCurrent()) { + public void redstoneChange(BlockRedstoneEvent evt) { + if (evt.getOldCurrent() == evt.getNewCurrent()) { return; } - for (BlockFace face : WorldUtils.ALL_SIDES) { - Factory f = manager.getFactoryAt(e.getBlock().getRelative(face)); + Block powerSource = evt.getBlock(); + Material psType = powerSource.getType(); + if (psType == Material.REPEATER || psType == Material.COMPARATOR) { + BlockData psData = powerSource.getState().getBlockData(); + BlockFace direction = ((Directional) psData).getFacing(); + // repeaters "face" their input apparently + Block poweredBlock = powerSource.getRelative(direction.getOppositeFace()); + Factory f = manager.getFactoryAt(poweredBlock); if (f != null) { - f.getInteractionManager().redStoneEvent(e, e.getBlock().getRelative(face)); + f.getInteractionManager().redStoneEvent(evt, poweredBlock); + } + } else { + for (BlockFace direction : WorldUtils.ALL_SIDES) { + Block poweredBlock = powerSource.getRelative(direction); + Factory f = manager.getFactoryAt(poweredBlock); + if (f != null) { + f.getInteractionManager().redStoneEvent(evt, poweredBlock); + } } } } @@ -103,29 +120,29 @@ public void burnListener(BlockBurnEvent e) { } @EventHandler - public void playerInteract(PlayerInteractEvent e) { - Block block = e.getClickedBlock(); - Player player = e.getPlayer(); + public void playerInteract(PlayerInteractEvent evt) { + Block block = evt.getClickedBlock(); + Player player = evt.getPlayer(); if (block != null && manager.isPossibleInteractionBlock(block.getType())) { - BlockFace bf = e.getBlockFace(); - Factory c = manager.getFactoryAt(block); - if (e.getAction() == Action.RIGHT_CLICK_BLOCK) { - if (c != null) { - c.getInteractionManager().rightClick(player, block, bf); + BlockFace blockFace = evt.getBlockFace(); + Factory factory = manager.getFactoryAt(block); + if (evt.getAction() == Action.RIGHT_CLICK_BLOCK) { + if (factory != null) { + factory.getInteractionManager().rightClick(player, block, blockFace); } else { // check if chest is other half of double chest if (block.getType() == Material.CHEST || block.getType() == Material.TRAPPED_CHEST) { for (Block b : MultiBlockStructure.searchForBlockOnSides(block, block.getType())) { Factory f = manager.getFactoryAt(b); if (f != null) { - f.getInteractionManager().rightClick(player, b, bf); + f.getInteractionManager().rightClick(player, b, blockFace); } } } } } - if (e.getAction() == Action.LEFT_CLICK_BLOCK) { - if (c == null) { + if (evt.getAction() == Action.LEFT_CLICK_BLOCK) { + if (factory == null) { if (manager.isPossibleCenterBlock(block.getType())) { if (player.getInventory().getItemInMainHand().getType() == manager .getFactoryInteractionMaterial()) { @@ -137,13 +154,13 @@ public void playerInteract(PlayerInteractEvent e) { for (Block b : MultiBlockStructure.searchForBlockOnAllSides(block, block.getType())) { Factory f = manager.getFactoryAt(b); if (f != null) { - f.getInteractionManager().leftClick(player, b, bf); + f.getInteractionManager().leftClick(player, b, blockFace); } } } } } else { - c.getInteractionManager().leftClick(player, block, bf); + factory.getInteractionManager().leftClick(player, block, blockFace); } } diff --git a/src/main/java/com/github/igotyou/FactoryMod/powerManager/FurnacePowerManager.java b/src/main/java/com/github/igotyou/FactoryMod/powerManager/FurnacePowerManager.java index 4618e81c..cb7594b4 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/powerManager/FurnacePowerManager.java +++ b/src/main/java/com/github/igotyou/FactoryMod/powerManager/FurnacePowerManager.java @@ -1,9 +1,11 @@ package com.github.igotyou.FactoryMod.powerManager; +import com.github.igotyou.FactoryMod.utility.IIOFInventoryProvider; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.Furnace; import org.bukkit.inventory.FurnaceInventory; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import vg.civcraft.mc.civmodcore.itemHandling.ItemMap; @@ -17,6 +19,7 @@ public class FurnacePowerManager implements IPowerManager { private int powerCounter; private int fuelConsumptionIntervall; private Block furnace; + private IIOFInventoryProvider iofProvider; public FurnacePowerManager(Block furnace, ItemStack fuel, int fuelConsumptionIntervall) { @@ -30,11 +33,27 @@ public FurnacePowerManager(ItemStack fuel, int fuelConsumptionIntervall) { this.fuelConsumptionIntervall = fuelConsumptionIntervall; } + public void setIofProvider(IIOFInventoryProvider iofProvider) { + this.iofProvider = iofProvider; + } + + public IIOFInventoryProvider getIofProvider() { + return iofProvider; + } + public int getPowerCounter() { return powerCounter; } public boolean powerAvailable(int fuelCount) { + if (iofProvider != null) { + Inventory fuelInv = iofProvider.getFuelInventory(); + if (fuelInv != null) { + ItemMap im = new ItemMap(fuelInv); + return im.getAmount(fuel) >= fuelCount; + } + } + if (furnace.getType() != Material.FURNACE) { return false; } @@ -62,6 +81,16 @@ public void setPowerCounter(int amount) { } public void consumePower(int fuelCount) { + if (iofProvider != null) { + Inventory fuelInv = iofProvider.getFuelInventory(); + if (fuelInv != null) { + for (int i = 0; i < fuelCount; i++) { + fuelInv.removeItem(fuel); + } + return; + } + } + FurnaceInventory fi = ((Furnace) furnace.getState()).getInventory(); for(int i = 0; i < fuelCount; i++) @@ -69,6 +98,13 @@ public void consumePower(int fuelCount) { } public int getFuelAmountAvailable() { + if (iofProvider != null) { + Inventory fuelInv = iofProvider.getFuelInventory(); + if (fuelInv != null) { + ItemMap im = new ItemMap(fuelInv); + return im.getAmount(fuel); + } + } return new ItemMap(((Furnace) furnace.getState()).getInventory()).getAmount(fuel); } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/AOERepairRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/AOERepairRecipe.java index 668fb6cc..2970a4c3 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/AOERepairRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/AOERepairRecipe.java @@ -9,6 +9,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; @@ -133,11 +135,10 @@ public List getOutputRepresentation(Inventory i, FurnCraftChestFactor } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - Chest c = (Chest) i.getHolder(); - Location loc = c.getLocation(); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + Location loc = fccf.getChest().getLocation(); List facs = getNearbyFactoriesSortedByDistance(loc); - int essenceCount = new ItemMap(i).getAmount(essence); + int essenceCount = new ItemMap(inputInv).getAmount(essence); for (FurnCraftChestFactory fac : facs) { PercentageHealthRepairManager rm = (PercentageHealthRepairManager) fac .getRepairManager(); @@ -154,7 +155,7 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { Inventory targetInv = ((InventoryHolder) (fac.getChest() .getState())).getInventory(); if (remMap.fitsIn(targetInv)) { - if (remMap.removeSafelyFrom(i)) { + if (remMap.removeSafelyFrom(inputInv)) { targetInv.addItem(remStack); for (IRecipe rec : fac.getRecipes()) { if (rec instanceof RepairRecipe) { diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/CompactingRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/CompactingRecipe.java index 70edaa31..b41926fa 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/CompactingRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/CompactingRecipe.java @@ -5,6 +5,8 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.Material; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -30,12 +32,12 @@ public CompactingRecipe(String identifier, ItemMap input, List exclude } @Override - public boolean enoughMaterialAvailable(Inventory i) { - if (!input.isContainedIn(i)) { + public boolean enoughMaterialAvailable(Inventory inputInv) { + if (!input.isContainedIn(inputInv)) { return false; } - ItemMap im = new ItemMap(i); - for (ItemStack is : i.getContents()) { + ItemMap im = new ItemMap(inputInv); + for (ItemStack is : inputInv.getContents()) { if (is != null) { if (compactable(is, im)) { return true; @@ -56,25 +58,26 @@ public String getName() { } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); - if (input.isContainedIn(i)) { - ItemMap im = new ItemMap(i); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); + if (input.isContainedIn(inputInv)) { + ItemMap im = new ItemMap(inputInv); //technically we could just directly work with the ItemMap here to iterate over the items so we dont check identical items multiple times, //but using the iterator of the inventory preserves the order of the inventory, which is more important here to guarantee one behavior //to the player - for (ItemStack is : i.getContents()) { + for (ItemStack is : inputInv.getContents()) { if (is != null) { if (compactable(is, im)) { - if (input.removeSafelyFrom(i)) { - compact(is,i); + if (input.removeSafelyFrom(inputInv)) { + compact(is, inputInv, outputInv); } break; } } } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } @@ -134,13 +137,13 @@ public Material getRecipeRepresentationMaterial() { * * @param is */ - private void compact(ItemStack is, Inventory i) { + private void compact(ItemStack is, Inventory inputInv, Inventory outputInv) { ItemStack copy = is.clone(); copy.setAmount(getCompactStackSize(copy.getType())); ItemMap toRemove = new ItemMap(copy); - if (toRemove.removeSafelyFrom(i)) { + if (toRemove.removeSafelyFrom(inputInv)) { compactStack(copy); - i.addItem(copy); + outputInv.addItem(copy); } } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/DecompactingRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/DecompactingRecipe.java index bf40ff23..3ac9dae0 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/DecompactingRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/DecompactingRecipe.java @@ -4,6 +4,8 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.Material; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -27,11 +29,11 @@ public DecompactingRecipe(String identifier, ItemMap input, String name, int pro } @Override - public boolean enoughMaterialAvailable(Inventory i) { - if (!input.isContainedIn(i)) { + public boolean enoughMaterialAvailable(Inventory inputInv) { + if (!input.isContainedIn(inputInv)) { return false; } - for (ItemStack is : i.getContents()) { + for (ItemStack is : inputInv.getContents()) { if (is != null) { if (isDecompactable(is)) { return true; @@ -42,10 +44,11 @@ public boolean enoughMaterialAvailable(Inventory i) { } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); - if (input.isContainedIn(i)) { - for (ItemStack is : i.getContents()) { + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); + if (input.isContainedIn(inputInv)) { + for (ItemStack is : inputInv.getContents()) { if (is != null) { if (isDecompactable(is)) { ItemStack removeClone = is.clone(); @@ -54,11 +57,11 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { ItemMap toAdd = new ItemMap(); removeCompactLore(removeClone); toAdd.addItemAmount(removeClone, CompactingRecipe.getCompactStackSize(removeClone.getType())); - if (toAdd.fitsIn(i)) { //fits in chest - if (input.removeSafelyFrom(i)) { //remove extra input - if (toRemove.removeSafelyFrom(i)) { //remove one compacted item + if (toAdd.fitsIn(outputInv)) { //fits in chest + if (input.removeSafelyFrom(inputInv)) { //remove extra input + if (toRemove.removeSafelyFrom(inputInv)) { //remove one compacted item for(ItemStack add : toAdd.getItemStackRepresentation()) { - i.addItem(add); + outputInv.addItem(add); } } } @@ -70,7 +73,7 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { } } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/DeterministicEnchantingRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/DeterministicEnchantingRecipe.java index 15a5ed0f..a58b2f0b 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/DeterministicEnchantingRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/DeterministicEnchantingRecipe.java @@ -4,6 +4,8 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; @@ -27,10 +29,10 @@ public DeterministicEnchantingRecipe(String identifier, String name, int product } @Override - public boolean enoughMaterialAvailable(Inventory i) { - if (input.isContainedIn(i)) { + public boolean enoughMaterialAvailable(Inventory inputInv) { + if (input.isContainedIn(inputInv)) { ItemStack toolio = tool.getItemStackRepresentation().get(0); - for (ItemStack is : i.getContents()) { + for (ItemStack is : inputInv.getContents()) { if (is != null && toolio.getType() == is.getType() && toolio.getEnchantmentLevel(enchant) == is.getEnchantmentLevel(enchant)) { return true; @@ -80,11 +82,12 @@ public List getInputRepresentation(Inventory i, FurnCraftChestFactory } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); - if (input.removeSafelyFrom(i)) { + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); + if (input.removeSafelyFrom(inputInv)) { ItemStack toolio = tool.getItemStackRepresentation().get(0); - for (ItemStack is : i.getContents()) { + for (ItemStack is : inputInv.getContents()) { if (is != null && toolio.getType() == is.getType() && toolio.getEnchantmentLevel(enchant) == is.getEnchantmentLevel(enchant)) { ItemMeta im = is.getItemMeta(); @@ -95,7 +98,7 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { } } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/DummyParsingRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/DummyParsingRecipe.java index 9c3a3d69..fa233ee4 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/DummyParsingRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/DummyParsingRecipe.java @@ -2,6 +2,8 @@ import com.github.igotyou.FactoryMod.factories.FurnCraftChestFactory; import java.util.List; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.Material; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -14,7 +16,7 @@ public DummyParsingRecipe(String identifier, String name, int productionTime, It } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/FactoryMaterialReturnRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/FactoryMaterialReturnRecipe.java index 1e4aca3d..75cf0771 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/FactoryMaterialReturnRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/FactoryMaterialReturnRecipe.java @@ -6,6 +6,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -68,7 +70,7 @@ public Material getRecipeRepresentationMaterial() { } @Override - public boolean applyEffect(Inventory i, final FurnCraftChestFactory fccf) { + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { FactoryMod.getInstance().getManager().removeFactory(fccf); for (Block b : fccf.getMultiBlockStructure().getRelevantBlocks()) { b.setType(Material.AIR); diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/IRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/IRecipe.java index 3d5bf6ce..b0c3d1e5 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/IRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/IRecipe.java @@ -7,12 +7,11 @@ * Encapsulates a specific functionality for a FurnCraftChest factory. Each * factory of this type can have of many different recipes and what the recipe * actually does is completly kept inside the recipe's class - * */ public interface IRecipe { /** * @return The identifier for this recipe, which is used both internally and - * to display the recipe to a player + * to display the recipe to a player */ public String getName(); @@ -29,28 +28,26 @@ public interface IRecipe { /** * Checks whether enough material is available in the given inventory to run * this recipe at least once - * - * @param i - * Inventory to check + * + * @param inputInv Inventory to check * @return true if the recipe could be run at least once, false if not */ - public boolean enoughMaterialAvailable(Inventory i); + public boolean enoughMaterialAvailable(Inventory inputInv); /** * Applies whatever the recipe actually does, it's main functionality - * - * @param i - * Inventory which contains the materials to work with - * @param f - * Factory which is run + * + * @param inputInv Inventory which contains the materials to work with + * @param outputInv Inventory to add output items to. + * @param fccf Factory which is run * @return true if the recipe could be run; false otherwise (e.g: not enough storage space) */ - public boolean applyEffect(Inventory i, FurnCraftChestFactory f); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf); /** * Each implementation of this class has to specify a unique identifier, * which is used to identify instances of this recipe in the config - * + * * @return Unique identifier for the implementation */ public String getTypeIdentifier(); diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/InputRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/InputRecipe.java index d9344751..29457c84 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/InputRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/InputRecipe.java @@ -140,8 +140,8 @@ public ItemMap getInput() { } @Override - public boolean enoughMaterialAvailable(Inventory i) { - return input.isContainedIn(i); + public boolean enoughMaterialAvailable(Inventory inputInv) { + return input.isContainedIn(inputInv); } @Override diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/LoreEnchantRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/LoreEnchantRecipe.java index d9ee9305..a619278f 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/LoreEnchantRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/LoreEnchantRecipe.java @@ -4,6 +4,8 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -38,10 +40,10 @@ public LoreEnchantRecipe(String identifier, String name, int productionTime, Ite } @Override - public boolean enoughMaterialAvailable(Inventory i) { - if (input.isContainedIn(i)) { + public boolean enoughMaterialAvailable(Inventory inputInv) { + if (input.isContainedIn(inputInv)) { ItemStack toolio = tool.getItemStackRepresentation().get(0); - for (ItemStack is : i.getContents()) { + for (ItemStack is : inputInv.getContents()) { if (is != null && toolio.getType() == is.getType() && hasStackRequiredLore(is)) { return true; } @@ -88,11 +90,12 @@ public List getInputRepresentation(Inventory i, FurnCraftChestFactory } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); - if (input.removeSafelyFrom(i)) { + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); + if (input.removeSafelyFrom(inputInv)) { ItemStack toolio = tool.getItemStackRepresentation().get(0); - for (ItemStack is : i.getContents()) { + for (ItemStack is : inputInv.getContents()) { if (is != null && toolio.getType() == is.getType() && hasStackRequiredLore(is)) { ItemMeta im = is.getItemMeta(); if (im == null) { @@ -112,7 +115,7 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { } } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/PlayerHeadRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/PlayerHeadRecipe.java index 77987fee..cae1ddde 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/PlayerHeadRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/PlayerHeadRecipe.java @@ -5,6 +5,8 @@ import java.util.Collections; import java.util.List; import java.util.Random; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -48,15 +50,16 @@ public Material getRecipeRepresentationMaterial() { } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory f) { - logBeforeRecipeRun(i, f); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); ItemMap toRemove = input.clone(); ArrayList players = new ArrayList<>(Bukkit.getOnlinePlayers()); if (players.isEmpty()) { return false; } - if (toRemove.isContainedIn(i)) { - if (toRemove.removeSafelyFrom(i)) { + if (toRemove.isContainedIn(inputInv)) { + if (toRemove.removeSafelyFrom(inputInv)) { Random rand = new Random(); Player player = players.get(rand.nextInt(players.size())); ItemStack is = new ItemStack(Material.PLAYER_HEAD, 1); @@ -64,10 +67,10 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory f) { im.setOwningPlayer(Bukkit.getOfflinePlayer(player.getUniqueId())); im.setDisplayName(player.getDisplayName()); is.setItemMeta(im); - i.addItem(is); + outputInv.addItem(is); } } - logAfterRecipeRun(i, f); + logAfterRecipeRun(combo, fccf); return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintBookRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintBookRecipe.java index ba813585..6ad5bb62 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintBookRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintBookRecipe.java @@ -1,9 +1,12 @@ package com.github.igotyou.FactoryMod.recipes; import com.github.igotyou.FactoryMod.factories.FurnCraftChestFactory; + import java.util.ArrayList; import java.util.LinkedList; import java.util.List; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; @@ -33,35 +36,34 @@ public PrintBookRecipe( ItemMap input, ItemMap printingPlate, int outputAmount - ) - { + ) { super(identifier, name, productionTime, input); this.printingPlate = printingPlate; this.outputAmount = outputAmount; - } + } @Override - public boolean enoughMaterialAvailable(Inventory i) { - return this.input.isContainedIn(i) && getPrintingPlateItemStack(i, this.printingPlate) != null; + public boolean enoughMaterialAvailable(Inventory inputInv) { + return this.input.isContainedIn(inputInv) && getPrintingPlateItemStack(inputInv, this.printingPlate) != null; } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); - ItemStack printingPlateStack = getPrintingPlateItemStack(i, this.printingPlate); + ItemStack printingPlateStack = getPrintingPlateItemStack(inputInv, this.printingPlate); ItemMap toRemove = this.input.clone(); if (printingPlateStack != null - && toRemove.isContainedIn(i) - && toRemove.removeSafelyFrom(i) - ) - { - ItemStack book = createBook(printingPlateStack, this.outputAmount); - i.addItem(book); + && toRemove.isContainedIn(inputInv) + && toRemove.removeSafelyFrom(inputInv) + ) { + ItemStack book = createBook(printingPlateStack, this.outputAmount); + outputInv.addItem(book); } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } @@ -90,7 +92,7 @@ public List getInputRepresentation(Inventory i, FurnCraftChestFactory ItemStack printingPlateStack = getPrintingPlateItemStack(i, this.printingPlate); - if(printingPlateStack != null) { + if (printingPlateStack != null) { result.add(printingPlateStack.clone()); } @@ -125,13 +127,12 @@ public Material getRecipeRepresentationMaterial() { protected ItemStack getPrintingPlateItemStack(Inventory i, ItemMap printingPlate) { ItemMap items = new ItemMap(i).getStacksByMaterial(printingPlate.getItemStackRepresentation().get(0).getType()); - for(ItemStack is : items.getItemStackRepresentation()) { + for (ItemStack is : items.getItemStackRepresentation()) { ItemMeta itemMeta = is.getItemMeta(); - if(itemMeta.getDisplayName().equals(PrintingPlateRecipe.itemName) + if (itemMeta.getDisplayName().equals(PrintingPlateRecipe.itemName) && itemMeta.hasEnchant(Enchantment.DURABILITY) - ) - { + ) { return is; } } @@ -143,7 +144,7 @@ protected ItemStack getPrintingPlateItemStack(Inventory i, ItemMap printingPlate public String getTypeIdentifier() { return "PRINTBOOK"; } - + @Override public List getTextualOutputRepresentation(Inventory i, FurnCraftChestFactory fccf) { ItemStack is = new ItemStack(Material.WRITTEN_BOOK, outputAmount); diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintNoteRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintNoteRecipe.java index e7942f0a..66054cb9 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintNoteRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintNoteRecipe.java @@ -1,13 +1,15 @@ /** * @author Aleksey Terzi - * */ package com.github.igotyou.FactoryMod.recipes; import com.github.igotyou.FactoryMod.factories.FurnCraftChestFactory; + import java.util.ArrayList; import java.util.List; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.inventory.Inventory; @@ -42,36 +44,35 @@ public PrintNoteRecipe( String identifier, String name, int productionTime, - ItemMap input, + ItemMap input, ItemMap printingPlate, int outputAmount, boolean secureNote, String title - ) - { + ) { super(identifier, name, productionTime, input, printingPlate, outputAmount); this.secureNote = secureNote; - if(title != null && title.length() > 0) { + if (title != null && title.length() > 0) { this.title = title; } else { - this.title = secureNote ? secureNoteName: pamphletName; + this.title = secureNote ? secureNoteName : pamphletName; } - } + } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); - ItemStack printingPlateStack = getPrintingPlateItemStack(i, getPrintingPlate()); + ItemStack printingPlateStack = getPrintingPlateItemStack(inputInv, getPrintingPlate()); ItemMap toRemove = this.input.clone(); if (printingPlateStack != null - && toRemove.isContainedIn(i) - && toRemove.removeSafelyFrom(i) - ) - { + && toRemove.isContainedIn(inputInv) + && toRemove.removeSafelyFrom(inputInv) + ) { BookInfo info = getBookInfo(printingPlateStack); ItemStack paper = new ItemStack(Material.PAPER, getOutputAmount()); @@ -80,21 +81,21 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { paperMeta.setLore(info.lines); paper.setItemMeta(paperMeta); - i.addItem(paper); + outputInv.addItem(paper); } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } private BookInfo getBookInfo(ItemStack printingPlateStack) { ItemStack book = createBook(printingPlateStack, 1); - BookMeta bookMeta = (BookMeta)book.getItemMeta(); - String text = bookMeta.getPageCount() > 0 ? bookMeta.getPage(1): ""; + BookMeta bookMeta = (BookMeta) book.getItemMeta(); + String text = bookMeta.getPageCount() > 0 ? bookMeta.getPage(1) : ""; String[] lines = text.split("\n"); List fixedLines = new ArrayList<>(); - for(String line : lines) { + for (String line : lines) { fixedLines.add(ChatColor.GRAY + line .replaceAll(ChatColor.BLACK.toString(), ChatColor.GRAY.toString()) .replaceAll(ChatColor.RESET.toString(), ChatColor.GRAY.toString())); @@ -104,9 +105,9 @@ private BookInfo getBookInfo(ItemStack printingPlateStack) { BookInfo info = new BookInfo(); info.lines = fixedLines; - info.title = bookTitle != null && bookTitle.length() > 0 ? bookTitle: this.title; + info.title = bookTitle != null && bookTitle.length() > 0 ? bookTitle : this.title; - if(this.secureNote) { + if (this.secureNote) { TagManager printingPlateTag = new TagManager(printingPlateStack); String serialNumber = printingPlateTag.getString("SN"); info.lines.add(serialNumber); diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintingPlateJsonRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintingPlateJsonRecipe.java index fc13db26..9c59008a 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintingPlateJsonRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintingPlateJsonRecipe.java @@ -2,6 +2,7 @@ import com.github.igotyou.FactoryMod.FactoryMod; import com.github.igotyou.FactoryMod.factories.FurnCraftChestFactory; +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -40,8 +41,8 @@ public PrintingPlateJsonRecipe(String identifier, String name, int productionTim } @Override - public boolean enoughMaterialAvailable(Inventory i) { - String[] pages = String.join("", ((BookMeta) getBook(i).getItemMeta()).getPages()).split("<>"); + public boolean enoughMaterialAvailable(Inventory inputInv) { + String[] pages = String.join("", ((BookMeta) getBook(inputInv).getItemMeta()).getPages()).split("<>"); for (String page : pages) { try { @@ -50,25 +51,26 @@ public boolean enoughMaterialAvailable(Inventory i) { String result = checkForIllegalSections(element); if (result != null) { - factioryError(i, "Banned Tag Error", "Error Message: " + result); + factioryError(inputInv, "Banned Tag Error", "Error Message: " + result); return false; } } catch (JsonSyntaxException e) { - factioryError(i, "JSON Syntax Error", e.toString()); + factioryError(inputInv, "JSON Syntax Error", e.toString()); return false; } } - return this.input.isContainedIn(i) && getBook(i) != null; + return this.input.isContainedIn(inputInv) && getBook(inputInv) != null; } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); - ItemStack book = getBook(i); + ItemStack book = getBook(inputInv); BookMeta bookMeta = (BookMeta) book.getItemMeta(); if (!bookMeta.hasGeneration()) { bookMeta.setGeneration(BookMeta.Generation.ORIGINAL); @@ -91,9 +93,9 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { ItemMap toRemove = input.clone(); ItemMap toAdd = output.clone(); - if (toRemove.isContainedIn(i) && toRemove.removeSafelyFrom(i)) { + if (toRemove.isContainedIn(inputInv) && toRemove.removeSafelyFrom(inputInv)) { for (ItemStack is : toAdd.getItemStackRepresentation()) { - is = addTags(i, serialNumber, is, bookNBT); + is = addTags(serialNumber, is, bookNBT); ItemUtils.setDisplayName(is, itemName); ItemUtils.setLore(is, @@ -105,11 +107,11 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { ); is.addUnsafeEnchantment(Enchantment.DURABILITY, 1); is.getItemMeta().addItemFlags(ItemFlag.HIDE_ENCHANTS); - i.addItem(is); + outputInv.addItem(is); } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintingPlateRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintingPlateRecipe.java index aafd3bd4..ece77d85 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintingPlateRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/PrintingPlateRecipe.java @@ -10,6 +10,8 @@ import java.util.LinkedList; import java.util.List; import java.util.UUID; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import net.minecraft.server.v1_16_R3.NBTTagCompound; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -38,15 +40,16 @@ public PrintingPlateRecipe(String identifier, String name, int productionTime, I } @Override - public boolean enoughMaterialAvailable(Inventory i) { - return this.input.isContainedIn(i) && getBook(i) != null; + public boolean enoughMaterialAvailable(Inventory inputInv) { + return this.input.isContainedIn(inputInv) && getBook(inputInv) != null; } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); - ItemStack book = getBook(i); + ItemStack book = getBook(inputInv); BookMeta bookMeta = (BookMeta)book.getItemMeta(); if (!bookMeta.hasGeneration()){ bookMeta.setGeneration(Generation.TATTERED); @@ -56,9 +59,9 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { ItemMap toRemove = input.clone(); ItemMap toAdd = output.clone(); - if (toRemove.isContainedIn(i) && toRemove.removeSafelyFrom(i)) { + if (toRemove.isContainedIn(inputInv) && toRemove.removeSafelyFrom(inputInv)) { for(ItemStack is: toAdd.getItemStackRepresentation()) { - is = addTags(i, serialNumber, is, CraftItemStack.asNMSCopy(book).getTag()); + is = addTags(serialNumber, is, CraftItemStack.asNMSCopy(book).getTag()); ItemUtils.setDisplayName(is, itemName); ItemUtils.setLore(is, @@ -69,15 +72,22 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { ); is.addUnsafeEnchantment(Enchantment.DURABILITY, 1); is.getItemMeta().addItemFlags(ItemFlag.HIDE_ENCHANTS); - i.addItem(is); + outputInv.addItem(is); } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } + /** + * @deprecated {@code Inventory i} isn't being used, switch to the overload without it. + */ public static ItemStack addTags(Inventory i, String serialNumber, ItemStack plate, NBTTagCompound bookTag) { + return addTags(serialNumber, plate, bookTag); + } + + public static ItemStack addTags(String serialNumber, ItemStack plate, NBTTagCompound bookTag) { net.minecraft.server.v1_16_R3.ItemStack nmsPlate = CraftItemStack.asNMSCopy(plate); NBTTagCompound plateTag = nmsPlate.getOrCreateTag(); diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/ProductionRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/ProductionRecipe.java index 1d3819c9..5038e057 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/ProductionRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/ProductionRecipe.java @@ -6,6 +6,8 @@ import java.util.List; import java.util.Map.Entry; import java.util.Random; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.inventory.Inventory; @@ -111,8 +113,9 @@ public List getGuaranteedOutput(Inventory i, FurnCraftChestFactory fc } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); ItemMap toRemove = input.clone(); ItemMap toAdd; if (getModifier() == null) { @@ -128,17 +131,17 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { } } } - if (toRemove.isContainedIn(i)) { - if (!toAdd.fitsIn(i)) { // does not fit in chest + if (toRemove.isContainedIn(inputInv)) { + if (!toAdd.fitsIn(outputInv)) { // does not fit in chest return false; } - if (toRemove.removeSafelyFrom(i)) { + if (toRemove.removeSafelyFrom(inputInv)) { for (ItemStack is : toAdd.getItemStackRepresentation()) { - i.addItem(is); + outputInv.addItem(is); } } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/PylonRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/PylonRecipe.java index 3ebb141e..f93740c8 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/PylonRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/PylonRecipe.java @@ -6,6 +6,8 @@ import java.util.List; import java.util.Map.Entry; import java.util.Set; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.inventory.Inventory; @@ -28,17 +30,18 @@ public PylonRecipe(String identifier, String name, int productionTime, ItemMap i } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - if (!input.isContainedIn(i)) { + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + if (!input.isContainedIn(inputInv)) { return false; } ItemMap actualOutput = getCurrentOutput(); - if (!actualOutput.fitsIn(i)) { + if (!actualOutput.fitsIn(outputInv)) { return false; } - if (input.removeSafelyFrom(i)) { + if (input.removeSafelyFrom(inputInv)) { for (ItemStack is : actualOutput.getItemStackRepresentation()) { - i.addItem(is); + outputInv.addItem(is); } } return true; @@ -81,8 +84,8 @@ public Material getRecipeRepresentationMaterial() { } @Override - public boolean enoughMaterialAvailable(Inventory i) { - return input.isContainedIn(i) && skyView(); + public boolean enoughMaterialAvailable(Inventory inputInv) { + return input.isContainedIn(inputInv) && skyView(); } public int getWeight() { diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/RandomEnchantingRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/RandomEnchantingRecipe.java index 41329934..6c4aa90e 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/RandomEnchantingRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/RandomEnchantingRecipe.java @@ -5,6 +5,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Random; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; @@ -91,12 +93,13 @@ public List getOutputRepresentation(Inventory i, FurnCraftChestFactor } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); for (ItemStack is : input.getItemStackRepresentation()) { - i.removeItem(is); + inputInv.removeItem(is); } - for (ItemStack is : i.getContents()) { + for (ItemStack is : inputInv.getContents()) { if (is != null && is.getType() == tool && !is.getItemMeta().hasEnchants()) { boolean applied = false; @@ -112,7 +115,7 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { break; } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/RandomOutputRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/RandomOutputRecipe.java index 21cf4e22..e1b417b0 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/RandomOutputRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/RandomOutputRecipe.java @@ -7,6 +7,8 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Random; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.inventory.Inventory; @@ -45,8 +47,9 @@ public RandomOutputRecipe(String identifier, String name, int productionTime, It } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); ItemMap toRemove = input.clone(); ItemMap toAdd = null; int counter = 0; @@ -64,14 +67,14 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { FactoryMod.getInstance().warning("Unable to find a random item to output. Recipe execution was cancelled," + fccf.getLogData()); return false; } - if (toRemove.isContainedIn(i)) { - if (toRemove.removeSafelyFrom(i)) { + if (toRemove.isContainedIn(inputInv)) { + if (toRemove.removeSafelyFrom(inputInv)) { for(ItemStack is: toAdd.getItemStackRepresentation()) { - i.addItem(is); + outputInv.addItem(is); } } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/RecipeScalingUpgradeRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/RecipeScalingUpgradeRecipe.java index f622e8f8..4279ca74 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/RecipeScalingUpgradeRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/RecipeScalingUpgradeRecipe.java @@ -4,6 +4,8 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.Material; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -24,14 +26,15 @@ public RecipeScalingUpgradeRecipe(String identifier, String name, int production } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); if (toUpgrade == null || !fccf.getRecipes().contains(toUpgrade)) { return false; } ItemMap toRemove = input.clone(); - if (toRemove.isContainedIn(i)) { - if (toRemove.removeSafelyFrom(i)) { + if (toRemove.isContainedIn(inputInv)) { + if (toRemove.removeSafelyFrom(inputInv)) { if (newRank == 1) { fccf.addRecipe(toUpgrade); } @@ -46,7 +49,7 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { } } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/RepairRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/RepairRecipe.java index 7b65eca8..7eec6a10 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/RepairRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/RepairRecipe.java @@ -6,6 +6,8 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.inventory.Inventory; @@ -45,10 +47,11 @@ public List getInputRepresentation(Inventory i, FurnCraftChestFactory } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logBeforeRecipeRun(i, fccf); - if (enoughMaterialAvailable(i)) { - if (input.removeSafelyFrom(i)) { + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); + if (enoughMaterialAvailable(inputInv)) { + if (input.removeSafelyFrom(inputInv)) { ((PercentageHealthRepairManager) (fccf.getRepairManager())) .repair(healthPerRun); LoggingUtils.log(((PercentageHealthRepairManager) (fccf @@ -57,7 +60,7 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { + fccf.getLogData() + " after repairing"); } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/Upgraderecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/Upgraderecipe.java index 867b96f1..11347b37 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/Upgraderecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/Upgraderecipe.java @@ -6,6 +6,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; @@ -26,10 +28,11 @@ public Upgraderecipe(String identifier, String name, int productionTime, ItemMap } @Override - public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { - logAfterRecipeRun(i, fccf); - if (input.isContainedIn(i)) { - if (input.removeSafelyFrom(i)) { + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + logBeforeRecipeRun(combo, fccf); + if (input.isContainedIn(inputInv)) { + if (input.removeSafelyFrom(inputInv)) { FurnCraftChestEgg e = egg; fccf.upgrade(e.getName(), e.getRecipes(), e.getFuel(), @@ -37,7 +40,7 @@ public boolean applyEffect(Inventory i, FurnCraftChestFactory fccf) { e.getDamagePerDamagingPeriod(), e.getBreakGracePeriod(), e.getCitadelBreakReduction()); } } - logAfterRecipeRun(i, fccf); + logAfterRecipeRun(combo, fccf); return true; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/recipes/WordBankRecipe.java b/src/main/java/com/github/igotyou/FactoryMod/recipes/WordBankRecipe.java index 5e6f4e10..3e5eae6c 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/recipes/WordBankRecipe.java +++ b/src/main/java/com/github/igotyou/FactoryMod/recipes/WordBankRecipe.java @@ -12,6 +12,8 @@ import java.util.List; import java.util.Map.Entry; import java.util.Random; + +import com.github.igotyou.FactoryMod.utility.MultiInventoryWrapper; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -47,8 +49,9 @@ public WordBankRecipe(String identifier, String name, int productionTime, String } @Override - public boolean applyEffect(Inventory inventory, FurnCraftChestFactory factory) { - ItemStack toApply = inventory.getItem(0); + public boolean applyEffect(Inventory inputInv, Inventory outputInv, FurnCraftChestFactory fccf) { + MultiInventoryWrapper combo = new MultiInventoryWrapper(inputInv, outputInv); + ItemStack toApply = inputInv.getItem(0); if (!ItemUtils.isValidItem(toApply)) { return false; } @@ -56,13 +59,13 @@ public boolean applyEffect(Inventory inventory, FurnCraftChestFactory factory) { return false; } ItemMap input = new ItemMap(); - for (int i = 1; i < inventory.getSize(); i++) { - ItemStack is = inventory.getItem(i); + for (int i = 1; i < inputInv.getSize(); i++) { + ItemStack is = inputInv.getItem(i); if (!ItemUtils.isValidItem(is)) { continue; } input.addItemStack(is); - inventory.setItem(i, null); + inputInv.setItem(i, null); } //tell player what the recipe consumed StringBuilder sb = new StringBuilder(); @@ -77,8 +80,8 @@ public boolean applyEffect(Inventory inventory, FurnCraftChestFactory factory) { String result = sb.substring(0, sb.length() - 2); String name = getHash(input); ItemUtils.setDisplayName(toApply, name); - if (factory.getActivator() != null) { - Player player = Bukkit.getPlayer(factory.getActivator()); + if (fccf.getActivator() != null) { + Player player = Bukkit.getPlayer(fccf.getActivator()); if (player != null) { player.sendMessage(result + " into " + name); } @@ -121,16 +124,16 @@ public Material getRecipeRepresentationMaterial() { } @Override - public boolean enoughMaterialAvailable(Inventory inventory) { - ItemStack toApply = inventory.getItem(0); + public boolean enoughMaterialAvailable(Inventory inputInv) { + ItemStack toApply = inputInv.getItem(0); if (!ItemUtils.isValidItem(toApply)) { return false; } if (ItemUtils.getDisplayName(toApply) != null) { return false; } - for (int i = 1; i < inventory.getSize(); i++) { - ItemStack is = inventory.getItem(i); + for (int i = 1; i < inputInv.getSize(); i++) { + ItemStack is = inputInv.getItem(i); if (!ItemUtils.isValidItem(is)) { continue; } diff --git a/src/main/java/com/github/igotyou/FactoryMod/structures/FurnCraftChestStructure.java b/src/main/java/com/github/igotyou/FactoryMod/structures/FurnCraftChestStructure.java index f121f502..17832767 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/structures/FurnCraftChestStructure.java +++ b/src/main/java/com/github/igotyou/FactoryMod/structures/FurnCraftChestStructure.java @@ -27,60 +27,18 @@ public FurnCraftChestStructure(Block center) { chestBlocks.addAll(searchForBlockOnAllSides(center, Material.CHEST)); chestBlocks.addAll(searchForBlockOnAllSides(center, Material.TRAPPED_CHEST)); for (Block b : chestBlocks) { - switch (center.getFace(b)) { - case SOUTH: - if (center.getRelative(BlockFace.NORTH).getType() == Material.FURNACE) { - chest = b.getLocation(); - furnace = center.getRelative(BlockFace.NORTH) - .getLocation(); - } - break; - case NORTH: - if (center.getRelative(BlockFace.SOUTH).getType() == Material.FURNACE) { - chest = b.getLocation(); - furnace = center.getRelative(BlockFace.SOUTH) - .getLocation(); - } - break; - case WEST: - if (center.getRelative(BlockFace.EAST).getType() == Material.FURNACE) { - chest = b.getLocation(); - furnace = center.getRelative(BlockFace.EAST) - .getLocation(); - } - break; - case EAST: - if (center.getRelative(BlockFace.WEST).getType() == Material.FURNACE) { - chest = b.getLocation(); - furnace = center.getRelative(BlockFace.WEST) - .getLocation(); - } - break; - case UP: - if (center.getRelative(BlockFace.DOWN).getType() == Material.FURNACE) { - chest = b.getLocation(); - furnace = center.getRelative(BlockFace.DOWN) - .getLocation(); - } - break; - case DOWN: - if (center.getRelative(BlockFace.UP).getType() == Material.FURNACE) { - chest = b.getLocation(); - furnace = center.getRelative(BlockFace.UP) - .getLocation(); - } - break; - default: + BlockFace chestFace = center.getFace(b); + if (chestFace == null) continue; // fricc off nullcheck + BlockFace furnaceFace = chestFace.getOppositeFace(); + Block furnaceBlock = center.getRelative(furnaceFace); + if (furnaceBlock.getType() == Material.FURNACE) { + chest = b.getLocation(); + furnace = furnaceBlock.getLocation(); break; } - } } - if (chest != null && furnace != null) { - complete = true; - } else { - complete = false; - } + complete = chest != null && furnace != null; } public FurnCraftChestStructure(List blocks) { diff --git a/src/main/java/com/github/igotyou/FactoryMod/utility/Direction.java b/src/main/java/com/github/igotyou/FactoryMod/utility/Direction.java new file mode 100644 index 00000000..2d3e33ed --- /dev/null +++ b/src/main/java/com/github/igotyou/FactoryMod/utility/Direction.java @@ -0,0 +1,86 @@ +package com.github.igotyou.FactoryMod.utility; + +import org.bukkit.block.BlockFace; + +import java.util.function.Function; + +/** + * @author caucow + */ +public enum Direction { + TOP(bf -> BlockFace.UP), // 1 + BOTTOM(bf -> BlockFace.DOWN), // 2 + LEFT(bf -> { + switch (bf) { + case NORTH: + return BlockFace.EAST; + case EAST: + return BlockFace.SOUTH; + case SOUTH: + return BlockFace.WEST; + case WEST: + return BlockFace.NORTH; + default: + return bf; + } + }), // 4 + RIGHT(bf -> { + switch (bf) { + case NORTH: + return BlockFace.WEST; + case EAST: + return BlockFace.NORTH; + case SOUTH: + return BlockFace.EAST; + case WEST: + return BlockFace.SOUTH; + default: + return bf; + } + }), // 8 + FRONT(bf -> bf), // 16 + BACK(BlockFace::getOppositeFace); // 32 + + private final Function facingModifier; + + private Direction(Function facingModifier) { + this.facingModifier = facingModifier; + } + + /** + * @param front direction a block (such as a furnace) is facing. + * @return BlockFace in this direction, relative to the player's perspective when the player and block are + * facing each other. + */ + public BlockFace getBlockFacing(BlockFace front) { + return facingModifier.apply(front); + } + + public static Direction getDirection(BlockFace front, BlockFace axis) { + for (Direction dir : Direction.values()) { + // if dir's transformation of front == axis + if (dir.getBlockFacing(front) == axis) { + return dir; + } + } + throw new IllegalArgumentException("Direction can only be gotten from an axis-aligned BlockFace."); + } + + private static BlockFace getBlockFaceFromDirection(int dirx, int dirz) { + switch (dirz) { + case 1: + return BlockFace.SOUTH; + case -1: + return BlockFace.NORTH; + case 0: { + switch (dirx) { + case 1: + return BlockFace.EAST; + case -1: + return BlockFace.WEST; + } + } + } + throw new IllegalArgumentException("Not a horizontal ordinal: (" + dirx + "," + dirz + ")"); + } +} diff --git a/src/main/java/com/github/igotyou/FactoryMod/utility/FileHandler.java b/src/main/java/com/github/igotyou/FactoryMod/utility/FileHandler.java index 5978f938..8c4a11da 100644 --- a/src/main/java/com/github/igotyou/FactoryMod/utility/FileHandler.java +++ b/src/main/java/com/github/igotyou/FactoryMod/utility/FileHandler.java @@ -99,6 +99,9 @@ public void save(Collection factories) { config.set(current + ".runcounts." + i.getName(), fccf.getRunCount(i)); config.set(current + ".recipeLevels." + i.getName(), fccf.getRecipeLevel(i)); } + config.set(current + ".furnace-io", fccf.getFurnaceIOSelector().toConfigSection()); + config.set(current + ".table-io", fccf.getTableIOSelector().toConfigSection()); + config.set(current + ".ui-menu-mode", fccf.getUiMenuMode().name()); } else if (f instanceof Pipe) { Pipe p = (Pipe) f; config.set(current + ".type", "PIPE"); @@ -258,9 +261,6 @@ private void loadFromFile(File f, Map eggs) { } boolean autoSelect = current.getBoolean("autoSelect", false); - if (recipes == null) { - recipes = new LinkedList<>(); - } FurnCraftChestFactory fac = (FurnCraftChestFactory) egg.revive(blocks, health, selectedRecipe, runtime, breakTime, recipes); String activator = current.getString("activator", "null"); @@ -297,6 +297,34 @@ private void loadFromFile(File f, Map eggs) { } } fac.setAutoSelect(autoSelect); + { + ConfigurationSection iosec = current.getConfigurationSection("furnace-io"); + if (iosec != null) { + IOSelector furnaceIoSelector = IOSelector.fromConfigSection(iosec); + fac.setFurnaceIOSelector(furnaceIoSelector); + } else { + // Nothing I guess, the furnace has no default state. + } + iosec = current.getConfigurationSection("table-io"); + if (iosec != null) { + IOSelector tableIoSelector = IOSelector.fromConfigSection(iosec); + fac.setTableIOSelector(tableIoSelector); + } else { + // Default table-side IO moved to FCCF.getTableIoSelector() lazy init + } + } + String menuModeRaw = current.getString("ui-menu-mode"); + FurnCraftChestFactory.UiMenuMode menuMode; + if (menuModeRaw == null) { + menuMode = FurnCraftChestFactory.UiMenuMode.SIMPLE; + } else { + try { + menuMode = FurnCraftChestFactory.UiMenuMode.valueOf(menuModeRaw); + } catch (IllegalArgumentException iae) { + menuMode = FurnCraftChestFactory.UiMenuMode.SIMPLE; + } + } + fac.setUiMenuMode(menuMode); manager.addFactory(fac); counter++; break; diff --git a/src/main/java/com/github/igotyou/FactoryMod/utility/IIOFInventoryProvider.java b/src/main/java/com/github/igotyou/FactoryMod/utility/IIOFInventoryProvider.java new file mode 100644 index 00000000..362b7609 --- /dev/null +++ b/src/main/java/com/github/igotyou/FactoryMod/utility/IIOFInventoryProvider.java @@ -0,0 +1,22 @@ +package com.github.igotyou.FactoryMod.utility; + +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.Nullable; + +/** + * Utility interface for classes that provide separate inventories for inputs, outputs, and fuel. + */ +public interface IIOFInventoryProvider { + + Inventory getInputInventory(); + Inventory getOutputInventory(); + @Nullable Inventory getFuelInventory(); + + int getInputCount(); + int getOutputCount(); + int getFuelCount(); + default int getTotalIOFCount() { + return getInputCount() + getOutputCount() + getFuelCount(); + } + +} diff --git a/src/main/java/com/github/igotyou/FactoryMod/utility/IOConfigSection.java b/src/main/java/com/github/igotyou/FactoryMod/utility/IOConfigSection.java new file mode 100644 index 00000000..7c41c447 --- /dev/null +++ b/src/main/java/com/github/igotyou/FactoryMod/utility/IOConfigSection.java @@ -0,0 +1,209 @@ +package com.github.igotyou.FactoryMod.utility; + +import com.github.igotyou.FactoryMod.FactoryMod; +import com.github.igotyou.FactoryMod.FactoryModManager; +import com.github.igotyou.FactoryMod.FactoryModPlayerSettings; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitTask; +import vg.civcraft.mc.civmodcore.inventory.items.ItemUtils; +import vg.civcraft.mc.civmodcore.inventorygui.Clickable; +import vg.civcraft.mc.civmodcore.inventorygui.ClickableInventory; +import vg.civcraft.mc.civmodcore.inventorygui.LClickable; +import vg.civcraft.mc.civmodcore.inventorygui.components.StaticDisplaySection; + +import java.util.UUID; + +/** + * @author caucow + */ +public class IOConfigSection extends StaticDisplaySection { + + private final UUID viewerId; + private final IOSelector ioSelector; + private final Material centerDisplay; + private final BlockFace front; + private final Block centerBlock; + private final IIOFInventoryProvider iofProvider; + private FactoryModPlayerSettings.IoConfigDirectionMode ioDirectionMode; + + public IOConfigSection(Player viewer, IOSelector ioSelector, Material centerDisplay, Block centerBlock, + BlockFace front, IIOFInventoryProvider iofProvider) { + super(9); + this.viewerId = viewer.getUniqueId(); + this.ioSelector = ioSelector; + this.centerDisplay = centerDisplay; + this.centerBlock = centerBlock; + this.front = front; + this.iofProvider = iofProvider; + rebuild(); + } + + private Clickable getIoButton(BlockFace dir) { + Block relativeBlock = centerBlock.getRelative(dir); + Material type = relativeBlock.getType(); + Direction relativeDir = Direction.getDirection(front, dir); + return getIoClickable(type, relativeDir, dir.name()); + } + + private Clickable getIoButton(Direction dir) { + BlockFace relativeDir = dir.getBlockFacing(front); + Block relativeBlock = centerBlock.getRelative(relativeDir); + Material type = relativeBlock.getType(); + return getIoClickable(type, dir, dir.name()); + } + + private Clickable getIoClickable(Material adjacentType, Direction dir, String dirLabel) { + IOSelector.IOState dirState = ioSelector.getState(dir); + boolean chestMissing = adjacentType != Material.CHEST && adjacentType != Material.TRAPPED_CHEST; + ItemStack display; + if (chestMissing) { + display = new ItemStack(Material.BARRIER); + ItemUtils.addComponentLore(display, Component + .text("") + .style(Style.style(TextDecoration.BOLD)) + .color(TextColor.color(255, 0, 0))); + } else { + display = dirState.getUIVisual(); + } + if (ioDirectionMode != null) { + for (String descLine : ioDirectionMode.fullDescription) { + ItemUtils.addComponentLore(display, + Component.text(descLine).color(TextColor.color(255, 255, 192))); + } + } + ItemUtils.setComponentDisplayName(display, + Component.text("\u00a7r") + .append(Component.text(dirLabel).color(TextColor.color(192, 192, 192))) + .append(Component.text(": ")) + .append(Component.text(dirState.displayName).color(TextColor.color(dirState.color))) + .asComponent()); + ItemUtils.addComponentLore(display, + Component.text("L/M/R click to toggle I/F/O") + .style(Style.style(TextDecoration.BOLD)) + .color(TextColor.color(255, 255, 255))); + FactoryModManager fmMgr = FactoryMod.getInstance().getManager(); + return new Clickable(display) { + private ClickableInventory inventory; + private int slot; + private BukkitTask reBarrierTask; + + @Override + protected void clicked(Player player) { + if (!ioSelector.isInput(dir)) { + if (iofProvider.getInputCount() >= fmMgr.getMaxInputChests()) { + player.sendMessage(ChatColor.RED + "This factory is at the maximum number of inputs."); + return; + } + if (iofProvider.getTotalIOFCount() >= fmMgr.getMaxTotalIOFChests()) { + player.sendMessage(ChatColor.RED + "This factory is at the maximum number of total I/O/Fs."); + return; + } + } + ioSelector.toggleInput(dir); + updateItem(); + } + + @Override + protected void onRightClick(Player player) { + if (!ioSelector.isOutput(dir)) { + if (iofProvider.getOutputCount() >= fmMgr.getMaxOutputChests()) { + player.sendMessage(ChatColor.RED + "This factory is at the maximum number of outputs."); + return; + } + if (iofProvider.getTotalIOFCount() >= fmMgr.getMaxTotalIOFChests()) { + player.sendMessage(ChatColor.RED + "This factory is at the maximum number of total I/O/Fs."); + return; + } + } + ioSelector.toggleOutput(dir); + updateItem(); + } + + @Override + protected void onMiddleClick(Player player) { + if (!ioSelector.isFuel(dir)) { + if (iofProvider.getFuelCount() >= fmMgr.getMaxFuelChests()) { + player.sendMessage(ChatColor.RED + "This factory is at the maximum number of fuel inputs."); + return; + } + if (iofProvider.getTotalIOFCount() >= fmMgr.getMaxTotalIOFChests()) { + player.sendMessage(ChatColor.RED + "This factory is at the maximum number of total I/O/Fs."); + return; + } + } + ioSelector.toggleFuel(dir); + updateItem(); + } + + @Override + protected void onDoubleClick(Player p) { } // nop + + @Override + public void addedToInventory(ClickableInventory inv, int slot) { + this.inventory = inv; + this.slot = slot; + } + + private void updateItem() { + IOSelector.IOState newState = ioSelector.getState(dir); + ItemStack curStack = getItemStack(); + curStack.setType(newState.getUIVisual().getType()); + ItemUtils.setComponentDisplayName(curStack, + Component.text("\u00a7r") + .append(Component.text(dirLabel).color(TextColor.color(192, 192, 192))) + .append(Component.text(": ")) + .append(Component.text(newState.displayName).color(TextColor.color(newState.color))) + .asComponent()); + if (inventory != null && inventory.getSlot(slot) == this) { + inventory.setSlot(this, slot); + } + if (chestMissing) { + if (reBarrierTask != null) { + reBarrierTask.cancel(); + } + reBarrierTask = Bukkit.getScheduler().runTaskLater(FactoryMod.getInstance(), () -> { + getItemStack().setType(Material.BARRIER); + inventory.setSlot(this, slot); + reBarrierTask = null; + }, 20); + } + } + }; + } + + @Override + protected void rebuild() { + ioDirectionMode = FactoryMod.getInstance().getManager().getPlayerSettings().getIoDirectionMode(viewerId); + switch (ioDirectionMode) { + case VISUAL_RELATIVE: { + set(getIoButton(Direction.TOP), 1); + set(getIoButton(Direction.FRONT), 2); + set(getIoButton(Direction.LEFT), 3); + set(getIoButton(Direction.RIGHT), 5); + set(getIoButton(Direction.BOTTOM), 7); + set(getIoButton(Direction.BACK), 8); + break; + } + case CARDINAL: { + set(getIoButton(BlockFace.NORTH), 1); + set(getIoButton(BlockFace.UP), 2); + set(getIoButton(BlockFace.WEST), 3); + set(getIoButton(BlockFace.EAST), 5); + set(getIoButton(BlockFace.SOUTH), 7); + set(getIoButton(BlockFace.DOWN), 8); + break; + } + } + set(new LClickable(centerDisplay, p -> {}), 4); + } +} diff --git a/src/main/java/com/github/igotyou/FactoryMod/utility/IOSelector.java b/src/main/java/com/github/igotyou/FactoryMod/utility/IOSelector.java new file mode 100644 index 00000000..c8148b24 --- /dev/null +++ b/src/main/java/com/github/igotyou/FactoryMod/utility/IOSelector.java @@ -0,0 +1,233 @@ +package com.github.igotyou.FactoryMod.utility; + +import org.bukkit.Material; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author caucow + */ +public class IOSelector { + + private final EnumSet inputs; + private final EnumSet outputs; + private final EnumSet fuel; + + public IOSelector(Collection inMask, Collection outMask, Collection fuel) { + this(); + this.inputs.addAll(inMask); + this.outputs.addAll(outMask); + this.fuel.addAll(fuel); + } + + public IOSelector() { + this.inputs = EnumSet.noneOf(Direction.class); + this.outputs = EnumSet.noneOf(Direction.class); + this.fuel = EnumSet.noneOf(Direction.class); + } + + public IOState getState(Direction direction) { + return IOState.fromIO(inputs.contains(direction), outputs.contains(direction), fuel.contains(direction)); + } + + public void setState(Direction direction, IOState state) { + if (state.isIn()) { + inputs.add(direction); + } else { + inputs.remove(direction); + } + if (state.isOut()) { + outputs.add(direction); + } else { + outputs.remove(direction); + } + if (state.isFuel()) { + fuel.add(direction); + } else { + fuel.remove(direction); + } + } + + public int getInputCount() { + return inputs.size(); + } + + public int getOutputCount() { + return outputs.size(); + } + + public int getFuelCount() { + return fuel.size(); + } + + public int getTotalIOFCount() { + return getInputCount() + getOutputCount() + getFuelCount(); + } + + public boolean toggleInput(Direction direction) { + boolean added = inputs.add(direction); + if (!added) { + inputs.remove(direction); + } + return added; + } + + public boolean isInput(Direction direction) { + return inputs.contains(direction); + } + + public boolean toggleOutput(Direction direction) { + boolean added = outputs.add(direction); + if (!added) { + outputs.remove(direction); + } + return added; + } + + public boolean isOutput(Direction direction) { + return outputs.contains(direction); + } + + public boolean toggleFuel(Direction direction) { + boolean added = fuel.add(direction); + if (!added) { + fuel.remove(direction); + } + return added; + } + + public boolean isFuel(Direction direction) { + return fuel.contains(direction); + } + + public boolean hasInputs() { + return !inputs.isEmpty(); + } + + public List getInputs(BlockFace front) { + Direction[] values = Direction.values(); + List bfList = new ArrayList<>(values.length); + for (Direction dir : values) { + if (inputs.contains(dir)) { + bfList.add(dir.getBlockFacing(front)); + } + } + return bfList; + } + + public boolean hasOutputs() { + return !outputs.isEmpty(); + } + + public List getOutputs(BlockFace front) { + Direction[] values = Direction.values(); + List bfList = new ArrayList<>(values.length); + for (Direction dir : values) { + if (outputs.contains(dir)) { + bfList.add(dir.getBlockFacing(front)); + } + } + return bfList; + } + + public boolean hasFuel() { + return !fuel.isEmpty(); + } + + public List getFuel(BlockFace front) { + Direction[] values = Direction.values(); + List bfList = new ArrayList<>(values.length); + for (Direction dir : values) { + if (fuel.contains(dir)) { + bfList.add(dir.getBlockFacing(front)); + } + } + return bfList; + } + + public IOState cycleDirection(Direction direction, boolean backwards) { + IOState cur = getState(direction); + if (backwards) { + cur = cur.last(); + } else { + cur = cur.next(); + } + setState(direction, cur); + return cur; + } + + public ConfigurationSection toConfigSection() { + ConfigurationSection sec = new YamlConfiguration(); + sec.set("in", inputs.stream().map(Enum::name).collect(Collectors.toList())); + sec.set("out", outputs.stream().map(Enum::name).collect(Collectors.toList())); + sec.set("fuel", fuel.stream().map(Enum::name).collect(Collectors.toList())); + return sec; + } + + public static IOSelector fromConfigSection(ConfigurationSection conf) { + List inList = conf.getStringList("in").stream().map(Direction::valueOf).collect(Collectors.toList()); + List outList = conf.getStringList("out").stream().map(Direction::valueOf).collect(Collectors.toList()); + List fuelList = conf.getStringList("fuel").stream().map(Direction::valueOf).collect(Collectors.toList()); + return new IOSelector(inList, outList, fuelList); + } + + public enum IOState { + IGNORED("Ignored", new ItemStack(Material.GRAY_WOOL), 0x808080), + INPUT("Input", new ItemStack(Material.BLUE_WOOL), 0x4040FF), + OUTPUT("Output", new ItemStack(Material.RED_WOOL), 0xFF4040), + BOTH("Input+Output", new ItemStack(Material.PURPLE_WOOL), 0xFF40FF), + FUEL("Fuel", new ItemStack(Material.LIGHT_GRAY_WOOL), 0xA0A0A0), + INPUT_FUEL("Input+Fuel", new ItemStack(Material.CYAN_WOOL), 0x8060FF), + OUTPUT_FUEL("Output+Fuel", new ItemStack(Material.PINK_WOOL), 0xFF6080), + BOTH_FUEL("Input+Output+Fuel", new ItemStack(Material.MAGENTA_WOOL), 0xFF60FF); + + public final String displayName; + private final ItemStack uiVisual; + public final int color; + + IOState(String displayName, ItemStack uiVisual, int color) { + this.displayName = displayName; + this.uiVisual = uiVisual; + this.color = color; + } + + public ItemStack getUIVisual() { + return uiVisual.clone(); + } + + public boolean isIn() { + return (ordinal() & 1) != 0; + } + + public boolean isOut() { + return (ordinal() & 2) != 0; + } + + public boolean isFuel() { + return (ordinal() & 4) != 0; + } + + public IOState next() { + IOState[] values = values(); + return values[(ordinal() + values.length + 1) % values.length]; + } + + public IOState last() { + IOState[] values = values(); + return values[(ordinal() + values.length + values.length - 1) % values.length]; + } + + public static IOState fromIO(boolean in, boolean out, boolean fuel) { + return IOState.values()[(in ? 1 : 0) | (out ? 2 : 0) | (fuel ? 4 : 0)]; + } + } + +} diff --git a/src/main/java/com/github/igotyou/FactoryMod/utility/MultiInventoryWrapper.java b/src/main/java/com/github/igotyou/FactoryMod/utility/MultiInventoryWrapper.java new file mode 100644 index 00000000..3c6262bf --- /dev/null +++ b/src/main/java/com/github/igotyou/FactoryMod/utility/MultiInventoryWrapper.java @@ -0,0 +1,387 @@ +package com.github.igotyou.FactoryMod.utility; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.DoubleChest; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +/** + * @author caucow + */ +public class MultiInventoryWrapper implements Inventory { + + private final Inventory[] wrapped; + private final int size; + private final int[] slotOffsets; + + public MultiInventoryWrapper(Inventory... wrapped) { + this(new ArrayList<>(Arrays.asList(wrapped))); + } + + public MultiInventoryWrapper(List wrapped) { + Inventory[] wrappedArr = uniquify(wrapped); + this.wrapped = wrappedArr; + int lsize = 0; + int[] lslotOffsets = new int[wrappedArr.length]; + for (int i = 0; i < wrappedArr.length; i++) { + Inventory inv = wrappedArr[i]; + lslotOffsets[i] = lsize; + lsize += inv.getSize(); + if (inv.getMaxStackSize() != 64) { + throw new IllegalArgumentException("Inventory max stack size must be 64"); + } + } + this.size = lsize; + this.slotOffsets = lslotOffsets; + } + + private int getInventoryIndex(int combinedSlot) { + for (int i = 0; i < wrapped.length - 1; i++) { + if (combinedSlot < slotOffsets[i + 1]) { + return i; + } + } + if (combinedSlot < size) { + return wrapped.length - 1; + } + throw new IndexOutOfBoundsException("Slot index " + combinedSlot + + " is outside the bounds of the multi-inventory"); + } + + @Override + public int close() { + List viewers = getViewers(); + int num = viewers.size(); + viewers.forEach(HumanEntity::closeInventory); + return num; + } + + @Override + public int getSize() { + return size; + } + + @Override + public int getMaxStackSize() { + return 64; + } + + @Override + public void setMaxStackSize(int i) { + throw new UnsupportedOperationException(); + } + + @Override + public @Nullable ItemStack getItem(int i) { + int invi = getInventoryIndex(i); + return wrapped[invi].getItem(i - slotOffsets[invi]); + } + + @Override + public void setItem(int i, @Nullable ItemStack itemStack) { + int invi = getInventoryIndex(i); + wrapped[invi].setItem(i - slotOffsets[invi], itemStack); + } + + @Override + public @NotNull HashMap addItem(@NotNull ItemStack... itemStacks) throws IllegalArgumentException { + HashMap result = null; + for (int invi = 0; invi < wrapped.length; invi++) { + result = wrapped[invi].addItem(itemStacks); + itemStacks = new ItemStack[result.size()]; + int itemi = 0; + Iterator> eit = result.entrySet().iterator(); + for (; eit.hasNext() && itemi < itemStacks.length; itemi++) { + Map.Entry entry = eit.next(); + itemStacks[itemi] = entry.getValue(); + } + } + return result == null ? new HashMap<>() : result; + } + + @Override + public @NotNull HashMap removeItem(@NotNull ItemStack... itemStacks) throws IllegalArgumentException { + HashMap result = null; + for (int invi = 0; invi < wrapped.length; invi++) { + result = wrapped[invi].removeItem(itemStacks); + if (result.isEmpty()) { + break; + } + itemStacks = new ItemStack[result.size()]; + int itemi = 0; + Iterator> eit = result.entrySet().iterator(); + for (; eit.hasNext() && itemi < itemStacks.length; itemi++) { + Map.Entry entry = eit.next(); + itemStacks[itemi] = entry.getValue(); + } + } + return result == null ? new HashMap<>() : result; + } + + @Override + public @NotNull HashMap removeItemAnySlot(@NotNull ItemStack... itemStacks) throws IllegalArgumentException { + HashMap result = null; + for (int i = 0; i < wrapped.length; i++) { + result = wrapped[i].removeItemAnySlot(itemStacks); + itemStacks = new ItemStack[result.size()]; + int index = 0; + Iterator> eit = result.entrySet().iterator(); + for (; eit.hasNext() && index < itemStacks.length; index++) { + Map.Entry entry = eit.next(); + itemStacks[i] = entry.getValue(); + } + } + return result == null ? new HashMap<>() : result; + } + + @Override + public @org.checkerframework.checker.nullness.qual.Nullable ItemStack @NonNull [] getContents() { + ItemStack[] combinedContents = new ItemStack[size]; + for (int inv = 0, slot = 0; inv < wrapped.length; inv++) { + ItemStack[] sub = wrapped[inv].getContents(); + System.arraycopy(sub, 0, combinedContents, slot, sub.length); + slot += sub.length; + } + return combinedContents; + } + + @Override + public void setContents(@NotNull ItemStack[] combinedContents) throws IllegalArgumentException { + for (int inv = 0, slot = 0; inv < wrapped.length && slotOffsets[inv] < combinedContents.length; inv++) { + ItemStack[] sub = new ItemStack[wrapped[inv].getSize()]; + System.arraycopy(combinedContents, slotOffsets[inv], sub, 0, Math.min(sub.length, slot - slotOffsets[inv])); + wrapped[inv].setContents(sub); + slot += sub.length; + } + } + + @Override + public @NotNull ItemStack[] getStorageContents() { + return getContents(); + } + + @Override + public void setStorageContents(@NotNull ItemStack[] combinedContents) throws IllegalArgumentException { + setContents(combinedContents); + } + + @Override + public boolean contains(@NotNull Material material) throws IllegalArgumentException { + for (Inventory inv : wrapped) { + if (inv.contains(material)) { + return true; + } + } + return false; + } + + @Override + public boolean contains(@Nullable ItemStack itemStack) { + for (Inventory inv : wrapped) { + if (inv.contains(itemStack)) { + return true; + } + } + return false; + } + + @Override + public boolean contains(@NotNull Material material, int i) throws IllegalArgumentException { + int invi = getInventoryIndex(i); + return wrapped[invi].contains(material, i - slotOffsets[invi]); + } + + @Override + public boolean contains(@Nullable ItemStack itemStack, int i) { + int invi = getInventoryIndex(i); + return wrapped[invi].contains(itemStack, i - slotOffsets[invi]); + } + + @Override + public boolean containsAtLeast(@Nullable ItemStack itemStack, int i) { + int invi = getInventoryIndex(i); + return wrapped[invi].containsAtLeast(itemStack, i - slotOffsets[invi]); + } + + @Override + public @NotNull HashMap all(@NotNull Material material) throws IllegalArgumentException { + HashMap result = new HashMap<>(); + for (int i = 0; i < wrapped.length; i++) { + HashMap partial = wrapped[i].all(material); + for (Map.Entry entry : partial.entrySet()) { + result.put(entry.getKey() + slotOffsets[i], entry.getValue()); + } + } + return result; + } + + @Override + public @NotNull HashMap all(@Nullable ItemStack itemStack) { + HashMap result = new HashMap<>(); + for (int i = 0; i < wrapped.length; i++) { + HashMap partial = wrapped[i].all(itemStack); + for (Map.Entry entry : partial.entrySet()) { + result.put(entry.getKey() + slotOffsets[i], entry.getValue()); + } + } + return result; + } + + @Override + public int first(@NotNull Material material) throws IllegalArgumentException { + for (int i = 0; i < wrapped.length; i++) { + int result = wrapped[i].first(material); + if (result != -1) { + return result + slotOffsets[i]; + } + } + return -1; + } + + @Override + public int first(@NotNull ItemStack itemStack) { + for (int i = 0; i < wrapped.length; i++) { + int result = wrapped[i].first(itemStack); + if (result != -1) { + return result + slotOffsets[i]; + } + } + return -1; + } + + @Override + public int firstEmpty() { + for (int i = 0; i < wrapped.length; i++) { + int result = wrapped[i].firstEmpty(); + if (result != -1) { + return result + slotOffsets[i]; + } + } + return -1; + } + + @Override + public boolean isEmpty() { + for (Inventory inv : wrapped) { + if (!inv.isEmpty()) { + return false; + } + } + return true; + } + + @Override + public void remove(@NotNull Material material) throws IllegalArgumentException { + for (Inventory inv : wrapped) { + inv.remove(material); + } + } + + @Override + public void remove(@NotNull ItemStack itemStack) { + for (Inventory inv : wrapped) { + inv.remove(itemStack); + } + } + + @Override + public void clear(int i) { + int invi = getInventoryIndex(i); + wrapped[invi].clear(i - slotOffsets[invi]); + } + + @Override + public void clear() { + for (Inventory inv : wrapped) { + inv.clear(); + } + } + + @Override + public @NotNull List getViewers() { + ArrayList list = new ArrayList<>(); + for (Inventory inv : wrapped) { + list.addAll(inv.getViewers()); + } + return list; + } + + @Override + public @NotNull InventoryType getType() { + return InventoryType.CHEST; + } + + @Override + public @Nullable InventoryHolder getHolder() { + return null; + } + + @Override + public @Nullable InventoryHolder getHolder(boolean b) { + return null; + } + + @Override + public @NotNull ListIterator iterator() { + throw new UnsupportedOperationException("More effort to implement than can be bothered atm. Feel free to CIY"); + } + + @Override + public @NotNull ListIterator iterator(int i) { + throw new UnsupportedOperationException("More effort to implement than can be bothered atm. Feel free to CIY"); + } + + @Override + public @Nullable Location getLocation() { + return null; + } + + private static Inventory[] uniquify(List wrapped) { + ListIterator inverator = wrapped.listIterator(); + while (inverator.hasNext()) { + Inventory next = inverator.next(); + if (next instanceof MultiInventoryWrapper) { + inverator.remove(); + for (Inventory inv : ((MultiInventoryWrapper) next).wrapped) { + inverator.add(inv); + inverator.previous(); + } + } + } + List invHolders = new ArrayList<>(wrapped.size()); + List uniqueInvs = new ArrayList<>(wrapped.size()); + for (Inventory inv : wrapped) { + + InventoryHolder holder = inv.getHolder(); + if (holder instanceof DoubleChest) { + DoubleChest dch = (DoubleChest) holder; + InventoryHolder hleft = dch.getLeftSide(); + InventoryHolder hright = dch.getRightSide(); + if (invHolders.contains(dch) || invHolders.contains(hleft) || invHolders.contains(hright)) { + continue; + } + invHolders.add(hleft); + invHolders.add(hright); + } + invHolders.add(holder); + uniqueInvs.add(inv); + } + Inventory[] wrappedArr = uniqueInvs.toArray(new Inventory[uniqueInvs.size()]); + return wrappedArr; + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index ee39aa00..829d2334 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -194,6 +194,13 @@ use_recipe_yamlidentifiers: false #How often factory data is saved automatically. Recommended value and default is 15 minutes. Set to -1 to disable saving_intervall: 15m +# Maximum number of input, output, fuel, and total IOF chests. If a chest is used for multiple settings, it is counted +# multiple times. +max_input_chests: 10 +max_output_chests: 10 +max_fuel_chests: 10 +max_iof_chests: 15 + #---------------------------------------------------------------------------------------------------------------------- #Factories