Skip to content

Commit 6d92a1f

Browse files
MergeMode
- Implemented strict logic ensuring mode only transitions to higher strictness (Global -> Adjacent -> None).
1 parent 85d0a14 commit 6d92a1f

5 files changed

Lines changed: 95 additions & 22 deletions

File tree

src/main/java/com/ref/aea/api/modifier/PatternEncodingModifier.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,34 @@ ModificationResult apply(
2424
C customContext);
2525

2626
record ModificationResult(
27-
List<List<GenericStack>> inputs, List<GenericStack> outputs, boolean mergeAdjacently) {}
27+
List<List<GenericStack>> inputs, List<GenericStack> outputs, MergeMode mergeMode) {}
2828

2929
record ModificationContext(
3030
Object recipeBase, IRecipeSlotsView slotsView, Player player, boolean maxTransfer) {}
31+
32+
/**
33+
* Defines how identical ingredients are merged during pattern encoding.
34+
*
35+
* <p>The merge mode is strictly monotonic, meaning it can only transition to a more restrictive
36+
* state during the modification chain: {@link #GLOBAL} -> {@link #ADJACENT} -> {@link #NONE}.
37+
*/
38+
enum MergeMode {
39+
/**
40+
* Standard AE2 behavior. Consolidates all equal items into a single slot, regardless of their
41+
* position in the recipe.
42+
*/
43+
GLOBAL,
44+
45+
/**
46+
* Merges items only if they are sequentially adjacent in the list. Useful for recipes where
47+
* order matters but consecutive duplicates should be combined.
48+
*/
49+
ADJACENT,
50+
51+
/**
52+
* No merging performed. Every item defined in the list occupies a new slot (until slots run
53+
* out), preserving exact count and position.
54+
*/
55+
NONE
56+
}
3157
}

src/main/java/com/ref/aea/config/AEAClientConfig.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.ref.aea.config;
22

