|
1 | 1 | package gregtech.common.metatileentities.multi.electric; |
2 | 2 |
|
3 | | -import gregtech.api.capability.IMultipleTankHandler; |
4 | | -import gregtech.api.capability.impl.MultiblockRecipeLogic; |
5 | | -import gregtech.api.metatileentity.MetaTileEntity; |
6 | | -import gregtech.api.metatileentity.MetaTileEntityHolder; |
7 | | -import gregtech.api.metatileentity.multiblock.IMultiblockPart; |
8 | | -import gregtech.api.metatileentity.multiblock.MultiblockAbility; |
9 | | -import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; |
10 | | -import gregtech.api.multiblock.BlockPattern; |
11 | | -import gregtech.api.multiblock.FactoryBlockPattern; |
12 | | -import gregtech.api.multiblock.PatternMatchContext; |
13 | | -import gregtech.api.recipes.CountableIngredient; |
14 | | -import gregtech.api.recipes.Recipe; |
15 | | -import gregtech.api.recipes.RecipeMaps; |
16 | | -import gregtech.api.render.ICubeRenderer; |
17 | | -import gregtech.api.render.Textures; |
18 | | -import gregtech.common.blocks.BlockMetalCasing.MetalCasingType; |
19 | | -import gregtech.common.blocks.BlockWireCoil.CoilType; |
20 | | -import gregtech.common.blocks.MetaBlocks; |
21 | | -import net.minecraft.block.state.IBlockState; |
22 | | -import net.minecraft.item.ItemStack; |
23 | | -import net.minecraft.util.ResourceLocation; |
24 | | -import net.minecraft.util.text.ITextComponent; |
25 | | -import net.minecraft.util.text.TextComponentTranslation; |
26 | | -import net.minecraftforge.items.IItemHandlerModifiable; |
27 | | - |
28 | | -import java.util.ArrayList; |
29 | | -import java.util.Collections; |
30 | | -import java.util.List; |
| 3 | +import gregtech.api.capability.*; |
| 4 | +import gregtech.api.capability.impl.*; |
| 5 | +import gregtech.api.metatileentity.*; |
| 6 | +import gregtech.api.metatileentity.multiblock.*; |
| 7 | +import gregtech.api.multiblock.*; |
| 8 | +import gregtech.api.recipes.*; |
| 9 | +import gregtech.api.render.*; |
| 10 | +import gregtech.api.util.*; |
| 11 | +import gregtech.common.blocks.BlockMetalCasing.*; |
| 12 | +import gregtech.common.blocks.BlockWireCoil.*; |
| 13 | +import gregtech.common.blocks.*; |
| 14 | +import net.minecraft.block.state.*; |
| 15 | +import net.minecraft.item.*; |
| 16 | +import net.minecraft.util.*; |
| 17 | +import net.minecraft.util.text.*; |
| 18 | +import net.minecraftforge.items.*; |
| 19 | + |
| 20 | +import java.util.*; |
31 | 21 |
|
32 | 22 | public class MetaTileEntityMultiFurnace extends RecipeMapMultiblockController { |
33 | 23 |
|
@@ -130,40 +120,133 @@ protected void trySearchNewRecipe() { |
130 | 120 | } |
131 | 121 |
|
132 | 122 | @Override |
133 | | - protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMultipleTankHandler fluidInputs) { |
| 123 | + protected Recipe findRecipe(long maxVoltage, |
| 124 | + IItemHandlerModifiable inputs, |
| 125 | + IMultipleTankHandler fluidInputs) |
| 126 | + { |
134 | 127 | int currentItemsEngaged = 0; |
135 | | - int maxItemsLimit = 32 * heatingCoilLevel; |
136 | | - ArrayList<CountableIngredient> recipeInputs = new ArrayList<>(); |
137 | | - ArrayList<ItemStack> recipeOutputs = new ArrayList<>(); |
138 | | - for (int index = 0; index < inputs.getSlots(); index++) { |
139 | | - ItemStack stackInSlot = inputs.getStackInSlot(index); |
140 | | - if (stackInSlot.isEmpty()) |
| 128 | + final int maxItemsLimit = 32 * heatingCoilLevel; |
| 129 | + final ArrayList<CountableIngredient> recipeInputs = new ArrayList<>(); |
| 130 | + final ArrayList<ItemStack> recipeOutputs = new ArrayList<>(); |
| 131 | + |
| 132 | + /* Iterate over the input items looking for more things to add until we run either out of input items |
| 133 | + * or we have exceeded the number of items permissible from the smelting bonus |
| 134 | + */ |
| 135 | + for(int index = 0; index < inputs.getSlots() && currentItemsEngaged < maxItemsLimit; index++) { |
| 136 | + |
| 137 | + // Skip this slot if it is empty. |
| 138 | + final ItemStack currentInputItem = inputs.getStackInSlot(index); |
| 139 | + if(currentInputItem.isEmpty()) |
141 | 140 | continue; |
| 141 | + |
| 142 | + // Determine if there is a valid recipe for this item. If not, skip it. |
142 | 143 | Recipe matchingRecipe = recipeMap.findRecipe(maxVoltage, |
143 | | - Collections.singletonList(stackInSlot), Collections.emptyList(), 0); |
144 | | - CountableIngredient inputIngredient = matchingRecipe == null ? null : matchingRecipe.getInputs().get(0); |
145 | | - if (inputIngredient != null && (maxItemsLimit - currentItemsEngaged) >= inputIngredient.getCount()) { |
146 | | - ItemStack outputStack = matchingRecipe.getOutputs().get(0).copy(); |
147 | | - int overclockAmount = Math.min(stackInSlot.getCount() / inputIngredient.getCount(), |
148 | | - (maxItemsLimit - currentItemsEngaged) / inputIngredient.getCount()); |
| 144 | + Collections.singletonList(currentInputItem), |
| 145 | + Collections.emptyList(), 0); |
| 146 | + CountableIngredient inputIngredient; |
| 147 | + if(matchingRecipe != null) |
| 148 | + inputIngredient = matchingRecipe.getInputs().get(0); |
| 149 | + else |
| 150 | + continue; |
| 151 | + |
| 152 | + // There's something not right with this recipe if the ingredient is null. |
| 153 | + if(inputIngredient == null) |
| 154 | + throw new IllegalStateException( |
| 155 | + String.format("Got recipe with null ingredient %s", matchingRecipe)); |
| 156 | + |
| 157 | + // If there are enough slots left to smelt this item stack |
| 158 | + int itemsLeftUntilMax = (maxItemsLimit - currentItemsEngaged); |
| 159 | + if(itemsLeftUntilMax >= inputIngredient.getCount()) { |
| 160 | + |
| 161 | + /* Choose the lesser of the number of possible crafts in this ingredient's stack, or the number of |
| 162 | + * items remaining to reach the coil bonus's max smelted items. |
| 163 | + */ |
| 164 | + int craftsPossible = currentInputItem.getCount() / inputIngredient.getCount(); |
| 165 | + int craftsUntilMax = itemsLeftUntilMax / inputIngredient.getCount(); |
| 166 | + int recipeMultiplier = Math.min(craftsPossible, craftsUntilMax); |
| 167 | + |
| 168 | + // copy the outputs list so we don't mutate it yet |
| 169 | + ArrayList<ItemStack> temp = new ArrayList<>(recipeOutputs); |
| 170 | + |
| 171 | + // Process the stacks to see how many items this makes |
| 172 | + computeOutputItemStacks(temp, matchingRecipe.getOutputs().get(0), recipeMultiplier); |
| 173 | + |
| 174 | + // determine if there is enough room in the output to fit all of this |
| 175 | + boolean canFitOutputs = InventoryUtils.simulateItemStackMerge(temp, this.getOutputInventory()); |
| 176 | + |
| 177 | + // if there isn't, we can't process this recipe. |
| 178 | + if(!canFitOutputs) |
| 179 | + break; |
| 180 | + |
| 181 | + // otherwise, let's add the new output items and keep going |
| 182 | + temp.removeAll(recipeOutputs); |
| 183 | + recipeOutputs.addAll(temp); |
| 184 | + |
| 185 | + // Add the ingredients to the list of things to smelt. |
149 | 186 | recipeInputs.add(new CountableIngredient(inputIngredient.getIngredient(), |
150 | | - inputIngredient.getCount() * overclockAmount)); |
151 | | - if (!outputStack.isEmpty()) { |
152 | | - outputStack.setCount(outputStack.getCount() * overclockAmount); |
153 | | - recipeOutputs.add(outputStack); |
154 | | - } |
155 | | - currentItemsEngaged += inputIngredient.getCount() * overclockAmount; |
| 187 | + inputIngredient.getCount() * recipeMultiplier)); |
| 188 | + |
| 189 | + currentItemsEngaged += inputIngredient.getCount() * recipeMultiplier; |
156 | 190 | } |
| 191 | + } |
157 | 192 |
|
158 | | - if (currentItemsEngaged >= maxItemsLimit) break; |
| 193 | + // If there were no accepted ingredients, then there is no recipe to process. |
| 194 | + if(recipeInputs.isEmpty()) { |
| 195 | + //Set here to prevent recipe deadlock on world load with full output bus |
| 196 | + forceRecipeRecheck = true; |
| 197 | + return null; |
159 | 198 | } |
160 | | - return recipeInputs.isEmpty() ? null : recipeMap.recipeBuilder() |
| 199 | + |
| 200 | + return recipeMap.recipeBuilder() |
161 | 201 | .inputsIngredients(recipeInputs) |
162 | 202 | .outputs(recipeOutputs) |
163 | 203 | .EUt(Math.max(1, 16 / heatingCoilDiscount)) |
164 | 204 | .duration((int) Math.max(1.0, 256 * (currentItemsEngaged / (maxItemsLimit * 1.0)))) |
165 | 205 | .build().getResult(); |
166 | 206 | } |
| 207 | + |
| 208 | + /** |
| 209 | + * Computes the minimal number of ItemStacks necessary to store a multiplied recipe output, then |
| 210 | + * generates the stacks. The result is then stored in {@code recipeOutputs}. |
| 211 | + * |
| 212 | + * @param recipeOutputs a collection of outputs to store the resulting output ItemStacks |
| 213 | + * @param outputStack an ItemStack representing the output item of a recipe |
| 214 | + * @param overclockAmount the number of times that {@code outputStack}'s quantity should |
| 215 | + * be multiplied by for the desired total |
| 216 | + */ |
| 217 | + private void computeOutputItemStacks(Collection<ItemStack> recipeOutputs, |
| 218 | + ItemStack outputStack, |
| 219 | + int overclockAmount) |
| 220 | + { |
| 221 | + if(!outputStack.isEmpty()) { |
| 222 | + // number of output items we're generating |
| 223 | + int finalAmount = outputStack.getCount() * overclockAmount; |
| 224 | + |
| 225 | + // max items allowed in a stack |
| 226 | + int maxCount = outputStack.getMaxStackSize(); |
| 227 | + |
| 228 | + // number of whole stacks of output this will make |
| 229 | + int numStacks = finalAmount / maxCount; |
| 230 | + |
| 231 | + // number of items left (partial stack) |
| 232 | + int remainder = finalAmount % maxCount; |
| 233 | + |
| 234 | + // Add full stacks of the output item |
| 235 | + for(int fullStacks = numStacks; fullStacks > 0; fullStacks--) { |
| 236 | + ItemStack full = outputStack.copy(); |
| 237 | + full.setCount(maxCount); |
| 238 | + recipeOutputs.add(full); |
| 239 | + } |
| 240 | + |
| 241 | + // if there is a partial stack, add it too |
| 242 | + if(remainder > 0) { |
| 243 | + ItemStack partial = outputStack.copy(); |
| 244 | + partial.setCount(remainder); |
| 245 | + recipeOutputs.add(partial); |
| 246 | + } |
| 247 | + } |
| 248 | + } |
| 249 | + |
167 | 250 | } |
168 | 251 |
|
169 | 252 | } |
0 commit comments