From c6454cc4762ee02a6377df2b6a775e84adb24eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Mon, 15 Mar 2021 13:18:58 -0300 Subject: [PATCH 01/26] Reworked trySearchNewRecipe and findRecipe takes in consideration the result of the last iteration when: 1. no recipe found for current items in inputInventory. 2. if the recipe found cant push its result due to lack of space in the outputinventory. --- .../capability/impl/AbstractRecipeLogic.java | 102 +++++++++++++++--- .../electric/MetaTileEntityMultiFurnace.java | 27 +++-- 2 files changed, 105 insertions(+), 24 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 6b92342620..d20fcb44c2 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -38,6 +38,8 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable protected boolean forceRecipeRecheck; protected ItemStack[] lastItemInputs; protected FluidStack[] lastFluidInputs; + protected ItemStack[] lastItemOutputs; + protected FluidStack[] lastFluidOutputs; protected Recipe previousRecipe; protected boolean allowOverclocking = true; private long overclockVoltage = 0; @@ -54,6 +56,8 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable protected boolean workingEnabled = true; protected boolean hasNotEnoughEnergy; protected boolean wasActiveAndNeedsUpdate; + protected boolean isOutputsFull = false; + protected boolean invalidInputsForRecipes = false; public AbstractRecipeLogic(MetaTileEntity tileEntity, RecipeMap recipeMap) { super(tileEntity); @@ -149,22 +153,37 @@ protected void trySearchNewRecipe() { Recipe currentRecipe = null; IItemHandlerModifiable importInventory = getInputInventory(); IMultipleTankHandler importFluids = getInputTank(); - if (previousRecipe != null && previousRecipe.matches(false, importInventory, importFluids)) { - //if previous recipe still matches inputs, try to use it - currentRecipe = previousRecipe; - } else { - boolean dirty = checkRecipeInputsDirty(importInventory, importFluids); - if (dirty || forceRecipeRecheck) { + + boolean inputsChanged = checkRecipeInputsDirty(importInventory, importFluids); + // if the output is full check if the output changed so we can process recipes results again. + if (this.isOutputsFull) { + IItemHandlerModifiable exportInventory = getOutputInventory(); + IMultipleTankHandler exportFluids = getOutputTank(); + if (hasMachineOutputChanged(exportInventory, exportFluids)) { + this.isOutputsFull = false; + } + } + + if (inputsChanged || (!invalidInputsForRecipes && !this.isOutputsFull) || this.forceRecipeRecheck) { + if (this.previousRecipe != null && this.previousRecipe.matches(false, importInventory, importFluids)) { + //if previous recipe still matches inputs, try to use it + currentRecipe = this.previousRecipe; + } else { this.forceRecipeRecheck = false; //else, try searching new recipe for given inputs currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); if (currentRecipe != null) { this.previousRecipe = currentRecipe; + this.invalidInputsForRecipes = false; + } else { + //no recipe found for the current inputs. + //search again when inputs change + this.invalidInputsForRecipes = true; } } - } - if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { - setupRecipe(currentRecipe); + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { + setupRecipe(currentRecipe); + } } } @@ -206,6 +225,8 @@ protected boolean checkRecipeInputsDirty(IItemHandler inputs, IMultipleTankHandl lastStack.setCount(currentStack.getCount()); shouldRecheckRecipe = true; } + if (shouldRecheckRecipe) + return true; } for (int i = 0; i < lastFluidInputs.length; i++) { FluidStack currentStack = fluidInputs.getTankAt(i).getFluid(); @@ -219,8 +240,51 @@ protected boolean checkRecipeInputsDirty(IItemHandler inputs, IMultipleTankHandl lastStack.amount = currentStack.amount; shouldRecheckRecipe = true; } + if (shouldRecheckRecipe) + return true; } - return shouldRecheckRecipe; + return false; + } + + protected boolean hasMachineOutputChanged(IItemHandler outputs, IMultipleTankHandler fluidOutputs) { + boolean outputChanged = false; + if (lastItemOutputs == null || lastItemOutputs.length != outputs.getSlots()) { + this.lastItemOutputs = new ItemStack[outputs.getSlots()]; + Arrays.fill(lastItemOutputs, ItemStack.EMPTY); + } + if (lastFluidOutputs == null || lastFluidOutputs.length != fluidOutputs.getTanks()) { + this.lastFluidOutputs = new FluidStack[fluidOutputs.getTanks()]; + } + for (int i = 0; i < lastItemOutputs.length; i++) { + ItemStack currentStack = outputs.getStackInSlot(i); + ItemStack lastStack = lastItemOutputs[i]; + if (!areItemStacksEqual(currentStack, lastStack)) { + this.lastItemOutputs[i] = currentStack.isEmpty() ? ItemStack.EMPTY : currentStack.copy(); + outputChanged = true; + } else if (currentStack.getCount() != lastStack.getCount()) { + lastStack.setCount(currentStack.getCount()); + outputChanged = true; + } + if (outputChanged) + return true; + } + + for (int i = 0; i < lastFluidOutputs.length; i++) { + FluidStack currentStack = fluidOutputs.getTankAt(i).getFluid(); + FluidStack lastStack = lastFluidOutputs[i]; + if ((currentStack == null && lastStack != null) || + (currentStack != null && !currentStack.isFluidEqual(lastStack))) { + this.lastFluidOutputs[i] = currentStack == null ? null : currentStack.copy(); + outputChanged = true; + } else if (currentStack != null && lastStack != null && + currentStack.amount != lastStack.amount) { + lastStack.amount = currentStack.amount; + outputChanged = true; + } + if (outputChanged) + return true; + } + return false; } protected static boolean areItemStacksEqual(ItemStack stackA, ItemStack stackB) { @@ -236,11 +300,19 @@ protected boolean setupAndConsumeRecipeInputs(Recipe recipe) { IItemHandlerModifiable exportInventory = getOutputInventory(); IMultipleTankHandler importFluids = getInputTank(); IMultipleTankHandler exportFluids = getOutputTank(); - return (totalEUt >= 0 ? getEnergyStored() >= (totalEUt > getEnergyCapacity() / 2 ? resultOverclock[0] : totalEUt) : - (getEnergyStored() - resultOverclock[0] <= getEnergyCapacity())) && - MetaTileEntity.addItemsToItemHandler(exportInventory, true, recipe.getAllItemOutputs(exportInventory.getSlots())) && - MetaTileEntity.addFluidsToFluidHandler(exportFluids, true, recipe.getFluidOutputs()) && - recipe.matches(true, importInventory, importFluids); + if (!(totalEUt >= 0 ? getEnergyStored() >= (totalEUt > getEnergyCapacity() / 2 ? resultOverclock[0] : totalEUt) : + (getEnergyStored() - resultOverclock[0] <= getEnergyCapacity()))) { + return false; + } + if (!MetaTileEntity.addItemsToItemHandler(exportInventory, true, recipe.getAllItemOutputs(exportInventory.getSlots()))) { + this.isOutputsFull = true; + return false; + } + if (!MetaTileEntity.addFluidsToFluidHandler(exportFluids, true, recipe.getFluidOutputs())) { + this.isOutputsFull = true; + return false; + } + return recipe.matches(true, importInventory, importFluids); } protected int[] calculateOverclock(int EUt, int duration) { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index 10878bcb90..6754d69a1c 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -105,24 +105,30 @@ protected void trySearchNewRecipe() { Recipe currentRecipe = null; IItemHandlerModifiable importInventory = getInputInventory(); IMultipleTankHandler importFluids = getInputTank(); - boolean dirty = checkRecipeInputsDirty(importInventory, importFluids); + + boolean inputsChanged = checkRecipeInputsDirty(importInventory, importFluids); + if (this.isOutputsFull) { + IItemHandlerModifiable exportInventory = getOutputInventory(); + IMultipleTankHandler exportFluids = getOutputTank(); + if (hasMachineOutputChanged(exportInventory, exportFluids)) { + this.isOutputsFull = false; + } + } + //inverse of logic in normal AbstractRecipeLogic //for MultiSmelter, we can reuse previous recipe if inputs didn't change //otherwise, we need to recompute it for new ingredients //but technically, it means we can cache multi smelter recipe, but changing inputs have more priority - if(dirty || forceRecipeRecheck) { + if (inputsChanged || (!invalidInputsForRecipes && !this.isOutputsFull) || this.forceRecipeRecheck) { this.forceRecipeRecheck = false; //else, try searching new recipe for given inputs currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); if (currentRecipe != null) { this.previousRecipe = currentRecipe; } - } else if (previousRecipe != null && previousRecipe.matches(false, importInventory, importFluids)) { - //if previous recipe still matches inputs, try to use it - currentRecipe = previousRecipe; - } - if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { - setupRecipe(currentRecipe); + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { + setupRecipe(currentRecipe); + } } } @@ -139,6 +145,7 @@ protected Recipe findRecipe(long maxVoltage, /* Iterate over the input items looking for more things to add until we run either out of input items * or we have exceeded the number of items permissible from the smelting bonus */ + this.invalidInputsForRecipes = true; for(int index = 0; index < inputs.getSlots() && currentItemsEngaged < maxItemsLimit; index++) { // Skip this slot if it is empty. @@ -151,8 +158,10 @@ protected Recipe findRecipe(long maxVoltage, Collections.singletonList(currentInputItem), Collections.emptyList(), 0); CountableIngredient inputIngredient; - if(matchingRecipe != null) + if(matchingRecipe != null) { inputIngredient = matchingRecipe.getInputs().get(0); + this.invalidInputsForRecipes = false; + } else continue; From 9c622beb21fd173d932893ad5b6a386574206e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Mon, 15 Mar 2021 20:31:42 -0300 Subject: [PATCH 02/26] rework logic --- .../api/capability/impl/AbstractRecipeLogic.java | 15 +++++++++------ .../electric/MetaTileEntityMultiFurnace.java | 13 +++++++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index d20fcb44c2..6bea2dabc8 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -154,7 +154,6 @@ protected void trySearchNewRecipe() { IItemHandlerModifiable importInventory = getInputInventory(); IMultipleTankHandler importFluids = getInputTank(); - boolean inputsChanged = checkRecipeInputsDirty(importInventory, importFluids); // if the output is full check if the output changed so we can process recipes results again. if (this.isOutputsFull) { IItemHandlerModifiable exportInventory = getOutputInventory(); @@ -164,11 +163,14 @@ protected void trySearchNewRecipe() { } } - if (inputsChanged || (!invalidInputsForRecipes && !this.isOutputsFull) || this.forceRecipeRecheck) { + if (!invalidInputsForRecipes && !this.isOutputsFull) { if (this.previousRecipe != null && this.previousRecipe.matches(false, importInventory, importFluids)) { //if previous recipe still matches inputs, try to use it currentRecipe = this.previousRecipe; - } else { + } + } + if (currentRecipe == null) { + if (checkRecipeInputsDirty(importInventory, importFluids) || this.forceRecipeRecheck) { this.forceRecipeRecheck = false; //else, try searching new recipe for given inputs currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); @@ -181,9 +183,9 @@ protected void trySearchNewRecipe() { this.invalidInputsForRecipes = true; } } - if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { - setupRecipe(currentRecipe); - } + } + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { + setupRecipe(currentRecipe); } } @@ -312,6 +314,7 @@ protected boolean setupAndConsumeRecipeInputs(Recipe recipe) { this.isOutputsFull = true; return false; } + this.isOutputsFull = false; return recipe.matches(true, importInventory, importFluids); } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index 6754d69a1c..e27473fdf8 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -106,7 +106,6 @@ protected void trySearchNewRecipe() { IItemHandlerModifiable importInventory = getInputInventory(); IMultipleTankHandler importFluids = getInputTank(); - boolean inputsChanged = checkRecipeInputsDirty(importInventory, importFluids); if (this.isOutputsFull) { IItemHandlerModifiable exportInventory = getOutputInventory(); IMultipleTankHandler exportFluids = getOutputTank(); @@ -119,19 +118,25 @@ protected void trySearchNewRecipe() { //for MultiSmelter, we can reuse previous recipe if inputs didn't change //otherwise, we need to recompute it for new ingredients //but technically, it means we can cache multi smelter recipe, but changing inputs have more priority - if (inputsChanged || (!invalidInputsForRecipes && !this.isOutputsFull) || this.forceRecipeRecheck) { + if (checkRecipeInputsDirty(importInventory, importFluids) || this.forceRecipeRecheck) { this.forceRecipeRecheck = false; //else, try searching new recipe for given inputs currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); if (currentRecipe != null) { this.previousRecipe = currentRecipe; } - if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { - setupRecipe(currentRecipe); + } else if (!invalidInputsForRecipes && !this.isOutputsFull) { + if (previousRecipe != null && previousRecipe.matches(false, importInventory, importFluids)) { + //if previous recipe still matches inputs, try to use it + currentRecipe = previousRecipe; } } + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { + setupRecipe(currentRecipe); + } } + @Override protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, From 3c0e6f1e5d93aaa6b3dd72501b52f5a3252011c7 Mon Sep 17 00:00:00 2001 From: Exa <11907282+Exaxxion@users.noreply.github.com> Date: Tue, 16 Mar 2021 16:39:25 -0700 Subject: [PATCH 03/26] Refactor trySearchNewRecipe; add test to show issue re: lastItemOutputs --- .../capability/impl/AbstractRecipeLogic.java | 59 +++++----- .../impl/AbstractRecipeLogicTest.java | 111 ++++++++++++++++++ 2 files changed, 138 insertions(+), 32 deletions(-) create mode 100644 src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 6bea2dabc8..7acae87d86 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -15,6 +15,7 @@ import net.minecraft.nbt.NBTTagList; import net.minecraft.network.PacketBuffer; import net.minecraft.util.NonNullList; +import net.minecraft.world.*; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.Constants; import net.minecraftforge.fluids.FluidStack; @@ -110,7 +111,8 @@ public T getCapability(Capability capability) { @Override public void update() { - if (!getMetaTileEntity().getWorld().isRemote) { + World world = getMetaTileEntity().getWorld(); + if (world == null || !world.isRemote) { if (workingEnabled) { if (progressTime > 0) { updateRecipeProgress(); @@ -154,39 +156,34 @@ protected void trySearchNewRecipe() { IItemHandlerModifiable importInventory = getInputInventory(); IMultipleTankHandler importFluids = getInputTank(); - // if the output is full check if the output changed so we can process recipes results again. - if (this.isOutputsFull) { - IItemHandlerModifiable exportInventory = getOutputInventory(); - IMultipleTankHandler exportFluids = getOutputTank(); - if (hasMachineOutputChanged(exportInventory, exportFluids)) { - this.isOutputsFull = false; - } - } + // If a recheck is forced, skip the fail-fast options + if (!this.forceRecipeRecheck) { + // if the output is full check if the output changed so we can process recipes results again. + if (this.isOutputsFull && !hasMachineOutputChanged(getOutputInventory(), getOutputTank())) return; + else this.isOutputsFull = false; + + // if the inputs were bad last time, check if they've changed before trying to find a new recipe. + if (this.invalidInputsForRecipes && !checkRecipeInputsDirty(importInventory, importFluids)) return; - if (!invalidInputsForRecipes && !this.isOutputsFull) { - if (this.previousRecipe != null && this.previousRecipe.matches(false, importInventory, importFluids)) { - //if previous recipe still matches inputs, try to use it + // see if the last recipe we used still works + if (this.previousRecipe != null && this.previousRecipe.matches(false, importInventory, importFluids)) currentRecipe = this.previousRecipe; - } } + + // If there is no active recipe, then we need to find one. if (currentRecipe == null) { - if (checkRecipeInputsDirty(importInventory, importFluids) || this.forceRecipeRecheck) { - this.forceRecipeRecheck = false; - //else, try searching new recipe for given inputs - currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); - if (currentRecipe != null) { - this.previousRecipe = currentRecipe; - this.invalidInputsForRecipes = false; - } else { - //no recipe found for the current inputs. - //search again when inputs change - this.invalidInputsForRecipes = true; - } - } + this.forceRecipeRecheck = false; + currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); } - if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { + + // If a recipe was found, then inputs were valid. + if(!(this.invalidInputsForRecipes = currentRecipe == null)) + // replace old recipe with new one + this.previousRecipe = currentRecipe; + + // proceed if we have a usable recipe. + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) setupRecipe(currentRecipe); - } } public void forceRecipeRecheck() { @@ -396,9 +393,6 @@ protected void completeRecipe() { this.itemOutputs = null; this.hasNotEnoughEnergy = false; this.wasActiveAndNeedsUpdate = true; - //force recipe recheck because inputs could have changed since last time - //we checked them before starting our recipe, especially if recipe took long time - this.forceRecipeRecheck = true; } public double getProgressPercent() { @@ -431,7 +425,8 @@ public void setMaxProgress(int maxProgress) { protected void setActive(boolean active) { this.isActive = active; metaTileEntity.markDirty(); - if (!metaTileEntity.getWorld().isRemote) { + World world = metaTileEntity.getWorld(); + if (world != null && world.isRemote) { writeCustomData(1, buf -> buf.writeBoolean(active)); } } diff --git a/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java b/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java new file mode 100644 index 0000000000..e5dd5c59a0 --- /dev/null +++ b/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java @@ -0,0 +1,111 @@ +package gregtech.api.capability.impl; + +import gregtech.api.*; +import gregtech.api.metatileentity.*; +import gregtech.api.recipes.*; +import gregtech.api.recipes.builders.*; +import gregtech.api.render.*; +import net.minecraft.init.*; +import net.minecraft.item.*; +import net.minecraft.util.*; +import org.junit.*; + +import static org.junit.Assert.*; + +public class AbstractRecipeLogicTest { + + @BeforeClass + public static void init() { + Bootstrap.register(); + } + + @Test + public void trySearchNewRecipe() { + + // Create an empty recipe map to work with + RecipeMap map = new RecipeMap<>("chemical_reactor", + 0, + 2, + 0, + 2, + 0, + 3, + 0, + 2, + new SimpleRecipeBuilder().EUt(30)); + + MetaTileEntity at = + GregTechAPI.registerMetaTileEntity(190, + new SimpleMachineMetaTileEntity( + new ResourceLocation(GTValues.MODID,"chemical_reactor.lv"), + map, + Textures.CHEMICAL_REACTOR_OVERLAY, + 1)); + + map.recipeBuilder() + .inputs(new ItemStack(Blocks.COBBLESTONE)) + .outputs(new ItemStack(Blocks.STONE)) + .EUt(1).duration(1) + .buildAndRegister(); + + AbstractRecipeLogic arl = new AbstractRecipeLogic(at, map) { + @Override + protected long getEnergyStored() { return Long.MAX_VALUE; } + @Override + protected long getEnergyCapacity() { return Long.MAX_VALUE; } + @Override + protected boolean drawEnergy(int recipeEUt) { return true; } + @Override + protected long getMaxVoltage() { return 32; } + }; + + arl.lastItemInputs = null; + arl.lastItemOutputs = null; + arl.lastFluidInputs = null; + arl.lastFluidOutputs = null; + arl.isOutputsFull = false; + arl.invalidInputsForRecipes = false; + arl.trySearchNewRecipe(); + + // no recipe found + assertTrue(arl.invalidInputsForRecipes); + assertFalse(arl.isActive); + assertNull(arl.previousRecipe); + + // put an item in the inventory that will trigger recipe recheck + arl.getInputInventory().insertItem(0, new ItemStack(Blocks.COBBLESTONE, 16), false); + arl.trySearchNewRecipe(); + assertFalse(arl.invalidInputsForRecipes); + assertNotNull(arl.previousRecipe); + assertTrue(arl.isActive); + assertEquals(15, arl.getInputInventory().getStackInSlot(0).getCount()); + + // Save a reference to the old recipe so we can make sure it's getting reused + Recipe prev = arl.previousRecipe; + + // Finish the recipe, the output should generate, and the next iteration should begin + arl.update(); + assertEquals(prev, arl.previousRecipe); + assertTrue(AbstractRecipeLogic.areItemStacksEqual(arl.getOutputInventory().getStackInSlot(0), + new ItemStack(Blocks.STONE, 1))); + assertTrue(arl.isActive); + + // Complete the second iteration, but the machine stops because its output is now full + arl.getOutputInventory().setStackInSlot(0, new ItemStack(Blocks.STONE, 63)); + arl.getOutputInventory().setStackInSlot(1, new ItemStack(Blocks.STONE, 64)); + arl.update(); + assertFalse(arl.isActive); + assertTrue(arl.isOutputsFull); + + // Try to process again and get failed out because of full buffer. + arl.update(); + assertFalse(arl.isActive); + assertTrue(arl.isOutputsFull); + + // Some room is freed in the output bus, so we can continue now. + arl.getOutputInventory().setStackInSlot(1, ItemStack.EMPTY); + arl.update(); + assertTrue(arl.isActive); + assertFalse(arl.isOutputsFull); + } +} \ No newline at end of file From 2655473d2063cc3ff00af7275bc59aae16c5baf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Thu, 25 Mar 2021 18:33:01 -0300 Subject: [PATCH 04/26] Changed item merging from full inventory copy to partial stacks copy avoids copying itemstacks that are at max size, and cant be merged into anyway --- .../api/metatileentity/MetaTileEntity.java | 13 +++++++++---- .../java/gregtech/api/util/InventoryUtils.java | 17 ++++++++++++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index 4ca7412551..b8b794673a 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -22,6 +22,7 @@ import gregtech.api.render.Textures; import gregtech.api.util.GTFluidUtils; import gregtech.api.util.GTUtility; +import gregtech.api.util.InventoryUtils; import net.minecraft.block.Block; import net.minecraft.block.state.BlockFaceShape; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -56,8 +57,6 @@ import java.util.List; import java.util.function.Consumer; -import static gregtech.api.util.InventoryUtils.simulateItemStackMerge; - public abstract class MetaTileEntity implements ICoverable { public static final int DEFAULT_PAINTING_COLOR = 0xFFFFFF; @@ -973,8 +972,14 @@ public static boolean addItemsToItemHandler(final IItemHandler handler, final boolean simulate, final List items) { // determine if there is sufficient room to insert all items into the target inventory - final boolean canMerge = simulateItemStackMerge(items, handler); - + boolean canMerge; + if (items.size() == 1) { + canMerge = ItemHandlerHelper.insertItemStacked(handler, items.get(0), true).isEmpty(); + } else { + // merging 2 or more stacks may change the slots available for merging, + // needing full simulation of the state of the inventory after every merge + canMerge = InventoryUtils.simulateItemStackMerge(items, handler); + } // if we're not simulating and the merge should succeed, perform the merge. if (!simulate && canMerge) items.forEach(stack -> { diff --git a/src/main/java/gregtech/api/util/InventoryUtils.java b/src/main/java/gregtech/api/util/InventoryUtils.java index 9102e89b6c..5697d952f1 100755 --- a/src/main/java/gregtech/api/util/InventoryUtils.java +++ b/src/main/java/gregtech/api/util/InventoryUtils.java @@ -43,6 +43,21 @@ public static List deepCopy(final IItemHandler inventory, .collect(Collectors.toList()); } + /** + * Creates a copy of the partial stacks in target inventory + * + * @param inventory the target inventory + * @return a copy of the partial stacks of the inventory. + */ + public static List copyPartialStacks(final IItemHandler inventory) { + + return streamFrom(inventory) + .filter(not(ItemStack::isEmpty)) + .filter(not(itemStack -> itemStack.getCount() == itemStack.getMaxStackSize())) + .map(ItemStack::copy) + .collect(Collectors.toList()); + } + /** * Determines whether all specified items will fit into a target inventory by * simulating merging like items into existing stacks, then checking if there @@ -75,7 +90,7 @@ public static boolean simulateItemStackMerge(List inputItems, itemStacks.sort(Comparator.comparingInt(ItemStack::getCount)); // Deep copy the contents of the target inventory, skipping empty stacks - final List inventoryStacks = deepCopy(inventory, false); + final List inventoryStacks = copyPartialStacks(inventory); // Perform a merge of the ItemStacks mergeItemStacks(itemStacks, inventoryStacks); From 27f470089148e4f2f0bcfa5f88cc9dc55226c97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Mon, 29 Mar 2021 22:18:52 -0300 Subject: [PATCH 05/26] Implement notifiable item/fluid handlers can notify controllers/metatileentities of inventory changes --- .../api/capability/INotifiableHandler.java | 46 +++++++++++++++++++ .../impl/NotifiableFilteredFluidHandler.java | 29 ++++++++++++ .../capability/impl/NotifiableFluidTank.java | 30 ++++++++++++ .../impl/NotifiableItemStackHandler.java | 31 +++++++++++++ .../api/metatileentity/MetaTileEntity.java | 20 +++++++- .../WorkableTieredMetaTileEntity.java | 12 ++--- .../multiblock/IMultiblockPart.java | 5 ++ .../multiblock/MultiblockControllerBase.java | 1 + .../electric/MetaTileEntityMacerator.java | 6 +-- .../MetaTileEntityFluidHatch.java | 1 + .../multiblockpart/MetaTileEntityItemBus.java | 14 +++++- 11 files changed, 182 insertions(+), 13 deletions(-) create mode 100644 src/main/java/gregtech/api/capability/INotifiableHandler.java create mode 100644 src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java create mode 100644 src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java create mode 100644 src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java diff --git a/src/main/java/gregtech/api/capability/INotifiableHandler.java b/src/main/java/gregtech/api/capability/INotifiableHandler.java new file mode 100644 index 0000000000..401c081bc3 --- /dev/null +++ b/src/main/java/gregtech/api/capability/INotifiableHandler.java @@ -0,0 +1,46 @@ +package gregtech.api.capability; + +import gregtech.api.metatileentity.MetaTileEntity; + +import java.util.HashSet; +import java.util.Iterator; + +/** + * For Item and Fluid handlers capable of notifying entities when + * their contents change + */ +public interface INotifiableHandler { + + /** + * Notifies the entities of the changes in their inventories + * An iterator is used to remove invalid TileEntities + * @param isExport boolean specifying if a handler is an output handler + */ + + default void notifyMetaTileEntitiesOfChange(boolean isExport) { + Iterator iterator = getNotifiableMetaTileEntities().iterator(); + while (iterator.hasNext()) { + MetaTileEntity mte = iterator.next(); + if (mte != null && mte.isValid()) { + if (isExport) mte.setOutputsDirty(true); + else mte.setInputsDirty(true); + } else { + iterator.remove(); + } + } + } + + /** + * returns a HashSet containing the notifiable MetaTileEntities + * @return + */ + HashSet getNotifiableMetaTileEntities(); + + /** + * + * @param metaTileEntity MetaTileEntity to be notified + */ + default void addNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + getNotifiableMetaTileEntities().add(metaTileEntity); + } +} diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java new file mode 100644 index 0000000000..6ab8409be0 --- /dev/null +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java @@ -0,0 +1,29 @@ +package gregtech.api.capability.impl; + +import gregtech.api.capability.INotifiableHandler; +import gregtech.api.metatileentity.MetaTileEntity; + +import java.util.HashSet; + +public class NotifiableFilteredFluidHandler extends FilteredFluidHandler implements INotifiableHandler { + + HashSet entityToSetDirty = new HashSet<>(); + private final boolean isExport; + + public NotifiableFilteredFluidHandler(int capacity, MetaTileEntity entityToSetDirty, boolean isExport) { + super(capacity); + this.entityToSetDirty.add(entityToSetDirty); + this.isExport = isExport; + } + + @Override + protected void onContentsChanged() { + super.onContentsChanged(); + notifyMetaTileEntitiesOfChange(isExport); + } + + @Override + public HashSet getNotifiableMetaTileEntities() { + return this.entityToSetDirty; + } +} diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java new file mode 100644 index 0000000000..713bcda71f --- /dev/null +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java @@ -0,0 +1,30 @@ +package gregtech.api.capability.impl; + +import gregtech.api.capability.INotifiableHandler; +import gregtech.api.metatileentity.MetaTileEntity; +import net.minecraftforge.fluids.FluidTank; + +import java.util.HashSet; + +public class NotifiableFluidTank extends FluidTank implements INotifiableHandler { + + HashSet entityToSetDirty = new HashSet<>(); + private final boolean isExport; + + public NotifiableFluidTank(int capacity, MetaTileEntity entityToSetDirty, boolean isExport) { + super(capacity); + this.entityToSetDirty.add(entityToSetDirty); + this.isExport = isExport; + } + + @Override + protected void onContentsChanged() { + super.onContentsChanged(); + notifyMetaTileEntitiesOfChange(isExport); + } + + @Override + public HashSet getNotifiableMetaTileEntities(){ + return this.entityToSetDirty; + } +} diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java new file mode 100644 index 0000000000..146791afc8 --- /dev/null +++ b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java @@ -0,0 +1,31 @@ +package gregtech.api.capability.impl; + +import gregtech.api.capability.INotifiableHandler; +import gregtech.api.metatileentity.MetaTileEntity; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; + +import java.util.HashSet; + +public class NotifiableItemStackHandler extends ItemStackHandler implements IItemHandlerModifiable, INotifiableHandler { + + HashSet entityToSetDirty = new HashSet<>(); + private final boolean isExport; + + public NotifiableItemStackHandler(int slots, MetaTileEntity entityToSetDirty, boolean isExport) { + super(slots); + this.entityToSetDirty.add(entityToSetDirty); + this.isExport = isExport; + } + + @Override + public void onContentsChanged(int slot) { + super.onContentsChanged(slot); + notifyMetaTileEntitiesOfChange(isExport); + } + + @Override + public HashSet getNotifiableMetaTileEntities() { + return this.entityToSetDirty; + } +} diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index b8b794673a..c002d83fdf 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -88,7 +88,9 @@ public abstract class MetaTileEntity implements ICoverable { private int cachedLightValue; protected boolean isFragile = false; - private final CoverBehavior[] coverBehaviors = new CoverBehavior[6]; + private CoverBehavior[] coverBehaviors = new CoverBehavior[6]; + protected boolean outputDirty; + protected boolean inputDirty; public MetaTileEntity(ResourceLocation metaTileEntityId) { this.metaTileEntityId = metaTileEntityId; @@ -256,6 +258,22 @@ public final String getMetaFullName() { return getMetaName() + ".name"; } + public final void setInputsDirty(boolean dirty) { + this.inputDirty = dirty; + } + + public final boolean isInputsDirty() { + return this.inputDirty; + } + + public final void setOutputsDirty(boolean dirty) { + this.outputDirty = dirty; + } + + public final boolean isOutputsDirty() { + return this.outputDirty; + } + /** * Adds a trait to this meta tile entity * traits are objects linked with meta tile entity and performing certain diff --git a/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java index a64c9b1383..80865fa9a2 100644 --- a/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java @@ -4,9 +4,7 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; import gregtech.api.GTValues; -import gregtech.api.capability.impl.RecipeLogicEnergy; -import gregtech.api.capability.impl.FilteredFluidHandler; -import gregtech.api.capability.impl.FluidTankList; +import gregtech.api.capability.impl.*; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; import gregtech.api.render.OrientedOverlayRenderer; @@ -56,13 +54,13 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, @Override protected IItemHandlerModifiable createImportItemHandler() { if (workable == null) return new ItemStackHandler(0); - return new ItemStackHandler(workable.recipeMap.getMaxInputs()); + return new NotifiableItemStackHandler(workable.recipeMap.getMaxInputs(), this,false); } @Override protected IItemHandlerModifiable createExportItemHandler() { if (workable == null) return new ItemStackHandler(0); - return new ItemStackHandler(workable.recipeMap.getMaxOutputs()); + return new NotifiableItemStackHandler(workable.recipeMap.getMaxOutputs(), this,true); } @Override @@ -70,7 +68,7 @@ protected FluidTankList createImportFluidHandler() { if (workable == null) return new FluidTankList(false); FilteredFluidHandler[] fluidImports = new FilteredFluidHandler[workable.recipeMap.getMaxFluidInputs()]; for (int i = 0; i < fluidImports.length; i++) { - FilteredFluidHandler filteredFluidHandler = new FilteredFluidHandler(getInputTankCapacity(i)); + NotifiableFilteredFluidHandler filteredFluidHandler = new NotifiableFilteredFluidHandler(getInputTankCapacity(i),this,false); filteredFluidHandler.setFillPredicate(this::canInputFluid); fluidImports[i] = filteredFluidHandler; } @@ -82,7 +80,7 @@ protected FluidTankList createExportFluidHandler() { if (workable == null) return new FluidTankList(false); FluidTank[] fluidExports = new FluidTank[workable.recipeMap.getMaxFluidOutputs()]; for (int i = 0; i < fluidExports.length; i++) { - fluidExports[i] = new FluidTank(getOutputTankCapacity(i)); + fluidExports[i] = new NotifiableFluidTank(getOutputTankCapacity(i),this,true); } return new FluidTankList(false, fluidExports); } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java b/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java index ca3213547f..924bb52f6e 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java @@ -1,5 +1,7 @@ package gregtech.api.metatileentity.multiblock; +import gregtech.api.metatileentity.MetaTileEntity; + public interface IMultiblockPart { boolean isAttachedToMultiBlock(); @@ -8,4 +10,7 @@ public interface IMultiblockPart { void removeFromMultiBlock(MultiblockControllerBase controllerBase); + default void addEntityToDirtyableHandlers(MetaTileEntity metaTileEntity) { + + } } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java index 73f3f9d9e9..c4b7c879dc 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java @@ -184,6 +184,7 @@ protected void checkStructurePattern() { } if (checkStructureComponents(parts, abilities)) { parts.forEach(part -> part.addToMultiBlock(this)); + parts.forEach(part -> part.addEntityToDirtyableHandlers(this)); this.multiblockParts.addAll(parts); this.multiblockAbilities.putAll(abilities); this.structureFormed = true; diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java index f019595b7e..2d7dcc26ee 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java @@ -9,9 +9,9 @@ import gregtech.api.recipes.RecipeMap; import gregtech.api.render.OrientedOverlayRenderer; import gregtech.api.util.GTUtility; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class MetaTileEntityMacerator extends SimpleMachineMetaTileEntity { @@ -41,11 +41,11 @@ protected int getMachineTierForRecipe(Recipe recipe) { @Override protected IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(outputAmount); + return new NotifiableItemStackHandler(outputAmount,this,true); } @Override public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { return new MetaTileEntityMacerator(metaTileEntityId, workable.recipeMap, outputAmount, renderer, getTier()); } -} \ No newline at end of file +} diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java index 332cff55ec..adfee81f26 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java @@ -17,6 +17,7 @@ import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.render.SimpleOverlayRenderer; import gregtech.api.render.Textures; +import gregtech.api.capability.impl.NotifiableFluidTank; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java index a3703f5588..cf66336373 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java @@ -13,6 +13,7 @@ import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.render.SimpleOverlayRenderer; import gregtech.api.render.Textures; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -70,12 +71,12 @@ private int getInventorySize() { @Override protected IItemHandlerModifiable createExportItemHandler() { - return isExportHatch ? new ItemStackHandler(getInventorySize()) : new ItemStackHandler(0); + return isExportHatch ? new NotifiableItemStackHandler(getInventorySize(),getController(),true) : new ItemStackHandler(0); } @Override protected IItemHandlerModifiable createImportItemHandler() { - return isExportHatch ? new ItemStackHandler(0) : new ItemStackHandler(getInventorySize()); + return isExportHatch ? new ItemStackHandler(0) : new NotifiableItemStackHandler(getInventorySize(),getController(), false); } @Override @@ -88,6 +89,15 @@ public void registerAbilities(List abilityList) { abilityList.add(isExportHatch ? this.exportItems : this.importItems); } + @Override + public void addEntityToDirtyableHandlers(MetaTileEntity metaTileEntity) { + NotifiableItemStackHandler handler; + if (isExportHatch) handler = (NotifiableItemStackHandler) getExportItems(); + else handler = (NotifiableItemStackHandler) getImportItems(); + handler.addNotifiableMetaTileEntity(metaTileEntity); + handler.notifyMetaTileEntitiesOfChange(isExportHatch); + } + @Override protected ModularUI createUI(EntityPlayer entityPlayer) { int rowSize = (int) Math.sqrt(getInventorySize()); From 114626878657aa219e21297d9529bb1824ff0a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Mon, 29 Mar 2021 22:22:27 -0300 Subject: [PATCH 06/26] enable the recipe logic to make use of the notifiable handlers recipe logic can wait for changes to the output if it cant process recipes if the output is full. can also wait for changes in the input inventory in case a recipe was searched for but didnt result in a valid recipe. implemented tests. one simulates a chemical reactor, the other one an electric blast furnace --- .../capability/impl/AbstractRecipeLogic.java | 141 +++------- .../electric/MetaTileEntityMultiFurnace.java | 42 ++- .../impl/AbstractRecipeLogicTest.java | 15 +- .../impl/MultiblockRecipeLogicTest.java | 255 ++++++++++++++++++ 4 files changed, 319 insertions(+), 134 deletions(-) create mode 100644 src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 7acae87d86..51589c448d 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -24,7 +24,6 @@ import net.minecraftforge.items.IItemHandlerModifiable; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.function.LongSupplier; @@ -37,10 +36,6 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable public final RecipeMap recipeMap; protected boolean forceRecipeRecheck; - protected ItemStack[] lastItemInputs; - protected FluidStack[] lastFluidInputs; - protected ItemStack[] lastItemOutputs; - protected FluidStack[] lastFluidOutputs; protected Recipe previousRecipe; protected boolean allowOverclocking = true; private long overclockVoltage = 0; @@ -57,8 +52,8 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable protected boolean workingEnabled = true; protected boolean hasNotEnoughEnergy; protected boolean wasActiveAndNeedsUpdate; - protected boolean isOutputsFull = false; - protected boolean invalidInputsForRecipes = false; + protected boolean isOutputsFull; + protected boolean invalidInputsForRecipes; public AbstractRecipeLogic(MetaTileEntity tileEntity, RecipeMap recipeMap) { super(tileEntity); @@ -117,7 +112,8 @@ public void update() { if (progressTime > 0) { updateRecipeProgress(); } - if (progressTime == 0) { + //check everything that would make a recipe never start here. + if (progressTime == 0 && shouldSearchForRecipes()){ trySearchNewRecipe(); } } @@ -128,6 +124,24 @@ public void update() { } } + boolean shouldSearchForRecipes() { + return canWorkWithInputs() && canFitNewOutputs(); + } + + boolean canFitNewOutputs() { + // if the output is full check if the output changed so we can process recipes results again. + if (this.isOutputsFull && !metaTileEntity.isOutputsDirty()) return false; + else { this.isOutputsFull = false; metaTileEntity.setOutputsDirty(false); } + return true; + } + + boolean canWorkWithInputs() { + // if the inputs were bad last time, check if they've changed before trying to find a new recipe. + if (this.invalidInputsForRecipes && !metaTileEntity.isInputsDirty()) return false; + else { this.invalidInputsForRecipes = false; } + return true; + } + protected void updateRecipeProgress() { boolean drawEnergy = drawEnergy(recipeEUt); if (drawEnergy || (recipeEUt < 0)) { @@ -156,34 +170,27 @@ protected void trySearchNewRecipe() { IItemHandlerModifiable importInventory = getInputInventory(); IMultipleTankHandler importFluids = getInputTank(); - // If a recheck is forced, skip the fail-fast options - if (!this.forceRecipeRecheck) { - // if the output is full check if the output changed so we can process recipes results again. - if (this.isOutputsFull && !hasMachineOutputChanged(getOutputInventory(), getOutputTank())) return; - else this.isOutputsFull = false; - - // if the inputs were bad last time, check if they've changed before trying to find a new recipe. - if (this.invalidInputsForRecipes && !checkRecipeInputsDirty(importInventory, importFluids)) return; - - // see if the last recipe we used still works - if (this.previousRecipe != null && this.previousRecipe.matches(false, importInventory, importFluids)) - currentRecipe = this.previousRecipe; - } - + // see if the last recipe we used still works + if (this.previousRecipe != null && this.previousRecipe.matches(false, importInventory, importFluids)) + currentRecipe = this.previousRecipe; // If there is no active recipe, then we need to find one. - if (currentRecipe == null) { - this.forceRecipeRecheck = false; + else { + metaTileEntity.setInputsDirty(false); currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); } - // If a recipe was found, then inputs were valid. - if(!(this.invalidInputsForRecipes = currentRecipe == null)) + // recipe multiplying machines may not be able to fit + // the multiplied recipes. in that case the inputs are valid + if (!(this.invalidInputsForRecipes = (currentRecipe == null && !this.isOutputsFull))) // replace old recipe with new one this.previousRecipe = currentRecipe; // proceed if we have a usable recipe. - if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { setupRecipe(currentRecipe); + //avoid new recipe lookup caused by item consumption from input + metaTileEntity.setInputsDirty(false); + } } public void forceRecipeRecheck() { @@ -205,85 +212,9 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul return recipeMap.findRecipe(maxVoltage, inputs, fluidInputs, getMinTankCapacity(getOutputTank())); } + @Deprecated protected boolean checkRecipeInputsDirty(IItemHandler inputs, IMultipleTankHandler fluidInputs) { - boolean shouldRecheckRecipe = false; - if (lastItemInputs == null || lastItemInputs.length != inputs.getSlots()) { - this.lastItemInputs = new ItemStack[inputs.getSlots()]; - Arrays.fill(lastItemInputs, ItemStack.EMPTY); - } - if (lastFluidInputs == null || lastFluidInputs.length != fluidInputs.getTanks()) { - this.lastFluidInputs = new FluidStack[fluidInputs.getTanks()]; - } - for (int i = 0; i < lastItemInputs.length; i++) { - ItemStack currentStack = inputs.getStackInSlot(i); - ItemStack lastStack = lastItemInputs[i]; - if (!areItemStacksEqual(currentStack, lastStack)) { - this.lastItemInputs[i] = currentStack.isEmpty() ? ItemStack.EMPTY : currentStack.copy(); - shouldRecheckRecipe = true; - } else if (currentStack.getCount() != lastStack.getCount()) { - lastStack.setCount(currentStack.getCount()); - shouldRecheckRecipe = true; - } - if (shouldRecheckRecipe) - return true; - } - for (int i = 0; i < lastFluidInputs.length; i++) { - FluidStack currentStack = fluidInputs.getTankAt(i).getFluid(); - FluidStack lastStack = lastFluidInputs[i]; - if ((currentStack == null && lastStack != null) || - (currentStack != null && !currentStack.isFluidEqual(lastStack))) { - this.lastFluidInputs[i] = currentStack == null ? null : currentStack.copy(); - shouldRecheckRecipe = true; - } else if (currentStack != null && lastStack != null && - currentStack.amount != lastStack.amount) { - lastStack.amount = currentStack.amount; - shouldRecheckRecipe = true; - } - if (shouldRecheckRecipe) - return true; - } - return false; - } - - protected boolean hasMachineOutputChanged(IItemHandler outputs, IMultipleTankHandler fluidOutputs) { - boolean outputChanged = false; - if (lastItemOutputs == null || lastItemOutputs.length != outputs.getSlots()) { - this.lastItemOutputs = new ItemStack[outputs.getSlots()]; - Arrays.fill(lastItemOutputs, ItemStack.EMPTY); - } - if (lastFluidOutputs == null || lastFluidOutputs.length != fluidOutputs.getTanks()) { - this.lastFluidOutputs = new FluidStack[fluidOutputs.getTanks()]; - } - for (int i = 0; i < lastItemOutputs.length; i++) { - ItemStack currentStack = outputs.getStackInSlot(i); - ItemStack lastStack = lastItemOutputs[i]; - if (!areItemStacksEqual(currentStack, lastStack)) { - this.lastItemOutputs[i] = currentStack.isEmpty() ? ItemStack.EMPTY : currentStack.copy(); - outputChanged = true; - } else if (currentStack.getCount() != lastStack.getCount()) { - lastStack.setCount(currentStack.getCount()); - outputChanged = true; - } - if (outputChanged) - return true; - } - - for (int i = 0; i < lastFluidOutputs.length; i++) { - FluidStack currentStack = fluidOutputs.getTankAt(i).getFluid(); - FluidStack lastStack = lastFluidOutputs[i]; - if ((currentStack == null && lastStack != null) || - (currentStack != null && !currentStack.isFluidEqual(lastStack))) { - this.lastFluidOutputs[i] = currentStack == null ? null : currentStack.copy(); - outputChanged = true; - } else if (currentStack != null && lastStack != null && - currentStack.amount != lastStack.amount) { - lastStack.amount = currentStack.amount; - outputChanged = true; - } - if (outputChanged) - return true; - } - return false; + return this.getMetaTileEntity().isInputsDirty(); } protected static boolean areItemStacksEqual(ItemStack stackA, ItemStack stackB) { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index e27473fdf8..ce492c2a94 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -104,35 +104,28 @@ protected void trySearchNewRecipe() { long maxVoltage = getMaxVoltage(); Recipe currentRecipe = null; IItemHandlerModifiable importInventory = getInputInventory(); - IMultipleTankHandler importFluids = getInputTank(); - - if (this.isOutputsFull) { - IItemHandlerModifiable exportInventory = getOutputInventory(); - IMultipleTankHandler exportFluids = getOutputTank(); - if (hasMachineOutputChanged(exportInventory, exportFluids)) { - this.isOutputsFull = false; - } - } //inverse of logic in normal AbstractRecipeLogic //for MultiSmelter, we can reuse previous recipe if inputs didn't change //otherwise, we need to recompute it for new ingredients //but technically, it means we can cache multi smelter recipe, but changing inputs have more priority - if (checkRecipeInputsDirty(importInventory, importFluids) || this.forceRecipeRecheck) { - this.forceRecipeRecheck = false; - //else, try searching new recipe for given inputs - currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); - if (currentRecipe != null) { - this.previousRecipe = currentRecipe; - } - } else if (!invalidInputsForRecipes && !this.isOutputsFull) { - if (previousRecipe != null && previousRecipe.matches(false, importInventory, importFluids)) { - //if previous recipe still matches inputs, try to use it - currentRecipe = previousRecipe; - } + if (metaTileEntity.isInputsDirty()) { + metaTileEntity.setInputsDirty(false); + //Inputs changed, try searching new recipe for given inputs + currentRecipe = findRecipe(maxVoltage, importInventory, null); + } else if (previousRecipe != null && previousRecipe.matches(false, importInventory, null)) { + //if previous recipe still matches inputs, try to use it + currentRecipe = previousRecipe; } + if ( currentRecipe != null) + // replace old recipe with new one + this.previousRecipe = currentRecipe; + + // proceed if we have a usable recipe. if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { setupRecipe(currentRecipe); + //avoid new recipe lookup caused by item consumption from input + metaTileEntity.setInputsDirty(false); } } @@ -212,9 +205,12 @@ protected Recipe findRecipe(long maxVoltage, } // If there were no accepted ingredients, then there is no recipe to process. - if(recipeInputs.isEmpty()) { + // the output may be filled up + if(recipeInputs.isEmpty() && !invalidInputsForRecipes) { //Set here to prevent recipe deadlock on world load with full output bus - forceRecipeRecheck = true; + this.isOutputsFull = true; + return null; + } else if (recipeInputs.isEmpty()) { return null; } diff --git a/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java b/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java index e5dd5c59a0..8bf9948673 100644 --- a/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java +++ b/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java @@ -42,13 +42,14 @@ public void trySearchNewRecipe() { Textures.CHEMICAL_REACTOR_OVERLAY, 1)); + MetaTileEntity atte = new MetaTileEntityHolder().setMetaTileEntity(at); map.recipeBuilder() .inputs(new ItemStack(Blocks.COBBLESTONE)) .outputs(new ItemStack(Blocks.STONE)) .EUt(1).duration(1) .buildAndRegister(); - AbstractRecipeLogic arl = new AbstractRecipeLogic(at, map) { + AbstractRecipeLogic arl = new AbstractRecipeLogic(atte, map) { @Override protected long getEnergyStored() { return Long.MAX_VALUE; } @Override @@ -59,10 +60,6 @@ public void trySearchNewRecipe() { protected long getMaxVoltage() { return 32; } }; - arl.lastItemInputs = null; - arl.lastItemOutputs = null; - arl.lastFluidInputs = null; - arl.lastFluidOutputs = null; arl.isOutputsFull = false; arl.invalidInputsForRecipes = false; arl.trySearchNewRecipe(); @@ -74,11 +71,15 @@ public void trySearchNewRecipe() { // put an item in the inventory that will trigger recipe recheck arl.getInputInventory().insertItem(0, new ItemStack(Blocks.COBBLESTONE, 16), false); + // Inputs change. did we detect it ? + assertTrue(arl.getMetaTileEntity().isInputsDirty()); arl.trySearchNewRecipe(); assertFalse(arl.invalidInputsForRecipes); assertNotNull(arl.previousRecipe); assertTrue(arl.isActive); assertEquals(15, arl.getInputInventory().getStackInSlot(0).getCount()); + //assert the consumption of the inputs did not mark the arl to look for a new recipe + assertFalse(arl.getMetaTileEntity().isInputsDirty()); // Save a reference to the old recipe so we can make sure it's getting reused Recipe prev = arl.previousRecipe; @@ -107,5 +108,7 @@ public void trySearchNewRecipe() { arl.update(); assertTrue(arl.isActive); assertFalse(arl.isOutputsFull); + assertTrue(AbstractRecipeLogic.areItemStacksEqual(arl.getOutputInventory().getStackInSlot(0), + new ItemStack(Blocks.STONE, 1))); } -} \ No newline at end of file +} diff --git a/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java b/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java new file mode 100644 index 0000000000..d2ff17065d --- /dev/null +++ b/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java @@ -0,0 +1,255 @@ +package gregtech.api.capability.impl; + +import gregtech.api.GTValues; +import gregtech.api.GregTechAPI; + +import gregtech.api.capability.IMultipleTankHandler; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.metatileentity.multiblock.*; +import gregtech.api.recipes.Recipe; +import gregtech.api.recipes.RecipeMap; +import gregtech.api.recipes.RecipeMaps; +import gregtech.api.recipes.builders.BlastRecipeBuilder; +import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityFluidHatch; +import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityItemBus; +import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityMultiblockPart; +import gregtech.common.metatileentities.multi.electric.MetaTileEntityElectricBlastFurnace; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.init.Bootstrap; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.items.IItemHandlerModifiable; + +import org.junit.BeforeClass; +import org.junit.Test; +import java.lang.reflect.Field; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; + +public class MultiblockRecipeLogicTest { + + @BeforeClass + public static void init() { + Bootstrap.register(); + } + + private static ResourceLocation gregtechId(String name) { + return new ResourceLocation(GTValues.MODID, name); + } + + @Test + public void trySearchNewRecipe() { + + // Create an empty recipe map to work with + RecipeMap map = new RecipeMap<>("blast_furnace", + 1, + 3, + 1, + 2, + 0, + 1, + 0, + 1, + new BlastRecipeBuilder().EUt(32)); + + RecipeMaps.BLAST_RECIPES.recipeBuilder() + .inputs(new ItemStack(Blocks.COBBLESTONE)) + .outputs(new ItemStack(Blocks.STONE)) + .EUt(1).duration(1) + .blastFurnaceTemp(1) + .buildAndRegister(); + + RecipeMapMultiblockController mbt = + GregTechAPI.registerMetaTileEntity(511, + new MetaTileEntityElectricBlastFurnace( + // super function calls the world, which equal null in test + new ResourceLocation(GTValues.MODID, "electric_blast_furnace")) { + @Override + protected IBlockState getCasingState() { + return null; + } + // function checks for the temperature of the recipe against the coils + @Override + public boolean checkRecipe(Recipe recipe, boolean consumeIfSuccess) { + return true; + } + }); + //isValid() check in the dirtying logic requires both a metatileentity and a holder + try { + Field field = MetaTileEntity.class.getDeclaredField("holder"); + field.setAccessible(true); + field.set(mbt, new MetaTileEntityHolder()); + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + } + + try { + Field field = MetaTileEntityHolder.class.getDeclaredField("metaTileEntity"); + field.setAccessible(true); + field.set(mbt.getHolder(), mbt); + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + } + + //Controller and isAttachedToMultiBlock need the world so we fake it here. + MetaTileEntityItemBus importItemBus = new MetaTileEntityItemBus(gregtechId("item_bus.export.lv"), 1, false) { + @Override + public boolean isAttachedToMultiBlock() { + return true; + } + + @Override + public MultiblockControllerBase getController() { + return mbt; + } + }; + MetaTileEntityItemBus exportItemBus = new MetaTileEntityItemBus(gregtechId("item_bus.export.lv"), 1, true) { + @Override + public boolean isAttachedToMultiBlock() { + return true; + } + + @Override + public MultiblockControllerBase getController() { + return mbt; + } + }; + MetaTileEntityFluidHatch importFluidBus = new MetaTileEntityFluidHatch(gregtechId("fluid_hatch.import.lv"), 1, false) { + @Override + public boolean isAttachedToMultiBlock() { + return true; + } + + @Override + public MultiblockControllerBase getController() { + return mbt; + } + }; + MetaTileEntityFluidHatch exportFluidBus = new MetaTileEntityFluidHatch(gregtechId("fluid_hatch.export.lv"), 1, true) { + @Override + public boolean isAttachedToMultiBlock() { + return true; + } + + @Override + public MultiblockControllerBase getController() { + return mbt; + } + }; + + //Controller is a private field but we need that information + try { + Field field = MetaTileEntityMultiblockPart.class.getDeclaredField("controllerTile"); + field.setAccessible(true); + field.set(importItemBus, mbt); + field.set(exportItemBus, mbt); + field.set(importFluidBus, mbt); + field.set(exportFluidBus, mbt); + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + } + + MultiblockRecipeLogic mbl = new MultiblockRecipeLogic(mbt) { + + @Override + protected long getEnergyStored() { + return Long.MAX_VALUE; + } + + @Override + protected long getEnergyCapacity() { + return Long.MAX_VALUE; + } + + @Override + protected boolean drawEnergy(int recipeEUt) { + return true; + } + + @Override + protected long getMaxVoltage() { + return 32; + } + // since the hatches were not really added to a valid multiblock structure, + // refer to their inventories directly + @Override + protected IItemHandlerModifiable getInputInventory() { + return importItemBus.getImportItems(); + } + + @Override + protected IItemHandlerModifiable getOutputInventory() { + return exportItemBus.getExportItems(); + } + + @Override + protected IMultipleTankHandler getInputTank() { + return importFluidBus.getImportFluids(); + } + + @Override + protected IMultipleTankHandler getOutputTank() { + return importFluidBus.getExportFluids(); + } + + }; + + mbl.isOutputsFull = false; + mbl.invalidInputsForRecipes = false; + mbl.trySearchNewRecipe(); + + // no recipe found + assertTrue(mbl.invalidInputsForRecipes); + assertFalse(mbl.isActive); + assertNull(mbl.previousRecipe); + + // put an item in the inventory that will trigger recipe recheck + mbl.getInputInventory().insertItem(0, new ItemStack(Blocks.COBBLESTONE, 16), false); + // Inputs change. did we detect it ? + assertTrue(mbt.isInputsDirty()); + mbl.trySearchNewRecipe(); + assertFalse(mbl.invalidInputsForRecipes); + assertNotNull(mbl.previousRecipe); + assertTrue(mbl.isActive); + assertEquals(15, mbl.getInputInventory().getStackInSlot(0).getCount()); + //assert the consumption of the inputs did not mark the arl to look for a new recipe + assertFalse(mbt.isInputsDirty()); + + // Save a reference to the old recipe so we can make sure it's getting reused + Recipe prev = mbl.previousRecipe; + + // Finish the recipe, the output should generate, and the next iteration should begin + mbl.updateWorkable(); + assertEquals(prev, mbl.previousRecipe); + assertTrue(AbstractRecipeLogic.areItemStacksEqual(mbl.getOutputInventory().getStackInSlot(0), + new ItemStack(Blocks.STONE, 1))); + assertTrue(mbl.isActive); + + // Complete the second iteration, but the machine stops because its output is now full + mbl.getOutputInventory().setStackInSlot(0, new ItemStack(Blocks.STONE, 63)); + mbl.getOutputInventory().setStackInSlot(1, new ItemStack(Blocks.STONE, 64)); + mbl.getOutputInventory().setStackInSlot(2, new ItemStack(Blocks.STONE, 64)); + mbl.getOutputInventory().setStackInSlot(3, new ItemStack(Blocks.STONE, 64)); + mbl.updateWorkable(); + assertFalse(mbl.isActive); + assertTrue(mbl.isOutputsFull); + + // Try to process again and get failed out because of full buffer. + mbl.updateWorkable(); + assertFalse(mbl.isActive); + assertTrue(mbl.isOutputsFull); + + // Some room is freed in the output bus, so we can continue now. + mbl.getOutputInventory().setStackInSlot(1, ItemStack.EMPTY); + assertTrue(mbt.isOutputsDirty()); + mbl.updateWorkable(); + assertTrue(mbl.isActive); + assertFalse(mbl.isOutputsFull); + mbl.completeRecipe(); + assertTrue(AbstractRecipeLogic.areItemStacksEqual(mbl.getOutputInventory().getStackInSlot(0), + new ItemStack(Blocks.STONE, 1))); + } +} From ba882eebf0edb25b6347bb77bd42d57dada12c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Wed, 31 Mar 2021 14:55:04 -0300 Subject: [PATCH 07/26] address issues bought up on discussion restored cover field as final deprecated old arrays moved method to protected add java doc for deprecated checkRecipeInputsDirty renamed variables from single to plural for more clarity added instance checks before casting --- .../api/capability/impl/AbstractRecipeLogic.java | 12 +++++++++--- .../impl/NotifiableFilteredFluidHandler.java | 8 ++++---- .../api/capability/impl/NotifiableFluidTank.java | 8 ++++---- .../impl/NotifiableItemStackHandler.java | 8 ++++---- .../api/metatileentity/MetaTileEntity.java | 10 +++++----- .../multiblockpart/MetaTileEntityFluidHatch.java | 1 - .../multiblockpart/MetaTileEntityItemBus.java | 14 +++++++++----- 7 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 51589c448d..4b14d9f0c0 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -36,6 +36,8 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable public final RecipeMap recipeMap; protected boolean forceRecipeRecheck; + @Deprecated protected ItemStack[] lastItemInputs; + @Deprecated protected FluidStack[] lastFluidInputs; protected Recipe previousRecipe; protected boolean allowOverclocking = true; private long overclockVoltage = 0; @@ -124,18 +126,18 @@ public void update() { } } - boolean shouldSearchForRecipes() { + protected boolean shouldSearchForRecipes() { return canWorkWithInputs() && canFitNewOutputs(); } - boolean canFitNewOutputs() { + protected boolean canFitNewOutputs() { // if the output is full check if the output changed so we can process recipes results again. if (this.isOutputsFull && !metaTileEntity.isOutputsDirty()) return false; else { this.isOutputsFull = false; metaTileEntity.setOutputsDirty(false); } return true; } - boolean canWorkWithInputs() { + protected boolean canWorkWithInputs() { // if the inputs were bad last time, check if they've changed before trying to find a new recipe. if (this.invalidInputsForRecipes && !metaTileEntity.isInputsDirty()) return false; else { this.invalidInputsForRecipes = false; } @@ -212,6 +214,10 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul return recipeMap.findRecipe(maxVoltage, inputs, fluidInputs, getMinTankCapacity(getOutputTank())); } + /** + * @deprecated Use {@link MetaTileEntity#isInputsDirty() } instead + * Left here for binary compatibility purposes + */ @Deprecated protected boolean checkRecipeInputsDirty(IItemHandler inputs, IMultipleTankHandler fluidInputs) { return this.getMetaTileEntity().isInputsDirty(); diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java index 6ab8409be0..c44738cc11 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java @@ -7,12 +7,12 @@ public class NotifiableFilteredFluidHandler extends FilteredFluidHandler implements INotifiableHandler { - HashSet entityToSetDirty = new HashSet<>(); + HashSet entitiesToNotify = new HashSet<>(); private final boolean isExport; - public NotifiableFilteredFluidHandler(int capacity, MetaTileEntity entityToSetDirty, boolean isExport) { + public NotifiableFilteredFluidHandler(int capacity, MetaTileEntity entityToNotify, boolean isExport) { super(capacity); - this.entityToSetDirty.add(entityToSetDirty); + this.entitiesToNotify.add(entityToNotify); this.isExport = isExport; } @@ -24,6 +24,6 @@ protected void onContentsChanged() { @Override public HashSet getNotifiableMetaTileEntities() { - return this.entityToSetDirty; + return this.entitiesToNotify; } } diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java index 713bcda71f..4a9adc17dc 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java @@ -8,12 +8,12 @@ public class NotifiableFluidTank extends FluidTank implements INotifiableHandler { - HashSet entityToSetDirty = new HashSet<>(); + HashSet entitiesToNotify = new HashSet<>(); private final boolean isExport; - public NotifiableFluidTank(int capacity, MetaTileEntity entityToSetDirty, boolean isExport) { + public NotifiableFluidTank(int capacity, MetaTileEntity entityToNotify, boolean isExport) { super(capacity); - this.entityToSetDirty.add(entityToSetDirty); + this.entitiesToNotify.add(entityToNotify); this.isExport = isExport; } @@ -25,6 +25,6 @@ protected void onContentsChanged() { @Override public HashSet getNotifiableMetaTileEntities(){ - return this.entityToSetDirty; + return this.entitiesToNotify; } } diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java index 146791afc8..6830838239 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java @@ -9,12 +9,12 @@ public class NotifiableItemStackHandler extends ItemStackHandler implements IItemHandlerModifiable, INotifiableHandler { - HashSet entityToSetDirty = new HashSet<>(); + HashSet entitiesToNotify = new HashSet<>(); private final boolean isExport; - public NotifiableItemStackHandler(int slots, MetaTileEntity entityToSetDirty, boolean isExport) { + public NotifiableItemStackHandler(int slots, MetaTileEntity entityToNotify, boolean isExport) { super(slots); - this.entityToSetDirty.add(entityToSetDirty); + this.entitiesToNotify.add(entityToNotify); this.isExport = isExport; } @@ -26,6 +26,6 @@ public void onContentsChanged(int slot) { @Override public HashSet getNotifiableMetaTileEntities() { - return this.entityToSetDirty; + return this.entitiesToNotify; } } diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index c002d83fdf..f255326b94 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -88,7 +88,7 @@ public abstract class MetaTileEntity implements ICoverable { private int cachedLightValue; protected boolean isFragile = false; - private CoverBehavior[] coverBehaviors = new CoverBehavior[6]; + private final CoverBehavior[] coverBehaviors = new CoverBehavior[6]; protected boolean outputDirty; protected boolean inputDirty; @@ -258,19 +258,19 @@ public final String getMetaFullName() { return getMetaName() + ".name"; } - public final void setInputsDirty(boolean dirty) { + public void setInputsDirty(boolean dirty) { this.inputDirty = dirty; } - public final boolean isInputsDirty() { + public boolean isInputsDirty() { return this.inputDirty; } - public final void setOutputsDirty(boolean dirty) { + public void setOutputsDirty(boolean dirty) { this.outputDirty = dirty; } - public final boolean isOutputsDirty() { + public boolean isOutputsDirty() { return this.outputDirty; } diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java index adfee81f26..f590b054e3 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java @@ -25,7 +25,6 @@ import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; -import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java index cf66336373..96e291455a 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java @@ -91,11 +91,15 @@ public void registerAbilities(List abilityList) { @Override public void addEntityToDirtyableHandlers(MetaTileEntity metaTileEntity) { - NotifiableItemStackHandler handler; - if (isExportHatch) handler = (NotifiableItemStackHandler) getExportItems(); - else handler = (NotifiableItemStackHandler) getImportItems(); - handler.addNotifiableMetaTileEntity(metaTileEntity); - handler.notifyMetaTileEntitiesOfChange(isExportHatch); + NotifiableItemStackHandler handler = null; + if (isExportHatch && getExportItems() instanceof NotifiableItemStackHandler) + handler = (NotifiableItemStackHandler) getExportItems(); + else if (!isExportHatch && getImportItems() instanceof NotifiableItemStackHandler) + handler = (NotifiableItemStackHandler) getImportItems(); + if (handler != null) { + handler.addNotifiableMetaTileEntity(metaTileEntity); + handler.notifyMetaTileEntitiesOfChange(isExportHatch); + } } @Override From 5c8815dc05e5187dc8177963cfd613820bb714db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Wed, 31 Mar 2021 15:23:10 -0300 Subject: [PATCH 08/26] made a declaration more obvious and with more detailed explanation match formatting to the project. --- .../capability/impl/AbstractRecipeLogic.java | 22 +++++++++++++------ .../capability/impl/NotifiableFluidTank.java | 2 +- .../electric/MetaTileEntityMultiFurnace.java | 4 ++-- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 4b14d9f0c0..756dd55411 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -115,7 +115,7 @@ public void update() { updateRecipeProgress(); } //check everything that would make a recipe never start here. - if (progressTime == 0 && shouldSearchForRecipes()){ + if (progressTime == 0 && shouldSearchForRecipes()) { trySearchNewRecipe(); } } @@ -133,14 +133,19 @@ protected boolean shouldSearchForRecipes() { protected boolean canFitNewOutputs() { // if the output is full check if the output changed so we can process recipes results again. if (this.isOutputsFull && !metaTileEntity.isOutputsDirty()) return false; - else { this.isOutputsFull = false; metaTileEntity.setOutputsDirty(false); } + else { + this.isOutputsFull = false; + metaTileEntity.setOutputsDirty(false); + } return true; } protected boolean canWorkWithInputs() { // if the inputs were bad last time, check if they've changed before trying to find a new recipe. if (this.invalidInputsForRecipes && !metaTileEntity.isInputsDirty()) return false; - else { this.invalidInputsForRecipes = false; } + else { + this.invalidInputsForRecipes = false; + } return true; } @@ -181,11 +186,14 @@ protected void trySearchNewRecipe() { currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); } // If a recipe was found, then inputs were valid. - // recipe multiplying machines may not be able to fit - // the multiplied recipes. in that case the inputs are valid - if (!(this.invalidInputsForRecipes = (currentRecipe == null && !this.isOutputsFull))) - // replace old recipe with new one + if (currentRecipe != null) { + this.invalidInputsForRecipes = false; this.previousRecipe = currentRecipe; + // Add-ons may Override findRecipe method but not trySearchNewRecipe, in that case + // they may return a null recipe. Since we only check for items and fluid here, having + // findRecipe return a null recipe with isOutputsFull being true, means we have a valid + // recipe in the input waiting for space in the output. + } else this.invalidInputsForRecipes = !this.isOutputsFull; // proceed if we have a usable recipe. if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java index 4a9adc17dc..f62b41b240 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java @@ -24,7 +24,7 @@ protected void onContentsChanged() { } @Override - public HashSet getNotifiableMetaTileEntities(){ + public HashSet getNotifiableMetaTileEntities() { return this.entitiesToNotify; } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index ce492c2a94..1a931e62f3 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -117,7 +117,7 @@ protected void trySearchNewRecipe() { //if previous recipe still matches inputs, try to use it currentRecipe = previousRecipe; } - if ( currentRecipe != null) + if (currentRecipe != null) // replace old recipe with new one this.previousRecipe = currentRecipe; @@ -206,7 +206,7 @@ protected Recipe findRecipe(long maxVoltage, // If there were no accepted ingredients, then there is no recipe to process. // the output may be filled up - if(recipeInputs.isEmpty() && !invalidInputsForRecipes) { + if (recipeInputs.isEmpty() && !invalidInputsForRecipes) { //Set here to prevent recipe deadlock on world load with full output bus this.isOutputsFull = true; return null; From 281cabccc62af84e54ead0352dac4519b180f1ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Wed, 31 Mar 2021 15:52:23 -0300 Subject: [PATCH 09/26] reverted change due to NPE --- .../multi/electric/MetaTileEntityMultiFurnace.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index 1a931e62f3..095dbebf94 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -104,6 +104,7 @@ protected void trySearchNewRecipe() { long maxVoltage = getMaxVoltage(); Recipe currentRecipe = null; IItemHandlerModifiable importInventory = getInputInventory(); + IMultipleTankHandler importFluids = getInputTank(); //inverse of logic in normal AbstractRecipeLogic //for MultiSmelter, we can reuse previous recipe if inputs didn't change @@ -112,8 +113,8 @@ protected void trySearchNewRecipe() { if (metaTileEntity.isInputsDirty()) { metaTileEntity.setInputsDirty(false); //Inputs changed, try searching new recipe for given inputs - currentRecipe = findRecipe(maxVoltage, importInventory, null); - } else if (previousRecipe != null && previousRecipe.matches(false, importInventory, null)) { + currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); + } else if (previousRecipe != null && previousRecipe.matches(false, importInventory, importFluids)) { //if previous recipe still matches inputs, try to use it currentRecipe = previousRecipe; } From d2a0a7d7ecacb98e2b7d95ff55ff484454a90a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Fri, 2 Apr 2021 08:08:42 -0300 Subject: [PATCH 10/26] fix multismelter getting stuck when its output gets full --- .../multi/electric/MetaTileEntityMultiFurnace.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index 095dbebf94..6207e4de6f 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -117,6 +117,9 @@ protected void trySearchNewRecipe() { } else if (previousRecipe != null && previousRecipe.matches(false, importInventory, importFluids)) { //if previous recipe still matches inputs, try to use it currentRecipe = previousRecipe; + } else { + metaTileEntity.setInputsDirty(false); + currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); } if (currentRecipe != null) // replace old recipe with new one From 268a9387b1e04f9f4493d35f2c6626b4d2ef14b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Fri, 2 Apr 2021 11:46:18 -0300 Subject: [PATCH 11/26] switched from HashSet to ArrayList. --- .../api/capability/INotifiableHandler.java | 14 +++++++------- .../impl/NotifiableFilteredFluidHandler.java | 7 ++++--- .../api/capability/impl/NotifiableFluidTank.java | 7 ++++--- .../impl/NotifiableItemStackHandler.java | 7 ++++--- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/java/gregtech/api/capability/INotifiableHandler.java b/src/main/java/gregtech/api/capability/INotifiableHandler.java index 401c081bc3..9cea3f4cd2 100644 --- a/src/main/java/gregtech/api/capability/INotifiableHandler.java +++ b/src/main/java/gregtech/api/capability/INotifiableHandler.java @@ -2,8 +2,8 @@ import gregtech.api.metatileentity.MetaTileEntity; -import java.util.HashSet; import java.util.Iterator; +import java.util.List; /** * For Item and Fluid handlers capable of notifying entities when @@ -20,10 +20,10 @@ public interface INotifiableHandler { default void notifyMetaTileEntitiesOfChange(boolean isExport) { Iterator iterator = getNotifiableMetaTileEntities().iterator(); while (iterator.hasNext()) { - MetaTileEntity mte = iterator.next(); - if (mte != null && mte.isValid()) { - if (isExport) mte.setOutputsDirty(true); - else mte.setInputsDirty(true); + MetaTileEntity metaTileEntity = iterator.next(); + if (metaTileEntity != null && metaTileEntity.isValid()) { + if (isExport) metaTileEntity.setOutputsDirty(true); + else metaTileEntity.setInputsDirty(true); } else { iterator.remove(); } @@ -31,10 +31,10 @@ default void notifyMetaTileEntitiesOfChange(boolean isExport) { } /** - * returns a HashSet containing the notifiable MetaTileEntities + * returns a List containing the notifiable MetaTileEntities * @return */ - HashSet getNotifiableMetaTileEntities(); + List getNotifiableMetaTileEntities(); /** * diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java index c44738cc11..6554b4da20 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java @@ -3,11 +3,12 @@ import gregtech.api.capability.INotifiableHandler; import gregtech.api.metatileentity.MetaTileEntity; -import java.util.HashSet; +import java.util.ArrayList; +import java.util.List; public class NotifiableFilteredFluidHandler extends FilteredFluidHandler implements INotifiableHandler { - HashSet entitiesToNotify = new HashSet<>(); + List entitiesToNotify = new ArrayList<>(); private final boolean isExport; public NotifiableFilteredFluidHandler(int capacity, MetaTileEntity entityToNotify, boolean isExport) { @@ -23,7 +24,7 @@ protected void onContentsChanged() { } @Override - public HashSet getNotifiableMetaTileEntities() { + public List getNotifiableMetaTileEntities() { return this.entitiesToNotify; } } diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java index f62b41b240..764e91b057 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java @@ -4,11 +4,12 @@ import gregtech.api.metatileentity.MetaTileEntity; import net.minecraftforge.fluids.FluidTank; -import java.util.HashSet; +import java.util.ArrayList; +import java.util.List; public class NotifiableFluidTank extends FluidTank implements INotifiableHandler { - HashSet entitiesToNotify = new HashSet<>(); + List entitiesToNotify = new ArrayList<>(); private final boolean isExport; public NotifiableFluidTank(int capacity, MetaTileEntity entityToNotify, boolean isExport) { @@ -24,7 +25,7 @@ protected void onContentsChanged() { } @Override - public HashSet getNotifiableMetaTileEntities() { + public List getNotifiableMetaTileEntities() { return this.entitiesToNotify; } } diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java index 6830838239..12e72eba9e 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java @@ -5,11 +5,12 @@ import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; -import java.util.HashSet; +import java.util.ArrayList; +import java.util.List; public class NotifiableItemStackHandler extends ItemStackHandler implements IItemHandlerModifiable, INotifiableHandler { - HashSet entitiesToNotify = new HashSet<>(); + List entitiesToNotify = new ArrayList<>(); private final boolean isExport; public NotifiableItemStackHandler(int slots, MetaTileEntity entityToNotify, boolean isExport) { @@ -25,7 +26,7 @@ public void onContentsChanged(int slot) { } @Override - public HashSet getNotifiableMetaTileEntities() { + public List getNotifiableMetaTileEntities() { return this.entitiesToNotify; } } From 3b6cd4c368edf16cac9a6e6f55096f222214778e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Thu, 8 Apr 2021 23:56:58 -0300 Subject: [PATCH 12/26] switch to a linked list reformatted javadoc re-based --- .../java/gregtech/api/capability/INotifiableHandler.java | 9 ++++----- .../capability/impl/NotifiableFilteredFluidHandler.java | 7 +++---- .../api/capability/impl/NotifiableFluidTank.java | 7 +++---- .../api/capability/impl/NotifiableItemStackHandler.java | 7 +++---- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/main/java/gregtech/api/capability/INotifiableHandler.java b/src/main/java/gregtech/api/capability/INotifiableHandler.java index 9cea3f4cd2..c746fdeaa2 100644 --- a/src/main/java/gregtech/api/capability/INotifiableHandler.java +++ b/src/main/java/gregtech/api/capability/INotifiableHandler.java @@ -3,7 +3,7 @@ import gregtech.api.metatileentity.MetaTileEntity; import java.util.Iterator; -import java.util.List; +import java.util.LinkedList; /** * For Item and Fluid handlers capable of notifying entities when @@ -14,6 +14,7 @@ public interface INotifiableHandler { /** * Notifies the entities of the changes in their inventories * An iterator is used to remove invalid TileEntities + * * @param isExport boolean specifying if a handler is an output handler */ @@ -31,13 +32,11 @@ default void notifyMetaTileEntitiesOfChange(boolean isExport) { } /** - * returns a List containing the notifiable MetaTileEntities - * @return + * @return a List containing the notifiable MetaTileEntities */ - List getNotifiableMetaTileEntities(); + LinkedList getNotifiableMetaTileEntities(); /** - * * @param metaTileEntity MetaTileEntity to be notified */ default void addNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java index 6554b4da20..b3aa0dbd6c 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java @@ -3,12 +3,11 @@ import gregtech.api.capability.INotifiableHandler; import gregtech.api.metatileentity.MetaTileEntity; -import java.util.ArrayList; -import java.util.List; +import java.util.LinkedList; public class NotifiableFilteredFluidHandler extends FilteredFluidHandler implements INotifiableHandler { - List entitiesToNotify = new ArrayList<>(); + LinkedList entitiesToNotify = new LinkedList<>(); private final boolean isExport; public NotifiableFilteredFluidHandler(int capacity, MetaTileEntity entityToNotify, boolean isExport) { @@ -24,7 +23,7 @@ protected void onContentsChanged() { } @Override - public List getNotifiableMetaTileEntities() { + public LinkedList getNotifiableMetaTileEntities() { return this.entitiesToNotify; } } diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java index 764e91b057..d0c3081b5c 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java @@ -4,12 +4,11 @@ import gregtech.api.metatileentity.MetaTileEntity; import net.minecraftforge.fluids.FluidTank; -import java.util.ArrayList; -import java.util.List; +import java.util.LinkedList; public class NotifiableFluidTank extends FluidTank implements INotifiableHandler { - List entitiesToNotify = new ArrayList<>(); + LinkedList entitiesToNotify = new LinkedList<>(); private final boolean isExport; public NotifiableFluidTank(int capacity, MetaTileEntity entityToNotify, boolean isExport) { @@ -25,7 +24,7 @@ protected void onContentsChanged() { } @Override - public List getNotifiableMetaTileEntities() { + public LinkedList getNotifiableMetaTileEntities() { return this.entitiesToNotify; } } diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java index 12e72eba9e..22186c706c 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java @@ -5,12 +5,11 @@ import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; -import java.util.ArrayList; -import java.util.List; +import java.util.LinkedList; public class NotifiableItemStackHandler extends ItemStackHandler implements IItemHandlerModifiable, INotifiableHandler { - List entitiesToNotify = new ArrayList<>(); + LinkedList entitiesToNotify = new LinkedList<>(); private final boolean isExport; public NotifiableItemStackHandler(int slots, MetaTileEntity entityToNotify, boolean isExport) { @@ -26,7 +25,7 @@ public void onContentsChanged(int slot) { } @Override - public List getNotifiableMetaTileEntities() { + public LinkedList getNotifiableMetaTileEntities() { return this.entitiesToNotify; } } From 279dd31511e40f3e0dcb3b7b42ce6cedb6c9269f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Sun, 11 Apr 2021 10:50:02 -0300 Subject: [PATCH 13/26] Simplified handler logic by only allowing one metatile to be notified --- .../api/capability/INotifiableHandler.java | 26 +++++-------------- .../impl/NotifiableFilteredFluidHandler.java | 12 ++++----- .../capability/impl/NotifiableFluidTank.java | 12 ++++----- .../impl/NotifiableItemStackHandler.java | 12 ++++----- .../multiblock/IMultiblockPart.java | 2 +- .../multiblock/MultiblockControllerBase.java | 2 +- .../multiblockpart/MetaTileEntityItemBus.java | 6 ++--- 7 files changed, 26 insertions(+), 46 deletions(-) diff --git a/src/main/java/gregtech/api/capability/INotifiableHandler.java b/src/main/java/gregtech/api/capability/INotifiableHandler.java index c746fdeaa2..9ffcc15016 100644 --- a/src/main/java/gregtech/api/capability/INotifiableHandler.java +++ b/src/main/java/gregtech/api/capability/INotifiableHandler.java @@ -2,9 +2,6 @@ import gregtech.api.metatileentity.MetaTileEntity; -import java.util.Iterator; -import java.util.LinkedList; - /** * For Item and Fluid handlers capable of notifying entities when * their contents change @@ -18,28 +15,17 @@ public interface INotifiableHandler { * @param isExport boolean specifying if a handler is an output handler */ - default void notifyMetaTileEntitiesOfChange(boolean isExport) { - Iterator iterator = getNotifiableMetaTileEntities().iterator(); - while (iterator.hasNext()) { - MetaTileEntity metaTileEntity = iterator.next(); - if (metaTileEntity != null && metaTileEntity.isValid()) { - if (isExport) metaTileEntity.setOutputsDirty(true); - else metaTileEntity.setInputsDirty(true); - } else { - iterator.remove(); - } + default void notifyMetaTileEntityOfChange(MetaTileEntity metaTileEntity, boolean isExport) { + if (metaTileEntity != null && metaTileEntity.isValid()) { + if (isExport) metaTileEntity.setOutputsDirty(true); + else metaTileEntity.setInputsDirty(true); } } - /** - * @return a List containing the notifiable MetaTileEntities - */ - LinkedList getNotifiableMetaTileEntities(); - /** * @param metaTileEntity MetaTileEntity to be notified */ - default void addNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { - getNotifiableMetaTileEntities().add(metaTileEntity); + default void setNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + } } diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java index b3aa0dbd6c..b6d967ea68 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java @@ -3,27 +3,25 @@ import gregtech.api.capability.INotifiableHandler; import gregtech.api.metatileentity.MetaTileEntity; -import java.util.LinkedList; - public class NotifiableFilteredFluidHandler extends FilteredFluidHandler implements INotifiableHandler { - LinkedList entitiesToNotify = new LinkedList<>(); + MetaTileEntity notifiableEntity; private final boolean isExport; public NotifiableFilteredFluidHandler(int capacity, MetaTileEntity entityToNotify, boolean isExport) { super(capacity); - this.entitiesToNotify.add(entityToNotify); + this.notifiableEntity = entityToNotify; this.isExport = isExport; } @Override protected void onContentsChanged() { super.onContentsChanged(); - notifyMetaTileEntitiesOfChange(isExport); + notifyMetaTileEntityOfChange(notifiableEntity, isExport); } @Override - public LinkedList getNotifiableMetaTileEntities() { - return this.entitiesToNotify; + public void setNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + this.notifiableEntity = metaTileEntity; } } diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java index d0c3081b5c..e99ce3a16c 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java @@ -4,27 +4,25 @@ import gregtech.api.metatileentity.MetaTileEntity; import net.minecraftforge.fluids.FluidTank; -import java.util.LinkedList; - public class NotifiableFluidTank extends FluidTank implements INotifiableHandler { - LinkedList entitiesToNotify = new LinkedList<>(); + MetaTileEntity notifiableEntity; private final boolean isExport; public NotifiableFluidTank(int capacity, MetaTileEntity entityToNotify, boolean isExport) { super(capacity); - this.entitiesToNotify.add(entityToNotify); + this.notifiableEntity = entityToNotify; this.isExport = isExport; } @Override protected void onContentsChanged() { super.onContentsChanged(); - notifyMetaTileEntitiesOfChange(isExport); + notifyMetaTileEntityOfChange(notifiableEntity, isExport); } @Override - public LinkedList getNotifiableMetaTileEntities() { - return this.entitiesToNotify; + public void setNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + this.notifiableEntity = metaTileEntity; } } diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java index 22186c706c..17c1df963c 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java @@ -5,27 +5,25 @@ import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; -import java.util.LinkedList; - public class NotifiableItemStackHandler extends ItemStackHandler implements IItemHandlerModifiable, INotifiableHandler { - LinkedList entitiesToNotify = new LinkedList<>(); + MetaTileEntity notifiableEntity; private final boolean isExport; public NotifiableItemStackHandler(int slots, MetaTileEntity entityToNotify, boolean isExport) { super(slots); - this.entitiesToNotify.add(entityToNotify); + this.notifiableEntity = entityToNotify; this.isExport = isExport; } @Override public void onContentsChanged(int slot) { super.onContentsChanged(slot); - notifyMetaTileEntitiesOfChange(isExport); + notifyMetaTileEntityOfChange(notifiableEntity, isExport); } @Override - public LinkedList getNotifiableMetaTileEntities() { - return this.entitiesToNotify; + public void setNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + this.notifiableEntity = metaTileEntity; } } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java b/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java index 924bb52f6e..6c33c7a4ad 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java @@ -10,7 +10,7 @@ public interface IMultiblockPart { void removeFromMultiBlock(MultiblockControllerBase controllerBase); - default void addEntityToDirtyableHandlers(MetaTileEntity metaTileEntity) { + default void setupNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { } } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java index c4b7c879dc..ef6d75300c 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java @@ -184,7 +184,7 @@ protected void checkStructurePattern() { } if (checkStructureComponents(parts, abilities)) { parts.forEach(part -> part.addToMultiBlock(this)); - parts.forEach(part -> part.addEntityToDirtyableHandlers(this)); + parts.forEach(part -> part.setupNotifiableMetaTileEntity(this)); this.multiblockParts.addAll(parts); this.multiblockAbilities.putAll(abilities); this.structureFormed = true; diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java index 96e291455a..310a250f43 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java @@ -90,15 +90,15 @@ public void registerAbilities(List abilityList) { } @Override - public void addEntityToDirtyableHandlers(MetaTileEntity metaTileEntity) { + public void setupNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { NotifiableItemStackHandler handler = null; if (isExportHatch && getExportItems() instanceof NotifiableItemStackHandler) handler = (NotifiableItemStackHandler) getExportItems(); else if (!isExportHatch && getImportItems() instanceof NotifiableItemStackHandler) handler = (NotifiableItemStackHandler) getImportItems(); if (handler != null) { - handler.addNotifiableMetaTileEntity(metaTileEntity); - handler.notifyMetaTileEntitiesOfChange(isExportHatch); + handler.setNotifiableMetaTileEntity(metaTileEntity); + handler.notifyMetaTileEntityOfChange(this, isExportHatch); } } From e63495148772e2246dc2f248aa99bc364f84097a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Tue, 25 May 2021 15:04:31 -0300 Subject: [PATCH 14/26] address issues brought up --- .../capability/impl/AbstractRecipeLogic.java | 10 ++++------ .../electric/MetaTileEntityMultiFurnace.java | 19 +++++++------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 756dd55411..34455965a7 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -109,7 +109,7 @@ public T getCapability(Capability capability) { @Override public void update() { World world = getMetaTileEntity().getWorld(); - if (world == null || !world.isRemote) { + if (world != null && !world.isRemote) { if (workingEnabled) { if (progressTime > 0) { updateRecipeProgress(); @@ -182,7 +182,6 @@ protected void trySearchNewRecipe() { currentRecipe = this.previousRecipe; // If there is no active recipe, then we need to find one. else { - metaTileEntity.setInputsDirty(false); currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); } // If a recipe was found, then inputs were valid. @@ -196,11 +195,10 @@ protected void trySearchNewRecipe() { } else this.invalidInputsForRecipes = !this.isOutputsFull; // proceed if we have a usable recipe. - if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) setupRecipe(currentRecipe); - //avoid new recipe lookup caused by item consumption from input - metaTileEntity.setInputsDirty(false); - } + // Inputs have been inspected. + metaTileEntity.setInputsDirty(false); } public void forceRecipeRecheck() { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index 6207e4de6f..291ff6c8f0 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -110,30 +110,25 @@ protected void trySearchNewRecipe() { //for MultiSmelter, we can reuse previous recipe if inputs didn't change //otherwise, we need to recompute it for new ingredients //but technically, it means we can cache multi smelter recipe, but changing inputs have more priority - if (metaTileEntity.isInputsDirty()) { - metaTileEntity.setInputsDirty(false); + if (metaTileEntity.isInputsDirty() || + previousRecipe == null || + !previousRecipe.matches(false,importInventory,importFluids)) { //Inputs changed, try searching new recipe for given inputs currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); - } else if (previousRecipe != null && previousRecipe.matches(false, importInventory, importFluids)) { + } else { //if previous recipe still matches inputs, try to use it currentRecipe = previousRecipe; - } else { - metaTileEntity.setInputsDirty(false); - currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); } if (currentRecipe != null) // replace old recipe with new one this.previousRecipe = currentRecipe; - // proceed if we have a usable recipe. - if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) setupRecipe(currentRecipe); - //avoid new recipe lookup caused by item consumption from input - metaTileEntity.setInputsDirty(false); - } + // Inputs have been inspected. + metaTileEntity.setInputsDirty(false); } - @Override protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, From 8d04e7654dbf434232d373e30350056a18370a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Thu, 25 Mar 2021 18:33:01 -0300 Subject: [PATCH 15/26] Revert "Changed item merging from full inventory copy to partial stacks copy" This reverts commit f05c19308c188138228257728e6fda14c91170dc. --- .../api/metatileentity/MetaTileEntity.java | 13 ++++--------- .../java/gregtech/api/util/InventoryUtils.java | 17 +---------------- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index f255326b94..c7110af926 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -22,7 +22,6 @@ import gregtech.api.render.Textures; import gregtech.api.util.GTFluidUtils; import gregtech.api.util.GTUtility; -import gregtech.api.util.InventoryUtils; import net.minecraft.block.Block; import net.minecraft.block.state.BlockFaceShape; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -57,6 +56,8 @@ import java.util.List; import java.util.function.Consumer; +import static gregtech.api.util.InventoryUtils.simulateItemStackMerge; + public abstract class MetaTileEntity implements ICoverable { public static final int DEFAULT_PAINTING_COLOR = 0xFFFFFF; @@ -990,14 +991,8 @@ public static boolean addItemsToItemHandler(final IItemHandler handler, final boolean simulate, final List items) { // determine if there is sufficient room to insert all items into the target inventory - boolean canMerge; - if (items.size() == 1) { - canMerge = ItemHandlerHelper.insertItemStacked(handler, items.get(0), true).isEmpty(); - } else { - // merging 2 or more stacks may change the slots available for merging, - // needing full simulation of the state of the inventory after every merge - canMerge = InventoryUtils.simulateItemStackMerge(items, handler); - } + final boolean canMerge = simulateItemStackMerge(items, handler); + // if we're not simulating and the merge should succeed, perform the merge. if (!simulate && canMerge) items.forEach(stack -> { diff --git a/src/main/java/gregtech/api/util/InventoryUtils.java b/src/main/java/gregtech/api/util/InventoryUtils.java index 5697d952f1..9102e89b6c 100755 --- a/src/main/java/gregtech/api/util/InventoryUtils.java +++ b/src/main/java/gregtech/api/util/InventoryUtils.java @@ -43,21 +43,6 @@ public static List deepCopy(final IItemHandler inventory, .collect(Collectors.toList()); } - /** - * Creates a copy of the partial stacks in target inventory - * - * @param inventory the target inventory - * @return a copy of the partial stacks of the inventory. - */ - public static List copyPartialStacks(final IItemHandler inventory) { - - return streamFrom(inventory) - .filter(not(ItemStack::isEmpty)) - .filter(not(itemStack -> itemStack.getCount() == itemStack.getMaxStackSize())) - .map(ItemStack::copy) - .collect(Collectors.toList()); - } - /** * Determines whether all specified items will fit into a target inventory by * simulating merging like items into existing stacks, then checking if there @@ -90,7 +75,7 @@ public static boolean simulateItemStackMerge(List inputItems, itemStacks.sort(Comparator.comparingInt(ItemStack::getCount)); // Deep copy the contents of the target inventory, skipping empty stacks - final List inventoryStacks = copyPartialStacks(inventory); + final List inventoryStacks = deepCopy(inventory, false); // Perform a merge of the ItemStacks mergeItemStacks(itemStacks, inventoryStacks); From 063a3e5db5d8dc16e6dfb1ee3f94b59793bdc44b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Fri, 28 May 2021 21:41:21 -0300 Subject: [PATCH 16/26] pass handlers around instead of a boolean --- .../api/capability/INotifiableHandler.java | 6 +- .../capability/impl/AbstractRecipeLogic.java | 26 +++++-- .../impl/MultiblockRecipeLogic.java | 12 ++++ .../impl/NotifiableFilteredFluidHandler.java | 2 +- .../capability/impl/NotifiableFluidTank.java | 2 +- .../impl/NotifiableItemStackHandler.java | 2 +- .../api/metatileentity/MetaTileEntity.java | 68 +++++++++++++++---- .../multiblockpart/MetaTileEntityItemBus.java | 2 +- .../electric/MetaTileEntityMultiFurnace.java | 5 +- 9 files changed, 94 insertions(+), 31 deletions(-) diff --git a/src/main/java/gregtech/api/capability/INotifiableHandler.java b/src/main/java/gregtech/api/capability/INotifiableHandler.java index 9ffcc15016..3fa6a7783f 100644 --- a/src/main/java/gregtech/api/capability/INotifiableHandler.java +++ b/src/main/java/gregtech/api/capability/INotifiableHandler.java @@ -15,10 +15,10 @@ public interface INotifiableHandler { * @param isExport boolean specifying if a handler is an output handler */ - default void notifyMetaTileEntityOfChange(MetaTileEntity metaTileEntity, boolean isExport) { + default void addToNotifiedList(MetaTileEntity metaTileEntity, T handler, boolean isExport) { if (metaTileEntity != null && metaTileEntity.isValid()) { - if (isExport) metaTileEntity.setOutputsDirty(true); - else metaTileEntity.setInputsDirty(true); + if (isExport) metaTileEntity.addNotifiedOutput(handler); + else metaTileEntity.addNotifiedInput(handler); } } diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 34455965a7..6b61f4fafb 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -130,19 +130,30 @@ protected boolean shouldSearchForRecipes() { return canWorkWithInputs() && canFitNewOutputs(); } + protected boolean hasNotifiedInputs() { + return (metaTileEntity.getNotifiedItemInputList().size() > 0 || + metaTileEntity.getNotifiedFluidInputList().size() > 0); + } + + protected boolean hasNotifiedOutputs() { + return (metaTileEntity.getNotifiedItemOutputList().size() > 0 || + metaTileEntity.getNotifiedFluidOutputList().size() > 0); + } + protected boolean canFitNewOutputs() { // if the output is full check if the output changed so we can process recipes results again. - if (this.isOutputsFull && !metaTileEntity.isOutputsDirty()) return false; + if (this.isOutputsFull && !hasNotifiedOutputs()) return false; else { this.isOutputsFull = false; - metaTileEntity.setOutputsDirty(false); + metaTileEntity.removeNotifiedOutput(getOutputInventory()); + metaTileEntity.removeNotifiedOutput(getOutputTank()); } return true; } protected boolean canWorkWithInputs() { // if the inputs were bad last time, check if they've changed before trying to find a new recipe. - if (this.invalidInputsForRecipes && !metaTileEntity.isInputsDirty()) return false; + if (this.invalidInputsForRecipes && !hasNotifiedInputs()) return false; else { this.invalidInputsForRecipes = false; } @@ -198,7 +209,8 @@ protected void trySearchNewRecipe() { if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) setupRecipe(currentRecipe); // Inputs have been inspected. - metaTileEntity.setInputsDirty(false); + metaTileEntity.removeNotifiedInput(importInventory); + metaTileEntity.removeNotifiedInput(importFluids); } public void forceRecipeRecheck() { @@ -221,12 +233,12 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul } /** - * @deprecated Use {@link MetaTileEntity#isInputsDirty() } instead + * @deprecated Use {@link #hasNotifiedInputs() } instead * Left here for binary compatibility purposes */ @Deprecated protected boolean checkRecipeInputsDirty(IItemHandler inputs, IMultipleTankHandler fluidInputs) { - return this.getMetaTileEntity().isInputsDirty(); + return this.hasNotifiedInputs(); } protected static boolean areItemStacksEqual(ItemStack stackA, ItemStack stackB) { @@ -369,7 +381,7 @@ protected void setActive(boolean active) { this.isActive = active; metaTileEntity.markDirty(); World world = metaTileEntity.getWorld(); - if (world != null && world.isRemote) { + if (world != null && !world.isRemote) { writeCustomData(1, buf -> buf.writeBoolean(active)); } } diff --git a/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java index d57e7ad67b..1e5a8de3b6 100644 --- a/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java @@ -60,6 +60,18 @@ protected boolean setupAndConsumeRecipeInputs(Recipe recipe) { } else return false; } + @Override + protected boolean hasNotifiedInputs() { + return (metaTileEntity.getNotifiedItemInputList().size() > 0 || + metaTileEntity.getNotifiedFluidInputList().size() > 0); + } + + @Override + protected boolean hasNotifiedOutputs() { + return (metaTileEntity.getNotifiedItemOutputList().size() > 0 || + metaTileEntity.getNotifiedFluidOutputList().size() > 0); + } + @Override protected long getEnergyStored() { return getEnergyContainer().getEnergyStored(); diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java index b6d967ea68..7e5d3ab455 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java @@ -17,7 +17,7 @@ public NotifiableFilteredFluidHandler(int capacity, MetaTileEntity entityToNotif @Override protected void onContentsChanged() { super.onContentsChanged(); - notifyMetaTileEntityOfChange(notifiableEntity, isExport); + addToNotifiedList(notifiableEntity, this, isExport); } @Override diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java index e99ce3a16c..2c54e096db 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java @@ -18,7 +18,7 @@ public NotifiableFluidTank(int capacity, MetaTileEntity entityToNotify, boolean @Override protected void onContentsChanged() { super.onContentsChanged(); - notifyMetaTileEntityOfChange(notifiableEntity, isExport); + addToNotifiedList(notifiableEntity, this, isExport); } @Override diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java index 17c1df963c..88e3c58e07 100644 --- a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java +++ b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java @@ -19,7 +19,7 @@ public NotifiableItemStackHandler(int slots, MetaTileEntity entityToNotify, bool @Override public void onContentsChanged(int slot) { super.onContentsChanged(slot); - notifyMetaTileEntityOfChange(notifiableEntity, isExport); + addToNotifiedList(notifiableEntity, this, isExport); } @Override diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index c7110af926..1ab49a3c02 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -12,9 +12,7 @@ import gregtech.api.GregTechAPI; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IEnergyContainer; -import gregtech.api.capability.impl.FluidHandlerProxy; -import gregtech.api.capability.impl.FluidTankList; -import gregtech.api.capability.impl.ItemHandlerProxy; +import gregtech.api.capability.impl.*; import gregtech.api.cover.CoverBehavior; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.ICoverable; @@ -42,6 +40,7 @@ import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.fluids.FluidActionResult; import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -52,8 +51,7 @@ import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import java.util.function.Consumer; import static gregtech.api.util.InventoryUtils.simulateItemStackMerge; @@ -90,8 +88,10 @@ public abstract class MetaTileEntity implements ICoverable { protected boolean isFragile = false; private final CoverBehavior[] coverBehaviors = new CoverBehavior[6]; - protected boolean outputDirty; - protected boolean inputDirty; + protected List notifiedItemOutputList = new ArrayList<>(); + protected List notifiedItemInputList = new ArrayList<>(); + protected List notifiedFluidInputList = new ArrayList<>(); + protected List notifiedFluidOutputList = new ArrayList<>(); public MetaTileEntity(ResourceLocation metaTileEntityId) { this.metaTileEntityId = metaTileEntityId; @@ -259,20 +259,42 @@ public final String getMetaFullName() { return getMetaName() + ".name"; } - public void setInputsDirty(boolean dirty) { - this.inputDirty = dirty; + public void addNotifiedInput (T input) { + if (input instanceof IItemHandlerModifiable) { + if (!notifiedItemInputList.contains(input)) { + this.notifiedItemInputList.add((IItemHandlerModifiable) input); + } + } else if (input instanceof FluidTank) { + if (!notifiedFluidInputList.contains(input)) { + this.notifiedFluidInputList.add((FluidTank) input); + } + } } - public boolean isInputsDirty() { - return this.inputDirty; + public void addNotifiedOutput (T output) { + if (output instanceof IItemHandlerModifiable) { + if (!notifiedItemOutputList.contains(output)) { + this.notifiedItemOutputList.add((IItemHandlerModifiable) output); + } + } else if (output instanceof NotifiableFluidTank) { + if (!notifiedFluidOutputList.contains(output)) { + this.notifiedFluidOutputList.add((NotifiableFluidTank) output); + } + } } - public void setOutputsDirty(boolean dirty) { - this.outputDirty = dirty; + public void removeNotifiedInput (T input) { + if (input instanceof IItemHandlerModifiable) + this.notifiedItemInputList.remove(input); + else if (input instanceof FluidTank) + this.notifiedFluidInputList.remove(input); } - public boolean isOutputsDirty() { - return this.outputDirty; + public void removeNotifiedOutput (T input) { + if (input instanceof IItemHandlerModifiable) + this.notifiedItemOutputList.remove(input); + else if (input instanceof FluidTank) + this.notifiedFluidOutputList.remove(input); } /** @@ -1231,6 +1253,22 @@ public FluidTankList getExportFluids() { return exportFluids; } + public List getNotifiedItemOutputList() { + return notifiedItemOutputList; + } + + public List getNotifiedItemInputList() { + return notifiedItemInputList; + } + + public List getNotifiedFluidInputList() { + return notifiedFluidInputList; + } + + public List getNotifiedFluidOutputList() { + return notifiedFluidOutputList; + } + public boolean isFragile() { return isFragile; } diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java index 310a250f43..85243139e9 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java @@ -98,7 +98,7 @@ else if (!isExportHatch && getImportItems() instanceof NotifiableItemStackHandle handler = (NotifiableItemStackHandler) getImportItems(); if (handler != null) { handler.setNotifiableMetaTileEntity(metaTileEntity); - handler.notifyMetaTileEntityOfChange(this, isExportHatch); + handler.addToNotifiedList(this, handler, isExportHatch); } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index 291ff6c8f0..e1198d9fab 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -110,7 +110,7 @@ protected void trySearchNewRecipe() { //for MultiSmelter, we can reuse previous recipe if inputs didn't change //otherwise, we need to recompute it for new ingredients //but technically, it means we can cache multi smelter recipe, but changing inputs have more priority - if (metaTileEntity.isInputsDirty() || + if (hasNotifiedInputs() || previousRecipe == null || !previousRecipe.matches(false,importInventory,importFluids)) { //Inputs changed, try searching new recipe for given inputs @@ -126,7 +126,8 @@ protected void trySearchNewRecipe() { if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) setupRecipe(currentRecipe); // Inputs have been inspected. - metaTileEntity.setInputsDirty(false); + metaTileEntity.getNotifiedItemInputList().clear(); + metaTileEntity.getNotifiedFluidOutputList().clear(); } @Override From 84a29ae06d37986e9ce0bd0ca88aaf1860e7f652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Fri, 28 May 2021 21:41:40 -0300 Subject: [PATCH 17/26] fix tests due to world being null --- .../api/capability/impl/AbstractRecipeLogicTest.java | 10 ++++++++-- .../capability/impl/MultiblockRecipeLogicTest.java | 12 +++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java b/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java index 8bf9948673..0fe2710c64 100644 --- a/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java +++ b/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java @@ -5,9 +5,12 @@ import gregtech.api.recipes.*; import gregtech.api.recipes.builders.*; import gregtech.api.render.*; +import gregtech.api.util.world.DummyWorld; import net.minecraft.init.*; import net.minecraft.item.*; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.*; +import net.minecraft.world.World; import org.junit.*; import static org.junit.Assert.*; @@ -22,6 +25,8 @@ public static void init() { @Test public void trySearchNewRecipe() { + World world = DummyWorld.INSTANCE; + // Create an empty recipe map to work with RecipeMap map = new RecipeMap<>("chemical_reactor", 0, @@ -43,6 +48,7 @@ public void trySearchNewRecipe() { 1)); MetaTileEntity atte = new MetaTileEntityHolder().setMetaTileEntity(at); + atte.getHolder().setWorld(world); map.recipeBuilder() .inputs(new ItemStack(Blocks.COBBLESTONE)) .outputs(new ItemStack(Blocks.STONE)) @@ -72,14 +78,14 @@ public void trySearchNewRecipe() { // put an item in the inventory that will trigger recipe recheck arl.getInputInventory().insertItem(0, new ItemStack(Blocks.COBBLESTONE, 16), false); // Inputs change. did we detect it ? - assertTrue(arl.getMetaTileEntity().isInputsDirty()); + assertTrue(arl.hasNotifiedInputs()); arl.trySearchNewRecipe(); assertFalse(arl.invalidInputsForRecipes); assertNotNull(arl.previousRecipe); assertTrue(arl.isActive); assertEquals(15, arl.getInputInventory().getStackInSlot(0).getCount()); //assert the consumption of the inputs did not mark the arl to look for a new recipe - assertFalse(arl.getMetaTileEntity().isInputsDirty()); + assertFalse(arl.hasNotifiedInputs()); // Save a reference to the old recipe so we can make sure it's getting reused Recipe prev = arl.previousRecipe; diff --git a/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java b/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java index d2ff17065d..0f67f4f673 100644 --- a/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java +++ b/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java @@ -11,6 +11,7 @@ import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.RecipeMaps; import gregtech.api.recipes.builders.BlastRecipeBuilder; +import gregtech.api.util.world.DummyWorld; import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityFluidHatch; import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityItemBus; import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityMultiblockPart; @@ -20,6 +21,7 @@ import net.minecraft.init.Bootstrap; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; import net.minecraftforge.items.IItemHandlerModifiable; import org.junit.BeforeClass; @@ -43,6 +45,8 @@ private static ResourceLocation gregtechId(String name) { @Test public void trySearchNewRecipe() { + World world = DummyWorld.INSTANCE; + // Create an empty recipe map to work with RecipeMap map = new RecipeMap<>("blast_furnace", 1, @@ -94,6 +98,8 @@ public boolean checkRecipe(Recipe recipe, boolean consumeIfSuccess) { e.printStackTrace(); } + mbt.getHolder().setWorld(world); + //Controller and isAttachedToMultiBlock need the world so we fake it here. MetaTileEntityItemBus importItemBus = new MetaTileEntityItemBus(gregtechId("item_bus.export.lv"), 1, false) { @Override @@ -209,14 +215,14 @@ protected IMultipleTankHandler getOutputTank() { // put an item in the inventory that will trigger recipe recheck mbl.getInputInventory().insertItem(0, new ItemStack(Blocks.COBBLESTONE, 16), false); // Inputs change. did we detect it ? - assertTrue(mbt.isInputsDirty()); + assertTrue(mbl.hasNotifiedInputs()); mbl.trySearchNewRecipe(); assertFalse(mbl.invalidInputsForRecipes); assertNotNull(mbl.previousRecipe); assertTrue(mbl.isActive); assertEquals(15, mbl.getInputInventory().getStackInSlot(0).getCount()); //assert the consumption of the inputs did not mark the arl to look for a new recipe - assertFalse(mbt.isInputsDirty()); + assertFalse(mbl.hasNotifiedInputs()); // Save a reference to the old recipe so we can make sure it's getting reused Recipe prev = mbl.previousRecipe; @@ -244,7 +250,7 @@ protected IMultipleTankHandler getOutputTank() { // Some room is freed in the output bus, so we can continue now. mbl.getOutputInventory().setStackInSlot(1, ItemStack.EMPTY); - assertTrue(mbt.isOutputsDirty()); + assertTrue(mbl.hasNotifiedOutputs()); mbl.updateWorkable(); assertTrue(mbl.isActive); assertFalse(mbl.isOutputsFull); From 381d0099a621882c7579a00b9aca41080d04290d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Sun, 30 May 2021 14:10:08 -0300 Subject: [PATCH 18/26] formatting --- .../api/capability/INotifiableHandler.java | 7 ++- .../capability/impl/AbstractRecipeLogic.java | 10 ++-- .../api/metatileentity/MetaTileEntity.java | 8 +-- .../WorkableTieredMetaTileEntity.java | 8 +-- .../multiblock/IMultiblockPart.java | 2 +- .../multiblockpart/MetaTileEntityItemBus.java | 9 +-- .../electric/MetaTileEntityMultiFurnace.java | 6 +- .../impl/AbstractRecipeLogicTest.java | 59 +++++++++++-------- .../impl/MultiblockRecipeLogicTest.java | 48 ++++++++------- 9 files changed, 88 insertions(+), 69 deletions(-) diff --git a/src/main/java/gregtech/api/capability/INotifiableHandler.java b/src/main/java/gregtech/api/capability/INotifiableHandler.java index 3fa6a7783f..e32ddf751e 100644 --- a/src/main/java/gregtech/api/capability/INotifiableHandler.java +++ b/src/main/java/gregtech/api/capability/INotifiableHandler.java @@ -17,8 +17,11 @@ public interface INotifiableHandler { default void addToNotifiedList(MetaTileEntity metaTileEntity, T handler, boolean isExport) { if (metaTileEntity != null && metaTileEntity.isValid()) { - if (isExport) metaTileEntity.addNotifiedOutput(handler); - else metaTileEntity.addNotifiedInput(handler); + if (isExport) { + metaTileEntity.addNotifiedOutput(handler); + } else { + metaTileEntity.addNotifiedInput(handler); + } } } diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 6b61f4fafb..d11310be4e 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -191,7 +191,7 @@ protected void trySearchNewRecipe() { // see if the last recipe we used still works if (this.previousRecipe != null && this.previousRecipe.matches(false, importInventory, importFluids)) currentRecipe = this.previousRecipe; - // If there is no active recipe, then we need to find one. + // If there is no active recipe, then we need to find one. else { currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); } @@ -199,10 +199,10 @@ protected void trySearchNewRecipe() { if (currentRecipe != null) { this.invalidInputsForRecipes = false; this.previousRecipe = currentRecipe; - // Add-ons may Override findRecipe method but not trySearchNewRecipe, in that case - // they may return a null recipe. Since we only check for items and fluid here, having - // findRecipe return a null recipe with isOutputsFull being true, means we have a valid - // recipe in the input waiting for space in the output. + // Add-ons may Override findRecipe method but not trySearchNewRecipe, in that case + // they may return a null recipe. Since we only check for items and fluid here, having + // findRecipe return a null recipe with isOutputsFull being true, means we have a valid + // recipe in the input waiting for space in the output. } else this.invalidInputsForRecipes = !this.isOutputsFull; // proceed if we have a usable recipe. diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index 1ab49a3c02..fe42549dad 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -259,7 +259,7 @@ public final String getMetaFullName() { return getMetaName() + ".name"; } - public void addNotifiedInput (T input) { + public void addNotifiedInput(T input) { if (input instanceof IItemHandlerModifiable) { if (!notifiedItemInputList.contains(input)) { this.notifiedItemInputList.add((IItemHandlerModifiable) input); @@ -271,7 +271,7 @@ public void addNotifiedInput (T input) { } } - public void addNotifiedOutput (T output) { + public void addNotifiedOutput(T output) { if (output instanceof IItemHandlerModifiable) { if (!notifiedItemOutputList.contains(output)) { this.notifiedItemOutputList.add((IItemHandlerModifiable) output); @@ -283,14 +283,14 @@ public void addNotifiedOutput (T output) { } } - public void removeNotifiedInput (T input) { + public void removeNotifiedInput(T input) { if (input instanceof IItemHandlerModifiable) this.notifiedItemInputList.remove(input); else if (input instanceof FluidTank) this.notifiedFluidInputList.remove(input); } - public void removeNotifiedOutput (T input) { + public void removeNotifiedOutput(T input) { if (input instanceof IItemHandlerModifiable) this.notifiedItemOutputList.remove(input); else if (input instanceof FluidTank) diff --git a/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java index 80865fa9a2..2ae8d2cd26 100644 --- a/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java @@ -54,13 +54,13 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, @Override protected IItemHandlerModifiable createImportItemHandler() { if (workable == null) return new ItemStackHandler(0); - return new NotifiableItemStackHandler(workable.recipeMap.getMaxInputs(), this,false); + return new NotifiableItemStackHandler(workable.recipeMap.getMaxInputs(), this, false); } @Override protected IItemHandlerModifiable createExportItemHandler() { if (workable == null) return new ItemStackHandler(0); - return new NotifiableItemStackHandler(workable.recipeMap.getMaxOutputs(), this,true); + return new NotifiableItemStackHandler(workable.recipeMap.getMaxOutputs(), this, true); } @Override @@ -68,7 +68,7 @@ protected FluidTankList createImportFluidHandler() { if (workable == null) return new FluidTankList(false); FilteredFluidHandler[] fluidImports = new FilteredFluidHandler[workable.recipeMap.getMaxFluidInputs()]; for (int i = 0; i < fluidImports.length; i++) { - NotifiableFilteredFluidHandler filteredFluidHandler = new NotifiableFilteredFluidHandler(getInputTankCapacity(i),this,false); + NotifiableFilteredFluidHandler filteredFluidHandler = new NotifiableFilteredFluidHandler(getInputTankCapacity(i), this, false); filteredFluidHandler.setFillPredicate(this::canInputFluid); fluidImports[i] = filteredFluidHandler; } @@ -80,7 +80,7 @@ protected FluidTankList createExportFluidHandler() { if (workable == null) return new FluidTankList(false); FluidTank[] fluidExports = new FluidTank[workable.recipeMap.getMaxFluidOutputs()]; for (int i = 0; i < fluidExports.length; i++) { - fluidExports[i] = new NotifiableFluidTank(getOutputTankCapacity(i),this,true); + fluidExports[i] = new NotifiableFluidTank(getOutputTankCapacity(i), this, true); } return new FluidTankList(false, fluidExports); } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java b/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java index 6c33c7a4ad..1d343bbb68 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java @@ -11,6 +11,6 @@ public interface IMultiblockPart { void removeFromMultiBlock(MultiblockControllerBase controllerBase); default void setupNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { - } + } diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java index 85243139e9..39783c005e 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java @@ -71,12 +71,12 @@ private int getInventorySize() { @Override protected IItemHandlerModifiable createExportItemHandler() { - return isExportHatch ? new NotifiableItemStackHandler(getInventorySize(),getController(),true) : new ItemStackHandler(0); + return isExportHatch ? new NotifiableItemStackHandler(getInventorySize(), getController(), true) : new ItemStackHandler(0); } @Override protected IItemHandlerModifiable createImportItemHandler() { - return isExportHatch ? new ItemStackHandler(0) : new NotifiableItemStackHandler(getInventorySize(),getController(), false); + return isExportHatch ? new ItemStackHandler(0) : new NotifiableItemStackHandler(getInventorySize(), getController(), false); } @Override @@ -92,10 +92,11 @@ public void registerAbilities(List abilityList) { @Override public void setupNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { NotifiableItemStackHandler handler = null; - if (isExportHatch && getExportItems() instanceof NotifiableItemStackHandler) + if (isExportHatch && getExportItems() instanceof NotifiableItemStackHandler) { handler = (NotifiableItemStackHandler) getExportItems(); - else if (!isExportHatch && getImportItems() instanceof NotifiableItemStackHandler) + } else if (!isExportHatch && getImportItems() instanceof NotifiableItemStackHandler) { handler = (NotifiableItemStackHandler) getImportItems(); + } if (handler != null) { handler.setNotifiableMetaTileEntity(metaTileEntity); handler.addToNotifiedList(this, handler, isExportHatch); diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index e1198d9fab..ea1c7ce861 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -111,11 +111,11 @@ protected void trySearchNewRecipe() { //otherwise, we need to recompute it for new ingredients //but technically, it means we can cache multi smelter recipe, but changing inputs have more priority if (hasNotifiedInputs() || - previousRecipe == null || - !previousRecipe.matches(false,importInventory,importFluids)) { + previousRecipe == null || + !previousRecipe.matches(false, importInventory, importFluids)) { //Inputs changed, try searching new recipe for given inputs currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); - } else { + } else { //if previous recipe still matches inputs, try to use it currentRecipe = previousRecipe; } diff --git a/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java b/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java index 0fe2710c64..aa3a3d78ab 100644 --- a/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java +++ b/src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java @@ -29,41 +29,52 @@ public void trySearchNewRecipe() { // Create an empty recipe map to work with RecipeMap map = new RecipeMap<>("chemical_reactor", - 0, - 2, - 0, - 2, - 0, - 3, - 0, - 2, - new SimpleRecipeBuilder().EUt(30)); + 0, + 2, + 0, + 2, + 0, + 3, + 0, + 2, + new SimpleRecipeBuilder().EUt(30)); MetaTileEntity at = - GregTechAPI.registerMetaTileEntity(190, - new SimpleMachineMetaTileEntity( - new ResourceLocation(GTValues.MODID,"chemical_reactor.lv"), - map, - Textures.CHEMICAL_REACTOR_OVERLAY, - 1)); + GregTechAPI.registerMetaTileEntity(190, + new SimpleMachineMetaTileEntity( + new ResourceLocation(GTValues.MODID, "chemical_reactor.lv"), + map, + Textures.CHEMICAL_REACTOR_OVERLAY, + 1)); MetaTileEntity atte = new MetaTileEntityHolder().setMetaTileEntity(at); atte.getHolder().setWorld(world); map.recipeBuilder() - .inputs(new ItemStack(Blocks.COBBLESTONE)) - .outputs(new ItemStack(Blocks.STONE)) - .EUt(1).duration(1) - .buildAndRegister(); + .inputs(new ItemStack(Blocks.COBBLESTONE)) + .outputs(new ItemStack(Blocks.STONE)) + .EUt(1).duration(1) + .buildAndRegister(); AbstractRecipeLogic arl = new AbstractRecipeLogic(atte, map) { @Override - protected long getEnergyStored() { return Long.MAX_VALUE; } + protected long getEnergyStored() { + return Long.MAX_VALUE; + } + @Override - protected long getEnergyCapacity() { return Long.MAX_VALUE; } + protected long getEnergyCapacity() { + return Long.MAX_VALUE; + } + @Override - protected boolean drawEnergy(int recipeEUt) { return true; } + protected boolean drawEnergy(int recipeEUt) { + return true; + } + @Override - protected long getMaxVoltage() { return 32; } + protected long getMaxVoltage() { + return 32; + } }; arl.isOutputsFull = false; @@ -94,7 +105,7 @@ public void trySearchNewRecipe() { arl.update(); assertEquals(prev, arl.previousRecipe); assertTrue(AbstractRecipeLogic.areItemStacksEqual(arl.getOutputInventory().getStackInSlot(0), - new ItemStack(Blocks.STONE, 1))); + new ItemStack(Blocks.STONE, 1))); assertTrue(arl.isActive); // Complete the second iteration, but the machine stops because its output is now full diff --git a/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java b/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java index 0f67f4f673..837f4cf1c4 100644 --- a/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java +++ b/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java @@ -26,6 +26,7 @@ import org.junit.BeforeClass; import org.junit.Test; + import java.lang.reflect.Field; import static org.junit.Assert.*; @@ -49,15 +50,15 @@ public void trySearchNewRecipe() { // Create an empty recipe map to work with RecipeMap map = new RecipeMap<>("blast_furnace", - 1, - 3, - 1, - 2, - 0, - 1, - 0, - 1, - new BlastRecipeBuilder().EUt(32)); + 1, + 3, + 1, + 2, + 0, + 1, + 0, + 1, + new BlastRecipeBuilder().EUt(32)); RecipeMaps.BLAST_RECIPES.recipeBuilder() .inputs(new ItemStack(Blocks.COBBLESTONE)) @@ -68,19 +69,21 @@ public void trySearchNewRecipe() { RecipeMapMultiblockController mbt = GregTechAPI.registerMetaTileEntity(511, - new MetaTileEntityElectricBlastFurnace( - // super function calls the world, which equal null in test - new ResourceLocation(GTValues.MODID, "electric_blast_furnace")) { - @Override - protected IBlockState getCasingState() { - return null; - } - // function checks for the temperature of the recipe against the coils - @Override - public boolean checkRecipe(Recipe recipe, boolean consumeIfSuccess) { - return true; - } - }); + new MetaTileEntityElectricBlastFurnace( + // super function calls the world, which equal null in test + new ResourceLocation(GTValues.MODID, "electric_blast_furnace")) { + @Override + protected void reinitializeStructurePattern() { + + } + + // function checks for the temperature of the recipe against the coils + @Override + public boolean checkRecipe(Recipe recipe, boolean consumeIfSuccess) { + return true; + } + }); + //isValid() check in the dirtying logic requires both a metatileentity and a holder try { Field field = MetaTileEntity.class.getDeclaredField("holder"); @@ -179,6 +182,7 @@ protected boolean drawEnergy(int recipeEUt) { protected long getMaxVoltage() { return 32; } + // since the hatches were not really added to a valid multiblock structure, // refer to their inventories directly @Override From 754e1b4f120d414f28eb5fa48c67374adbada32b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Sun, 30 May 2021 14:41:56 -0300 Subject: [PATCH 19/26] update javadoc --- src/main/java/gregtech/api/capability/INotifiableHandler.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/capability/INotifiableHandler.java b/src/main/java/gregtech/api/capability/INotifiableHandler.java index e32ddf751e..34cf1c3635 100644 --- a/src/main/java/gregtech/api/capability/INotifiableHandler.java +++ b/src/main/java/gregtech/api/capability/INotifiableHandler.java @@ -9,8 +9,7 @@ public interface INotifiableHandler { /** - * Notifies the entities of the changes in their inventories - * An iterator is used to remove invalid TileEntities + * Adds the notified handler to the notified list * * @param isExport boolean specifying if a handler is an output handler */ From 698d2250f55481b4b560a0ab7403a93bd49145f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Tue, 1 Jun 2021 23:45:41 -0300 Subject: [PATCH 20/26] simplify logic --- .../api/capability/impl/AbstractRecipeLogic.java | 8 ++++---- .../api/metatileentity/MetaTileEntity.java | 14 -------------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index d11310be4e..a7f4cdf855 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -145,8 +145,8 @@ protected boolean canFitNewOutputs() { if (this.isOutputsFull && !hasNotifiedOutputs()) return false; else { this.isOutputsFull = false; - metaTileEntity.removeNotifiedOutput(getOutputInventory()); - metaTileEntity.removeNotifiedOutput(getOutputTank()); + metaTileEntity.getNotifiedItemOutputList().clear(); + metaTileEntity.getNotifiedFluidOutputList().clear(); } return true; } @@ -209,8 +209,8 @@ protected void trySearchNewRecipe() { if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) setupRecipe(currentRecipe); // Inputs have been inspected. - metaTileEntity.removeNotifiedInput(importInventory); - metaTileEntity.removeNotifiedInput(importFluids); + metaTileEntity.getNotifiedItemInputList().clear(); + metaTileEntity.getNotifiedFluidInputList().clear(); } public void forceRecipeRecheck() { diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index fe42549dad..2c4575294d 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -283,20 +283,6 @@ public void addNotifiedOutput(T output) { } } - public void removeNotifiedInput(T input) { - if (input instanceof IItemHandlerModifiable) - this.notifiedItemInputList.remove(input); - else if (input instanceof FluidTank) - this.notifiedFluidInputList.remove(input); - } - - public void removeNotifiedOutput(T input) { - if (input instanceof IItemHandlerModifiable) - this.notifiedItemOutputList.remove(input); - else if (input instanceof FluidTank) - this.notifiedFluidOutputList.remove(input); - } - /** * Adds a trait to this meta tile entity * traits are objects linked with meta tile entity and performing certain From 694d97bbe1cb8b92d8fc357807025707df8bfdc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Sat, 5 Jun 2021 12:01:22 -0300 Subject: [PATCH 21/26] match deprecated behaviour --- .../gregtech/api/capability/impl/AbstractRecipeLogic.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index a7f4cdf855..08a1efb59a 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -238,7 +238,10 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul */ @Deprecated protected boolean checkRecipeInputsDirty(IItemHandler inputs, IMultipleTankHandler fluidInputs) { - return this.hasNotifiedInputs(); + boolean isDirty = this.hasNotifiedInputs(); + metaTileEntity.getNotifiedItemInputList().clear(); + metaTileEntity.getNotifiedFluidInputList().clear(); + return isDirty; } protected static boolean areItemStacksEqual(ItemStack stackA, ItemStack stackB) { From b424b736d53448740adea8058a2a0c9ab3df3590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Sat, 5 Jun 2021 13:14:05 -0300 Subject: [PATCH 22/26] fix merge conflict --- .../MetaTileEntityFluidHatch.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java index f590b054e3..06e1a56dd1 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java @@ -4,6 +4,7 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; import gregtech.api.capability.impl.FluidTankList; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; import gregtech.api.gui.ModularUI.Builder; @@ -36,14 +37,14 @@ public class MetaTileEntityFluidHatch extends MetaTileEntityMultiblockPart imple private static final int INITIAL_INVENTORY_SIZE = 8000; private ItemStackHandler containerInventory; - private FluidTank fluidTank; + private NotifiableFluidTank fluidTank; private boolean isExportHatch; public MetaTileEntityFluidHatch(ResourceLocation metaTileEntityId, int tier, boolean isExportHatch) { super(metaTileEntityId, tier); this.containerInventory = new ItemStackHandler(2); this.isExportHatch = isExportHatch; - this.fluidTank = new FluidTank(getInventorySize()); + this.fluidTank = new NotifiableFluidTank(getInventorySize(), this, isExportHatch); initializeInventory(); } @@ -120,6 +121,20 @@ public void registerAbilities(List abilityList) { abilityList.addAll(isExportHatch ? this.exportFluids.getFluidTanks() : this.importFluids.getFluidTanks()); } + @Override + public void setupNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + NotifiableFluidTank handler = null; + if (isExportHatch) { + handler = (NotifiableFluidTank) getExportFluids().getTankAt(0); + } else { + handler = (NotifiableFluidTank) getImportFluids().getTankAt(0); + } + if (handler != null) { + handler.setNotifiableMetaTileEntity(metaTileEntity); + handler.addToNotifiedList(this, handler, isExportHatch); + } + } + @Override protected ModularUI createUI(EntityPlayer entityPlayer) { return createTankUI((isExportHatch ? exportFluids : importFluids).getTankAt(0), containerInventory, getMetaFullName(), entityPlayer) From 36ac87237f3b10947af86a5c42f3d17d8112a92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Sat, 5 Jun 2021 13:19:27 -0300 Subject: [PATCH 23/26] removed unnecesarry override and imports --- .../api/capability/impl/MultiblockRecipeLogic.java | 12 ------------ .../multiblockpart/MetaTileEntityFluidHatch.java | 1 - 2 files changed, 13 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java index 1e5a8de3b6..d57e7ad67b 100644 --- a/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java @@ -60,18 +60,6 @@ protected boolean setupAndConsumeRecipeInputs(Recipe recipe) { } else return false; } - @Override - protected boolean hasNotifiedInputs() { - return (metaTileEntity.getNotifiedItemInputList().size() > 0 || - metaTileEntity.getNotifiedFluidInputList().size() > 0); - } - - @Override - protected boolean hasNotifiedOutputs() { - return (metaTileEntity.getNotifiedItemOutputList().size() > 0 || - metaTileEntity.getNotifiedFluidOutputList().size() > 0); - } - @Override protected long getEnergyStored() { return getEnergyContainer().getEnergyStored(); diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java index 06e1a56dd1..1664c39e60 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java @@ -4,7 +4,6 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; import gregtech.api.capability.impl.FluidTankList; -import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; import gregtech.api.gui.ModularUI.Builder; From 4eaff0fd47f05272a2c511867933145d6172ebbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Sat, 5 Jun 2021 22:55:18 -0300 Subject: [PATCH 24/26] address reviewed issues --- .../metatileentities/electric/MetaTileEntityMacerator.java | 2 +- .../multi/electric/MetaTileEntityMultiFurnace.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java index 2d7dcc26ee..e20fc866a5 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java @@ -41,7 +41,7 @@ protected int getMachineTierForRecipe(Recipe recipe) { @Override protected IItemHandlerModifiable createExportItemHandler() { - return new NotifiableItemStackHandler(outputAmount,this,true); + return new NotifiableItemStackHandler(outputAmount, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index ea1c7ce861..c414d6fa2c 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -127,7 +127,6 @@ protected void trySearchNewRecipe() { setupRecipe(currentRecipe); // Inputs have been inspected. metaTileEntity.getNotifiedItemInputList().clear(); - metaTileEntity.getNotifiedFluidOutputList().clear(); } @Override From dfd6617a080a3b99f77618e6c051563f9c7a302c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Sat, 5 Jun 2021 22:55:58 -0300 Subject: [PATCH 25/26] Add notifiable handlers to steam variant of metaTileEntities --- .../metatileentities/steam/SteamAlloySmelter.java | 10 +++++----- .../common/metatileentities/steam/SteamCompressor.java | 10 +++++----- .../common/metatileentities/steam/SteamExtractor.java | 10 +++++----- .../common/metatileentities/steam/SteamFurnace.java | 10 +++++----- .../common/metatileentities/steam/SteamHammer.java | 10 +++++----- .../common/metatileentities/steam/SteamMacerator.java | 10 +++++----- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamAlloySmelter.java b/src/main/java/gregtech/common/metatileentities/steam/SteamAlloySmelter.java index 5a7704f877..25076e17ba 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamAlloySmelter.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamAlloySmelter.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.ModularUI; import gregtech.api.gui.resources.TextureArea; import gregtech.api.gui.widgets.ProgressWidget; @@ -13,7 +14,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamAlloySmelter extends SteamMetaTileEntity { @@ -32,13 +32,13 @@ protected boolean isBrickedCasing() { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(2); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(2, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamCompressor.java b/src/main/java/gregtech/common/metatileentities/steam/SteamCompressor.java index 2efacbf4a1..f6d2c28419 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamCompressor.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamCompressor.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ProgressWidget; import gregtech.api.gui.widgets.ProgressWidget.MoveType; @@ -12,7 +13,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamCompressor extends SteamMetaTileEntity { @@ -26,13 +26,13 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(1, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamExtractor.java b/src/main/java/gregtech/common/metatileentities/steam/SteamExtractor.java index c9d59185bc..9966264a14 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamExtractor.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamExtractor.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ProgressWidget; import gregtech.api.gui.widgets.SlotWidget; @@ -11,7 +12,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamExtractor extends SteamMetaTileEntity { @@ -25,13 +25,13 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(1, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamFurnace.java b/src/main/java/gregtech/common/metatileentities/steam/SteamFurnace.java index 375aefb678..f6d39bfb28 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamFurnace.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ProgressWidget; import gregtech.api.gui.widgets.ProgressWidget.MoveType; @@ -12,7 +13,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamFurnace extends SteamMetaTileEntity { @@ -31,13 +31,13 @@ protected boolean isBrickedCasing() { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(1, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamHammer.java b/src/main/java/gregtech/common/metatileentities/steam/SteamHammer.java index c21c7eb069..b382694c51 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamHammer.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamHammer.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ImageWidget; import gregtech.api.gui.widgets.ProgressWidget; @@ -12,7 +13,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamHammer extends SteamMetaTileEntity { @@ -26,13 +26,13 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(1, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamMacerator.java b/src/main/java/gregtech/common/metatileentities/steam/SteamMacerator.java index bb19827bed..e9a50894f5 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamMacerator.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamMacerator.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.capability.impl.RecipeLogicSteam; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ProgressWidget; @@ -12,7 +13,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamMacerator extends SteamMetaTileEntity { @@ -28,13 +28,13 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(1, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override From c8477136b6317e0aaba1221ab50aef421f87ac76 Mon Sep 17 00:00:00 2001 From: PrototypeTrousers Date: Thu, 22 Jul 2021 18:18:27 -0300 Subject: [PATCH 26/26] make the if statements more readable --- .../capability/impl/AbstractRecipeLogic.java | 10 +++------- .../electric/MetaTileEntityMultiFurnace.java | 19 +++++++++---------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 08a1efb59a..c85045228f 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -195,15 +195,11 @@ protected void trySearchNewRecipe() { else { currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); } - // If a recipe was found, then inputs were valid. + // If a recipe was found, then inputs were valid. Cache found recipe. if (currentRecipe != null) { - this.invalidInputsForRecipes = false; this.previousRecipe = currentRecipe; - // Add-ons may Override findRecipe method but not trySearchNewRecipe, in that case - // they may return a null recipe. Since we only check for items and fluid here, having - // findRecipe return a null recipe with isOutputsFull being true, means we have a valid - // recipe in the input waiting for space in the output. - } else this.invalidInputsForRecipes = !this.isOutputsFull; + } + this.invalidInputsForRecipes = (currentRecipe == null); // proceed if we have a usable recipe. if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index c414d6fa2c..1651bc56c4 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -142,7 +142,9 @@ protected Recipe findRecipe(long maxVoltage, /* Iterate over the input items looking for more things to add until we run either out of input items * or we have exceeded the number of items permissible from the smelting bonus */ - this.invalidInputsForRecipes = true; + boolean matchedRecipe = false; + boolean canFitOutputs = true; + for(int index = 0; index < inputs.getSlots() && currentItemsEngaged < maxItemsLimit; index++) { // Skip this slot if it is empty. @@ -157,7 +159,7 @@ protected Recipe findRecipe(long maxVoltage, CountableIngredient inputIngredient; if(matchingRecipe != null) { inputIngredient = matchingRecipe.getInputs().get(0); - this.invalidInputsForRecipes = false; + matchedRecipe = true; } else continue; @@ -185,7 +187,7 @@ protected Recipe findRecipe(long maxVoltage, computeOutputItemStacks(temp, matchingRecipe.getOutputs().get(0), recipeMultiplier); // determine if there is enough room in the output to fit all of this - boolean canFitOutputs = InventoryUtils.simulateItemStackMerge(temp, this.getOutputInventory()); + canFitOutputs = InventoryUtils.simulateItemStackMerge(temp, this.getOutputInventory()); // if there isn't, we can't process this recipe. if(!canFitOutputs) @@ -203,13 +205,10 @@ protected Recipe findRecipe(long maxVoltage, } } - // If there were no accepted ingredients, then there is no recipe to process. - // the output may be filled up - if (recipeInputs.isEmpty() && !invalidInputsForRecipes) { - //Set here to prevent recipe deadlock on world load with full output bus - this.isOutputsFull = true; - return null; - } else if (recipeInputs.isEmpty()) { + this.invalidInputsForRecipes = !matchedRecipe; + this.isOutputsFull = !canFitOutputs; + + if (recipeInputs.isEmpty()) { return null; }