33
import com.ref.aea.AEA;
4+
import com.ref.aea.api.modifier.PatternEncodingModifier;
45
import java.util.List;
56
import java.util.Set;
67
import java.util.stream.Collectors;
@@ -19,6 +20,17 @@ public class AEAClientConfig {
1920
.comment("Whether to use Encode Pattern Transfer Modifier")
2021
.define("useModifier", true);
2122

23+
private static final ForgeConfigSpec.EnumValue<PatternEncodingModifier.MergeMode>
24+
GLOBAL_MERGE_MODE =
25+
BUILDER
26+
.comment(
27+
"Defines the global merge strategy for pattern encoding.",
28+
"GLOBAL: Standard AE2 behavior. Merges all identical items into one slot.",
29+
"ADJACENT: Merges identical items only if they are next to each other in the list.",
30+
"NONE: No merging. Every item gets its own slot (until full).",
31+
"Note: The merge mode is strictly monotonic (GLOBAL -> ADJACENT -> NONE). A higher strictness level set here or by other modifiers cannot be reverted.")
32+
.defineEnum("globalMergeMode", PatternEncodingModifier.MergeMode.GLOBAL);
33+
2234
private static final ForgeConfigSpec.IntValue IO_MULTIPLIER =
2335
BUILDER.defineInRange("ioMultiplier", 1, 1, Integer.MAX_VALUE);
2436

@@ -37,6 +49,7 @@ public class AEAClientConfig {
3749
public static final ForgeConfigSpec SPEC = BUILDER.build();
3850

3951
public static boolean useModifier;
52+
public static PatternEncodingModifier.MergeMode globalMergeMode;
4053
public static int ioMultiplier;
4154
public static boolean ioLog;
4255
public static boolean debugLog;
@@ -47,6 +60,7 @@ public class AEAClientConfig {
4760
static void onLoad(final ModConfigEvent event) {
4861
if (event.getConfig().getSpec() != SPEC) return;
4962
useModifier = USE_MODIFIER.get();
63+
globalMergeMode = GLOBAL_MERGE_MODE.get();
5064
ioMultiplier = IO_MULTIPLIER.get();
5165
inputsBlackList =
5266
INPUTS_BLACK_LIST.get().stream().map(ResourceLocation::parse).collect(Collectors.toSet());

src/main/java/com/ref/aea/core/modifier/GlobalModifier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public ModificationResult apply(
6666
.toList();
6767

6868
return new ModificationResult(
69-
processedInputs, processedOutputs, modificationResult.mergeAdjacently());
69+
processedInputs, processedOutputs, AEAClientConfig.globalMergeMode);
7070
}
7171

7272
public GenericStack applyMultiplier(GenericStack stack) {

src/main/java/com/ref/aea/core/modifier/PatternEncodingModifierService.java

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import net.minecraftforge.api.distmarker.Dist;
1919
import net.minecraftforge.api.distmarker.OnlyIn;
2020
import org.apache.commons.lang3.tuple.Pair;
21+
import org.jetbrains.annotations.NotNull;
2122

2223
@OnlyIn(Dist.CLIENT)
2324
public class PatternEncodingModifierService {
@@ -45,50 +46,80 @@ public static void encode(
4546
boolean maxTransfer) {
4647
List<List<GenericStack>> inputs = GenericEntryStackHelper.ofInputs(slotsView);
4748
List<GenericStack> outputs = GenericEntryStackHelper.ofOutputs(slotsView);
49+
4850
PatternEncodingModifier.ModificationResult modificationResult =
49-
new PatternEncodingModifier.ModificationResult(inputs, outputs, false);
51+
new PatternEncodingModifier.ModificationResult(
52+
inputs, outputs, PatternEncodingModifier.MergeMode.GLOBAL);
53+
5054
PatternEncodingModifier.ModificationContext modificationContext =
5155
new PatternEncodingModifier.ModificationContext(recipeBase, slotsView, player, maxTransfer);
5256

5357
for (var modifier : Modifiers) {
54-
modificationResult = modifier.modify(modificationResult, modificationContext);
58+
modificationResult = getModificationResult(modificationResult, modificationContext, modifier);
5559
}
56-
modificationResult = GlobalModifier.INSTANCE.modify(modificationResult, modificationContext);
5760

58-
if (modificationResult.mergeAdjacently()) {
59-
PatternEncodingModifierService.encodeProcessingRecipeAdjacentMerge(
60-
menu, modificationResult.inputs(), modificationResult.outputs());
61-
} else {
61+
modificationResult =
62+
getModificationResult(modificationResult, modificationContext, GlobalModifier.INSTANCE);
63+
64+
if (modificationResult.mergeMode() == PatternEncodingModifier.MergeMode.GLOBAL) {
6265
EncodingHelper.encodeProcessingRecipe(
6366
menu, modificationResult.inputs(), modificationResult.outputs());
67+
} else {
68+
PatternEncodingModifierService.encodeProcessingRecipeCustom(
69+
menu,
70+
modificationResult.inputs(),
71+
modificationResult.outputs(),
72+
modificationResult.mergeMode());
6473
}
6574
}
6675

67-
public static void encodeProcessingRecipeAdjacentMerge(
76+
private static PatternEncodingModifier.@NotNull ModificationResult getModificationResult(
77+
PatternEncodingModifier.ModificationResult modificationResult,
78+
PatternEncodingModifier.ModificationContext modificationContext,
79+
PatternEncodingModifier<?> modifier) {
80+
var beforeGlobalMode = modificationResult.mergeMode();
81+
var afterGlobalResult = modifier.modify(modificationResult, modificationContext);
82+
83+
if (afterGlobalResult.mergeMode().ordinal() < beforeGlobalMode.ordinal()) {
84+
modificationResult =
85+
new PatternEncodingModifier.ModificationResult(
86+
afterGlobalResult.inputs(), afterGlobalResult.outputs(), beforeGlobalMode);
87+
} else {
88+
modificationResult = afterGlobalResult;
89+
}
90+
return modificationResult;
91+
}
92+
93+
public static void encodeProcessingRecipeCustom(
6894
PatternEncodingTermMenu menu,
6995
List<List<GenericStack>> genericIngredients,
70-
List<GenericStack> genericResults) {
96+
List<GenericStack> genericResults,
97+
PatternEncodingModifier.MergeMode mode) {
98+
7199
menu.setMode(EncodingMode.PROCESSING);
72100
Map<AEKey, Integer> ingredientPriorities =
73101
EncodingHelper.getIngredientPriorities(menu, ENTRY_COMPARATOR);
74-
encodeBestMatchingStacksIntoSlotsAdjacent(
75-
genericIngredients, ingredientPriorities, menu.getProcessingInputSlots());
76-
encodeBestMatchingStacksIntoSlotsAdjacent(
102+
103+
encodeBestMatchingStacksIntoSlots(
104+
genericIngredients, ingredientPriorities, menu.getProcessingInputSlots(), mode);
105+
encodeBestMatchingStacksIntoSlots(
77106
genericResults.stream().map(List::of).toList(),
78107
ingredientPriorities,
79-
menu.getProcessingOutputSlots());
108+
menu.getProcessingOutputSlots(),
109+
mode);
80110
}
81111

82-
private static void encodeBestMatchingStacksIntoSlotsAdjacent(
112+
private static void encodeBestMatchingStacksIntoSlots(
83113
List<List<GenericStack>> possibleInputsBySlot,
84114
Map<AEKey, Integer> ingredientPriorities,
85-
FakeSlot[] slots) {
115+
FakeSlot[] slots,
116+
PatternEncodingModifier.MergeMode mode) {
117+
86118
ArrayList<GenericStack> encodedInputs = new ArrayList<>();
87119

88120
for (List<GenericStack> genericIngredient : possibleInputsBySlot) {
89121
if (!genericIngredient.isEmpty()) {
90-
addOrMergeAdjacent(
91-
encodedInputs, findBestIngredient(ingredientPriorities, genericIngredient));
122+
addStack(encodedInputs, findBestIngredient(ingredientPriorities, genericIngredient), mode);
92123
}
93124
}
94125

@@ -111,8 +142,9 @@ private static GenericStack findBestIngredient(
111142
.orElseThrow();
112143
}
113144

114-
private static void addOrMergeAdjacent(List<GenericStack> stacks, GenericStack newStack) {
115-
if (!stacks.isEmpty()) {
145+
private static void addStack(
146+
List<GenericStack> stacks, GenericStack newStack, PatternEncodingModifier.MergeMode mode) {
147+
if (mode == PatternEncodingModifier.MergeMode.ADJACENT && !stacks.isEmpty()) {
116148
int lastIndex = stacks.size() - 1;
117149
GenericStack lastStack = stacks.get(lastIndex);
118150

src/main/java/com/ref/aea/integration/create/MechanicalCraftingRecipePatternEncodingModifier.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public ModificationResult apply(
2828
ModificationResult modificationResult,
2929
ModificationContext modificationContext,
3030
Boolean customContext) {
31-
return new ModificationResult(modificationResult.inputs(), modificationResult.outputs(), true);
31+
return new ModificationResult(
32+
modificationResult.inputs(), modificationResult.outputs(), MergeMode.ADJACENT);
3233
}
3334
}

0 commit comments

Comments
 (0)