Skip to content

Commit cdba098

Browse files
Refactor OR and XOR chance logic rolls to multiply outputs for Guaranteed Rolls rather than adding (#4211)
1 parent c1ffc1f commit cdba098

File tree

3 files changed

+63
-29
lines changed

3 files changed

+63
-29
lines changed

src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeRunner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ private void fillContentMatchList(Map<RecipeCapability<?>, List<Content>> entrie
9999
// add chanced contents to the recipe content map
100100
if (!chancedContents.isEmpty()) {
101101
var cache = this.chanceCaches.get(cap);
102-
chancedContents = logic.roll(chancedContents, function, recipeTier, chanceTier, cache,
102+
chancedContents = logic.roll(cap, chancedContents, function, recipeTier, chanceTier, cache,
103103
recipe.getTotalRuns());
104104

105105
for (Content cont : chancedContents) {

src/main/java/com/gregtechceu/gtceu/api/recipe/chance/logic/ChanceLogic.java

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import com.gregtechceu.gtceu.api.GTCEuAPI;
44
import com.gregtechceu.gtceu.api.GTValues;
5+
import com.gregtechceu.gtceu.api.capability.recipe.RecipeCapability;
56
import com.gregtechceu.gtceu.api.recipe.chance.boost.ChanceBoostFunction;
67
import com.gregtechceu.gtceu.api.recipe.content.Content;
8+
import com.gregtechceu.gtceu.api.recipe.content.ContentModifier;
79
import com.gregtechceu.gtceu.api.registry.GTRegistries;
810

911
import net.minecraft.network.chat.Component;
@@ -37,10 +39,10 @@ public abstract class ChanceLogic {
3739
public static final ChanceLogic OR = new ChanceLogic("or") {
3840

3941
@Override
40-
public @Unmodifiable List<@NotNull Content> roll(@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
41-
@NotNull ChanceBoostFunction boostFunction,
42-
int recipeTier, int chanceTier,
43-
@Nullable Object2IntMap<?> cache, int times) {
42+
public @Unmodifiable List<@NotNull Content> roll(RecipeCapability<?> cap,
43+
@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
44+
@NotNull ChanceBoostFunction boostFunction, int recipeTier,
45+
int chanceTier, @Nullable Object2IntMap<?> cache, int times) {
4446
ImmutableList.Builder<Content> builder = ImmutableList.builder();
4547
for (Content entry : chancedEntries) {
4648
int maxChance = entry.maxChance;
@@ -51,7 +53,7 @@ public abstract class ChanceLogic {
5153
int newChance = getChance(entry, boostFunction, recipeTier, chanceTier);
5254
int totalChance = times * newChance;
5355
int guaranteed = totalChance / maxChance;
54-
if (guaranteed > 0) builder.addAll(Collections.nCopies(guaranteed, entry));
56+
if (guaranteed > 0) builder.add(entry.copyChanced(cap, ContentModifier.multiplier(guaranteed)));
5557
newChance = totalChance % maxChance;
5658

5759
int cached = getCachedChance(entry, cache);
@@ -83,10 +85,10 @@ public String toString() {
8385
public static final ChanceLogic AND = new ChanceLogic("and") {
8486

8587
@Override
86-
public @Unmodifiable List<@NotNull Content> roll(@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
87-
@NotNull ChanceBoostFunction boostFunction,
88-
int recipeTier, int chanceTier,
89-
@Nullable Object2IntMap<?> cache, int times) {
88+
public @Unmodifiable List<@NotNull Content> roll(RecipeCapability<?> cap,
89+
@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
90+
@NotNull ChanceBoostFunction boostFunction, int recipeTier,
91+
int chanceTier, @Nullable Object2IntMap<?> cache, int times) {
9092
ImmutableList.Builder<Content> builder = ImmutableList.builder();
9193
for (int i = 0; i < times; ++i) {
9294
boolean failed = false;
@@ -123,10 +125,10 @@ public String toString() {
123125
public static final ChanceLogic FIRST = new ChanceLogic("first") {
124126

125127
@Override
126-
public @Unmodifiable List<@NotNull Content> roll(@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
127-
@NotNull ChanceBoostFunction boostFunction,
128-
int recipeTier, int chanceTier,
129-
@Nullable Object2IntMap<?> cache, int times) {
128+
public @Unmodifiable List<@NotNull Content> roll(RecipeCapability<?> cap,
129+
@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
130+
@NotNull ChanceBoostFunction boostFunction, int recipeTier,
131+
int chanceTier, @Nullable Object2IntMap<?> cache, int times) {
130132
ImmutableList.Builder<Content> builder = ImmutableList.builder();
131133
for (int i = 0; i < times; ++i) {
132134
Content selected = null;
@@ -163,10 +165,10 @@ public String toString() {
163165
public static final ChanceLogic XOR = new ChanceLogic("xor") {
164166

165167
@Override
166-
public @Unmodifiable List<@NotNull Content> roll(@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
167-
@NotNull ChanceBoostFunction boostFunction,
168-
int recipeTier, int chanceTier,
169-
@Nullable Object2IntMap<?> cache, int times) {
168+
public @Unmodifiable List<@NotNull Content> roll(RecipeCapability<?> cap,
169+
@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
170+
@NotNull ChanceBoostFunction boostFunction, int recipeTier,
171+
int chanceTier, @Nullable Object2IntMap<?> cache, int times) {
170172
// Have to set up a system where all chances are set to be out of 10000
171173
IntList chancesOutOfTenThousand = new IntArrayList();
172174

@@ -208,7 +210,21 @@ public String toString() {
208210

209211
// Use the new, normalized list for the logic
210212
ImmutableList.Builder<Content> builder = ImmutableList.builder();
211-
for (int i = 0; i < times; ++i) {
213+
// for high run counts: calculate guaranteed rolls
214+
int nonGuaranteedTimes = times;
215+
if (times > 1) {
216+
for (Content entry : normalizedEntries) {
217+
int newChance = getChance(entry, boostFunction, recipeTier, chanceTier);
218+
int totalChance = times * newChance;
219+
int guaranteed = totalChance / 10000;
220+
if (guaranteed > 0) {
221+
builder.add(entry.copyChanced(cap, ContentModifier.multiplier(guaranteed)));
222+
nonGuaranteedTimes -= guaranteed;
223+
}
224+
}
225+
}
226+
// roll for non-guaranteed
227+
for (int i = 0; i < nonGuaranteedTimes; ++i) {
212228
Content selected = null;
213229
int maxChance = getMaxChancedValue();
214230
for (Content entry : normalizedEntries) {
@@ -245,10 +261,10 @@ public String toString() {
245261
public static final ChanceLogic NONE = new ChanceLogic("none") {
246262

247263
@Override
248-
public @Unmodifiable List<@NotNull Content> roll(@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
249-
@NotNull ChanceBoostFunction boostFunction,
250-
int recipeTier, int chanceTier,
251-
@Nullable Object2IntMap<?> cache, int times) {
264+
public @Unmodifiable List<@NotNull Content> roll(RecipeCapability<?> cap,
265+
@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
266+
@NotNull ChanceBoostFunction boostFunction, int recipeTier,
267+
int chanceTier, @Nullable Object2IntMap<?> cache, int times) {
252268
return Collections.emptyList();
253269
}
254270

@@ -329,11 +345,11 @@ static void updateCachedChance(Object ingredient, @Nullable Object2IntMap<?> cac
329345
* @param times the number of times to roll
330346
* @return a list of the produced outputs, empty if roll fails
331347
*/
332-
public abstract @Unmodifiable List<@NotNull Content> roll(@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
348+
public abstract @Unmodifiable List<@NotNull Content> roll(RecipeCapability<?> cap,
349+
@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
333350
@NotNull ChanceBoostFunction boostFunction,
334-
int recipeTier,
335-
int chanceTier, @Nullable Object2IntMap<?> cache,
336-
int times);
351+
int recipeTier, int chanceTier,
352+
@Nullable Object2IntMap<?> cache, int times);
337353

338354
/**
339355
* Roll the chance and attempt to produce the output
@@ -346,10 +362,11 @@ static void updateCachedChance(Object ingredient, @Nullable Object2IntMap<?> cac
346362
* @return a list of the produced outputs
347363
*/
348364
@Unmodifiable
349-
public List<@NotNull Content> roll(@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
365+
public List<@NotNull Content> roll(RecipeCapability<?> cap,
366+
@NotNull @Unmodifiable List<@NotNull Content> chancedEntries,
350367
@NotNull ChanceBoostFunction boostFunction, int recipeTier, int chanceTier,
351368
int times) {
352-
return roll(chancedEntries, boostFunction, recipeTier, chanceTier, null, times);
369+
return roll(cap, chancedEntries, boostFunction, recipeTier, chanceTier, null, times);
353370
}
354371

355372
@NotNull

src/main/java/com/gregtechceu/gtceu/api/recipe/content/Content.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,16 @@ public static <T> Codec<Content> codec(RecipeCapability<T> capability) {
5555
.apply(instance, Content::new));
5656
}
5757

58+
/**
59+
* Directly copies a Content.
60+
*/
5861
public Content copy(RecipeCapability<?> capability) {
5962
return new Content(capability.copyContent(content), chance, maxChance, tierChanceBoost);
6063
}
6164

65+
/**
66+
* Applies a {@link ContentModifier} to a Content. Does not apply the Modifier if the Content has a Chance.
67+
*/
6268
public Content copy(RecipeCapability<?> capability, @NotNull ContentModifier modifier) {
6369
if (modifier == ContentModifier.IDENTITY || chance < maxChance) {
6470
return copy(capability);
@@ -67,6 +73,17 @@ public Content copy(RecipeCapability<?> capability, @NotNull ContentModifier mod
6773
}
6874
}
6975

76+
/**
77+
* Applies a {@link ContentModifier} to a Content. Even if the content has a Chance.
78+
*/
79+
public Content copyChanced(RecipeCapability<?> capability, @NotNull ContentModifier modifier) {
80+
if (modifier == ContentModifier.IDENTITY) {
81+
return copy(capability);
82+
} else {
83+
return new Content(capability.copyContent(content, modifier), chance, maxChance, tierChanceBoost);
84+
}
85+
}
86+
7087
public boolean isChanced() {
7188
return chance > 0 && chance < maxChance;
7289
}

0 commit comments

Comments
 (0)