aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/gregtech/api/util/GT_ParallelHelper.java100
-rw-r--r--src/main/java/gregtech/api/util/GT_Recipe.java20
2 files changed, 80 insertions, 40 deletions
diff --git a/src/main/java/gregtech/api/util/GT_ParallelHelper.java b/src/main/java/gregtech/api/util/GT_ParallelHelper.java
index e836122f37..6ec736b15f 100644
--- a/src/main/java/gregtech/api/util/GT_ParallelHelper.java
+++ b/src/main/java/gregtech/api/util/GT_ParallelHelper.java
@@ -1,7 +1,9 @@
package gregtech.api.util;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
+import java.util.Random;
import java.util.function.Function;
import javax.annotation.Nonnull;
@@ -373,12 +375,12 @@ public class GT_ParallelHelper {
double tickTimeAfterOC = calculator.setParallel(originalMaxParallel)
.calculateDurationUnderOneTick();
if (tickTimeAfterOC < 1) {
- maxParallel = (int) (maxParallel / tickTimeAfterOC);
+ maxParallel = GT_Utility.safeInt((long) (maxParallel / tickTimeAfterOC), 0);
}
int maxParallelBeforeBatchMode = maxParallel;
if (batchMode) {
- maxParallel *= batchModifier;
+ maxParallel = GT_Utility.safeInt((long) maxParallel * batchModifier, 0);
}
final ItemStack[] truncatedItemOutputs = recipe.mOutputs != null
@@ -511,31 +513,42 @@ public class GT_ParallelHelper {
itemOutputs = customItemOutputCalculation.apply(currentParallel);
return;
}
- itemOutputs = new ItemStack[truncatedItemOutputs.length];
+ ArrayList<ItemStack> itemOutputsList = new ArrayList<>();
+ Random rand = new Random();
for (int i = 0; i < truncatedItemOutputs.length; i++) {
- if (recipe.getOutputChance(i) >= 10000) {
- ItemStack item = recipe.getOutput(i)
- .copy();
- item.stackSize *= currentParallel;
- itemOutputs[i] = item;
- continue;
- }
- int items = 0;
- int itemStackSize = recipe.getOutput(i).stackSize;
- for (int roll = 0; roll < currentParallel; roll++) {
- if (recipe.getOutputChance(i) > XSTR.XSTR_INSTANCE.nextInt(10000)) {
- items += itemStackSize;
- }
- }
- ItemStack item = recipe.getOutput(i)
+ if (recipe.getOutput(i) == null) continue;
+ long items = 0;
+ ItemStack origin = recipe.getOutput(i)
.copy();
- if (items == 0) {
- item = null;
+ final long itemStackSize = origin.stackSize;
+
+ if (recipe.getOutputChance(i) >= 10000) {
+ items = itemStackSize * currentParallel;
} else {
- item.stackSize = items;
+ double chance = (double) recipe.getOutputChance(i) / 10000;
+ double mean = currentParallel * chance;
+ double stdDev = Math.sqrt(currentParallel * chance * (1 - chance));
+ // Check if everything within 3 standard deviations of mean is within the range
+ // of possible values (0 ~ currentParallel)
+ boolean isSuitableForFittingWithNormalDistribution = mean - 3 * stdDev >= 0
+ && mean + 3 * stdDev <= currentParallel;
+ if (isSuitableForFittingWithNormalDistribution) {
+ // Use Normal Distribution to fit Binomial Distribution
+ items = (long) Math.ceil(itemStackSize * (stdDev * rand.nextGaussian() + mean));
+ items = Math.max(Math.min(items, itemStackSize * currentParallel), 0);
+ } else {
+ // Do Binomial Distribution by loop
+ for (int roll = 0; roll < currentParallel; roll++) {
+ if (recipe.getOutputChance(i) > XSTR.XSTR_INSTANCE.nextInt(10000)) {
+ items += itemStackSize;
+ }
+ }
+ }
}
- itemOutputs[i] = item;
+
+ addItemsLong(itemOutputsList, origin, items);
}
+ itemOutputs = itemOutputsList.toArray(new ItemStack[0]);
}
private void calculateFluidOutputs(FluidStack[] truncatedFluidOutputs) {
@@ -543,16 +556,43 @@ public class GT_ParallelHelper {
fluidOutputs = customFluidOutputCalculation.apply(currentParallel);
return;
}
- fluidOutputs = new FluidStack[truncatedFluidOutputs.length];
+ ArrayList<FluidStack> fluidOutputsList = new ArrayList<>();
for (int i = 0; i < truncatedFluidOutputs.length; i++) {
- if (recipe.getFluidOutput(i) == null) {
- fluidOutputs[i] = null;
- } else {
- FluidStack tFluid = recipe.getFluidOutput(i)
- .copy();
- tFluid.amount *= currentParallel;
- fluidOutputs[i] = tFluid;
+ if (recipe.getFluidOutput(i) == null) continue;
+ FluidStack origin = recipe.getFluidOutput(i)
+ .copy();
+ long fluids = (long) origin.amount * currentParallel;
+
+ addFluidsLong(fluidOutputsList, origin, fluids);
+ }
+ fluidOutputs = fluidOutputsList.toArray(new FluidStack[0]);
+ }
+
+ public static void addItemsLong(ArrayList<ItemStack> itemList, ItemStack origin, long amount) {
+ if (amount >= 0) {
+ while (amount > Integer.MAX_VALUE) {
+ ItemStack item = origin.copy();
+ item.stackSize = Integer.MAX_VALUE;
+ itemList.add(item);
+ amount -= Integer.MAX_VALUE;
+ }
+ ItemStack item = origin.copy();
+ item.stackSize = (int) amount;
+ itemList.add(item);
+ }
+ }
+
+ public static void addFluidsLong(ArrayList<FluidStack> fluidList, FluidStack origin, long amount) {
+ if (amount >= 0) {
+ while (amount > Integer.MAX_VALUE) {
+ FluidStack fluid = origin.copy();
+ fluid.amount = Integer.MAX_VALUE;
+ fluidList.add(fluid);
+ amount -= Integer.MAX_VALUE;
}
+ FluidStack fluid = origin.copy();
+ fluid.amount = (int) amount;
+ fluidList.add(fluid);
}
}
diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java
index 57f619eb7e..159ac1bbd1 100644
--- a/src/main/java/gregtech/api/util/GT_Recipe.java
+++ b/src/main/java/gregtech/api/util/GT_Recipe.java
@@ -415,12 +415,12 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
public void consumeInput(int amountMultiplier, FluidStack[] aFluidInputs, ItemStack... aInputs) {
if (amountMultiplier <= 0) return;
- int remainingCost;
+ long remainingCost;
if (aFluidInputs != null) {
for (FluidStack recipeFluidCost : mFluidInputs) {
if (recipeFluidCost != null) {
- remainingCost = recipeFluidCost.amount * amountMultiplier;
+ remainingCost = (long) recipeFluidCost.amount * amountMultiplier;
for (FluidStack providedFluid : aFluidInputs) {
if (providedFluid != null && providedFluid.isFluidEqual(recipeFluidCost)) {
@@ -441,7 +441,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
for (ItemStack recipeItemCost : mInputs) {
ItemStack unifiedItemCost = GT_OreDictUnificator.get_nocopy(true, recipeItemCost);
if (unifiedItemCost != null) {
- remainingCost = recipeItemCost.stackSize * amountMultiplier;
+ remainingCost = (long) recipeItemCost.stackSize * amountMultiplier;
for (ItemStack providedItem : aInputs) {
if (isNBTSensitive && !GT_Utility.areStacksEqual(providedItem, unifiedItemCost, false)) {
@@ -484,23 +484,23 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
if (aFluidInputs != null) {
// Create map for fluid -> stored amount
- Map<Fluid, Integer> fluidMap = new HashMap<>();
- Map<Fluid, Integer> fluidCost = new HashMap<>();
+ Map<Fluid, Long> fluidMap = new HashMap<>();
+ Map<Fluid, Long> fluidCost = new HashMap<>();
for (FluidStack fluidStack : aFluidInputs) {
if (fluidStack == null) continue;
- fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
+ fluidMap.merge(fluidStack.getFluid(), (long) fluidStack.amount, Long::sum);
}
for (FluidStack fluidStack : mFluidInputs) {
if (fluidStack == null) continue;
- fluidCost.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
+ fluidCost.merge(fluidStack.getFluid(), (long) fluidStack.amount, Long::sum);
}
// Check how many parallels can it perform for each fluid
- for (Map.Entry<Fluid, Integer> costEntry : fluidCost.entrySet()) {
+ for (Map.Entry<Fluid, Long> costEntry : fluidCost.entrySet()) {
if (costEntry.getValue() > 0) {
currentParallel = Math.min(
currentParallel,
- (double) fluidMap.getOrDefault(costEntry.getKey(), 0) / costEntry.getValue());
+ (double) fluidMap.getOrDefault(costEntry.getKey(), 0L) / costEntry.getValue());
}
if (currentParallel <= 0) {
return 0;
@@ -509,7 +509,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
}
double remainingCost;
- int providedAmount;
+ long providedAmount;
if (aInputs != null) {
nextRecipeItemCost: for (ItemStack recipeItemCost : mInputs) {