From bcb52ceecff13342e9131a48b0a4d14721c8611b Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:47:46 -0700 Subject: [PATCH 01/45] initial rework --- .../gregtech/api/recipes/chance/BaseChanceEntry.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java index b1bcb49f0ce..8569fac6508 100644 --- a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java +++ b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java @@ -11,10 +11,21 @@ public abstract class BaseChanceEntry implements ChanceEntry { private final T ingredient; private final int chance; + private final int numerator; + private final int denominator; public BaseChanceEntry(@NotNull T ingredient, int chance) { this.ingredient = ingredient; this.chance = chance; + this.numerator = 1; + this.denominator = (int) (1 / chance); + } + + public BaseChanceEntry(@NotNull T ingredient, int numerator, int denominator) { + this.ingredient = ingredient; + this.chance = Math.floorDiv(numerator, denominator); + this.numerator = numerator; + this.denominator = denominator; } @Override From 783e5f3e195ecc01f3fb942ec6ddb2ab7737cd0e Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:50:13 -0700 Subject: [PATCH 02/45] a bit more work --- .../api/recipes/chance/BaseChanceEntry.java | 18 ++++++++++++++++-- .../api/recipes/chance/ChanceEntry.java | 3 +++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java index 8569fac6508..811449386f6 100644 --- a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java +++ b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java @@ -1,5 +1,7 @@ package gregtech.api.recipes.chance; +import gregtech.api.recipes.chance.output.ChancedOutputLogic; + import org.jetbrains.annotations.NotNull; /** @@ -17,8 +19,10 @@ public abstract class BaseChanceEntry implements ChanceEntry { public BaseChanceEntry(@NotNull T ingredient, int chance) { this.ingredient = ingredient; this.chance = chance; - this.numerator = 1; - this.denominator = (int) (1 / chance); + // chance of 500 = 5% + // 5% = 5/100 or 500 / 10000 + this.numerator = chance; + this.denominator = ChancedOutputLogic.getMaxChancedValue(); } public BaseChanceEntry(@NotNull T ingredient, int numerator, int denominator) { @@ -37,4 +41,14 @@ public BaseChanceEntry(@NotNull T ingredient, int numerator, int denominator) { public int getChance() { return chance; } + + @Override + public int getNumerator() { + return numerator; + } + + @Override + public int getDenominator() { + return denominator; + } } diff --git a/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java b/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java index e5eeda1a875..fcdd17e89b0 100644 --- a/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java +++ b/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java @@ -20,6 +20,9 @@ public interface ChanceEntry { */ int getChance(); + int getNumerator(); + int getDenominator(); + /** * @return a copy of the chance entry */ From c29e0b17b8b1921287b6f22b955310f99f7c5711 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 13:51:39 -0700 Subject: [PATCH 03/45] :todayiwill: --- .../capability/impl/AbstractRecipeLogic.java | 14 ++++++-- .../java/gregtech/api/recipes/Recipe.java | 15 +++++--- .../api/recipes/chance/ChanceEntry.java | 1 + .../chance/boost/ChanceBoostFunction.java | 4 +-- .../chance/output/ChancedOutputList.java | 5 +-- .../chance/output/ChancedOutputLogic.java | 35 ++++++++++++++----- .../chance/output/ChancedOutputLogicTest.java | 15 +++++--- 7 files changed, 65 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 455ae3afd47..05c7e089a4c 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -24,6 +24,7 @@ import gregtech.api.util.GTLog; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.GTUtility; +import gregtech.api.util.ItemStackHashStrategy; import gregtech.common.ConfigHolder; import net.minecraft.item.ItemStack; @@ -37,12 +38,15 @@ import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.items.IItemHandlerModifiable; +import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenCustomHashMap; import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.Map; import static gregtech.api.GTValues.ULV; import static gregtech.api.recipes.logic.OverclockingLogic.*; @@ -70,7 +74,13 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable, protected int maxProgressTime; protected long recipeEUt; protected List fluidOutputs; + protected Map fluidChancesCache = new Object2IntArrayMap<>(); protected List itemOutputs; + protected Map itemChancesCache = new Object2IntOpenCustomHashMap<>( + ItemStackHashStrategy.builder() + .compareItem(true) + .compareDamage(true) + .build()); protected boolean isActive; protected boolean workingEnabled = true; @@ -949,9 +959,9 @@ protected void setupRecipe(@NotNull Recipe recipe) { RecipeMap map = getRecipeMap(); if (map != null) { this.fluidOutputs = GTUtility - .copyFluidList(recipe.getResultFluidOutputs(recipeTier, machineTier, map)); + .copyFluidList(recipe.getResultFluidOutputs(recipeTier, machineTier, map, fluidChancesCache)); this.itemOutputs = GTUtility - .copyStackList(recipe.getResultItemOutputs(recipeTier, machineTier, map)); + .copyStackList(recipe.getResultItemOutputs(recipeTier, machineTier, map, itemChancesCache)); } if (this.wasActiveAndNeedsUpdate) { diff --git a/src/main/java/gregtech/api/recipes/Recipe.java b/src/main/java/gregtech/api/recipes/Recipe.java index ff495651ac5..45f3f992a37 100644 --- a/src/main/java/gregtech/api/recipes/Recipe.java +++ b/src/main/java/gregtech/api/recipes/Recipe.java @@ -469,10 +469,11 @@ public List getOutputs() { * @param recipeMap The RecipeMap that the recipe is being performed upon, used for chanced output calculation * @return A list of all resulting ItemStacks from the recipe, after chance has been applied to any chanced outputs */ - public List getResultItemOutputs(int recipeTier, int machineTier, RecipeMap recipeMap) { + public List getResultItemOutputs(int recipeTier, int machineTier, RecipeMap recipeMap, + Map cache) { List outputs = new ArrayList<>(getOutputs()); ChanceBoostFunction function = recipeMap.getChanceFunction(); - List chancedOutputsList = getChancedOutputs().roll(function, recipeTier, machineTier); + List chancedOutputsList = getChancedOutputs().roll(function, recipeTier, machineTier, cache); if (chancedOutputsList == null) return outputs; @@ -502,6 +503,10 @@ public List getResultItemOutputs(int recipeTier, int machineTier, Rec return outputs; } + public List getResultItemOutputs(int recipeTier, int machineTier, RecipeMap recipeMap) { + return getResultItemOutputs(recipeTier, machineTier, recipeMap, Collections.emptyMap()); + } + /** * Returns the maximum possible recipe outputs from a recipe, divided into regular and chanced outputs * Takes into account any specific output limiters, ie macerator slots, to trim down the output list @@ -664,11 +669,13 @@ public List getAllFluidOutputs() { * @param recipeMap The RecipeMap that the recipe is being performed upon, used for chanced output calculation * @return A list of all resulting ItemStacks from the recipe, after chance has been applied to any chanced outputs */ - public List getResultFluidOutputs(int recipeTier, int machineTier, RecipeMap recipeMap) { + public List getResultFluidOutputs(int recipeTier, int machineTier, RecipeMap recipeMap, + Map cache) { List outputs = new ArrayList<>(GTUtility.copyFluidList(getFluidOutputs())); ChanceBoostFunction function = recipeMap.getChanceFunction(); - List chancedOutputsList = getChancedFluidOutputs().roll(function, recipeTier, machineTier); + List chancedOutputsList = getChancedFluidOutputs().roll(function, recipeTier, machineTier, + cache); if (chancedOutputsList == null) return outputs; diff --git a/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java b/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java index fcdd17e89b0..25aecbd1de5 100644 --- a/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java +++ b/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java @@ -21,6 +21,7 @@ public interface ChanceEntry { int getChance(); int getNumerator(); + int getDenominator(); /** diff --git a/src/main/java/gregtech/api/recipes/chance/boost/ChanceBoostFunction.java b/src/main/java/gregtech/api/recipes/chance/boost/ChanceBoostFunction.java index e885f08af58..780f3d87366 100644 --- a/src/main/java/gregtech/api/recipes/chance/boost/ChanceBoostFunction.java +++ b/src/main/java/gregtech/api/recipes/chance/boost/ChanceBoostFunction.java @@ -15,9 +15,9 @@ public interface ChanceBoostFunction { */ ChanceBoostFunction OVERCLOCK = (entry, recipeTier, machineTier) -> { int tierDiff = machineTier - recipeTier; - if (tierDiff <= 0) return entry.getChance(); // equal or invalid tiers do not boost at all + if (tierDiff <= 0) return entry.getNumerator(); // equal or invalid tiers do not boost at all if (recipeTier == GTValues.ULV) tierDiff--; // LV does not boost over ULV - return entry.getChance() + (entry.getChanceBoost() * tierDiff); + return entry.getNumerator() + (entry.getChanceBoost() * tierDiff); }; /** diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputList.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputList.java index 71856282127..553e5d86c24 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputList.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputList.java @@ -8,6 +8,7 @@ import java.util.Collections; import java.util.List; +import java.util.Map; /** * A list of rollable chanced outputs @@ -39,8 +40,8 @@ public ChancedOutputList(@NotNull ChancedOutputLogic chancedOutputLogic, @NotNul * @return a list of the rolled outputs */ public @Nullable @Unmodifiable List roll(@NotNull ChanceBoostFunction boostFunction, int baseTier, - int machineTier) { - return chancedOutputLogic.roll(getChancedEntries(), boostFunction, baseTier, machineTier); + int machineTier, Map cache) { + return chancedOutputLogic.roll(getChancedEntries(), boostFunction, baseTier, machineTier, cache); } public @NotNull ChancedOutputLogic getChancedOutputLogic() { diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 738d9176233..ba31f2dd948 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -11,6 +11,7 @@ import java.util.Collections; import java.util.List; +import java.util.Map; /** * Logic for determining which chanced outputs should be produced from a list @@ -26,15 +27,26 @@ public interface ChancedOutputLogic { public @Nullable @Unmodifiable > List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, @NotNull ChanceBoostFunction boostFunction, - int baseTier, int machineTier) { - ImmutableList.Builder builder = null; + int baseTier, int machineTier, + Map cache) { + ImmutableList.Builder builder = ImmutableList.builder(); for (T entry : chancedEntries) { - if (passesChance(getChance(entry, boostFunction, baseTier, machineTier))) { - if (builder == null) builder = ImmutableList.builder(); + int numerator = getChance(entry, boostFunction, baseTier, machineTier); + int denominator = entry.getDenominator(); + int cached = cache.get(entry.getIngredient()); + if (cached + numerator >= denominator) { builder.add(entry); + cache.put(entry.getIngredient(), cached + numerator - denominator); + } else { + cache.put(entry.getIngredient(), cached + numerator); } + // if (passesChance(getChance(entry, boostFunction, baseTier, machineTier))) { + // builder.add(entry); + // } } - return builder == null ? null : builder.build(); + + List list = builder.build(); + return list.size() == 0 ? null : list; } @Override @@ -57,7 +69,8 @@ public String toString() { public @Nullable @Unmodifiable > List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, @NotNull ChanceBoostFunction boostFunction, - int baseTier, int machineTier) { + int baseTier, int machineTier, + Map cache) { for (T entry : chancedEntries) { if (!passesChance(getChance(entry, boostFunction, baseTier, machineTier))) { return null; @@ -86,7 +99,8 @@ public String toString() { public @Nullable @Unmodifiable > List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, @NotNull ChanceBoostFunction boostFunction, - int baseTier, int machineTier) { + int baseTier, int machineTier, + Map cache) { for (T entry : chancedEntries) { if (passesChance(getChance(entry, boostFunction, baseTier, machineTier))) { return Collections.singletonList(entry); @@ -115,7 +129,8 @@ public String toString() { public @Nullable @Unmodifiable > List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, @NotNull ChanceBoostFunction boostFunction, - int baseTier, int machineTier) { + int baseTier, int machineTier, + Map cache) { return null; } @@ -167,12 +182,14 @@ static int getMaxChancedValue() { * @param boostFunction the function to boost the entries' chances * @param baseTier the base tier of the recipe * @param machineTier the tier the recipe is run at + * @param cache * @return a list of the produced outputs */ > @Nullable @Unmodifiable List<@NotNull T> roll( @NotNull @Unmodifiable List<@NotNull T> chancedEntries, @NotNull ChanceBoostFunction boostFunction, - int baseTier, int machineTier); + int baseTier, int machineTier, + Map cache); @NotNull String getTranslationKey(); diff --git a/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java b/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java index 4e6cbf026c9..6c6f016d2ef 100644 --- a/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java +++ b/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.List; public class ChancedOutputLogicTest { @@ -42,7 +43,8 @@ public void testORLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - List list = ChancedOutputLogic.OR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); + List list = ChancedOutputLogic.OR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, + Collections.emptyMap()); listsMatch(chanceEntries, list); } @@ -53,7 +55,8 @@ public void testANDLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", 0)); - List list = ChancedOutputLogic.AND.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); + List list = ChancedOutputLogic.AND.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, + Collections.emptyMap()); MatcherAssert.assertThat(list, CoreMatchers.nullValue()); chanceEntries = ImmutableList.of( @@ -61,7 +64,7 @@ public void testANDLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - list = ChancedOutputLogic.AND.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); + list = ChancedOutputLogic.AND.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, Collections.emptyMap()); listsMatch(chanceEntries, list); } @@ -72,7 +75,8 @@ public void testXORLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - List list = ChancedOutputLogic.XOR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); + List list = ChancedOutputLogic.XOR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, + Collections.emptyMap()); MatcherAssert.assertThat(list, CoreMatchers.notNullValue()); MatcherAssert.assertThat(list.size(), CoreMatchers.is(1)); MatcherAssert.assertThat(list.get(0).getIngredient(), CoreMatchers.is(chanceEntries.get(0).getIngredient())); @@ -85,7 +89,8 @@ public void testNONELogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - List list = ChancedOutputLogic.NONE.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); + List list = ChancedOutputLogic.NONE.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, + Collections.emptyMap()); MatcherAssert.assertThat(list, CoreMatchers.nullValue()); } } From bf6786895959de41df7fce224aa9d0ce5973fe58 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:54:07 -0700 Subject: [PATCH 04/45] apply to all logic types --- .../chance/output/ChancedOutputLogic.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index ba31f2dd948..4c994e42e48 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -1,6 +1,5 @@ package gregtech.api.recipes.chance.output; -import gregtech.api.GTValues; import gregtech.api.recipes.chance.boost.BoostableChanceEntry; import gregtech.api.recipes.chance.boost.ChanceBoostFunction; @@ -34,7 +33,7 @@ public interface ChancedOutputLogic { int numerator = getChance(entry, boostFunction, baseTier, machineTier); int denominator = entry.getDenominator(); int cached = cache.get(entry.getIngredient()); - if (cached + numerator >= denominator) { + if (passesChance(cached + numerator, denominator)) { builder.add(entry); cache.put(entry.getIngredient(), cached + numerator - denominator); } else { @@ -71,12 +70,17 @@ public String toString() { @NotNull ChanceBoostFunction boostFunction, int baseTier, int machineTier, Map cache) { + boolean failed = false; for (T entry : chancedEntries) { - if (!passesChance(getChance(entry, boostFunction, baseTier, machineTier))) { - return null; + int cached = cache.get(entry.getIngredient()); + int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; + int denominator = entry.getDenominator(); + if (!passesChance(numerator, denominator)) { + cache.put(entry.getIngredient(), numerator); + failed = true; } } - return ImmutableList.copyOf(chancedEntries); + return failed ? null : ImmutableList.copyOf(chancedEntries); } @Override @@ -102,7 +106,11 @@ public String toString() { int baseTier, int machineTier, Map cache) { for (T entry : chancedEntries) { - if (passesChance(getChance(entry, boostFunction, baseTier, machineTier))) { + int cached = cache.get(entry.getIngredient()); + int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; + int denominator = entry.getDenominator(); + if (passesChance(numerator, denominator)) { + cache.put(entry.getIngredient(), numerator); return Collections.singletonList(entry); } } @@ -161,11 +169,13 @@ static int getChance(@NotNull ChancedOutput entry, @NotNull ChanceBoostFuncti } /** - * @param chance the chance to check + * @param numerator the chance to check + * @param denominator * @return if the roll with the chance is successful */ - static boolean passesChance(int chance) { - return chance > 0 && GTValues.RNG.nextInt(getMaxChancedValue()) <= chance; + static boolean passesChance(int numerator, int denominator) { + return numerator >= denominator; +// return chance > 0 && GTValues.RNG.nextInt(getMaxChancedValue()) <= chance; } /** From 27520192121b25c2845e93fe0b8ef74f10532e5c Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:16:08 -0700 Subject: [PATCH 05/45] fix OR logic and handle overflow --- .../chance/output/ChancedOutputLogic.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 4c994e42e48..e63f463455e 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -30,15 +30,16 @@ public interface ChancedOutputLogic { Map cache) { ImmutableList.Builder builder = ImmutableList.builder(); for (T entry : chancedEntries) { - int numerator = getChance(entry, boostFunction, baseTier, machineTier); + int cached = cache.getOrDefault(entry.getIngredient(), 0); + int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; int denominator = entry.getDenominator(); - int cached = cache.get(entry.getIngredient()); - if (passesChance(cached + numerator, denominator)) { - builder.add(entry); - cache.put(entry.getIngredient(), cached + numerator - denominator); - } else { - cache.put(entry.getIngredient(), cached + numerator); + if (passesChance(numerator, denominator)) { + do { + builder.add(entry); + numerator -= denominator; + } while (passesChance(numerator, denominator)); } + cache.put(entry.getIngredient(), numerator); // if (passesChance(getChance(entry, boostFunction, baseTier, machineTier))) { // builder.add(entry); // } @@ -72,7 +73,7 @@ public String toString() { Map cache) { boolean failed = false; for (T entry : chancedEntries) { - int cached = cache.get(entry.getIngredient()); + int cached = cache.getOrDefault(entry.getIngredient(), 0); int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; int denominator = entry.getDenominator(); if (!passesChance(numerator, denominator)) { @@ -106,7 +107,7 @@ public String toString() { int baseTier, int machineTier, Map cache) { for (T entry : chancedEntries) { - int cached = cache.get(entry.getIngredient()); + int cached = cache.getOrDefault(entry.getIngredient(), 0); int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; int denominator = entry.getDenominator(); if (passesChance(numerator, denominator)) { From 3fca554d06da5941f246b35846ba594d61e34cb2 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:18:39 -0700 Subject: [PATCH 06/45] fix tests --- .../recipes/chance/output/ChancedOutputLogicTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java b/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java index 6c6f016d2ef..f2c8dbf6923 100644 --- a/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java +++ b/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test; import java.util.Collections; +import java.util.HashMap; import java.util.List; public class ChancedOutputLogicTest { @@ -44,7 +45,7 @@ public void testORLogic() { new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); List list = ChancedOutputLogic.OR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, - Collections.emptyMap()); + new HashMap<>()); listsMatch(chanceEntries, list); } @@ -56,7 +57,7 @@ public void testANDLogic() { new TestChancedOutput("c", 0)); List list = ChancedOutputLogic.AND.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, - Collections.emptyMap()); + new HashMap<>()); MatcherAssert.assertThat(list, CoreMatchers.nullValue()); chanceEntries = ImmutableList.of( @@ -76,7 +77,7 @@ public void testXORLogic() { new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); List list = ChancedOutputLogic.XOR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, - Collections.emptyMap()); + new HashMap<>()); MatcherAssert.assertThat(list, CoreMatchers.notNullValue()); MatcherAssert.assertThat(list.size(), CoreMatchers.is(1)); MatcherAssert.assertThat(list.get(0).getIngredient(), CoreMatchers.is(chanceEntries.get(0).getIngredient())); @@ -90,7 +91,7 @@ public void testNONELogic() { new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); List list = ChancedOutputLogic.NONE.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, - Collections.emptyMap()); + new HashMap<>()); MatcherAssert.assertThat(list, CoreMatchers.nullValue()); } } From c843bb26dfb9d980c973bc6652a56189014e3a1a Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:22:51 -0700 Subject: [PATCH 07/45] remove commented code --- .../gregtech/api/recipes/chance/output/ChancedOutputLogic.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index e63f463455e..43460d0be13 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -40,9 +40,6 @@ public interface ChancedOutputLogic { } while (passesChance(numerator, denominator)); } cache.put(entry.getIngredient(), numerator); - // if (passesChance(getChance(entry, boostFunction, baseTier, machineTier))) { - // builder.add(entry); - // } } List list = builder.build(); From be2b58edd255741057fdfa4ef1b62dc07d6a2064 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:47:58 -0700 Subject: [PATCH 08/45] allow null and null check --- .../java/gregtech/api/recipes/Recipe.java | 2 +- .../chance/output/ChancedOutputLogic.java | 36 +++++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/Recipe.java b/src/main/java/gregtech/api/recipes/Recipe.java index 45f3f992a37..8de6e048cc9 100644 --- a/src/main/java/gregtech/api/recipes/Recipe.java +++ b/src/main/java/gregtech/api/recipes/Recipe.java @@ -504,7 +504,7 @@ public List getResultItemOutputs(int recipeTier, int machineTier, Rec } public List getResultItemOutputs(int recipeTier, int machineTier, RecipeMap recipeMap) { - return getResultItemOutputs(recipeTier, machineTier, recipeMap, Collections.emptyMap()); + return getResultItemOutputs(recipeTier, machineTier, recipeMap, null); } /** diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 43460d0be13..9e48913fe33 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -27,10 +27,13 @@ public interface ChancedOutputLogic { T extends ChancedOutput> List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, @NotNull ChanceBoostFunction boostFunction, int baseTier, int machineTier, - Map cache) { + @Nullable Map cache) { ImmutableList.Builder builder = ImmutableList.builder(); for (T entry : chancedEntries) { - int cached = cache.getOrDefault(entry.getIngredient(), 0); + int cached = 0; + if (cache != null) + cached = cache.getOrDefault(entry.getIngredient(), 0); + int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; int denominator = entry.getDenominator(); if (passesChance(numerator, denominator)) { @@ -39,7 +42,8 @@ public interface ChancedOutputLogic { numerator -= denominator; } while (passesChance(numerator, denominator)); } - cache.put(entry.getIngredient(), numerator); + if (cache != null) + cache.put(entry.getIngredient(), numerator); } List list = builder.build(); @@ -67,14 +71,19 @@ public String toString() { T extends ChancedOutput> List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, @NotNull ChanceBoostFunction boostFunction, int baseTier, int machineTier, - Map cache) { + @Nullable Map cache) { boolean failed = false; for (T entry : chancedEntries) { - int cached = cache.getOrDefault(entry.getIngredient(), 0); + int cached = 0; + if (cache != null) + cached = cache.getOrDefault(entry.getIngredient(), 0); + int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; int denominator = entry.getDenominator(); if (!passesChance(numerator, denominator)) { - cache.put(entry.getIngredient(), numerator); + if (cache != null) + cache.put(entry.getIngredient(), numerator); + failed = true; } } @@ -102,13 +111,18 @@ public String toString() { T extends ChancedOutput> List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, @NotNull ChanceBoostFunction boostFunction, int baseTier, int machineTier, - Map cache) { + @Nullable Map cache) { for (T entry : chancedEntries) { - int cached = cache.getOrDefault(entry.getIngredient(), 0); + int cached = 0; + if (cache != null) + cached = cache.getOrDefault(entry.getIngredient(), 0); + int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; int denominator = entry.getDenominator(); if (passesChance(numerator, denominator)) { - cache.put(entry.getIngredient(), numerator); + if (cache != null) + cache.put(entry.getIngredient(), numerator); + return Collections.singletonList(entry); } } @@ -136,7 +150,7 @@ public String toString() { T extends ChancedOutput> List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, @NotNull ChanceBoostFunction boostFunction, int baseTier, int machineTier, - Map cache) { + @Nullable Map cache) { return null; } @@ -197,7 +211,7 @@ static int getMaxChancedValue() { @NotNull @Unmodifiable List<@NotNull T> chancedEntries, @NotNull ChanceBoostFunction boostFunction, int baseTier, int machineTier, - Map cache); + @Nullable Map cache); @NotNull String getTranslationKey(); From ff83c37aeec43a65bbb4fb5719400cbddd77b5da Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:53:29 -0700 Subject: [PATCH 09/45] add default roll method --- .../chance/output/ChancedOutputLogic.java | 16 ++++++++++++++++ .../chance/output/ChancedOutputLogicTest.java | 14 +++++--------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 9e48913fe33..5a5fa8a46fb 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -213,6 +213,22 @@ static int getMaxChancedValue() { int baseTier, int machineTier, @Nullable Map cache); + /** + * Roll the chance and attempt to produce the output + * + * @param chancedEntries the list of entries to roll + * @param boostFunction the function to boost the entries' chances + * @param baseTier the base tier of the recipe + * @param machineTier the tier the recipe is run at + * @return a list of the produced outputs + */ + default > @Nullable @Unmodifiable List<@NotNull T> roll( + @NotNull @Unmodifiable List<@NotNull T> chancedEntries, + @NotNull ChanceBoostFunction boostFunction, + int baseTier, int machineTier) { + return roll(chancedEntries, boostFunction, baseTier, machineTier, null); + } + @NotNull String getTranslationKey(); } diff --git a/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java b/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java index f2c8dbf6923..fbe4a191a6b 100644 --- a/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java +++ b/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java @@ -44,8 +44,7 @@ public void testORLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - List list = ChancedOutputLogic.OR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, - new HashMap<>()); + List list = ChancedOutputLogic.OR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); listsMatch(chanceEntries, list); } @@ -56,8 +55,7 @@ public void testANDLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", 0)); - List list = ChancedOutputLogic.AND.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, - new HashMap<>()); + List list = ChancedOutputLogic.AND.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); MatcherAssert.assertThat(list, CoreMatchers.nullValue()); chanceEntries = ImmutableList.of( @@ -65,7 +63,7 @@ public void testANDLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - list = ChancedOutputLogic.AND.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, Collections.emptyMap()); + list = ChancedOutputLogic.AND.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); listsMatch(chanceEntries, list); } @@ -76,8 +74,7 @@ public void testXORLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - List list = ChancedOutputLogic.XOR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, - new HashMap<>()); + List list = ChancedOutputLogic.XOR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); MatcherAssert.assertThat(list, CoreMatchers.notNullValue()); MatcherAssert.assertThat(list.size(), CoreMatchers.is(1)); MatcherAssert.assertThat(list.get(0).getIngredient(), CoreMatchers.is(chanceEntries.get(0).getIngredient())); @@ -90,8 +87,7 @@ public void testNONELogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - List list = ChancedOutputLogic.NONE.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0, - new HashMap<>()); + List list = ChancedOutputLogic.NONE.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); MatcherAssert.assertThat(list, CoreMatchers.nullValue()); } } From beeb7bebacb2349c6b375c742340b7c181005f10 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:06:51 -0700 Subject: [PATCH 10/45] improve XOR --- .../api/recipes/chance/output/ChancedOutputLogic.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 5a5fa8a46fb..f8eb7330fd2 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -82,7 +82,7 @@ public String toString() { int denominator = entry.getDenominator(); if (!passesChance(numerator, denominator)) { if (cache != null) - cache.put(entry.getIngredient(), numerator); + cache.put(entry.getIngredient(), numerator % denominator); failed = true; } @@ -112,6 +112,7 @@ public String toString() { @NotNull ChanceBoostFunction boostFunction, int baseTier, int machineTier, @Nullable Map cache) { + T selected = null; for (T entry : chancedEntries) { int cached = 0; if (cache != null) @@ -121,12 +122,13 @@ public String toString() { int denominator = entry.getDenominator(); if (passesChance(numerator, denominator)) { if (cache != null) - cache.put(entry.getIngredient(), numerator); + cache.put(entry.getIngredient(), numerator % denominator); - return Collections.singletonList(entry); + if (selected == null) + selected = entry; } } - return null; + return selected == null ? null : Collections.singletonList(selected); } @Override From 75c1238771760837672396c71de32741b4686d64 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:13:17 -0700 Subject: [PATCH 11/45] not actually useful to seperate the fraction --- .../api/recipes/chance/BaseChanceEntry.java | 23 ------------------- .../api/recipes/chance/ChanceEntry.java | 4 ---- .../chance/output/ChancedOutputLogic.java | 22 ++++++++---------- 3 files changed, 9 insertions(+), 40 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java index 811449386f6..38b040bc50c 100644 --- a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java +++ b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java @@ -13,23 +13,10 @@ public abstract class BaseChanceEntry implements ChanceEntry { private final T ingredient; private final int chance; - private final int numerator; - private final int denominator; public BaseChanceEntry(@NotNull T ingredient, int chance) { this.ingredient = ingredient; this.chance = chance; - // chance of 500 = 5% - // 5% = 5/100 or 500 / 10000 - this.numerator = chance; - this.denominator = ChancedOutputLogic.getMaxChancedValue(); - } - - public BaseChanceEntry(@NotNull T ingredient, int numerator, int denominator) { - this.ingredient = ingredient; - this.chance = Math.floorDiv(numerator, denominator); - this.numerator = numerator; - this.denominator = denominator; } @Override @@ -41,14 +28,4 @@ public BaseChanceEntry(@NotNull T ingredient, int numerator, int denominator) { public int getChance() { return chance; } - - @Override - public int getNumerator() { - return numerator; - } - - @Override - public int getDenominator() { - return denominator; - } } diff --git a/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java b/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java index 25aecbd1de5..e5eeda1a875 100644 --- a/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java +++ b/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java @@ -20,10 +20,6 @@ public interface ChanceEntry { */ int getChance(); - int getNumerator(); - - int getDenominator(); - /** * @return a copy of the chance entry */ diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index f8eb7330fd2..2029e42617b 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -35,12 +35,11 @@ public interface ChancedOutputLogic { cached = cache.getOrDefault(entry.getIngredient(), 0); int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; - int denominator = entry.getDenominator(); - if (passesChance(numerator, denominator)) { + if (passesChance(numerator)) { do { builder.add(entry); - numerator -= denominator; - } while (passesChance(numerator, denominator)); + numerator -= getMaxChancedValue(); + } while (passesChance(numerator)); } if (cache != null) cache.put(entry.getIngredient(), numerator); @@ -79,10 +78,9 @@ public String toString() { cached = cache.getOrDefault(entry.getIngredient(), 0); int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; - int denominator = entry.getDenominator(); - if (!passesChance(numerator, denominator)) { + if (!passesChance(numerator)) { if (cache != null) - cache.put(entry.getIngredient(), numerator % denominator); + cache.put(entry.getIngredient(), numerator % getMaxChancedValue()); failed = true; } @@ -119,10 +117,9 @@ public String toString() { cached = cache.getOrDefault(entry.getIngredient(), 0); int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; - int denominator = entry.getDenominator(); - if (passesChance(numerator, denominator)) { + if (passesChance(numerator)) { if (cache != null) - cache.put(entry.getIngredient(), numerator % denominator); + cache.put(entry.getIngredient(), numerator % getMaxChancedValue()); if (selected == null) selected = entry; @@ -184,11 +181,10 @@ static int getChance(@NotNull ChancedOutput entry, @NotNull ChanceBoostFuncti /** * @param numerator the chance to check - * @param denominator * @return if the roll with the chance is successful */ - static boolean passesChance(int numerator, int denominator) { - return numerator >= denominator; + static boolean passesChance(int numerator) { + return numerator >= getMaxChancedValue(); // return chance > 0 && GTValues.RNG.nextInt(getMaxChancedValue()) <= chance; } From c9ea878a13049f4b6e601c3f1e877594a4630376 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:14:47 -0700 Subject: [PATCH 12/45] forgor + less spots --- .../api/recipes/chance/BaseChanceEntry.java | 2 -- .../recipes/chance/boost/ChanceBoostFunction.java | 4 ++-- .../recipes/chance/output/ChancedOutputLogic.java | 13 +++++++------ .../chance/output/ChancedOutputLogicTest.java | 2 -- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java index 38b040bc50c..b1bcb49f0ce 100644 --- a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java +++ b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java @@ -1,7 +1,5 @@ package gregtech.api.recipes.chance; -import gregtech.api.recipes.chance.output.ChancedOutputLogic; - import org.jetbrains.annotations.NotNull; /** diff --git a/src/main/java/gregtech/api/recipes/chance/boost/ChanceBoostFunction.java b/src/main/java/gregtech/api/recipes/chance/boost/ChanceBoostFunction.java index 780f3d87366..e885f08af58 100644 --- a/src/main/java/gregtech/api/recipes/chance/boost/ChanceBoostFunction.java +++ b/src/main/java/gregtech/api/recipes/chance/boost/ChanceBoostFunction.java @@ -15,9 +15,9 @@ public interface ChanceBoostFunction { */ ChanceBoostFunction OVERCLOCK = (entry, recipeTier, machineTier) -> { int tierDiff = machineTier - recipeTier; - if (tierDiff <= 0) return entry.getNumerator(); // equal or invalid tiers do not boost at all + if (tierDiff <= 0) return entry.getChance(); // equal or invalid tiers do not boost at all if (recipeTier == GTValues.ULV) tierDiff--; // LV does not boost over ULV - return entry.getNumerator() + (entry.getChanceBoost() * tierDiff); + return entry.getChance() + (entry.getChanceBoost() * tierDiff); }; /** diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 2029e42617b..04a93ddd54a 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -180,12 +180,12 @@ static int getChance(@NotNull ChancedOutput entry, @NotNull ChanceBoostFuncti } /** - * @param numerator the chance to check + * @param numerator the chance to check * @return if the roll with the chance is successful */ static boolean passesChance(int numerator) { return numerator >= getMaxChancedValue(); -// return chance > 0 && GTValues.RNG.nextInt(getMaxChancedValue()) <= chance; + // return chance > 0 && GTValues.RNG.nextInt(getMaxChancedValue()) <= chance; } /** @@ -220,10 +220,11 @@ static int getMaxChancedValue() { * @param machineTier the tier the recipe is run at * @return a list of the produced outputs */ - default > @Nullable @Unmodifiable List<@NotNull T> roll( - @NotNull @Unmodifiable List<@NotNull T> chancedEntries, - @NotNull ChanceBoostFunction boostFunction, - int baseTier, int machineTier) { + default > @Nullable @Unmodifiable List<@NotNull T> roll( + @NotNull @Unmodifiable List<@NotNull T> chancedEntries, + @NotNull ChanceBoostFunction boostFunction, + int baseTier, + int machineTier) { return roll(chancedEntries, boostFunction, baseTier, machineTier, null); } diff --git a/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java b/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java index fbe4a191a6b..4e6cbf026c9 100644 --- a/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java +++ b/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java @@ -10,8 +10,6 @@ import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.Test; -import java.util.Collections; -import java.util.HashMap; import java.util.List; public class ChancedOutputLogicTest { From a54a1fb0dabe0132f4f608f7c4ca9d1a3765b2e2 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:21:43 -0700 Subject: [PATCH 13/45] clear chance cache on new recipe --- .../java/gregtech/api/capability/impl/AbstractRecipeLogic.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 05c7e089a4c..ca018ca67a5 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -397,6 +397,8 @@ protected void trySearchNewRecipe() { // If there is no active recipe, then we need to find one. } else { currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); + fluidChancesCache.clear(); + itemChancesCache.clear(); } // If a recipe was found, then inputs were valid. Cache found recipe. if (currentRecipe != null) { From c89bb0e7c8e875f57c4e02be3722fab52321cccb Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 12:29:45 -0700 Subject: [PATCH 14/45] nvm we still need fraction split for handling irrational fractions --- .../api/recipes/chance/BaseChanceEntry.java | 14 +++++++++++++ .../chance/output/ChancedOutputLogic.java | 20 +++++++++---------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java index b1bcb49f0ce..a1380cac442 100644 --- a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java +++ b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java @@ -1,5 +1,7 @@ package gregtech.api.recipes.chance; +import gregtech.api.recipes.chance.output.ChancedOutputLogic; + import org.jetbrains.annotations.NotNull; /** @@ -11,10 +13,18 @@ public abstract class BaseChanceEntry implements ChanceEntry { private final T ingredient; private final int chance; + private final int maxChance; public BaseChanceEntry(@NotNull T ingredient, int chance) { this.ingredient = ingredient; this.chance = chance; + this.maxChance = ChancedOutputLogic.getMaxChancedValue(); + } + + public BaseChanceEntry(@NotNull T ingredient, int chance, int maxChance) { + this.ingredient = ingredient; + this.chance = chance; + this.maxChance = maxChance; } @Override @@ -26,4 +36,8 @@ public BaseChanceEntry(@NotNull T ingredient, int chance) { public int getChance() { return chance; } + + public int getMaxChance() { + return maxChance; + } } diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 04a93ddd54a..5f6c4fdcd73 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -35,11 +35,11 @@ public interface ChancedOutputLogic { cached = cache.getOrDefault(entry.getIngredient(), 0); int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; - if (passesChance(numerator)) { + int maxChance = entry.getMaxChance(); + if (passesChance(numerator, maxChance)) { do { builder.add(entry); - numerator -= getMaxChancedValue(); - } while (passesChance(numerator)); + } while ((numerator -= maxChance) > maxChance); } if (cache != null) cache.put(entry.getIngredient(), numerator); @@ -78,9 +78,9 @@ public String toString() { cached = cache.getOrDefault(entry.getIngredient(), 0); int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; - if (!passesChance(numerator)) { + if (!passesChance(numerator, entry.getMaxChance())) { if (cache != null) - cache.put(entry.getIngredient(), numerator % getMaxChancedValue()); + cache.put(entry.getIngredient(), numerator % entry.getMaxChance()); failed = true; } @@ -117,9 +117,9 @@ public String toString() { cached = cache.getOrDefault(entry.getIngredient(), 0); int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; - if (passesChance(numerator)) { + if (passesChance(numerator, entry.getMaxChance())) { if (cache != null) - cache.put(entry.getIngredient(), numerator % getMaxChancedValue()); + cache.put(entry.getIngredient(), numerator % entry.getMaxChance()); if (selected == null) selected = entry; @@ -180,11 +180,11 @@ static int getChance(@NotNull ChancedOutput entry, @NotNull ChanceBoostFuncti } /** - * @param numerator the chance to check + * @param chance the chance to check * @return if the roll with the chance is successful */ - static boolean passesChance(int numerator) { - return numerator >= getMaxChancedValue(); + static boolean passesChance(int chance, int maxChance) { + return chance >= maxChance; // return chance > 0 && GTValues.RNG.nextInt(getMaxChancedValue()) <= chance; } From f6acf900d461f15d43408f7db6d87eed864ad637 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 12:53:25 -0700 Subject: [PATCH 15/45] more fixed to logic --- .../chance/output/ChancedOutputLogic.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 5f6c4fdcd73..a7298abf421 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -30,19 +30,17 @@ public interface ChancedOutputLogic { @Nullable Map cache) { ImmutableList.Builder builder = ImmutableList.builder(); for (T entry : chancedEntries) { - int cached = 0; - if (cache != null) - cached = cache.getOrDefault(entry.getIngredient(), 0); + int cached = getCachedChance(entry.getIngredient(), cache); - int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; + int chance = getChance(entry, boostFunction, baseTier, machineTier) + cached; int maxChance = entry.getMaxChance(); - if (passesChance(numerator, maxChance)) { + if (passesChance(chance, maxChance)) { do { builder.add(entry); - } while ((numerator -= maxChance) > maxChance); + chance -= maxChance; + } while (passesChance(chance, maxChance)); } - if (cache != null) - cache.put(entry.getIngredient(), numerator); + updateCachedChance(entry.getIngredient(), cache, chance); } List list = builder.build(); @@ -73,17 +71,13 @@ public String toString() { @Nullable Map cache) { boolean failed = false; for (T entry : chancedEntries) { - int cached = 0; - if (cache != null) - cached = cache.getOrDefault(entry.getIngredient(), 0); - - int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; - if (!passesChance(numerator, entry.getMaxChance())) { - if (cache != null) - cache.put(entry.getIngredient(), numerator % entry.getMaxChance()); + int cached = getCachedChance(entry.getIngredient(), cache); + int chance = getChance(entry, boostFunction, baseTier, machineTier) + cached; + if (!passesChance(chance, entry.getMaxChance())) { failed = true; } + updateCachedChance(entry.getIngredient(), cache, chance); } return failed ? null : ImmutableList.copyOf(chancedEntries); } @@ -116,14 +110,11 @@ public String toString() { if (cache != null) cached = cache.getOrDefault(entry.getIngredient(), 0); - int numerator = getChance(entry, boostFunction, baseTier, machineTier) + cached; - if (passesChance(numerator, entry.getMaxChance())) { - if (cache != null) - cache.put(entry.getIngredient(), numerator % entry.getMaxChance()); - - if (selected == null) - selected = entry; + int chance = getChance(entry, boostFunction, baseTier, machineTier) + cached; + if (passesChance(chance, entry.getMaxChance()) && selected == null) { + selected = entry; } + updateCachedChance(entry.getIngredient(), cache, chance); } return selected == null ? null : Collections.singletonList(selected); } @@ -195,6 +186,15 @@ static int getMaxChancedValue() { return 10_000; } + static int getCachedChance(I ingredient, @Nullable Map cache) { + return cache == null ? 0 : cache.getOrDefault(ingredient, 0); + } + + static void updateCachedChance(I ingredient, @Nullable Map cache, int chance) { + if (cache == null) return; + cache.put(ingredient, chance); + } + /** * Roll the chance and attempt to produce the output * From 8bc237852c789f1400b0adfc818d9b8594c15c8d Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 12:53:48 -0700 Subject: [PATCH 16/45] add methods to RecipeBuilder add constructors --- .../gregtech/api/recipes/RecipeBuilder.java | 36 +++++++++++++++++++ .../chance/output/BoostableChanceOutput.java | 5 +++ .../recipes/chance/output/ChancedOutput.java | 5 +++ .../chance/output/impl/ChancedItemOutput.java | 4 +++ 4 files changed, 50 insertions(+) diff --git a/src/main/java/gregtech/api/recipes/RecipeBuilder.java b/src/main/java/gregtech/api/recipes/RecipeBuilder.java index d12ec1afb90..bebb296423a 100644 --- a/src/main/java/gregtech/api/recipes/RecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeBuilder.java @@ -650,6 +650,42 @@ public R chancedOutput(MetaItem.MetaValueItem item, int chance, int tierChanc return chancedOutput(item, 1, chance, tierChanceBoost); } + public R chancedOutput2(ItemStack stack, int chance, int maxChance, int tierChanceBoost) { + if (stack == null || stack.isEmpty()) { + return (R) this; + } + if (0 >= chance || chance > ChancedOutputLogic.getMaxChancedValue()) { + GTLog.logger.error("Chance cannot be less or equal to 0 or more than {}. Actual: {}.", + ChancedOutputLogic.getMaxChancedValue(), chance, new Throwable()); + recipeStatus = EnumValidationResult.INVALID; + return (R) this; + } + if (chance >= maxChance || maxChance > ChancedOutputLogic.getMaxChancedValue()) { + GTLog.logger.error("Max Chance cannot be less or equal to Chance or more than {}. Actual: {}.", + ChancedOutputLogic.getMaxChancedValue(), maxChance, new Throwable()); + recipeStatus = EnumValidationResult.INVALID; + return (R) this; + } + this.chancedOutputs.add(new ChancedItemOutput(stack.copy(), chance, maxChance, tierChanceBoost)); + return (R) this; + } + + public R chancedOutput2(OrePrefix prefix, Material material, int count, int chance, int maxChance, int tierChanceBoost) { + return chancedOutput2(OreDictUnifier.get(prefix, material, count), chance, maxChance, tierChanceBoost); + } + + public R chancedOutput2(OrePrefix prefix, Material material, int chance, int maxChance, int tierChanceBoost) { + return chancedOutput2(prefix, material, 1, chance, maxChance, tierChanceBoost); + } + + public R chancedOutput2(MetaItem.MetaValueItem item, int count, int chance, int maxChance, int tierChanceBoost) { + return chancedOutput2(item.getStackForm(count), chance, maxChance, tierChanceBoost); + } + + public R chancedOutput2(MetaItem.MetaValueItem item, int chance, int maxChance, int tierChanceBoost) { + return chancedOutput2(item, 1, chance, maxChance, tierChanceBoost); + } + public R chancedOutputs(List chancedOutputs) { for (ChancedItemOutput output : chancedOutputs) { this.chancedOutputs.add(output.copy()); diff --git a/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java b/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java index c7cadf8bc7c..8674b8e0ca3 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java @@ -18,6 +18,11 @@ public BoostableChanceOutput(@NotNull T ingredient, int chance, int chanceBoost) this.chanceBoost = chanceBoost; } + public BoostableChanceOutput(@NotNull T ingredient, int chance, int maxChance, int chanceBoost) { + super(ingredient, chance, maxChance); + this.chanceBoost = chanceBoost; + } + @Override public int getChanceBoost() { return this.chanceBoost; diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java index 9689fc1b208..ff6cd2f7de2 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java @@ -14,4 +14,9 @@ public abstract class ChancedOutput extends BaseChanceEntry { public ChancedOutput(@NotNull T ingredient, int chance) { super(ingredient, chance); } + + + public ChancedOutput(@NotNull T ingredient, int chance, int maxChance) { + super(ingredient, chance, maxChance); + } } diff --git a/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedItemOutput.java b/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedItemOutput.java index b49e640d942..c119bebe351 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedItemOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedItemOutput.java @@ -16,6 +16,10 @@ public ChancedItemOutput(@NotNull ItemStack ingredient, int chance, int chanceBo super(ingredient, chance, chanceBoost); } + public ChancedItemOutput(@NotNull ItemStack ingredient, int chance, int maxChance, int chanceBoost) { + super(ingredient, chance, maxChance, chanceBoost); + } + @Override public @NotNull ChancedItemOutput copy() { return new ChancedItemOutput(getIngredient().copy(), getChance(), getChanceBoost()); From 86c2f9018993e1c92d1da7cd5b9769d20d2ec6b6 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 12:55:01 -0700 Subject: [PATCH 17/45] forgor fluids --- .../api/recipes/chance/output/impl/ChancedFluidOutput.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedFluidOutput.java b/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedFluidOutput.java index 81a145fe1c8..de7732083a5 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedFluidOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedFluidOutput.java @@ -15,6 +15,10 @@ public ChancedFluidOutput(@NotNull FluidStack ingredient, int chance, int chance super(ingredient, chance, chanceBoost); } + public ChancedFluidOutput(@NotNull FluidStack ingredient, int chance, int maxChance, int chanceBoost) { + super(ingredient, chance, maxChance, chanceBoost); + } + @Override public @NotNull ChancedFluidOutput copy() { return new ChancedFluidOutput(getIngredient().copy(), getChance(), getChanceBoost()); From a95311f0cd1441dc109477dc08c04903f94d7114 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 13:08:13 -0700 Subject: [PATCH 18/45] fix and improve RecipeBuilder methods --- .../gregtech/api/recipes/RecipeBuilder.java | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/RecipeBuilder.java b/src/main/java/gregtech/api/recipes/RecipeBuilder.java index bebb296423a..fe90b010c50 100644 --- a/src/main/java/gregtech/api/recipes/RecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeBuilder.java @@ -650,10 +650,31 @@ public R chancedOutput(MetaItem.MetaValueItem item, int chance, int tierChanc return chancedOutput(item, 1, chance, tierChanceBoost); } - public R chancedOutput2(ItemStack stack, int chance, int maxChance, int tierChanceBoost) { + public R chancedOutput(ItemStack stack, String fraction, int tierChanceBoost) { if (stack == null || stack.isEmpty()) { return (R) this; } + + String[] split = fraction.split("/"); + if (split.length != 2) { + GTLog.logger.error("Fraction was not parsed correctly! Expected format is \"1/3\". Actual: \"{}\".", + fraction, new Throwable()); + recipeStatus = EnumValidationResult.INVALID; + return (R) this; + } + + int chance; + int maxChance; + try { + chance = Integer.parseInt(split[0]); + maxChance = Integer.parseInt(split[1]); + } catch (NumberFormatException e) { + GTLog.logger.error("Fraction was not parsed correctly! Expected format is \"1/3\". Actual: \"{}\".", + fraction, new Throwable()); + recipeStatus = EnumValidationResult.INVALID; + return (R) this; + } + if (0 >= chance || chance > ChancedOutputLogic.getMaxChancedValue()) { GTLog.logger.error("Chance cannot be less or equal to 0 or more than {}. Actual: {}.", ChancedOutputLogic.getMaxChancedValue(), chance, new Throwable()); @@ -670,20 +691,20 @@ public R chancedOutput2(ItemStack stack, int chance, int maxChance, int tierChan return (R) this; } - public R chancedOutput2(OrePrefix prefix, Material material, int count, int chance, int maxChance, int tierChanceBoost) { - return chancedOutput2(OreDictUnifier.get(prefix, material, count), chance, maxChance, tierChanceBoost); + public R chancedOutput(OrePrefix prefix, Material material, int count, String fraction, int tierChanceBoost) { + return chancedOutput(OreDictUnifier.get(prefix, material, count), fraction, tierChanceBoost); } - public R chancedOutput2(OrePrefix prefix, Material material, int chance, int maxChance, int tierChanceBoost) { - return chancedOutput2(prefix, material, 1, chance, maxChance, tierChanceBoost); + public R chancedOutput(OrePrefix prefix, Material material, String fraction, int tierChanceBoost) { + return chancedOutput(prefix, material, 1, fraction, tierChanceBoost); } - public R chancedOutput2(MetaItem.MetaValueItem item, int count, int chance, int maxChance, int tierChanceBoost) { - return chancedOutput2(item.getStackForm(count), chance, maxChance, tierChanceBoost); + public R chancedOutput(MetaItem.MetaValueItem item, int count, String fraction, int tierChanceBoost) { + return chancedOutput(item.getStackForm(count), fraction, tierChanceBoost); } - public R chancedOutput2(MetaItem.MetaValueItem item, int chance, int maxChance, int tierChanceBoost) { - return chancedOutput2(item, 1, chance, maxChance, tierChanceBoost); + public R chancedOutput(MetaItem.MetaValueItem item, String fraction, int tierChanceBoost) { + return chancedOutput(item, 1, fraction, tierChanceBoost); } public R chancedOutputs(List chancedOutputs) { From 9e4a06880c1a5233b9723f56cf72b53515a24908 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 13:28:19 -0700 Subject: [PATCH 19/45] convert certain chances to fraction form --- .../loaders/recipe/MachineRecipeLoader.java | 25 ++++++++++--------- .../loaders/recipe/MiscRecipeLoader.java | 2 +- .../recipe/chemistry/PetrochemRecipes.java | 16 ++++++------ .../recipe/chemistry/ReactorRecipes.java | 16 ++++++------ .../recipe/chemistry/SeparationRecipes.java | 8 +++--- .../recipe/handlers/OreRecipeHandler.java | 12 ++++----- 6 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java index 13606711c42..6c34975163b 100644 --- a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java @@ -969,7 +969,7 @@ private static void registerBlastFurnaceRecipes() { .input(ingot, Iron) .fluidInputs(Oxygen.getFluid(200)) .output(ingot, Steel) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .blastFurnaceTemp(1000) .buildAndRegister(); @@ -977,7 +977,7 @@ private static void registerBlastFurnaceRecipes() { .input(dust, Iron) .fluidInputs(Oxygen.getFluid(200)) .output(ingot, Steel) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .circuitMeta(2) .blastFurnaceTemp(1000) .buildAndRegister(); @@ -986,7 +986,7 @@ private static void registerBlastFurnaceRecipes() { .input(ingot, WroughtIron) .fluidInputs(Oxygen.getFluid(200)) .output(ingot, Steel) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .blastFurnaceTemp(1000) .buildAndRegister(); @@ -994,7 +994,7 @@ private static void registerBlastFurnaceRecipes() { .input(dust, WroughtIron) .fluidInputs(Oxygen.getFluid(200)) .output(ingot, Steel) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .circuitMeta(2) .blastFurnaceTemp(1000) .buildAndRegister(); @@ -1003,7 +1003,7 @@ private static void registerBlastFurnaceRecipes() { .input(dust, Iron, 4) .input(dust, Carbon) .output(ingot, Steel, 4) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .blastFurnaceTemp(2000) .buildAndRegister(); @@ -1011,19 +1011,19 @@ private static void registerBlastFurnaceRecipes() { .input(dust, WroughtIron, 4) .input(dust, Carbon) .output(ingot, Steel, 4) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .blastFurnaceTemp(2000) .buildAndRegister(); // Aluminium from aluminium oxide gems BLAST_RECIPES.recipeBuilder().duration(400).EUt(100).input(dust, Ruby).output(nugget, Aluminium, 3) - .chancedOutput(dust, Ash, 1111, 0).blastFurnaceTemp(1200).buildAndRegister(); + .chancedOutput(dust, Ash, "1/9", 0).blastFurnaceTemp(1200).buildAndRegister(); BLAST_RECIPES.recipeBuilder().duration(320).EUt(100).input(gem, Ruby).output(nugget, Aluminium, 3) - .chancedOutput(dust, Ash, 1111, 0).blastFurnaceTemp(1200).buildAndRegister(); + .chancedOutput(dust, Ash, "1/9", 0).blastFurnaceTemp(1200).buildAndRegister(); BLAST_RECIPES.recipeBuilder().duration(400).EUt(100).input(dust, GreenSapphire).output(nugget, Aluminium, 3) - .chancedOutput(dust, Ash, 1111, 0).blastFurnaceTemp(1200).buildAndRegister(); + .chancedOutput(dust, Ash, "1/9", 0).blastFurnaceTemp(1200).buildAndRegister(); BLAST_RECIPES.recipeBuilder().duration(320).EUt(100).input(gem, GreenSapphire).output(nugget, Aluminium, 3) - .chancedOutput(dust, Ash, 1111, 0).blastFurnaceTemp(1200).buildAndRegister(); + .chancedOutput(dust, Ash, "1/9", 0).blastFurnaceTemp(1200).buildAndRegister(); BLAST_RECIPES.recipeBuilder().duration(400).EUt(100).input(dust, Sapphire).output(nugget, Aluminium, 3) .blastFurnaceTemp(1200).buildAndRegister(); BLAST_RECIPES.recipeBuilder().duration(320).EUt(100).input(gem, Sapphire).output(nugget, Aluminium, 3) @@ -1084,7 +1084,7 @@ private static void registerBlastFurnaceMetallurgyRecipes() { .input(dust, SiliconDioxide, 3) .input(dust, Carbon, 2) .output(ingotHot, Silicon) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .fluidOutputs(CarbonMonoxide.getFluid(2000)) .buildAndRegister(); } @@ -1095,7 +1095,7 @@ private static void createSulfurDioxideRecipe(Material inputMaterial, Material o .input(dust, inputMaterial) .fluidInputs(Oxygen.getFluid(3000)) .output(dust, outputMaterial) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .fluidOutputs(SulfurDioxide.getFluid(sulfurDioxideAmount)) .buildAndRegister(); } @@ -1164,6 +1164,7 @@ private static void registerRecyclingRecipes() { MACERATOR_RECIPES.recipeBuilder() .input(stone, Soapstone) .output(dustImpure, Talc) + // todo fraction 1/90 and handle tier boost .chancedOutput(dust, Chromite, 111, 30) .buildAndRegister(); diff --git a/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java index fb3b3173dc4..cfdf9734078 100644 --- a/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java @@ -80,7 +80,7 @@ public static void init() { .chancedOutput(gem, Flint, 9000, 0) .chancedOutput(gem, Flint, 8000, 0) .chancedOutput(gem, Flint, 6000, 0) - .chancedOutput(gem, Flint, 3300, 0) + .chancedOutput(gem, Flint, "1/3", 0) .chancedOutput(gem, Flint, 2500, 0) .buildAndRegister(); diff --git a/src/main/java/gregtech/loaders/recipe/chemistry/PetrochemRecipes.java b/src/main/java/gregtech/loaders/recipe/chemistry/PetrochemRecipes.java index abbf301bb49..f0f39731b1a 100644 --- a/src/main/java/gregtech/loaders/recipe/chemistry/PetrochemRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/chemistry/PetrochemRecipes.java @@ -231,7 +231,7 @@ private static void distillationRecipes() { DISTILLATION_RECIPES.recipeBuilder() .fluidInputs(LightlySteamCrackedHeavyFuel.getFluid(1000)) - .chancedOutput(dust, Carbon, 1111, 0) + .chancedOutput(dust, Carbon, "1/9", 0) .fluidOutputs(LightFuel.getFluid(300)) .fluidOutputs(Naphtha.getFluid(50)) .fluidOutputs(Toluene.getFluid(25)) @@ -247,7 +247,7 @@ private static void distillationRecipes() { DISTILLATION_RECIPES.recipeBuilder() .fluidInputs(SeverelySteamCrackedHeavyFuel.getFluid(1000)) - .chancedOutput(dust, Carbon, 3333, 0) + .chancedOutput(dust, Carbon, "1/3", 0) .fluidOutputs(LightFuel.getFluid(100)) .fluidOutputs(Naphtha.getFluid(125)) .fluidOutputs(Toluene.getFluid(80)) @@ -283,7 +283,7 @@ private static void distillationRecipes() { DISTILLATION_RECIPES.recipeBuilder() .fluidInputs(LightlySteamCrackedLightFuel.getFluid(1000)) - .chancedOutput(dust, Carbon, 1111, 0) + .chancedOutput(dust, Carbon, "1/9", 0) .fluidOutputs(HeavyFuel.getFluid(150)) .fluidOutputs(Naphtha.getFluid(400)) .fluidOutputs(Toluene.getFluid(40)) @@ -299,7 +299,7 @@ private static void distillationRecipes() { DISTILLATION_RECIPES.recipeBuilder() .fluidInputs(SeverelySteamCrackedLightFuel.getFluid(1000)) - .chancedOutput(dust, Carbon, 3333, 0) + .chancedOutput(dust, Carbon, "1/3", 0) .fluidOutputs(HeavyFuel.getFluid(50)) .fluidOutputs(Naphtha.getFluid(100)) .fluidOutputs(Toluene.getFluid(30)) @@ -331,7 +331,7 @@ private static void distillationRecipes() { DISTILLATION_RECIPES.recipeBuilder() .fluidInputs(LightlySteamCrackedNaphtha.getFluid(1000)) - .chancedOutput(dust, Carbon, 1111, 0) + .chancedOutput(dust, Carbon, "1/9", 0) .fluidOutputs(HeavyFuel.getFluid(75)) .fluidOutputs(LightFuel.getFluid(150)) .fluidOutputs(Toluene.getFluid(40)) @@ -347,7 +347,7 @@ private static void distillationRecipes() { DISTILLATION_RECIPES.recipeBuilder() .fluidInputs(SeverelySteamCrackedNaphtha.getFluid(1000)) - .chancedOutput(dust, Carbon, 3333, 0) + .chancedOutput(dust, Carbon, "1/3", 0) .fluidOutputs(HeavyFuel.getFluid(25)) .fluidOutputs(LightFuel.getFluid(50)) .fluidOutputs(Toluene.getFluid(20)) @@ -377,7 +377,7 @@ private static void distillationRecipes() { DISTILLATION_RECIPES.recipeBuilder() .fluidInputs(LightlySteamCrackedGas.getFluid(1000)) - .chancedOutput(dust, Carbon, 1111, 0) + .chancedOutput(dust, Carbon, "1/9", 0) .fluidOutputs(Propene.getFluid(45)) .fluidOutputs(Ethane.getFluid(8)) .fluidOutputs(Ethylene.getFluid(85)) @@ -387,7 +387,7 @@ private static void distillationRecipes() { DISTILLATION_RECIPES.recipeBuilder() .fluidInputs(SeverelySteamCrackedGas.getFluid(1000)) - .chancedOutput(dust, Carbon, 1111, 0) + .chancedOutput(dust, Carbon, "1/9", 0) .fluidOutputs(Propene.getFluid(8)) .fluidOutputs(Ethane.getFluid(45)) .fluidOutputs(Ethylene.getFluid(92)) diff --git a/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java b/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java index 7178cadecbf..540bcf4b2e2 100644 --- a/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java @@ -339,7 +339,7 @@ public static void init() { .circuitMeta(1) .input(gem, Charcoal) .fluidInputs(Oxygen.getFluid(1000)) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .fluidOutputs(CarbonMonoxide.getFluid(1000)) .duration(80).EUt(VA[ULV]).buildAndRegister(); @@ -347,7 +347,7 @@ public static void init() { .circuitMeta(1) .input(gem, Coal) .fluidInputs(Oxygen.getFluid(1000)) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .fluidOutputs(CarbonMonoxide.getFluid(1000)) .duration(80).EUt(VA[ULV]).buildAndRegister(); @@ -355,7 +355,7 @@ public static void init() { .circuitMeta(1) .input(dust, Charcoal) .fluidInputs(Oxygen.getFluid(1000)) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .fluidOutputs(CarbonMonoxide.getFluid(1000)) .duration(80).EUt(VA[ULV]).buildAndRegister(); @@ -364,7 +364,7 @@ public static void init() { .input(dust, Coal) .circuitMeta(1) .fluidInputs(Oxygen.getFluid(1000)) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .fluidOutputs(CarbonMonoxide.getFluid(1000)) .buildAndRegister(); @@ -409,7 +409,7 @@ public static void init() { .circuitMeta(2) .input(gem, Charcoal) .fluidInputs(Oxygen.getFluid(2000)) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .fluidOutputs(CarbonDioxide.getFluid(1000)) .duration(80).EUt(VA[ULV]).buildAndRegister(); @@ -417,7 +417,7 @@ public static void init() { .circuitMeta(2) .input(gem, Coal) .fluidInputs(Oxygen.getFluid(2000)) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .fluidOutputs(CarbonDioxide.getFluid(1000)) .duration(80).EUt(VA[ULV]).buildAndRegister(); @@ -425,7 +425,7 @@ public static void init() { .circuitMeta(2) .input(dust, Charcoal) .fluidInputs(Oxygen.getFluid(2000)) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .fluidOutputs(CarbonDioxide.getFluid(1000)) .duration(80).EUt(VA[ULV]).buildAndRegister(); @@ -433,7 +433,7 @@ public static void init() { .circuitMeta(2) .input(dust, Coal) .fluidInputs(Oxygen.getFluid(2000)) - .chancedOutput(dust, Ash, 1111, 0) + .chancedOutput(dust, Ash, "1/9", 0) .fluidOutputs(CarbonDioxide.getFluid(1000)) .duration(80).EUt(VA[ULV]).buildAndRegister(); diff --git a/src/main/java/gregtech/loaders/recipe/chemistry/SeparationRecipes.java b/src/main/java/gregtech/loaders/recipe/chemistry/SeparationRecipes.java index 59f27762319..c57c7544733 100644 --- a/src/main/java/gregtech/loaders/recipe/chemistry/SeparationRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/chemistry/SeparationRecipes.java @@ -263,8 +263,8 @@ public static void init() { .input(dust, Stone) .chancedOutput(dust, Quartzite, 2500, 0) .chancedOutput(dust, PotassiumFeldspar, 2500, 0) - .chancedOutput(dust, Marble, 2222, 0) - .chancedOutput(dust, Biotite, 1111, 0) + .chancedOutput(dust, Marble, "2/9", 0) + .chancedOutput(dust, Biotite, "1/9", 0) .chancedOutput(dust, MetalMixture, 825, 80) .chancedOutput(dust, Sodalite, 550, 55) .buildAndRegister(); @@ -273,8 +273,8 @@ public static void init() { .input(dust, MetalMixture) .chancedOutput(dust, BandedIron, 2500, 0) .chancedOutput(dust, Bauxite, 2500, 0) - .chancedOutput(dust, Pyrolusite, 2222, 0) - .chancedOutput(dust, Barite, 1111, 0) + .chancedOutput(dust, Pyrolusite, "2/9", 0) + .chancedOutput(dust, Barite, "1/9", 0) .chancedOutput(dust, Chromite, 825, 80) .chancedOutput(dust, Ilmenite, 550, 55) .buildAndRegister(); diff --git a/src/main/java/gregtech/loaders/recipe/handlers/OreRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/OreRecipeHandler.java index c31486610f2..b5bcfe58574 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/OreRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/OreRecipeHandler.java @@ -163,7 +163,7 @@ public static void processCrushedOre(OrePrefix crushedPrefix, Material material, .fluidInputs(Materials.Water.getFluid(1000)) .circuitMeta(1) .outputs(crushedPurifiedOre) - .chancedOutput(OrePrefix.dust, byproductMaterial, 3333, 0) + .chancedOutput(OrePrefix.dust, byproductMaterial, "1/3", 0) .output(OrePrefix.dust, Materials.Stone) .buildAndRegister(); @@ -171,7 +171,7 @@ public static void processCrushedOre(OrePrefix crushedPrefix, Material material, .input(crushedPrefix, material) .fluidInputs(Materials.DistilledWater.getFluid(100)) .outputs(crushedPurifiedOre) - .chancedOutput(OrePrefix.dust, byproductMaterial, 3333, 0) + .chancedOutput(OrePrefix.dust, byproductMaterial, "1/3", 0) .output(OrePrefix.dust, Materials.Stone) .duration(200) .buildAndRegister(); @@ -180,7 +180,7 @@ public static void processCrushedOre(OrePrefix crushedPrefix, Material material, .input(crushedPrefix, material) .outputs(crushedCentrifugedOre) .chancedOutput(OrePrefix.dust, property.getOreByProduct(1, material), property.getByProductMultiplier(), - 3333, 0) + "1/3", 0) .output(OrePrefix.dust, Materials.Stone) .buildAndRegister(); @@ -255,7 +255,7 @@ public static void processCrushedPurified(OrePrefix purifiedPrefix, Material mat RecipeMaps.THERMAL_CENTRIFUGE_RECIPES.recipeBuilder() .input(purifiedPrefix, material) .outputs(crushedCentrifugedStack) - .chancedOutput(OrePrefix.dust, byproductMaterial, 3333, 0) + .chancedOutput(OrePrefix.dust, byproductMaterial, "1/3", 0) .buildAndRegister(); } @@ -311,7 +311,7 @@ public static void processDirtyDust(OrePrefix dustPrefix, Material material, Ore .duration((int) (material.getMass() * 4)).EUt(24); if (byproduct.hasProperty(PropertyKey.DUST)) { - builder.chancedOutput(OrePrefix.dust, byproduct, 1111, 0); + builder.chancedOutput(OrePrefix.dust, byproduct, "1/9", 0); } else { builder.fluidOutputs(byproduct.getFluid(GTValues.L / 9)); } @@ -362,7 +362,7 @@ public static void processPureDust(OrePrefix purePrefix, Material material, OreP RecipeMaps.CENTRIFUGE_RECIPES.recipeBuilder() .input(purePrefix, material) .outputs(dustStack) - .chancedOutput(OrePrefix.dust, byproductMaterial, 1111, 0) + .chancedOutput(OrePrefix.dust, byproductMaterial, "1/9", 0) .duration(100) .EUt(5) .buildAndRegister(); From 288965411f103d8c763a263e98eacce847b7ab1e Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:11:11 -0700 Subject: [PATCH 20/45] fix copy --- .../api/recipes/chance/output/impl/ChancedFluidOutput.java | 2 +- .../api/recipes/chance/output/impl/ChancedItemOutput.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedFluidOutput.java b/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedFluidOutput.java index de7732083a5..21dcc6e96c0 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedFluidOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedFluidOutput.java @@ -21,7 +21,7 @@ public ChancedFluidOutput(@NotNull FluidStack ingredient, int chance, int maxCha @Override public @NotNull ChancedFluidOutput copy() { - return new ChancedFluidOutput(getIngredient().copy(), getChance(), getChanceBoost()); + return new ChancedFluidOutput(getIngredient().copy(), getChance(), getMaxChance(), getChanceBoost()); } @Override diff --git a/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedItemOutput.java b/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedItemOutput.java index c119bebe351..99c3e03a1ed 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedItemOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/impl/ChancedItemOutput.java @@ -22,7 +22,7 @@ public ChancedItemOutput(@NotNull ItemStack ingredient, int chance, int maxChanc @Override public @NotNull ChancedItemOutput copy() { - return new ChancedItemOutput(getIngredient().copy(), getChance(), getChanceBoost()); + return new ChancedItemOutput(getIngredient().copy(), getChance(), getMaxChance(), getChanceBoost()); } @Override From 7b7c3bcdd0f3b8bdb9b24a806f86c1da18b5c84d Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:18:21 -0700 Subject: [PATCH 21/45] also apply to chanced fluids --- .../gregtech/api/recipes/RecipeBuilder.java | 50 +++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/RecipeBuilder.java b/src/main/java/gregtech/api/recipes/RecipeBuilder.java index fe90b010c50..d6d39caecc1 100644 --- a/src/main/java/gregtech/api/recipes/RecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeBuilder.java @@ -738,6 +738,48 @@ public R chancedFluidOutput(FluidStack stack, int chance, int tierChanceBoost) { return (R) this; } + public R chancedFluidOutput(FluidStack stack, String fraction, int tierChanceBoost) { + if (stack == null || stack.amount == 0) { + return (R) this; + } + + String[] split = fraction.split("/"); + if (split.length != 2) { + GTLog.logger.error("Fraction was not parsed correctly! Expected format is \"1/3\". Actual: \"{}\".", + fraction, new Throwable()); + recipeStatus = EnumValidationResult.INVALID; + return (R) this; + } + + int chance; + int maxChance; + try { + chance = Integer.parseInt(split[0]); + maxChance = Integer.parseInt(split[1]); + } catch (NumberFormatException e) { + GTLog.logger.error("Fraction was not parsed correctly! Expected format is \"1/3\". Actual: \"{}\".", + fraction, new Throwable()); + recipeStatus = EnumValidationResult.INVALID; + return (R) this; + } + + if (0 >= chance || chance > ChancedOutputLogic.getMaxChancedValue()) { + GTLog.logger.error("Chance cannot be less or equal to 0 or more than {}. Actual: {}.", + ChancedOutputLogic.getMaxChancedValue(), chance, new Throwable()); + recipeStatus = EnumValidationResult.INVALID; + return (R) this; + } + if (chance >= maxChance || maxChance > ChancedOutputLogic.getMaxChancedValue()) { + GTLog.logger.error("Max Chance cannot be less or equal to Chance or more than {}. Actual: {}.", + ChancedOutputLogic.getMaxChancedValue(), maxChance, new Throwable()); + recipeStatus = EnumValidationResult.INVALID; + return (R) this; + } + + this.chancedFluidOutputs.add(new ChancedFluidOutput(stack.copy(), chance, tierChanceBoost)); + return (R) this; + } + public R chancedFluidOutputs(List chancedOutputs) { for (ChancedFluidOutput output : chancedOutputs) { this.chancedFluidOutputs.add(output.copy()); @@ -806,25 +848,25 @@ private static GTRecipeInput ofGroovyIngredient(IIngredient ingredient) { public void chancedOutputsMultiply(Recipe chancedOutputsFrom, int numberOfOperations) { for (ChancedItemOutput entry : chancedOutputsFrom.getChancedOutputs().getChancedEntries()) { - int chance = entry.getChance(); + String fraction = String.format("%d/%d", entry.getChance(), entry.getMaxChance()); int boost = entry.getChanceBoost(); // Add individual chanced outputs per number of parallel operations performed, to mimic regular recipes. // This is done instead of simply batching the chanced outputs by the number of parallel operations // performed for (int i = 0; i < numberOfOperations; i++) { - this.chancedOutput(entry.getIngredient().copy(), chance, boost); + this.chancedOutput(entry.getIngredient().copy(), fraction, boost); } } for (ChancedFluidOutput entry : chancedOutputsFrom.getChancedFluidOutputs().getChancedEntries()) { - int chance = entry.getChance(); + String fraction = String.format("%d/%d", entry.getChance(), entry.getMaxChance()); int boost = entry.getChanceBoost(); // Add individual chanced outputs per number of parallel operations performed, to mimic regular recipes. // This is done instead of simply batching the chanced outputs by the number of parallel operations // performed for (int i = 0; i < numberOfOperations; i++) { - this.chancedFluidOutput(entry.getIngredient().copy(), chance, boost); + this.chancedFluidOutput(entry.getIngredient().copy(), fraction, boost); } } } From 0374153d07aefa31718e89e48db642296145d581 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:45:49 -0700 Subject: [PATCH 22/45] fix chances on tooltips --- .../java/gregtech/api/recipes/chance/BaseChanceEntry.java | 1 + src/main/java/gregtech/api/recipes/chance/ChanceEntry.java | 2 ++ src/main/java/gregtech/api/util/TextFormattingUtil.java | 6 ++++++ .../java/gregtech/integration/jei/basic/OreByProduct.java | 7 +++++-- .../gregtech/integration/jei/recipe/GTRecipeWrapper.java | 7 ++++--- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java index a1380cac442..bbcc4dd7066 100644 --- a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java +++ b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java @@ -37,6 +37,7 @@ public int getChance() { return chance; } + @Override public int getMaxChance() { return maxChance; } diff --git a/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java b/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java index e5eeda1a875..dff3e68c954 100644 --- a/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java +++ b/src/main/java/gregtech/api/recipes/chance/ChanceEntry.java @@ -20,6 +20,8 @@ public interface ChanceEntry { */ int getChance(); + int getMaxChance(); + /** * @return a copy of the chance entry */ diff --git a/src/main/java/gregtech/api/util/TextFormattingUtil.java b/src/main/java/gregtech/api/util/TextFormattingUtil.java index 00a1f5f0aea..8a5f4af3f8c 100644 --- a/src/main/java/gregtech/api/util/TextFormattingUtil.java +++ b/src/main/java/gregtech/api/util/TextFormattingUtil.java @@ -1,6 +1,7 @@ package gregtech.api.util; import java.text.NumberFormat; +import java.util.Formatter; public class TextFormattingUtil { @@ -17,6 +18,7 @@ public class TextFormattingUtil { 'k', 'M', 'G', 'T', 'P', 'E' }; private static final NumberFormat NUMBER_FORMAT = NumberFormat.getInstance(); + private static final Formatter STRING_FORMAT = new Formatter(); public static String formatLongToCompactString(long value, int precision) { if (value == 0 || Math.abs(value) < Math.pow(10, precision)) { @@ -55,6 +57,10 @@ public static String formatNumbers(double number) { return NUMBER_FORMAT.format(number); } + public static String formatPercent(double number) { + return STRING_FORMAT.format("%,.2f", number).toString(); + } + /** Allows for formatting Long, Integer, Short, Byte, Number, AtomicInteger, AtomicLong, and BigInteger. */ public static String formatNumbers(Object number) { return NUMBER_FORMAT.format(number); diff --git a/src/main/java/gregtech/integration/jei/basic/OreByProduct.java b/src/main/java/gregtech/integration/jei/basic/OreByProduct.java index 8e062d069c0..fb6047b11a5 100755 --- a/src/main/java/gregtech/integration/jei/basic/OreByProduct.java +++ b/src/main/java/gregtech/integration/jei/basic/OreByProduct.java @@ -8,6 +8,7 @@ import gregtech.api.unification.material.properties.OreProperty; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.ore.OrePrefix; +import gregtech.api.util.TextFormattingUtil; import gregtech.client.utils.TooltipHelper; import gregtech.common.metatileentities.MetaTileEntities; @@ -26,6 +27,7 @@ import mezz.jei.api.recipe.IRecipeWrapper; import org.apache.commons.lang3.tuple.Pair; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; @@ -287,9 +289,10 @@ public void getIngredients(IIngredients ingredients) { public void addTooltip(int slotIndex, boolean input, Object ingredient, List tooltip) { if (chances.containsKey(slotIndex)) { ChancedItemOutput entry = chances.get(slotIndex); - double chance = entry.getChance() / 100.0; + double chance = 100 * (double) entry.getChance() / entry.getMaxChance(); + String percent = TextFormattingUtil.formatPercent(chance); double boost = entry.getChanceBoost() / 100.0; - tooltip.add(TooltipHelper.BLINKING_CYAN + I18n.format("gregtech.recipe.chance", chance, boost)); + tooltip.add(TooltipHelper.BLINKING_CYAN + I18n.format("gregtech.recipe.chance", percent, boost)); } } diff --git a/src/main/java/gregtech/integration/jei/recipe/GTRecipeWrapper.java b/src/main/java/gregtech/integration/jei/recipe/GTRecipeWrapper.java index 4d88c1f1e5b..951407563bb 100644 --- a/src/main/java/gregtech/integration/jei/recipe/GTRecipeWrapper.java +++ b/src/main/java/gregtech/integration/jei/recipe/GTRecipeWrapper.java @@ -203,14 +203,15 @@ public void addIngredientTooltips(@NotNull Collection tooltip, boolean n @Nullable Object ingredient, @Nullable Object ingredient2) { if (ingredient2 instanceof ChancedOutputLogic logic) { if (ingredient instanceof BoostableChanceEntryentry) { - double chance = entry.getChance() / 100.0; + double chance = 100 * (double) entry.getChance() / entry.getMaxChance(); + String percent = TextFormattingUtil.formatPercent(chance); double boost = entry.getChanceBoost() / 100.0; if (logic != ChancedOutputLogic.NONE && logic != ChancedOutputLogic.OR) { tooltip.add(TooltipHelper.BLINKING_CYAN + I18n.format("gregtech.recipe.chance_logic", - chance, boost, I18n.format(logic.getTranslationKey()))); + percent, boost, I18n.format(logic.getTranslationKey()))); } else { tooltip.add(TooltipHelper.BLINKING_CYAN + I18n.format("gregtech.recipe.chance", - chance, boost)); + percent, boost)); } } } else if (notConsumed) { From 6c586234fc14cae8b9d3528a6ae7e6ac822066db Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:48:00 -0700 Subject: [PATCH 23/45] move cache clear after recipe is valid and checked --- .../gregtech/api/capability/impl/AbstractRecipeLogic.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index ca018ca67a5..a32d9cead36 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -397,8 +397,6 @@ protected void trySearchNewRecipe() { // If there is no active recipe, then we need to find one. } else { currentRecipe = findRecipe(maxVoltage, importInventory, importFluids); - fluidChancesCache.clear(); - itemChancesCache.clear(); } // If a recipe was found, then inputs were valid. Cache found recipe. if (currentRecipe != null) { @@ -715,6 +713,8 @@ protected static boolean areItemStacksEqual(@NotNull ItemStack stackA, @NotNull this.isOutputsFull = false; if (recipe.matches(true, importInventory, importFluids)) { this.metaTileEntity.addNotifiedInput(importInventory); + this.itemChancesCache.clear(); + this.fluidChancesCache.clear(); return recipe; } } From 0443100c304e3ca7c973255180a82891679b46d0 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:18:53 -0700 Subject: [PATCH 24/45] move BaseChanceEntry up into ChancedOutput improve toString() --- .../api/recipes/chance/BaseChanceEntry.java | 44 ------------------- .../chance/output/BoostableChanceOutput.java | 1 + .../recipes/chance/output/ChancedOutput.java | 36 +++++++++++++-- 3 files changed, 33 insertions(+), 48 deletions(-) delete mode 100644 src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java diff --git a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java b/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java deleted file mode 100644 index bbcc4dd7066..00000000000 --- a/src/main/java/gregtech/api/recipes/chance/BaseChanceEntry.java +++ /dev/null @@ -1,44 +0,0 @@ -package gregtech.api.recipes.chance; - -import gregtech.api.recipes.chance.output.ChancedOutputLogic; - -import org.jetbrains.annotations.NotNull; - -/** - * Basic implementation for a chance entry. - * - * @param the type of ingredient contained by the chanced entry - */ -public abstract class BaseChanceEntry implements ChanceEntry { - - private final T ingredient; - private final int chance; - private final int maxChance; - - public BaseChanceEntry(@NotNull T ingredient, int chance) { - this.ingredient = ingredient; - this.chance = chance; - this.maxChance = ChancedOutputLogic.getMaxChancedValue(); - } - - public BaseChanceEntry(@NotNull T ingredient, int chance, int maxChance) { - this.ingredient = ingredient; - this.chance = chance; - this.maxChance = maxChance; - } - - @Override - public @NotNull T getIngredient() { - return ingredient; - } - - @Override - public int getChance() { - return chance; - } - - @Override - public int getMaxChance() { - return maxChance; - } -} diff --git a/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java b/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java index 8674b8e0ca3..01b6d5ed28e 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java @@ -33,6 +33,7 @@ public String toString() { return "BoostableChanceOutput{" + "ingredient=" + getIngredient() + ", chance=" + getChance() + + ", maxChance=" + getMaxChance() + ", chanceBoost=" + getChanceBoost() + '}'; } diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java index ff6cd2f7de2..61b24b42600 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java @@ -1,6 +1,6 @@ package gregtech.api.recipes.chance.output; -import gregtech.api.recipes.chance.BaseChanceEntry; +import gregtech.api.recipes.chance.ChanceEntry; import org.jetbrains.annotations.NotNull; @@ -9,14 +9,42 @@ * * @param the type of ingredient contained by the output */ -public abstract class ChancedOutput extends BaseChanceEntry { +public abstract class ChancedOutput implements ChanceEntry { + + private final T ingredient; + private int chance; + private int maxChance; public ChancedOutput(@NotNull T ingredient, int chance) { - super(ingredient, chance); + this.ingredient = ingredient; + this.chance = chance; + this.maxChance = ChancedOutputLogic.getMaxChancedValue(); } public ChancedOutput(@NotNull T ingredient, int chance, int maxChance) { - super(ingredient, chance, maxChance); + this.ingredient = ingredient; + this.chance = chance; + this.maxChance = maxChance; + } + + @Override + public @NotNull T getIngredient() { + return ingredient; + } + + @Override + public int getChance() { + return chance; + } + + @Override + public int getMaxChance() { + return maxChance; + } + + public void scale(int scalar) { + this.chance *= scalar; + this.maxChance *= scalar; } } From 376d19b2ffcca2f807ecec9d30df17797f4d89b9 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:20:51 -0700 Subject: [PATCH 25/45] spotless --- .../java/gregtech/api/recipes/chance/output/ChancedOutput.java | 1 - src/main/java/gregtech/integration/jei/basic/OreByProduct.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java index 61b24b42600..512f1d8d658 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java @@ -21,7 +21,6 @@ public ChancedOutput(@NotNull T ingredient, int chance) { this.maxChance = ChancedOutputLogic.getMaxChancedValue(); } - public ChancedOutput(@NotNull T ingredient, int chance, int maxChance) { this.ingredient = ingredient; this.chance = chance; diff --git a/src/main/java/gregtech/integration/jei/basic/OreByProduct.java b/src/main/java/gregtech/integration/jei/basic/OreByProduct.java index fb6047b11a5..56ed033c226 100755 --- a/src/main/java/gregtech/integration/jei/basic/OreByProduct.java +++ b/src/main/java/gregtech/integration/jei/basic/OreByProduct.java @@ -27,7 +27,6 @@ import mezz.jei.api.recipe.IRecipeWrapper; import org.apache.commons.lang3.tuple.Pair; -import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; From d688f339c487bc5928695e66dfff7a7617ff2bb7 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 16:09:43 -0700 Subject: [PATCH 26/45] try to make chance boost work correctly --- src/main/java/gregtech/api/recipes/RecipeBuilder.java | 11 ++++++++++- .../api/recipes/chance/output/ChancedOutput.java | 9 ++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/RecipeBuilder.java b/src/main/java/gregtech/api/recipes/RecipeBuilder.java index d6d39caecc1..bcbe97d6546 100644 --- a/src/main/java/gregtech/api/recipes/RecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeBuilder.java @@ -687,6 +687,11 @@ public R chancedOutput(ItemStack stack, String fraction, int tierChanceBoost) { recipeStatus = EnumValidationResult.INVALID; return (R) this; } + + int scalar = Math.floorDiv(ChancedOutputLogic.getMaxChancedValue(), maxChance); + chance *= scalar; + maxChance *= scalar; + this.chancedOutputs.add(new ChancedItemOutput(stack.copy(), chance, maxChance, tierChanceBoost)); return (R) this; } @@ -776,7 +781,11 @@ public R chancedFluidOutput(FluidStack stack, String fraction, int tierChanceBoo return (R) this; } - this.chancedFluidOutputs.add(new ChancedFluidOutput(stack.copy(), chance, tierChanceBoost)); + int scalar = Math.floorDiv(ChancedOutputLogic.getMaxChancedValue(), maxChance); + chance *= scalar; + maxChance *= scalar; + + this.chancedFluidOutputs.add(new ChancedFluidOutput(stack.copy(), chance, maxChance, tierChanceBoost)); return (R) this; } diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java index 512f1d8d658..a3d29c02368 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java @@ -12,8 +12,8 @@ public abstract class ChancedOutput implements ChanceEntry { private final T ingredient; - private int chance; - private int maxChance; + private final int chance; + private final int maxChance; public ChancedOutput(@NotNull T ingredient, int chance) { this.ingredient = ingredient; @@ -41,9 +41,4 @@ public int getChance() { public int getMaxChance() { return maxChance; } - - public void scale(int scalar) { - this.chance *= scalar; - this.maxChance *= scalar; - } } From 64920f865a51426fa8424922fcf12a1837860eca Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 16:14:57 -0700 Subject: [PATCH 27/45] rip formatter --- src/main/java/gregtech/api/util/TextFormattingUtil.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/gregtech/api/util/TextFormattingUtil.java b/src/main/java/gregtech/api/util/TextFormattingUtil.java index 8a5f4af3f8c..f01af12426c 100644 --- a/src/main/java/gregtech/api/util/TextFormattingUtil.java +++ b/src/main/java/gregtech/api/util/TextFormattingUtil.java @@ -1,7 +1,6 @@ package gregtech.api.util; import java.text.NumberFormat; -import java.util.Formatter; public class TextFormattingUtil { @@ -18,7 +17,6 @@ public class TextFormattingUtil { 'k', 'M', 'G', 'T', 'P', 'E' }; private static final NumberFormat NUMBER_FORMAT = NumberFormat.getInstance(); - private static final Formatter STRING_FORMAT = new Formatter(); public static String formatLongToCompactString(long value, int precision) { if (value == 0 || Math.abs(value) < Math.pow(10, precision)) { @@ -58,7 +56,7 @@ public static String formatNumbers(double number) { } public static String formatPercent(double number) { - return STRING_FORMAT.format("%,.2f", number).toString(); + return String.format("%,.2f", number); } /** Allows for formatting Long, Integer, Short, Byte, Number, AtomicInteger, AtomicLong, and BigInteger. */ From 3732ae09ddf2079b99ae08ab71916a7ccc3f1f9a Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 16:18:38 -0700 Subject: [PATCH 28/45] move cache clear --- .../gregtech/api/capability/impl/AbstractRecipeLogic.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index a32d9cead36..26380d301c1 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -400,6 +400,12 @@ protected void trySearchNewRecipe() { } // If a recipe was found, then inputs were valid. Cache found recipe. if (currentRecipe != null) { + + // we found a new recipe, clear the cache + if (!currentRecipe.equals(this.previousRecipe)) { + this.itemChancesCache.clear(); + this.fluidChancesCache.clear(); + } this.previousRecipe = currentRecipe; } this.invalidInputsForRecipes = (currentRecipe == null); @@ -713,8 +719,6 @@ protected static boolean areItemStacksEqual(@NotNull ItemStack stackA, @NotNull this.isOutputsFull = false; if (recipe.matches(true, importInventory, importFluids)) { this.metaTileEntity.addNotifiedInput(importInventory); - this.itemChancesCache.clear(); - this.fluidChancesCache.clear(); return recipe; } } From be0cdf1a25143d3db4e4bbb5d781ce8b4dd8a776 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 16:45:05 -0700 Subject: [PATCH 29/45] serialize chance cache --- .../capability/impl/AbstractRecipeLogic.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 26380d301c1..8c30c5dd959 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -1227,6 +1227,21 @@ public NBTTagCompound serializeNBT() { } compound.setTag("ItemOutputs", itemOutputsList); compound.setTag("FluidOutputs", fluidOutputsList); + + NBTTagList itemCache = new NBTTagList(); + for (var entry : itemChancesCache.entrySet()) { + var tag = entry.getKey().serializeNBT(); + tag.setInteger("CachedChance", entry.getValue()); + itemCache.appendTag(tag); + } + NBTTagList fluidCache = new NBTTagList(); + for (var entry : fluidChancesCache.entrySet()) { + var tag = entry.getKey().writeToNBT(new NBTTagCompound()); + tag.setInteger("CachedChance", entry.getValue()); + fluidCache.appendTag(tag); + } + compound.setTag("ItemChanceCache", itemCache); + compound.setTag("FluidChanceCache", fluidCache); } return compound; } @@ -1253,6 +1268,20 @@ public void deserializeNBT(@NotNull NBTTagCompound compound) { for (int i = 0; i < fluidOutputsList.tagCount(); i++) { this.fluidOutputs.add(FluidStack.loadFluidStackFromNBT(fluidOutputsList.getCompoundTagAt(i))); } + + NBTTagList itemCache = compound.getTagList("ItemChanceCache", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < itemCache.tagCount(); i++) { + var stack = itemCache.getCompoundTagAt(i); + int cache = stack.getInteger("CachedChance"); + this.itemChancesCache.put(new ItemStack(stack), cache); + } + + NBTTagList fluidCache = compound.getTagList("FluidChanceCache", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < fluidCache.tagCount(); i++) { + var stack = fluidCache.getCompoundTagAt(i); + int cache = stack.getInteger("CachedChance"); + this.fluidChancesCache.put(FluidStack.loadFluidStackFromNBT(stack), cache); + } } } } From aaeb90e2985b1b88fafcf5c9782309ab2cc1b3a6 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 17:04:28 -0700 Subject: [PATCH 30/45] add rng starting value for chance add check for previous recipe make XOR use cache getter method --- .../api/capability/impl/AbstractRecipeLogic.java | 2 +- .../recipes/chance/output/ChancedOutputLogic.java | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 8c30c5dd959..3a169ab7412 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -402,7 +402,7 @@ protected void trySearchNewRecipe() { if (currentRecipe != null) { // we found a new recipe, clear the cache - if (!currentRecipe.equals(this.previousRecipe)) { + if (this.previousRecipe != null && !currentRecipe.equals(this.previousRecipe)) { this.itemChancesCache.clear(); this.fluidChancesCache.clear(); } diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index a7298abf421..6ee918c2441 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -1,5 +1,6 @@ package gregtech.api.recipes.chance.output; +import gregtech.api.GTValues; import gregtech.api.recipes.chance.boost.BoostableChanceEntry; import gregtech.api.recipes.chance.boost.ChanceBoostFunction; @@ -30,7 +31,7 @@ public interface ChancedOutputLogic { @Nullable Map cache) { ImmutableList.Builder builder = ImmutableList.builder(); for (T entry : chancedEntries) { - int cached = getCachedChance(entry.getIngredient(), cache); + int cached = getCachedChance(entry, cache); int chance = getChance(entry, boostFunction, baseTier, machineTier) + cached; int maxChance = entry.getMaxChance(); @@ -71,7 +72,7 @@ public String toString() { @Nullable Map cache) { boolean failed = false; for (T entry : chancedEntries) { - int cached = getCachedChance(entry.getIngredient(), cache); + int cached = getCachedChance(entry, cache); int chance = getChance(entry, boostFunction, baseTier, machineTier) + cached; if (!passesChance(chance, entry.getMaxChance())) { @@ -106,9 +107,7 @@ public String toString() { @Nullable Map cache) { T selected = null; for (T entry : chancedEntries) { - int cached = 0; - if (cache != null) - cached = cache.getOrDefault(entry.getIngredient(), 0); + int cached = getCachedChance(entry, cache); int chance = getChance(entry, boostFunction, baseTier, machineTier) + cached; if (passesChance(chance, entry.getMaxChance()) && selected == null) { @@ -186,8 +185,8 @@ static int getMaxChancedValue() { return 10_000; } - static int getCachedChance(I ingredient, @Nullable Map cache) { - return cache == null ? 0 : cache.getOrDefault(ingredient, 0); + static > int getCachedChance(T entry, @Nullable Map cache) { + return cache == null ? 0 : cache.getOrDefault(entry.getIngredient(), GTValues.RNG.nextInt(entry.getMaxChance() + 1)); } static void updateCachedChance(I ingredient, @Nullable Map cache, int chance) { From fc4e13b4d75e4c7423c452c410b3ea82a35aab5d Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 17:12:04 -0700 Subject: [PATCH 31/45] update cache getter method --- .../api/recipes/chance/output/ChancedOutputLogic.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 6ee918c2441..729cf9d9fdf 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -186,7 +186,10 @@ static int getMaxChancedValue() { } static > int getCachedChance(T entry, @Nullable Map cache) { - return cache == null ? 0 : cache.getOrDefault(entry.getIngredient(), GTValues.RNG.nextInt(entry.getMaxChance() + 1)); + if (cache == null || !cache.containsKey(entry.getIngredient())) + return GTValues.RNG.nextInt(entry.getMaxChance() + 1); + + return cache.get(entry.getIngredient()); } static void updateCachedChance(I ingredient, @Nullable Map cache, int chance) { From f8ffbf3fe892008504dd28ca6a0eeb3ec58cd9f5 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 17:40:07 -0700 Subject: [PATCH 32/45] remove plus one + javadocs --- .../chance/output/ChancedOutputLogic.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 729cf9d9fdf..87c7c50d460 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -1,6 +1,7 @@ package gregtech.api.recipes.chance.output; import gregtech.api.GTValues; +import gregtech.api.recipes.chance.ChanceEntry; import gregtech.api.recipes.chance.boost.BoostableChanceEntry; import gregtech.api.recipes.chance.boost.ChanceBoostFunction; @@ -170,12 +171,12 @@ static int getChance(@NotNull ChancedOutput entry, @NotNull ChanceBoostFuncti } /** - * @param chance the chance to check + * @param chance the chance to be checked + * @param maxChance the max chance of the current entry * @return if the roll with the chance is successful */ static boolean passesChance(int chance, int maxChance) { return chance >= maxChance; - // return chance > 0 && GTValues.RNG.nextInt(getMaxChancedValue()) <= chance; } /** @@ -185,13 +186,24 @@ static int getMaxChancedValue() { return 10_000; } + /** + * @param entry the current entry + * @param cache the cache of previously rolled chances, can be null + * @return the cached chance, otherwise a random initial chance + * between 0 and {@link ChanceEntry#getMaxChance()} (exclusive) + */ static > int getCachedChance(T entry, @Nullable Map cache) { if (cache == null || !cache.containsKey(entry.getIngredient())) - return GTValues.RNG.nextInt(entry.getMaxChance() + 1); + return GTValues.RNG.nextInt(entry.getMaxChance()); return cache.get(entry.getIngredient()); } + /** + * @param ingredient the key used for the cache + * @param cache the cache of previously rolled chances, can be null + * @param chance the chance to update the cache with + */ static void updateCachedChance(I ingredient, @Nullable Map cache, int chance) { if (cache == null) return; cache.put(ingredient, chance); @@ -204,8 +216,8 @@ static void updateCachedChance(I ingredient, @Nullable Map cache * @param boostFunction the function to boost the entries' chances * @param baseTier the base tier of the recipe * @param machineTier the tier the recipe is run at - * @param cache - * @return a list of the produced outputs + * @param cache the cache of previously rolled chances, can be null + * @return a list of the produced outputs, or null if failed */ > @Nullable @Unmodifiable List<@NotNull T> roll( @NotNull @Unmodifiable List<@NotNull T> chancedEntries, From 9cfa1c296af3f5e26fe9bd07ab79074fd9c34b5e Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 18:04:36 -0700 Subject: [PATCH 33/45] create and implement FluidStackHashStrategy --- .../capability/impl/AbstractRecipeLogic.java | 5 +- .../api/util/FluidStackHashStrategy.java | 119 ++++++++++++++++++ 2 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 src/main/java/gregtech/api/util/FluidStackHashStrategy.java diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 3a169ab7412..35018026d13 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -21,6 +21,7 @@ import gregtech.api.recipes.properties.RecipePropertyStorage; import gregtech.api.recipes.properties.impl.CleanroomProperty; import gregtech.api.recipes.properties.impl.DimensionProperty; +import gregtech.api.util.FluidStackHashStrategy; import gregtech.api.util.GTLog; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.GTUtility; @@ -38,7 +39,6 @@ import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.items.IItemHandlerModifiable; -import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenCustomHashMap; import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; @@ -74,7 +74,8 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable, protected int maxProgressTime; protected long recipeEUt; protected List fluidOutputs; - protected Map fluidChancesCache = new Object2IntArrayMap<>(); + protected Map fluidChancesCache = new Object2IntOpenCustomHashMap<>( + FluidStackHashStrategy.comparingAllButCount()); protected List itemOutputs; protected Map itemChancesCache = new Object2IntOpenCustomHashMap<>( ItemStackHashStrategy.builder() diff --git a/src/main/java/gregtech/api/util/FluidStackHashStrategy.java b/src/main/java/gregtech/api/util/FluidStackHashStrategy.java new file mode 100644 index 00000000000..dfb196e8a76 --- /dev/null +++ b/src/main/java/gregtech/api/util/FluidStackHashStrategy.java @@ -0,0 +1,119 @@ +package gregtech.api.util; + +import net.minecraftforge.fluids.FluidStack; + +import it.unimi.dsi.fastutil.Hash; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +/** + * A configurable generator of hashing strategies, allowing for consideration of select properties of ItemStacks when + * considering equality. + */ +public interface FluidStackHashStrategy extends Hash.Strategy { + + /** + * @return a builder object for producing a custom ItemStackHashStrategy. + */ + static FluidStackHashStrategyBuilder builder() { + return new FluidStackHashStrategyBuilder(); + } + + /** + * Generates an ItemStackHash configured to compare every aspect of ItemStacks. + * + * @return the ItemStackHashStrategy as described above. + */ + static FluidStackHashStrategy comparingAll() { + return builder().compareFluid(true) + .compareCount(true) + .compareTag(true) + .build(); + } + + /** + * Generates an ItemStackHash configured to compare every aspect of ItemStacks except the number + * of items in the stack. + * + * @return the ItemStackHashStrategy as described above. + */ + static FluidStackHashStrategy comparingAllButCount() { + return builder().compareFluid(true) + .compareTag(true) + .build(); + } + + static FluidStackHashStrategy comparingItemDamageCount() { + return builder().compareFluid(true) + .compareCount(true) + .build(); + } + + /** + * Builder pattern class for generating customized ItemStackHashStrategy + */ + class FluidStackHashStrategyBuilder { + + private boolean item, count, tag; + + /** + * Defines whether the Item type should be considered for equality. + * + * @param choice {@code true} to consider this property, {@code false} to ignore it. + * @return {@code this} + */ + public FluidStackHashStrategyBuilder compareFluid(boolean choice) { + item = choice; + return this; + } + + /** + * Defines whether stack size should be considered for equality. + * + * @param choice {@code true} to consider this property, {@code false} to ignore it. + * @return {@code this} + */ + public FluidStackHashStrategyBuilder compareCount(boolean choice) { + count = choice; + return this; + } + + /** + * Defines whether NBT Tags should be considered for equality. + * + * @param choice {@code true} to consider this property, {@code false} to ignore it. + * @return {@code this} + */ + public FluidStackHashStrategyBuilder compareTag(boolean choice) { + tag = choice; + return this; + } + + /** + * @return the ItemStackHashStrategy as configured by "compare" methods. + */ + public FluidStackHashStrategy build() { + return new FluidStackHashStrategy() { + + @Override + public int hashCode(@Nullable FluidStack o) { + return o == null || o.amount == 0 ? 0 : Objects.hash( + item ? o.getFluid() : null, + count ? o.amount : null, + tag ? o.tag : null); + } + + @Override + public boolean equals(@Nullable FluidStack a, @Nullable FluidStack b) { + if (a == null || a.amount == 0) return b == null || b.amount == 0; + if (b == null || b.amount == 0) return false; + + return (!item || a.getFluid() == b.getFluid()) && + (!count || a.amount == b.amount) && + (!tag || Objects.equals(a.tag, b.tag)); + } + }; + } + } +} From eb3d5f0422fdea02bf738dd54b02a1c4c2c7af88 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 18:28:06 -0700 Subject: [PATCH 34/45] try to correct boost w/ javadoc simplify constructors --- .../chance/output/BoostableChanceOutput.java | 19 ++++++++++++++++--- .../recipes/chance/output/ChancedOutput.java | 4 +--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java b/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java index 01b6d5ed28e..b66aaea369f 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java @@ -14,13 +14,12 @@ public abstract class BoostableChanceOutput extends ChancedOutput implemen private final int chanceBoost; public BoostableChanceOutput(@NotNull T ingredient, int chance, int chanceBoost) { - super(ingredient, chance); - this.chanceBoost = chanceBoost; + this(ingredient, chance, ChancedOutputLogic.getMaxChancedValue(), chanceBoost); } public BoostableChanceOutput(@NotNull T ingredient, int chance, int maxChance, int chanceBoost) { super(ingredient, chance, maxChance); - this.chanceBoost = chanceBoost; + this.chanceBoost = fixBoost(chanceBoost); } @Override @@ -28,6 +27,20 @@ public int getChanceBoost() { return this.chanceBoost; } + /** + * Attempts to fix and round the given chance boost due to potential differences + * between the max chance and {@link ChancedOutputLogic#getMaxChancedValue()}. + *
+ * The worst case would be {@code 5,001 / 10,000} , meaning the boost would + * have to be halved to have the intended effect. + * @param chanceBoost the chance boost to be fixed + * @return the fixed chance boost + */ + private int fixBoost(int chanceBoost) { + float error = (float) ChancedOutputLogic.getMaxChancedValue() / getMaxChance(); + return Math.round(chanceBoost / error); + } + @Override public String toString() { return "BoostableChanceOutput{" + diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java index a3d29c02368..8f8b2deee19 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutput.java @@ -16,9 +16,7 @@ public abstract class ChancedOutput implements ChanceEntry { private final int maxChance; public ChancedOutput(@NotNull T ingredient, int chance) { - this.ingredient = ingredient; - this.chance = chance; - this.maxChance = ChancedOutputLogic.getMaxChancedValue(); + this(ingredient, chance, ChancedOutputLogic.getMaxChancedValue()); } public ChancedOutput(@NotNull T ingredient, int chance, int maxChance) { From 779ec16151dd7e762282c27b661e1761c0327dbc Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 3 Aug 2024 19:56:49 -0700 Subject: [PATCH 35/45] fix todo fix FluidStackHashStrategy javadocs compare fluids only for strategy --- .../capability/impl/AbstractRecipeLogic.java | 4 +- .../chance/output/BoostableChanceOutput.java | 3 +- .../api/util/FluidStackHashStrategy.java | 46 +++++++++---------- .../loaders/recipe/MachineRecipeLoader.java | 3 +- 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 35018026d13..942db5e8488 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -75,7 +75,9 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable, protected long recipeEUt; protected List fluidOutputs; protected Map fluidChancesCache = new Object2IntOpenCustomHashMap<>( - FluidStackHashStrategy.comparingAllButCount()); + FluidStackHashStrategy.builder() + .compareFluid(true) + .build()); protected List itemOutputs; protected Map itemChancesCache = new Object2IntOpenCustomHashMap<>( ItemStackHashStrategy.builder() diff --git a/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java b/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java index b66aaea369f..3e9e4177092 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java +++ b/src/main/java/gregtech/api/recipes/chance/output/BoostableChanceOutput.java @@ -29,10 +29,11 @@ public int getChanceBoost() { /** * Attempts to fix and round the given chance boost due to potential differences - * between the max chance and {@link ChancedOutputLogic#getMaxChancedValue()}. + * between the max chance and {@link ChancedOutputLogic#getMaxChancedValue()}. *
* The worst case would be {@code 5,001 / 10,000} , meaning the boost would * have to be halved to have the intended effect. + * * @param chanceBoost the chance boost to be fixed * @return the fixed chance boost */ diff --git a/src/main/java/gregtech/api/util/FluidStackHashStrategy.java b/src/main/java/gregtech/api/util/FluidStackHashStrategy.java index dfb196e8a76..6ade524c978 100644 --- a/src/main/java/gregtech/api/util/FluidStackHashStrategy.java +++ b/src/main/java/gregtech/api/util/FluidStackHashStrategy.java @@ -8,74 +8,74 @@ import java.util.Objects; /** - * A configurable generator of hashing strategies, allowing for consideration of select properties of ItemStacks when + * A configurable generator of hashing strategies, allowing for consideration of select properties of FluidStacks when * considering equality. */ public interface FluidStackHashStrategy extends Hash.Strategy { /** - * @return a builder object for producing a custom ItemStackHashStrategy. + * @return a builder object for producing a custom FluidStackHashStrategy. */ static FluidStackHashStrategyBuilder builder() { return new FluidStackHashStrategyBuilder(); } /** - * Generates an ItemStackHash configured to compare every aspect of ItemStacks. + * Generates an FluidStackHash configured to compare every aspect of FluidStacks. * - * @return the ItemStackHashStrategy as described above. + * @return the FluidStackHashStrategy as described above. */ static FluidStackHashStrategy comparingAll() { return builder().compareFluid(true) - .compareCount(true) + .compareAmount(true) .compareTag(true) .build(); } /** - * Generates an ItemStackHash configured to compare every aspect of ItemStacks except the number - * of items in the stack. + * Generates a FluidStackHash configured to compare every aspect of FluidStacks except the amount + * of fluid in the stack. * - * @return the ItemStackHashStrategy as described above. + * @return the FluidStackHashStrategy as described above. */ - static FluidStackHashStrategy comparingAllButCount() { + static FluidStackHashStrategy comparingAllButAmount() { return builder().compareFluid(true) .compareTag(true) .build(); } - static FluidStackHashStrategy comparingItemDamageCount() { + static FluidStackHashStrategy comparingFluidAndAmount() { return builder().compareFluid(true) - .compareCount(true) + .compareAmount(true) .build(); } /** - * Builder pattern class for generating customized ItemStackHashStrategy + * Builder pattern class for generating customized FluidStackHashStrategy */ class FluidStackHashStrategyBuilder { - private boolean item, count, tag; + private boolean fluid, amount, tag; /** - * Defines whether the Item type should be considered for equality. + * Defines whether the Fluid type should be considered for equality. * * @param choice {@code true} to consider this property, {@code false} to ignore it. * @return {@code this} */ public FluidStackHashStrategyBuilder compareFluid(boolean choice) { - item = choice; + fluid = choice; return this; } /** - * Defines whether stack size should be considered for equality. + * Defines whether fluid amount should be considered for equality. * * @param choice {@code true} to consider this property, {@code false} to ignore it. * @return {@code this} */ - public FluidStackHashStrategyBuilder compareCount(boolean choice) { - count = choice; + public FluidStackHashStrategyBuilder compareAmount(boolean choice) { + amount = choice; return this; } @@ -91,7 +91,7 @@ public FluidStackHashStrategyBuilder compareTag(boolean choice) { } /** - * @return the ItemStackHashStrategy as configured by "compare" methods. + * @return the FluidStackHashStrategy as configured by "compare" methods. */ public FluidStackHashStrategy build() { return new FluidStackHashStrategy() { @@ -99,8 +99,8 @@ public FluidStackHashStrategy build() { @Override public int hashCode(@Nullable FluidStack o) { return o == null || o.amount == 0 ? 0 : Objects.hash( - item ? o.getFluid() : null, - count ? o.amount : null, + fluid ? o.getFluid() : null, + amount ? o.amount : null, tag ? o.tag : null); } @@ -109,8 +109,8 @@ public boolean equals(@Nullable FluidStack a, @Nullable FluidStack b) { if (a == null || a.amount == 0) return b == null || b.amount == 0; if (b == null || b.amount == 0) return false; - return (!item || a.getFluid() == b.getFluid()) && - (!count || a.amount == b.amount) && + return (!fluid || a.getFluid() == b.getFluid()) && + (!amount || a.amount == b.amount) && (!tag || Objects.equals(a.tag, b.tag)); } }; diff --git a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java index 6c34975163b..b10f3968d8a 100644 --- a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java @@ -1164,8 +1164,7 @@ private static void registerRecyclingRecipes() { MACERATOR_RECIPES.recipeBuilder() .input(stone, Soapstone) .output(dustImpure, Talc) - // todo fraction 1/90 and handle tier boost - .chancedOutput(dust, Chromite, 111, 30) + .chancedOutput(dust, Chromite, "1/90", 30) .buildAndRegister(); if (!OreDictionary.getOres("stoneRedrock").isEmpty()) From 9f4280b49119f73d63837797502647218b84c31c Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sun, 4 Aug 2024 14:18:26 -0700 Subject: [PATCH 36/45] simplify roll by moving cache handling into `passesChance()` try to make outputs appear more random initially --- .../chance/output/ChancedOutputLogic.java | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 87c7c50d460..12e554e0821 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -1,7 +1,6 @@ package gregtech.api.recipes.chance.output; import gregtech.api.GTValues; -import gregtech.api.recipes.chance.ChanceEntry; import gregtech.api.recipes.chance.boost.BoostableChanceEntry; import gregtech.api.recipes.chance.boost.ChanceBoostFunction; @@ -31,18 +30,14 @@ public interface ChancedOutputLogic { int baseTier, int machineTier, @Nullable Map cache) { ImmutableList.Builder builder = ImmutableList.builder(); - for (T entry : chancedEntries) { - int cached = getCachedChance(entry, cache); - int chance = getChance(entry, boostFunction, baseTier, machineTier) + cached; - int maxChance = entry.getMaxChance(); - if (passesChance(chance, maxChance)) { + for (T entry : chancedEntries) { + int chance = getChance(entry, boostFunction, baseTier, machineTier); + if (passesChance(chance, entry, cache)) { do { builder.add(entry); - chance -= maxChance; - } while (passesChance(chance, maxChance)); + } while (passesChance(chance, entry, cache)); } - updateCachedChance(entry.getIngredient(), cache, chance); } List list = builder.build(); @@ -73,13 +68,10 @@ public String toString() { @Nullable Map cache) { boolean failed = false; for (T entry : chancedEntries) { - int cached = getCachedChance(entry, cache); - - int chance = getChance(entry, boostFunction, baseTier, machineTier) + cached; - if (!passesChance(chance, entry.getMaxChance())) { + int chance = getChance(entry, boostFunction, baseTier, machineTier); + if (!passesChance(chance, entry, cache)) { failed = true; } - updateCachedChance(entry.getIngredient(), cache, chance); } return failed ? null : ImmutableList.copyOf(chancedEntries); } @@ -108,13 +100,10 @@ public String toString() { @Nullable Map cache) { T selected = null; for (T entry : chancedEntries) { - int cached = getCachedChance(entry, cache); - - int chance = getChance(entry, boostFunction, baseTier, machineTier) + cached; - if (passesChance(chance, entry.getMaxChance()) && selected == null) { + int chance = getChance(entry, boostFunction, baseTier, machineTier); + if (passesChance(chance, entry, cache) && selected == null) { selected = entry; } - updateCachedChance(entry.getIngredient(), cache, chance); } return selected == null ? null : Collections.singletonList(selected); } @@ -171,12 +160,27 @@ static int getChance(@NotNull ChancedOutput entry, @NotNull ChanceBoostFuncti } /** - * @param chance the chance to be checked - * @param maxChance the max chance of the current entry + * @param chance the boosted chance to be checked + * @param entry the entry to get the max chance and ingredient of for comparison and cache + * @param cache the cache of previously rolled chances, can be null * @return if the roll with the chance is successful */ - static boolean passesChance(int chance, int maxChance) { - return chance >= maxChance; + static > boolean passesChance(int chance, T entry, @Nullable Map cache) { + if (cache == null || !cache.containsKey(entry.getIngredient())) { + int initial = GTValues.RNG.nextInt(entry.getMaxChance() + 1); + updateCachedChance(entry.getIngredient(), cache, initial); + return GTValues.RNG.nextInt(entry.getMaxChance()) <= entry.getChance(); + } + + int fullChance = getCachedChance(entry, cache) + chance; + if (fullChance >= entry.getMaxChance()) { + fullChance -= entry.getMaxChance(); + updateCachedChance(entry.getIngredient(), cache, fullChance); + return true; + } + + updateCachedChance(entry.getIngredient(), cache, fullChance); + return false; } /** @@ -189,12 +193,12 @@ static int getMaxChancedValue() { /** * @param entry the current entry * @param cache the cache of previously rolled chances, can be null - * @return the cached chance, otherwise a random initial chance - * between 0 and {@link ChanceEntry#getMaxChance()} (exclusive) + * @return the cached chance, otherwise 0 if + * the cache is null or does not contain the key */ static > int getCachedChance(T entry, @Nullable Map cache) { if (cache == null || !cache.containsKey(entry.getIngredient())) - return GTValues.RNG.nextInt(entry.getMaxChance()); + return 0; return cache.get(entry.getIngredient()); } From faefdf20262e72377d8c27eb19de4518181b4b26 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sun, 4 Aug 2024 14:35:34 -0700 Subject: [PATCH 37/45] remove while loop rip rollover --- .../api/recipes/chance/output/ChancedOutputLogic.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 12e554e0821..b7461ec7979 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -34,9 +34,7 @@ public interface ChancedOutputLogic { for (T entry : chancedEntries) { int chance = getChance(entry, boostFunction, baseTier, machineTier); if (passesChance(chance, entry, cache)) { - do { - builder.add(entry); - } while (passesChance(chance, entry, cache)); + builder.add(entry); } } @@ -174,7 +172,7 @@ static > boolean passesChance(int chance, T entry, int fullChance = getCachedChance(entry, cache) + chance; if (fullChance >= entry.getMaxChance()) { - fullChance -= entry.getMaxChance(); + fullChance %= entry.getMaxChance(); updateCachedChance(entry.getIngredient(), cache, fullChance); return true; } From c85d0d7c23408f2ae23746de3b980f2b12d94869 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sun, 4 Aug 2024 15:28:26 -0700 Subject: [PATCH 38/45] update chance lang --- src/main/resources/assets/gregtech/lang/en_us.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 389d68cd3ce..a6a6891c12e 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -5428,8 +5428,8 @@ gregtech.recipe.eu_inverted=Generation: %,d EU/t gregtech.recipe.duration=Duration: %s secs gregtech.recipe.amperage=Amperage: %,d gregtech.recipe.not_consumed=Does not get consumed in the process -gregtech.recipe.chance=Chance: %s%% +%s%%/tier -gregtech.recipe.chance_logic=Chance: %s%% +%s%%/tier (%s) +gregtech.recipe.chance=Chance: %s%% +%s%%/overclock +gregtech.recipe.chance_logic=Chance: %s%% +%s%%/overclock (%s) gregtech.chance_logic.or=OR gregtech.chance_logic.and=AND gregtech.chance_logic.xor=XOR From 3ab625a3288025f224a1b089b45d8576e9e86267 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sun, 4 Aug 2024 23:55:19 -0700 Subject: [PATCH 39/45] simplify initial rng slightly --- .../api/recipes/chance/output/ChancedOutputLogic.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index b7461ec7979..48735fca675 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -165,9 +165,9 @@ static int getChance(@NotNull ChancedOutput entry, @NotNull ChanceBoostFuncti */ static > boolean passesChance(int chance, T entry, @Nullable Map cache) { if (cache == null || !cache.containsKey(entry.getIngredient())) { - int initial = GTValues.RNG.nextInt(entry.getMaxChance() + 1); + int initial = GTValues.RNG.nextInt(entry.getMaxChance()); updateCachedChance(entry.getIngredient(), cache, initial); - return GTValues.RNG.nextInt(entry.getMaxChance()) <= entry.getChance(); + return initial <= entry.getChance(); } int fullChance = getCachedChance(entry, cache) + chance; From 7cbcb5fb1aee2261b8ee90bfe946b0168606fe1d Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Mon, 7 Oct 2024 11:07:30 -0700 Subject: [PATCH 40/45] try to make xor better make `passesChance()` defualt for override --- .../chance/output/ChancedOutputLogic.java | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 48735fca675..267d7ce5e6a 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -90,6 +90,8 @@ public String toString() { */ ChancedOutputLogic XOR = new ChancedOutputLogic() { + private int roll; + @Override public @Nullable @Unmodifiable > List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, @@ -97,15 +99,31 @@ public String toString() { int baseTier, int machineTier, @Nullable Map cache) { T selected = null; + int total = 1; + for (T entry : chancedEntries) { + total += entry.getMaxChance(); + } + + roll = GTValues.RNG.nextInt(total); for (T entry : chancedEntries) { int chance = getChance(entry, boostFunction, baseTier, machineTier); - if (passesChance(chance, entry, cache) && selected == null) { + if (passesChance(chance, entry, cache)) { selected = entry; } } return selected == null ? null : Collections.singletonList(selected); } + @Override + public > boolean passesChance(int chance, T entry, + @Nullable Map cache) { + int fullChance = getCachedChance(entry, cache) + chance; + boolean b = fullChance >= roll; + if (!b) roll -= fullChance; + updateCachedChance(entry, cache, fullChance); + return b; + } + @Override public @NotNull String getTranslationKey() { return "gregtech.chance_logic.xor"; @@ -163,22 +181,21 @@ static int getChance(@NotNull ChancedOutput entry, @NotNull ChanceBoostFuncti * @param cache the cache of previously rolled chances, can be null * @return if the roll with the chance is successful */ - static > boolean passesChance(int chance, T entry, @Nullable Map cache) { + default > boolean passesChance(int chance, T entry, @Nullable Map cache) { if (cache == null || !cache.containsKey(entry.getIngredient())) { int initial = GTValues.RNG.nextInt(entry.getMaxChance()); - updateCachedChance(entry.getIngredient(), cache, initial); + updateCachedChance(entry, cache, initial); return initial <= entry.getChance(); } + boolean roll = false; int fullChance = getCachedChance(entry, cache) + chance; if (fullChance >= entry.getMaxChance()) { - fullChance %= entry.getMaxChance(); - updateCachedChance(entry.getIngredient(), cache, fullChance); - return true; + roll = true; } - updateCachedChance(entry.getIngredient(), cache, fullChance); - return false; + updateCachedChance(entry, cache, fullChance); + return roll; } /** @@ -206,9 +223,9 @@ static > int getCachedChance(T entry, @Nullable Ma * @param cache the cache of previously rolled chances, can be null * @param chance the chance to update the cache with */ - static void updateCachedChance(I ingredient, @Nullable Map cache, int chance) { + static void updateCachedChance(ChancedOutput ingredient, @Nullable Map cache, int chance) { if (cache == null) return; - cache.put(ingredient, chance); + cache.put(ingredient.getIngredient(), chance % ingredient.getMaxChance()); } /** From 2cb3f2a87eab799bca43e86fb0303241fa53a68a Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Fri, 15 Nov 2024 22:18:46 -0700 Subject: [PATCH 41/45] what's this? committing to a pr that's very old and supposedly finished? move cache, machine tier, recipe tier, and boost function into RecipeContext add CalculatedOutput so that chance logic set amounts for overflowing chances fix XOR logic tests because the behavior of XOR was changed slightly --- .../capability/impl/AbstractRecipeLogic.java | 13 +- .../api/capability/impl/miner/MinerLogic.java | 6 +- .../java/gregtech/api/recipes/Recipe.java | 67 +++--- .../gregtech/api/recipes/RecipeContext.java | 55 +++++ .../chance/output/CalculatedOutput.java | 30 +++ .../chance/output/ChancedOutputList.java | 12 +- .../chance/output/ChancedOutputLogic.java | 199 +++++++----------- .../crafttweaker/recipe/CTRecipe.java | 7 +- .../chance/output/ChancedOutputLogicTest.java | 29 ++- 9 files changed, 235 insertions(+), 183 deletions(-) create mode 100644 src/main/java/gregtech/api/recipes/RecipeContext.java create mode 100644 src/main/java/gregtech/api/recipes/chance/output/CalculatedOutput.java diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 942db5e8488..24dd6739a97 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -14,6 +14,7 @@ import gregtech.api.metatileentity.multiblock.ParallelLogicType; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeBuilder; +import gregtech.api.recipes.RecipeContext; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.logic.IParallelableRecipeLogic; import gregtech.api.recipes.logic.OCParams; @@ -74,16 +75,18 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable, protected int maxProgressTime; protected long recipeEUt; protected List fluidOutputs; - protected Map fluidChancesCache = new Object2IntOpenCustomHashMap<>( + protected final Map fluidChancesCache = new Object2IntOpenCustomHashMap<>( FluidStackHashStrategy.builder() .compareFluid(true) .build()); protected List itemOutputs; - protected Map itemChancesCache = new Object2IntOpenCustomHashMap<>( + protected final Map itemChancesCache = new Object2IntOpenCustomHashMap<>( ItemStackHashStrategy.builder() .compareItem(true) .compareDamage(true) .build()); + private final RecipeContext itemContext = new RecipeContext<>(itemChancesCache); + private final RecipeContext fluidContext = new RecipeContext<>(fluidChancesCache); protected boolean isActive; protected boolean workingEnabled = true; @@ -968,9 +971,11 @@ protected void setupRecipe(@NotNull Recipe recipe) { RecipeMap map = getRecipeMap(); if (map != null) { this.fluidOutputs = GTUtility - .copyFluidList(recipe.getResultFluidOutputs(recipeTier, machineTier, map, fluidChancesCache)); + .copyFluidList(recipe.getResultFluidOutputs( + fluidContext.update(map.getChanceFunction(), recipeTier, machineTier))); this.itemOutputs = GTUtility - .copyStackList(recipe.getResultItemOutputs(recipeTier, machineTier, map, itemChancesCache)); + .copyStackList(recipe.getResultItemOutputs( + itemContext.update(map.getChanceFunction(), recipeTier, machineTier))); } if (this.wasActiveAndNeedsUpdate) { diff --git a/src/main/java/gregtech/api/capability/impl/miner/MinerLogic.java b/src/main/java/gregtech/api/capability/impl/miner/MinerLogic.java index 2565c02a7a5..8a916541fad 100644 --- a/src/main/java/gregtech/api/capability/impl/miner/MinerLogic.java +++ b/src/main/java/gregtech/api/capability/impl/miner/MinerLogic.java @@ -4,6 +4,7 @@ import gregtech.api.capability.IMiner; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.recipes.Recipe; +import gregtech.api.recipes.RecipeContext; import gregtech.api.recipes.RecipeMap; import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.ore.OrePrefix; @@ -451,8 +452,9 @@ protected static void applyTieredHammerNoRandomDrops(@NotNull IBlockState blockS Recipe recipe = map.findRecipe(Long.MAX_VALUE, Collections.singletonList(itemStack), Collections.emptyList()); if (recipe != null && !recipe.getOutputs().isEmpty()) { drops.clear(); - for (ItemStack outputStack : recipe.getResultItemOutputs(GTUtility.getTierByVoltage(recipe.getEUt()), tier, - map)) { + var context = new RecipeContext() + .update(map.getChanceFunction(), GTUtility.getTierByVoltage(recipe.getEUt()), tier); + for (ItemStack outputStack : recipe.getResultItemOutputs(context)) { outputStack = outputStack.copy(); if (OreDictUnifier.getPrefix(outputStack) == OrePrefix.crushed) { if (fortuneLevel > 0) { diff --git a/src/main/java/gregtech/api/recipes/Recipe.java b/src/main/java/gregtech/api/recipes/Recipe.java index 8de6e048cc9..4913ee94d14 100644 --- a/src/main/java/gregtech/api/recipes/Recipe.java +++ b/src/main/java/gregtech/api/recipes/Recipe.java @@ -2,7 +2,6 @@ import gregtech.api.capability.IMultipleTankHandler; import gregtech.api.recipes.category.GTRecipeCategory; -import gregtech.api.recipes.chance.boost.ChanceBoostFunction; import gregtech.api.recipes.chance.output.ChancedOutputList; import gregtech.api.recipes.chance.output.ChancedOutputLogic; import gregtech.api.recipes.chance.output.impl.ChancedFluidOutput; @@ -18,7 +17,6 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.oredict.OreDictionary; import com.google.common.collect.ImmutableList; @@ -464,38 +462,34 @@ public List getOutputs() { * The Recipe should be trimmed by calling {@link Recipe#getItemAndChanceOutputs(int)} before calling this method, * if trimming is required. * - * @param recipeTier The Voltage Tier of the Recipe, used for chanced output calculation - * @param machineTier The Voltage Tier of the Machine, used for chanced output calculation - * @param recipeMap The RecipeMap that the recipe is being performed upon, used for chanced output calculation + * @param context Context containing machine and recipe tier, the boost function, and the chance cache * @return A list of all resulting ItemStacks from the recipe, after chance has been applied to any chanced outputs */ - public List getResultItemOutputs(int recipeTier, int machineTier, RecipeMap recipeMap, - Map cache) { + public List getResultItemOutputs(RecipeContext context) { List outputs = new ArrayList<>(getOutputs()); - ChanceBoostFunction function = recipeMap.getChanceFunction(); - List chancedOutputsList = getChancedOutputs().roll(function, recipeTier, machineTier, cache); + var chancedOutputsList = getChancedOutputs().roll(context); if (chancedOutputsList == null) return outputs; Collection resultChanced = new ArrayList<>(); - for (ChancedItemOutput chancedOutput : chancedOutputsList) { - ItemStack stackToAdd = chancedOutput.getIngredient().copy(); - for (ItemStack stackInList : resultChanced) { - int insertable = stackInList.getMaxStackSize() - stackInList.getCount(); - if (insertable > 0 && ItemHandlerHelper.canItemStacksStack(stackInList, stackToAdd)) { - if (insertable >= stackToAdd.getCount()) { - stackInList.grow(stackToAdd.getCount()); - stackToAdd = ItemStack.EMPTY; - break; - } else { - stackInList.grow(insertable); - stackToAdd.shrink(insertable); - } - } - } - if (!stackToAdd.isEmpty()) { - resultChanced.add(stackToAdd); - } + for (var chancedOutput : chancedOutputsList) { + ItemStack stackToAdd = chancedOutput.createStack((output, count) -> GTUtility.copy(count, output)); + // for (ItemStack stackInList : resultChanced) { + // int insertable = stackInList.getMaxStackSize() - stackInList.getCount(); + // if (insertable > 0 && ItemHandlerHelper.canItemStacksStack(stackInList, stackToAdd)) { + // if (insertable >= stackToAdd.getCount()) { + // stackInList.grow(stackToAdd.getCount()); + // stackToAdd = ItemStack.EMPTY; + // break; + // } else { + // stackInList.grow(insertable); + // stackToAdd.shrink(insertable); + // } + // } + // } + // if (!stackToAdd.isEmpty()) { + // } + resultChanced.add(stackToAdd); } outputs.addAll(resultChanced); @@ -503,10 +497,6 @@ public List getResultItemOutputs(int recipeTier, int machineTier, Rec return outputs; } - public List getResultItemOutputs(int recipeTier, int machineTier, RecipeMap recipeMap) { - return getResultItemOutputs(recipeTier, machineTier, recipeMap, null); - } - /** * Returns the maximum possible recipe outputs from a recipe, divided into regular and chanced outputs * Takes into account any specific output limiters, ie macerator slots, to trim down the output list @@ -664,24 +654,19 @@ public List getAllFluidOutputs() { * The Recipe should be trimmed by calling {@link Recipe#getFluidAndChanceOutputs(int)} before calling this method, * if trimming is required. * - * @param recipeTier The Voltage Tier of the Recipe, used for chanced output calculation - * @param machineTier The Voltage Tier of the Machine, used for chanced output calculation - * @param recipeMap The RecipeMap that the recipe is being performed upon, used for chanced output calculation + * @param context Context containing machine and recipe tier, the boost function, and the chance cache * @return A list of all resulting ItemStacks from the recipe, after chance has been applied to any chanced outputs */ - public List getResultFluidOutputs(int recipeTier, int machineTier, RecipeMap recipeMap, - Map cache) { + public List getResultFluidOutputs(RecipeContext context) { List outputs = new ArrayList<>(GTUtility.copyFluidList(getFluidOutputs())); - ChanceBoostFunction function = recipeMap.getChanceFunction(); - List chancedOutputsList = getChancedFluidOutputs().roll(function, recipeTier, machineTier, - cache); + var chancedOutputsList = getChancedFluidOutputs().roll(context); if (chancedOutputsList == null) return outputs; Collection resultChanced = new ArrayList<>(); - for (ChancedFluidOutput chancedOutput : chancedOutputsList) { - FluidStack stackToAdd = chancedOutput.getIngredient().copy(); + for (var chancedOutput : chancedOutputsList) { + FluidStack stackToAdd = chancedOutput.createStack(FluidStack::new); for (FluidStack stackInList : resultChanced) { int insertable = stackInList.amount; if (insertable > 0 && stackInList.getFluid() == stackToAdd.getFluid()) { diff --git a/src/main/java/gregtech/api/recipes/RecipeContext.java b/src/main/java/gregtech/api/recipes/RecipeContext.java new file mode 100644 index 00000000000..2648debe988 --- /dev/null +++ b/src/main/java/gregtech/api/recipes/RecipeContext.java @@ -0,0 +1,55 @@ +package gregtech.api.recipes; + +import gregtech.api.recipes.chance.boost.BoostableChanceEntry; +import gregtech.api.recipes.chance.boost.ChanceBoostFunction; +import gregtech.api.recipes.chance.output.ChancedOutput; + +import java.util.Map; + +public class RecipeContext { + + private final Map cache; + ChanceBoostFunction boostFunction; + public int baseTier, machineTier; + + public RecipeContext(Map cache) { + this.cache = cache; + } + + public RecipeContext() { + this(null); + } + + public RecipeContext update(ChanceBoostFunction boostFunction, + int baseTier, int machineTier) { + this.boostFunction = boostFunction; + this.baseTier = baseTier; + this.machineTier = machineTier; + return this; + } + + public void updateCachedChance(ChancedOutput entry, int chance) { + if (cache == null) return; + cache.put(entry.getIngredient(), chance % entry.getMaxChance()); + } + + public int getCachedChance(ChancedOutput entry) { + if (cache == null || !cache.containsKey(entry.getIngredient())) + return -1; + + return cache.get(entry.getIngredient()); + } + + public int getChance(ChancedOutput entry) { + int cache = getCachedChance(entry); + if (cache == -1) cache = 0; + if (entry instanceof BoostableChanceEntryboostableChanceEntry) { + return boostChance(boostableChanceEntry) + cache; + } + return entry.getChance() + cache; + } + + public int boostChance(BoostableChanceEntry entry) { + return boostFunction.getBoostedChance(entry, baseTier, machineTier); + } +} diff --git a/src/main/java/gregtech/api/recipes/chance/output/CalculatedOutput.java b/src/main/java/gregtech/api/recipes/chance/output/CalculatedOutput.java new file mode 100644 index 00000000000..8a6c0c50177 --- /dev/null +++ b/src/main/java/gregtech/api/recipes/chance/output/CalculatedOutput.java @@ -0,0 +1,30 @@ +package gregtech.api.recipes.chance.output; + +public class CalculatedOutput { + + ChancedOutput output; + int amount; + + public CalculatedOutput(ChancedOutput output, int amount) { + this.output = output; + this.amount = amount; + } + + public CalculatedOutput(ChancedOutput output) { + this(output, 1); + } + + public I createStack(ChanceConverter converter) { + return converter.convert(output.getIngredient(), amount); + } + + public I getIngrediet() { + return output.getIngredient(); + } + + @FunctionalInterface + public interface ChanceConverter { + + I convert(I output, int count); + } +} diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputList.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputList.java index 553e5d86c24..3a2c0de1ba1 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputList.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputList.java @@ -1,6 +1,6 @@ package gregtech.api.recipes.chance.output; -import gregtech.api.recipes.chance.boost.ChanceBoostFunction; +import gregtech.api.recipes.RecipeContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -8,7 +8,6 @@ import java.util.Collections; import java.util.List; -import java.util.Map; /** * A list of rollable chanced outputs @@ -34,14 +33,11 @@ public ChancedOutputList(@NotNull ChancedOutputLogic chancedOutputLogic, @NotNul /** * Roll the chances for this output list * - * @param boostFunction the function used to boost the outputs - * @param baseTier the base tier of the recipe - * @param machineTier the tier the recipe is run at + * @param context Context containing machine and recipe tier, the boost function, and the chance cache * @return a list of the rolled outputs */ - public @Nullable @Unmodifiable List roll(@NotNull ChanceBoostFunction boostFunction, int baseTier, - int machineTier, Map cache) { - return chancedOutputLogic.roll(getChancedEntries(), boostFunction, baseTier, machineTier, cache); + public @Nullable @Unmodifiable List> roll(@NotNull RecipeContext context) { + return chancedOutputLogic.roll(getChancedEntries(), context); } public @NotNull ChancedOutputLogic getChancedOutputLogic() { diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 267d7ce5e6a..2dba13a54bb 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -1,8 +1,7 @@ package gregtech.api.recipes.chance.output; import gregtech.api.GTValues; -import gregtech.api.recipes.chance.boost.BoostableChanceEntry; -import gregtech.api.recipes.chance.boost.ChanceBoostFunction; +import gregtech.api.recipes.RecipeContext; import com.google.common.collect.ImmutableList; import org.jetbrains.annotations.NotNull; @@ -11,7 +10,6 @@ import java.util.Collections; import java.util.List; -import java.util.Map; /** * Logic for determining which chanced outputs should be produced from a list @@ -24,22 +22,22 @@ public interface ChancedOutputLogic { ChancedOutputLogic OR = new ChancedOutputLogic() { @Override - public @Nullable @Unmodifiable > List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, - @NotNull ChanceBoostFunction boostFunction, - int baseTier, int machineTier, - @Nullable Map cache) { - ImmutableList.Builder builder = ImmutableList.builder(); + public @Nullable @Unmodifiable > List<@NotNull CalculatedOutput> roll( + @NotNull @Unmodifiable List<@NotNull T> chancedEntries, + @NotNull RecipeContext context) { + ImmutableList.Builder> builder = ImmutableList.builder(); + boolean success = false; for (T entry : chancedEntries) { - int chance = getChance(entry, boostFunction, baseTier, machineTier); - if (passesChance(chance, entry, cache)) { - builder.add(entry); + int chance = context.getChance(entry); + if (passesChance(chance, entry, context)) { + success = true; + int amount = chance / entry.getMaxChance(); + builder.add(new CalculatedOutput<>(entry, amount)); } } - List list = builder.build(); - return list.size() == 0 ? null : list; + return success ? builder.build() : null; } @Override @@ -59,19 +57,20 @@ public String toString() { ChancedOutputLogic AND = new ChancedOutputLogic() { @Override - public @Nullable @Unmodifiable > List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, - @NotNull ChanceBoostFunction boostFunction, - int baseTier, int machineTier, - @Nullable Map cache) { + public @Nullable @Unmodifiable > List<@NotNull CalculatedOutput> roll( + @NotNull @Unmodifiable List<@NotNull T> chancedEntries, + @NotNull RecipeContext context) { + ImmutableList.Builder> builder = ImmutableList.builder(); boolean failed = false; for (T entry : chancedEntries) { - int chance = getChance(entry, boostFunction, baseTier, machineTier); - if (!passesChance(chance, entry, cache)) { + int chance = context.getChance(entry); + int amount = chance / entry.getMaxChance(); + builder.add(new CalculatedOutput<>(entry, amount)); + if (!passesChance(chance, entry, context)) { failed = true; } } - return failed ? null : ImmutableList.copyOf(chancedEntries); + return failed ? null : builder.build(); } @Override @@ -93,12 +92,10 @@ public String toString() { private int roll; @Override - public @Nullable @Unmodifiable > List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, - @NotNull ChanceBoostFunction boostFunction, - int baseTier, int machineTier, - @Nullable Map cache) { - T selected = null; + public @Nullable @Unmodifiable > List<@NotNull CalculatedOutput> roll( + @NotNull @Unmodifiable List<@NotNull T> chancedEntries, + @NotNull RecipeContext context) { + CalculatedOutput selected = null; int total = 1; for (T entry : chancedEntries) { total += entry.getMaxChance(); @@ -106,9 +103,9 @@ public String toString() { roll = GTValues.RNG.nextInt(total); for (T entry : chancedEntries) { - int chance = getChance(entry, boostFunction, baseTier, machineTier); - if (passesChance(chance, entry, cache)) { - selected = entry; + int chance = context.getChance(entry); + if (passesChance(chance, entry, context) && selected == null) { + selected = new CalculatedOutput<>(entry); } } return selected == null ? null : Collections.singletonList(selected); @@ -116,11 +113,10 @@ public String toString() { @Override public > boolean passesChance(int chance, T entry, - @Nullable Map cache) { - int fullChance = getCachedChance(entry, cache) + chance; - boolean b = fullChance >= roll; - if (!b) roll -= fullChance; - updateCachedChance(entry, cache, fullChance); + @NotNull RecipeContext context) { + boolean b = chance >= roll; + if (!b) roll -= chance; + context.updateCachedChance(entry, chance); return b; } @@ -141,11 +137,9 @@ public String toString() { ChancedOutputLogic NONE = new ChancedOutputLogic() { @Override - public @Nullable @Unmodifiable > List<@NotNull T> roll(@NotNull @Unmodifiable List<@NotNull T> chancedEntries, - @NotNull ChanceBoostFunction boostFunction, - int baseTier, int machineTier, - @Nullable Map cache) { + public @Nullable @Unmodifiable > List<@NotNull CalculatedOutput> roll( + @NotNull @Unmodifiable List<@NotNull T> chancedEntries, + @NotNull RecipeContext context) { return null; } @@ -161,40 +155,26 @@ public String toString() { }; /** - * @param entry the entry to get the complete chance for - * @param boostFunction the function boosting the entry's chance - * @param baseTier the base tier of the recipe - * @param machineTier the tier the recipe is run at - * @return the total chance for the entry - */ - static int getChance(@NotNull ChancedOutput entry, @NotNull ChanceBoostFunction boostFunction, int baseTier, - int machineTier) { - if (entry instanceof BoostableChanceEntryboostableChanceEntry) { - return boostFunction.getBoostedChance(boostableChanceEntry, baseTier, machineTier); - } - return entry.getChance(); - } - - /** - * @param chance the boosted chance to be checked - * @param entry the entry to get the max chance and ingredient of for comparison and cache - * @param cache the cache of previously rolled chances, can be null + * @param chance the boosted chance to be checked + * @param entry the entry to get the max chance and ingredient of for comparison and cache + * @param context Context containing machine and recipe tier, the boost function, and the chance cache * @return if the roll with the chance is successful */ - default > boolean passesChance(int chance, T entry, @Nullable Map cache) { - if (cache == null || !cache.containsKey(entry.getIngredient())) { + default > boolean passesChance(int chance, T entry, + @NotNull RecipeContext context) { + if (context.getCachedChance(entry) == -1) { int initial = GTValues.RNG.nextInt(entry.getMaxChance()); - updateCachedChance(entry, cache, initial); + context.updateCachedChance(entry, chance); return initial <= entry.getChance(); } boolean roll = false; - int fullChance = getCachedChance(entry, cache) + chance; + int fullChance = context.getChance(entry); if (fullChance >= entry.getMaxChance()) { roll = true; } - updateCachedChance(entry, cache, fullChance); + context.updateCachedChance(entry, fullChance); return roll; } @@ -205,61 +185,42 @@ static int getMaxChancedValue() { return 10_000; } - /** - * @param entry the current entry - * @param cache the cache of previously rolled chances, can be null - * @return the cached chance, otherwise 0 if - * the cache is null or does not contain the key - */ - static > int getCachedChance(T entry, @Nullable Map cache) { - if (cache == null || !cache.containsKey(entry.getIngredient())) - return 0; - - return cache.get(entry.getIngredient()); - } - - /** - * @param ingredient the key used for the cache - * @param cache the cache of previously rolled chances, can be null - * @param chance the chance to update the cache with - */ - static void updateCachedChance(ChancedOutput ingredient, @Nullable Map cache, int chance) { - if (cache == null) return; - cache.put(ingredient.getIngredient(), chance % ingredient.getMaxChance()); - } - - /** - * Roll the chance and attempt to produce the output - * - * @param chancedEntries the list of entries to roll - * @param boostFunction the function to boost the entries' chances - * @param baseTier the base tier of the recipe - * @param machineTier the tier the recipe is run at - * @param cache the cache of previously rolled chances, can be null - * @return a list of the produced outputs, or null if failed - */ - > @Nullable @Unmodifiable List<@NotNull T> roll( - @NotNull @Unmodifiable List<@NotNull T> chancedEntries, - @NotNull ChanceBoostFunction boostFunction, - int baseTier, int machineTier, - @Nullable Map cache); - - /** - * Roll the chance and attempt to produce the output - * - * @param chancedEntries the list of entries to roll - * @param boostFunction the function to boost the entries' chances - * @param baseTier the base tier of the recipe - * @param machineTier the tier the recipe is run at - * @return a list of the produced outputs - */ - default > @Nullable @Unmodifiable List<@NotNull T> roll( - @NotNull @Unmodifiable List<@NotNull T> chancedEntries, - @NotNull ChanceBoostFunction boostFunction, - int baseTier, - int machineTier) { - return roll(chancedEntries, boostFunction, baseTier, machineTier, null); - } + // /** + // * Roll the chance and attempt to produce the output + // * + // * @param chancedEntries the list of entries to roll + // * @param boostFunction the function to boost the entries' chances + // * @param baseTier the base tier of the recipe + // * @param machineTier the tier the recipe is run at + // * @param cache the cache of previously rolled chances, can be null + // * @return a list of the produced outputs, or null if failed + // */ + // > @Nullable @Unmodifiable List<@NotNull T> roll( + // @NotNull @Unmodifiable List<@NotNull T> chancedEntries, + // @NotNull ChanceBoostFunction boostFunction, + // int baseTier, int machineTier, + // @Nullable Map cache); + + // /** + // * Roll the chance and attempt to produce the output + // * + // * @param chancedEntries the list of entries to roll + // * @param boostFunction the function to boost the entries' chances + // * @param baseTier the base tier of the recipe + // * @param machineTier the tier the recipe is run at + // * @return a list of the produced outputs + // */ + // default > @Nullable @Unmodifiable List<@NotNull T> roll( + // @NotNull @Unmodifiable List<@NotNull T> chancedEntries, + // @NotNull ChanceBoostFunction boostFunction, + // int baseTier, + // int machineTier) { + // return roll(chancedEntries, boostFunction, baseTier, machineTier, null); + // } + + > @Nullable @Unmodifiable List<@NotNull CalculatedOutput> roll( + @NotNull @Unmodifiable List<@NotNull T> chancedEntries, + @NotNull RecipeContext context); @NotNull String getTranslationKey(); diff --git a/src/main/java/gregtech/integration/crafttweaker/recipe/CTRecipe.java b/src/main/java/gregtech/integration/crafttweaker/recipe/CTRecipe.java index ac71e2f0fbb..a524ce2802f 100644 --- a/src/main/java/gregtech/integration/crafttweaker/recipe/CTRecipe.java +++ b/src/main/java/gregtech/integration/crafttweaker/recipe/CTRecipe.java @@ -1,9 +1,12 @@ package gregtech.integration.crafttweaker.recipe; import gregtech.api.recipes.Recipe; +import gregtech.api.recipes.RecipeContext; import gregtech.api.recipes.RecipeMap; import gregtech.api.util.GTUtility; +import net.minecraft.item.ItemStack; + import crafttweaker.annotations.ZenRegister; import crafttweaker.api.item.IItemStack; import crafttweaker.api.liquid.ILiquidStack; @@ -49,7 +52,9 @@ public List getOutputs() { @ZenMethod public List getResultItemOutputs(@Optional(valueLong = 1) int tier) { - return this.backingRecipe.getResultItemOutputs(GTUtility.getTierByVoltage(getEUt()), tier, recipeMap) + return this.backingRecipe.getResultItemOutputs( + new RecipeContext() + .update(recipeMap.getChanceFunction(), GTUtility.getTierByVoltage(getEUt()), tier)) .stream() .map(MCItemStack::new) .collect(Collectors.toList()); diff --git a/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java b/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java index 4e6cbf026c9..c720d7a421e 100644 --- a/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java +++ b/src/test/java/gregtech/api/recipes/chance/output/ChancedOutputLogicTest.java @@ -1,5 +1,6 @@ package gregtech.api.recipes.chance.output; +import gregtech.api.recipes.RecipeContext; import gregtech.api.recipes.chance.ChanceEntry; import gregtech.api.recipes.chance.boost.ChanceBoostFunction; @@ -26,12 +27,15 @@ public TestChancedOutput(@NotNull String ingredient, int chance) { } } + private static final RecipeContext context = new RecipeContext().update(ChanceBoostFunction.NONE, 0, + 0); + private static > void listsMatch(@NotNull List original, - @Nullable List rolled) { + @Nullable List> rolled) { MatcherAssert.assertThat(rolled, CoreMatchers.notNullValue()); MatcherAssert.assertThat(rolled.size(), CoreMatchers.is(original.size())); for (int i = 0; i < original.size(); i++) { - MatcherAssert.assertThat(rolled.get(i).getIngredient(), CoreMatchers.is(original.get(i).getIngredient())); + MatcherAssert.assertThat(rolled.get(i).getIngrediet(), CoreMatchers.is(original.get(i).getIngredient())); } } @@ -42,7 +46,7 @@ public void testORLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - List list = ChancedOutputLogic.OR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); + var list = ChancedOutputLogic.OR.roll(chanceEntries, context); listsMatch(chanceEntries, list); } @@ -53,7 +57,7 @@ public void testANDLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", 0)); - List list = ChancedOutputLogic.AND.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); + var list = ChancedOutputLogic.AND.roll(chanceEntries, context); MatcherAssert.assertThat(list, CoreMatchers.nullValue()); chanceEntries = ImmutableList.of( @@ -61,7 +65,7 @@ public void testANDLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - list = ChancedOutputLogic.AND.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); + list = ChancedOutputLogic.AND.roll(chanceEntries, context); listsMatch(chanceEntries, list); } @@ -72,10 +76,19 @@ public void testXORLogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - List list = ChancedOutputLogic.XOR.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); + var list = ChancedOutputLogic.XOR.roll(chanceEntries, context); MatcherAssert.assertThat(list, CoreMatchers.notNullValue()); MatcherAssert.assertThat(list.size(), CoreMatchers.is(1)); - MatcherAssert.assertThat(list.get(0).getIngredient(), CoreMatchers.is(chanceEntries.get(0).getIngredient())); + boolean exists = false; + for (var e : chanceEntries) { + if (e.getIngredient().equals(list.get(0).getIngrediet())) + exists = true; + } + MatcherAssert.assertThat(exists, CoreMatchers.is(true)); + + // XOR does not always produce the first entry from the list + // MatcherAssert.assertThat(list.get(0).output.getIngredient(), + // CoreMatchers.is(chanceEntries.get(0).getIngredient())); } @Test @@ -85,7 +98,7 @@ public void testNONELogic() { new TestChancedOutput("b", ChancedOutputLogic.getMaxChancedValue()), new TestChancedOutput("c", ChancedOutputLogic.getMaxChancedValue())); - List list = ChancedOutputLogic.NONE.roll(chanceEntries, ChanceBoostFunction.NONE, 0, 0); + var list = ChancedOutputLogic.NONE.roll(chanceEntries, context); MatcherAssert.assertThat(list, CoreMatchers.nullValue()); } } From cfb212f188e0f36009141aee8dcdd8fbe325a29c Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Fri, 15 Nov 2024 23:17:04 -0700 Subject: [PATCH 42/45] fix issues with chance passing --- .../chance/output/ChancedOutputLogic.java | 47 ++----------------- 1 file changed, 4 insertions(+), 43 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 2dba13a54bb..0e53e3483d5 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -164,18 +164,12 @@ default > boolean passesChance(int chance, T entry @NotNull RecipeContext context) { if (context.getCachedChance(entry) == -1) { int initial = GTValues.RNG.nextInt(entry.getMaxChance()); - context.updateCachedChance(entry, chance); - return initial <= entry.getChance(); - } - - boolean roll = false; - int fullChance = context.getChance(entry); - if (fullChance >= entry.getMaxChance()) { - roll = true; + context.updateCachedChance(entry, initial); + return initial <= chance; } - context.updateCachedChance(entry, fullChance); - return roll; + context.updateCachedChance(entry, chance); + return chance >= entry.getMaxChance(); } /** @@ -185,39 +179,6 @@ static int getMaxChancedValue() { return 10_000; } - // /** - // * Roll the chance and attempt to produce the output - // * - // * @param chancedEntries the list of entries to roll - // * @param boostFunction the function to boost the entries' chances - // * @param baseTier the base tier of the recipe - // * @param machineTier the tier the recipe is run at - // * @param cache the cache of previously rolled chances, can be null - // * @return a list of the produced outputs, or null if failed - // */ - // > @Nullable @Unmodifiable List<@NotNull T> roll( - // @NotNull @Unmodifiable List<@NotNull T> chancedEntries, - // @NotNull ChanceBoostFunction boostFunction, - // int baseTier, int machineTier, - // @Nullable Map cache); - - // /** - // * Roll the chance and attempt to produce the output - // * - // * @param chancedEntries the list of entries to roll - // * @param boostFunction the function to boost the entries' chances - // * @param baseTier the base tier of the recipe - // * @param machineTier the tier the recipe is run at - // * @return a list of the produced outputs - // */ - // default > @Nullable @Unmodifiable List<@NotNull T> roll( - // @NotNull @Unmodifiable List<@NotNull T> chancedEntries, - // @NotNull ChanceBoostFunction boostFunction, - // int baseTier, - // int machineTier) { - // return roll(chancedEntries, boostFunction, baseTier, machineTier, null); - // } - > @Nullable @Unmodifiable List<@NotNull CalculatedOutput> roll( @NotNull @Unmodifiable List<@NotNull T> chancedEntries, @NotNull RecipeContext context); From 929f27c1c426ae0a925e0b40ace4e298a5d44c1c Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 16 Nov 2024 00:02:20 -0700 Subject: [PATCH 43/45] simplify xor and make passesChance static again --- .../chance/output/ChancedOutputLogic.java | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java index 0e53e3483d5..c4e7d1a1616 100644 --- a/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java +++ b/src/main/java/gregtech/api/recipes/chance/output/ChancedOutputLogic.java @@ -89,8 +89,6 @@ public String toString() { */ ChancedOutputLogic XOR = new ChancedOutputLogic() { - private int roll; - @Override public @Nullable @Unmodifiable > List<@NotNull CalculatedOutput> roll( @NotNull @Unmodifiable List<@NotNull T> chancedEntries, @@ -101,25 +99,19 @@ public String toString() { total += entry.getMaxChance(); } - roll = GTValues.RNG.nextInt(total); + int roll = GTValues.RNG.nextInt(total); for (T entry : chancedEntries) { int chance = context.getChance(entry); - if (passesChance(chance, entry, context) && selected == null) { + if (chance >= roll && selected == null) { selected = new CalculatedOutput<>(entry); + } else if (selected != null) { + roll -= chance; } + context.updateCachedChance(entry, chance); } return selected == null ? null : Collections.singletonList(selected); } - @Override - public > boolean passesChance(int chance, T entry, - @NotNull RecipeContext context) { - boolean b = chance >= roll; - if (!b) roll -= chance; - context.updateCachedChance(entry, chance); - return b; - } - @Override public @NotNull String getTranslationKey() { return "gregtech.chance_logic.xor"; @@ -155,16 +147,17 @@ public String toString() { }; /** - * @param chance the boosted chance to be checked - * @param entry the entry to get the max chance and ingredient of for comparison and cache + * @param chance the boosted chance plus the cached chance to be checked + * @param entry the entry to get the max chance and compare to chance * @param context Context containing machine and recipe tier, the boost function, and the chance cache * @return if the roll with the chance is successful */ - default > boolean passesChance(int chance, T entry, - @NotNull RecipeContext context) { + static > boolean passesChance(int chance, T entry, + @NotNull RecipeContext context) { if (context.getCachedChance(entry) == -1) { int initial = GTValues.RNG.nextInt(entry.getMaxChance()); context.updateCachedChance(entry, initial); + // chance here is the boosted (if possible) entry chance return initial <= chance; } From b33fafbd134f9f879501d41d9d2039092947ef9f Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 16 Nov 2024 00:11:20 -0700 Subject: [PATCH 44/45] put cache construction into context --- .../capability/impl/AbstractRecipeLogic.java | 33 ++++++++----------- .../gregtech/api/recipes/RecipeContext.java | 17 ++++++++-- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 24dd6739a97..8f69bc71407 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -40,14 +40,12 @@ import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.items.IItemHandlerModifiable; -import it.unimi.dsi.fastutil.objects.Object2IntOpenCustomHashMap; import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; -import java.util.Map; import static gregtech.api.GTValues.ULV; import static gregtech.api.recipes.logic.OverclockingLogic.*; @@ -75,18 +73,15 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable, protected int maxProgressTime; protected long recipeEUt; protected List fluidOutputs; - protected final Map fluidChancesCache = new Object2IntOpenCustomHashMap<>( - FluidStackHashStrategy.builder() - .compareFluid(true) - .build()); protected List itemOutputs; - protected final Map itemChancesCache = new Object2IntOpenCustomHashMap<>( - ItemStackHashStrategy.builder() - .compareItem(true) - .compareDamage(true) - .build()); - private final RecipeContext itemContext = new RecipeContext<>(itemChancesCache); - private final RecipeContext fluidContext = new RecipeContext<>(fluidChancesCache); + + private final RecipeContext itemContext = new RecipeContext<>(ItemStackHashStrategy.builder() + .compareItem(true) + .compareDamage(true) + .build()); + private final RecipeContext fluidContext = new RecipeContext<>(FluidStackHashStrategy.builder() + .compareFluid(true) + .build()); protected boolean isActive; protected boolean workingEnabled = true; @@ -409,8 +404,8 @@ protected void trySearchNewRecipe() { // we found a new recipe, clear the cache if (this.previousRecipe != null && !currentRecipe.equals(this.previousRecipe)) { - this.itemChancesCache.clear(); - this.fluidChancesCache.clear(); + this.itemContext.getCache().clear(); + this.fluidContext.getCache().clear(); } this.previousRecipe = currentRecipe; } @@ -1237,13 +1232,13 @@ public NBTTagCompound serializeNBT() { compound.setTag("FluidOutputs", fluidOutputsList); NBTTagList itemCache = new NBTTagList(); - for (var entry : itemChancesCache.entrySet()) { + for (var entry : itemContext.getCache().entrySet()) { var tag = entry.getKey().serializeNBT(); tag.setInteger("CachedChance", entry.getValue()); itemCache.appendTag(tag); } NBTTagList fluidCache = new NBTTagList(); - for (var entry : fluidChancesCache.entrySet()) { + for (var entry : fluidContext.getCache().entrySet()) { var tag = entry.getKey().writeToNBT(new NBTTagCompound()); tag.setInteger("CachedChance", entry.getValue()); fluidCache.appendTag(tag); @@ -1281,14 +1276,14 @@ public void deserializeNBT(@NotNull NBTTagCompound compound) { for (int i = 0; i < itemCache.tagCount(); i++) { var stack = itemCache.getCompoundTagAt(i); int cache = stack.getInteger("CachedChance"); - this.itemChancesCache.put(new ItemStack(stack), cache); + this.itemContext.updateCachedChance(new ItemStack(stack), cache); } NBTTagList fluidCache = compound.getTagList("FluidChanceCache", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < fluidCache.tagCount(); i++) { var stack = fluidCache.getCompoundTagAt(i); int cache = stack.getInteger("CachedChance"); - this.fluidChancesCache.put(FluidStack.loadFluidStackFromNBT(stack), cache); + this.fluidContext.updateCachedChance(FluidStack.loadFluidStackFromNBT(stack), cache); } } } diff --git a/src/main/java/gregtech/api/recipes/RecipeContext.java b/src/main/java/gregtech/api/recipes/RecipeContext.java index 2648debe988..aeed11a2614 100644 --- a/src/main/java/gregtech/api/recipes/RecipeContext.java +++ b/src/main/java/gregtech/api/recipes/RecipeContext.java @@ -4,6 +4,9 @@ import gregtech.api.recipes.chance.boost.ChanceBoostFunction; import gregtech.api.recipes.chance.output.ChancedOutput; +import it.unimi.dsi.fastutil.Hash; +import it.unimi.dsi.fastutil.objects.Object2IntOpenCustomHashMap; + import java.util.Map; public class RecipeContext { @@ -12,8 +15,8 @@ public class RecipeContext { ChanceBoostFunction boostFunction; public int baseTier, machineTier; - public RecipeContext(Map cache) { - this.cache = cache; + public RecipeContext(Hash.Strategy strategy) { + this.cache = new Object2IntOpenCustomHashMap<>(strategy); } public RecipeContext() { @@ -29,8 +32,12 @@ public RecipeContext update(ChanceBoostFunction boostFunction, } public void updateCachedChance(ChancedOutput entry, int chance) { + updateCachedChance(entry.getIngredient(), chance % entry.getMaxChance()); + } + + public void updateCachedChance(I ingredient, int chance) { if (cache == null) return; - cache.put(entry.getIngredient(), chance % entry.getMaxChance()); + cache.put(ingredient, chance); } public int getCachedChance(ChancedOutput entry) { @@ -52,4 +59,8 @@ public int getChance(ChancedOutput entry) { public int boostChance(BoostableChanceEntry entry) { return boostFunction.getBoostedChance(entry, baseTier, machineTier); } + + public Map getCache() { + return cache; + } } From e0de8fa9ace30a2699e44c3d256ee37745c65f18 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 21 Nov 2024 23:11:37 -0700 Subject: [PATCH 45/45] fix null strategy --- src/main/java/gregtech/api/recipes/RecipeContext.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/RecipeContext.java b/src/main/java/gregtech/api/recipes/RecipeContext.java index aeed11a2614..64756eb805f 100644 --- a/src/main/java/gregtech/api/recipes/RecipeContext.java +++ b/src/main/java/gregtech/api/recipes/RecipeContext.java @@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.Hash; import it.unimi.dsi.fastutil.objects.Object2IntOpenCustomHashMap; +import org.jetbrains.annotations.Nullable; import java.util.Map; @@ -15,8 +16,8 @@ public class RecipeContext { ChanceBoostFunction boostFunction; public int baseTier, machineTier; - public RecipeContext(Hash.Strategy strategy) { - this.cache = new Object2IntOpenCustomHashMap<>(strategy); + public RecipeContext(@Nullable Hash.Strategy strategy) { + this.cache = strategy == null ? null : new Object2IntOpenCustomHashMap<>(strategy); } public RecipeContext() {