diff options
4 files changed, 119 insertions, 36 deletions
diff --git a/src/functionalTest/java/gregtech/test/GTParallelHelperTest.java b/src/functionalTest/java/gregtech/test/GTParallelHelperTest.java index f5002a417c..517e41b8ba 100644 --- a/src/functionalTest/java/gregtech/test/GTParallelHelperTest.java +++ b/src/functionalTest/java/gregtech/test/GTParallelHelperTest.java @@ -1,6 +1,7 @@ package gregtech.test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; @@ -28,9 +29,9 @@ public class GTParallelHelperTest { ItemStack sulfurDust = Materials.Sulfur.getDust(1); rubberRecipe = new GT_Recipe( new ItemStack[] { rubberDust.copy(), sulfurDust.copy() }, + new ItemStack[] { Materials.Rubber.getDust(1), Materials.Rubber.getDustTiny(1) }, null, - null, - null, + new int[] { 10000, 6667 }, null, new FluidStack[] { Materials.Rubber.getMolten(1000) }, 1, @@ -83,4 +84,39 @@ public class GTParallelHelperTest { .build(); assertEquals(Integer.MAX_VALUE, helperWithBatchMode.getCurrentParallel()); } + + @Test + void chanceMultiplier() { + GT_ParallelHelper helper = new GT_ParallelHelper().setRecipe(rubberRecipe) + .setMachine(machine, false, false) + .setItemInputs(inputItems) + .setMaxParallel(10) + .setAvailableEUt(100) + .setConsumption(false) + .setOutputCalculation(true) + .setChanceMultiplier(10) + .build(); + + int rubberDustAmount = helper.getItemOutputs()[0].stackSize; + int rubberDustTinyAmount = helper.getItemOutputs()[1].stackSize; + + assertEquals(100, rubberDustAmount); + assertTrue(rubberDustTinyAmount >= 60 && rubberDustTinyAmount <= 70); + } + + @Test + void outputMultiplier() { + GT_ParallelHelper helper = new GT_ParallelHelper().setRecipe(rubberRecipe) + .setMachine(machine, false, false) + .setItemInputs(inputItems) + .setMaxParallel(1) + .setAvailableEUt(1) + .setConsumption(false) + .setOutputCalculation(true) + .setOutputMultiplier(2) + .build(); + + assertEquals(2000, helper.getFluidOutputs()[0].amount); + assertEquals(2, helper.getItemOutputs()[0].stackSize); + } } diff --git a/src/main/java/gregtech/api/util/GT_ParallelHelper.java b/src/main/java/gregtech/api/util/GT_ParallelHelper.java index c9ffaeb33e..141ea35e9e 100644 --- a/src/main/java/gregtech/api/util/GT_ParallelHelper.java +++ b/src/main/java/gregtech/api/util/GT_ParallelHelper.java @@ -123,6 +123,14 @@ public class GT_ParallelHelper { */ private float eutModifier = 1; /** + * Multiplier that is applied on the output chances + */ + private double chanceMultiplier = 1; + /** + * Multiplier by which the output will be multiplied + */ + private int outputMultiplier = 1; + /** * Method for calculating max parallel from given inputs. */ private MaxParallelCalculator maxParallelCalculator = GT_Recipe::maxParallelCalculatedByInputs; @@ -221,6 +229,25 @@ public class GT_ParallelHelper { return this; } + /** + * Sets the multiplier that is applied on output chances. 1 does nothing. 0.9 is 10% less. 1.1 is 10% more. + * Only useful for item outputs for sure. + */ + @Nonnull + public GT_ParallelHelper setChanceMultiplier(double chanceMultiplier) { + this.chanceMultiplier = chanceMultiplier; + return this; + } + + /** + * Sets the item/fluid output multiplier. 1 does nothing. 2 doubles the item and fluid outputs. + */ + @Nonnull + public GT_ParallelHelper setOutputMultiplier(int outputMultiplier) { + this.outputMultiplier = outputMultiplier; + return this; + } + @Nonnull public GT_ParallelHelper setCalculator(GT_OverclockCalculator calculator) { this.calculator = calculator; @@ -484,6 +511,9 @@ public class GT_ParallelHelper { voidProtectionHelper.setMachine(machine) .setItemOutputs(truncatedItemOutputs) .setFluidOutputs(truncatedFluidOutputs) + .setChangeGetter(recipe::getOutputChance) + .setOutputMultiplier(outputMultiplier) + .setChanceMultiplier(chanceMultiplier) .setMaxParallel(maxParallel) .setItemOutputInventory(itemOutputInventory) .setFluidOutputInventory(fluidOutputInventory) @@ -589,8 +619,10 @@ public class GT_ParallelHelper { ItemStack origin = recipe.getOutput(i) .copy(); final long itemStackSize = origin.stackSize; - double outputMultiplier = calculateChancedOutputMultiplier(recipe.getOutputChance(i), currentParallel); - long items = (long) Math.ceil(itemStackSize * outputMultiplier); + double chancedOutputMultiplier = calculateChancedOutputMultiplier( + (int) (recipe.getOutputChance(i) * chanceMultiplier), + currentParallel); + long items = (long) Math.ceil(itemStackSize * chancedOutputMultiplier * outputMultiplier); addItemsLong(itemOutputsList, origin, items); } itemOutputs = itemOutputsList.toArray(new ItemStack[0]); @@ -607,7 +639,7 @@ public class GT_ParallelHelper { if (recipe.getFluidOutput(i) == null) continue; FluidStack origin = recipe.getFluidOutput(i) .copy(); - long fluids = (long) origin.amount * currentParallel; + long fluids = (long) this.outputMultiplier * origin.amount * currentParallel; addFluidsLong(fluidOutputsList, origin, fluids); } @@ -617,9 +649,12 @@ public class GT_ParallelHelper { private static final Random rand = new Random(); public static double calculateChancedOutputMultiplier(int chanceInt, int parallel) { - if (chanceInt >= 10000) return parallel; - double multiplier = 0; - double chance = (double) chanceInt / 10000; + // Multiply the integer part of the chance directly with parallel + double multiplier = Math.floorDiv(chanceInt, 10000) * parallel; + int transformedChanceInt = chanceInt % 10000; + if (transformedChanceInt == 0) return multiplier; + // Calculation of the Decimal Part of chance + double chance = transformedChanceInt / 10000.0; double mean = parallel * chance; double stdDev = Math.sqrt(parallel * chance * (1 - chance)); // Check if everything within 3 standard deviations of mean is within the range @@ -627,12 +662,12 @@ public class GT_ParallelHelper { boolean isSuitableForFittingWithNormalDistribution = mean - 3 * stdDev >= 0 && mean + 3 * stdDev <= parallel; if (isSuitableForFittingWithNormalDistribution) { // Use Normal Distribution to fit Binomial Distribution - multiplier = stdDev * rand.nextGaussian() + mean; - multiplier = Math.max(Math.min(multiplier, parallel), 0); + double tMultiplier = stdDev * rand.nextGaussian() + mean; + multiplier += Math.max(Math.min(tMultiplier, parallel), 0); } else { // Do Binomial Distribution by loop for (int roll = 0; roll < parallel; roll++) { - if (chanceInt > XSTR.XSTR_INSTANCE.nextInt(10000)) { + if (transformedChanceInt > XSTR.XSTR_INSTANCE.nextInt(10000)) { multiplier += 1; } } diff --git a/src/main/java/gregtech/api/util/VoidProtectionHelper.java b/src/main/java/gregtech/api/util/VoidProtectionHelper.java index 245fc24bda..fdf47d06df 100644 --- a/src/main/java/gregtech/api/util/VoidProtectionHelper.java +++ b/src/main/java/gregtech/api/util/VoidProtectionHelper.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.PriorityQueue; +import java.util.function.Function; import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; @@ -70,6 +71,16 @@ public class VoidProtectionHelper { * Is this helper working for a MuTE? */ private boolean muteMode; + /** + * Multiplier by which the output will be multiplied + */ + private int outputMultiplier = 1; + /** + * Multiplier that is applied on the output chances + */ + private double chanceMultiplier = 1; + + private Function<Integer, Integer> chanceGetter = i -> 10000; public VoidProtectionHelper() {} @@ -123,6 +134,21 @@ public class VoidProtectionHelper { return this; } + public VoidProtectionHelper setOutputMultiplier(int outputMultiplier) { + this.outputMultiplier = outputMultiplier; + return this; + } + + public VoidProtectionHelper setChanceMultiplier(double chanceMultiplier) { + this.chanceMultiplier = chanceMultiplier; + return this; + } + + public VoidProtectionHelper setChangeGetter(Function<Integer, Integer> getter) { + this.chanceGetter = getter; + return this; + } + /** * Finishes the VoidProtectionHelper. Anything changed after this will not affect anything */ @@ -288,10 +314,10 @@ public class VoidProtectionHelper { // Iterate over the outputs, calculating require stack spacing they will require. for (FluidStack aY : fluidOutputs) { - if (aY == null || aY.amount <= 0) { - continue; - } - tFluidOutputMap.merge(aY, aY.amount, Integer::sum); + if (aY == null) continue; + int fluidAmount = aY.amount * outputMultiplier; + if (fluidAmount <= 0) continue; + tFluidOutputMap.merge(aY, fluidAmount, Integer::sum); tParallels.put(aY, new ParallelData(0, 0)); } @@ -369,12 +395,14 @@ public class VoidProtectionHelper { // issues with floating point math not being completely accurate when summing. Map<ItemStack, ParallelData> tParallels = new ItemStackMap<>(); int tSlotsFree = 0; + int index = 0; for (ItemStack tItem : itemOutputs) { // GT_RecipeBuilder doesn't handle null item output - if (tItem == null || tItem.stackSize <= 0) { - continue; - } - tItemOutputMap.merge(tItem, tItem.stackSize, Integer::sum); + if (tItem == null) continue; + int itemStackSize = (int) (tItem.stackSize * outputMultiplier + * Math.ceil(chanceMultiplier * chanceGetter.apply(index++) / 10000)); + if (itemStackSize <= 0) continue; + tItemOutputMap.merge(tItem, itemStackSize, Integer::sum); tParallels.put(tItem, new ParallelData(0, 0)); } diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java index 4a6ca3ee7a..5b7a1ec393 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java @@ -572,23 +572,7 @@ public class GT_MetaTileEntity_PCBFactory extends protected GT_ParallelHelper createParallelHelper(@Nonnull GT_Recipe recipe) { return super.createParallelHelper(recipe) .setEUtModifier((float) Math.sqrt(mUpgradesInstalled == 0 ? 1 : mUpgradesInstalled)) - .setCustomItemOutputCalculation(currentParallel -> { - ArrayList<ItemStack> chancedOutputs = new ArrayList<>(); - for (int i = 0; i < currentParallel; i++) { - for (ItemStack item : recipe.mOutputs) { - int remainingEfficiency = getMaxEfficiency(getControllerSlot()); - while (remainingEfficiency > 0) { - if (getBaseMetaTileEntity().getRandomNumber(10000) >= remainingEfficiency) { - remainingEfficiency -= 10000; - continue; - } - chancedOutputs.add(item); - remainingEfficiency -= 10000; - } - } - } - return chancedOutputs.toArray(new ItemStack[0]); - }); + .setChanceMultiplier(mRoughnessMultiplier); } }; } |