Skip to content

Commit e877f19

Browse files
committed
Refactor: Add support for Refined Storage
- Add an API layer to support multiple autocrafting mods. - Implement support for Refined Storage pattern encoding. - Make AE2 an optional dependency. - Add a MixinPlugin to conditionally apply mixins. - Update build scripts for new dependencies and repositories.
1 parent ea1a302 commit e877f19

20 files changed

Lines changed: 414 additions & 62 deletions

.github/workflows/build.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,22 @@ jobs:
1616
java-version: 21
1717
distribution: 'temurin'
1818

19+
- name: Setup Gradle
20+
uses: gradle/actions/setup-gradle@v5
21+
1922
- name: build
2023
run: |
2124
chmod +x ./gradlew
2225
./gradlew build
26+
env:
27+
GITHUB_MAVEN_PAT: ${{ secrets.MAVEN_PAT_GITHUB }}
2328

2429
- name: capture build artifact
2530
uses: actions/upload-artifact@v7
2631
with:
2732
path: build/libs/*
2833
archive: false
2934

30-
3135
- name: publish
3236
if: startsWith(github.ref, 'refs/tags/')
3337
uses: apehum/mc-publish@v1.2

build.gradle

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,25 @@ repositories {
1515
name = "TerraformersMC"
1616
url = "https://maven.terraformersmc.com/"
1717
}
18+
maven {
19+
url "https://cursemaven.com"
20+
}
21+
maven {
22+
name = "GitHubPackages"
23+
url = uri("https://maven.pkg.github.com/refinedmods/refinedstorage2")
24+
credentials {
25+
username = "link-fgfgui"
26+
password = System.getenv("GITHUB_MAVEN_PAT")
27+
}
28+
}
29+
maven {
30+
name = "GitHubPackages"
31+
url = uri("https://maven.pkg.github.com/refinedmods/refinedstorage-emi-integration")
32+
credentials {
33+
username = "link-fgfgui"
34+
password = System.getenv("GITHUB_MAVEN_PAT")
35+
}
36+
}
1837
}
1938

2039
base {
@@ -101,8 +120,14 @@ sourceSets.main.resources { srcDir 'src/generated/resources' }
101120

102121

103122
dependencies {
104-
implementation "org.appliedenergistics:appliedenergistics2:${ae2_version}"
123+
compileOnly "org.appliedenergistics:appliedenergistics2:${ae2_version}"
105124
implementation "dev.emi:emi-neoforge:${emi_version}"
125+
implementation "com.refinedmods.refinedstorage:refinedstorage-emi-integration-neoforge:${refinedstorage_emi_integration_version}"
126+
implementation "com.refinedmods.refinedstorage:refinedstorage-neoforge:${refinedstorage_version}"
127+
128+
runtimeOnly "curse.maven:powah-rearchitected-633483:7503293"
129+
runtimeOnly "curse.maven:cloth-config-348521:5729127"
130+
runtimeOnly "curse.maven:guideme-1173950:7127444"
106131
}
107132

108133
// This block of code expands all declared replace properties in the specified resource targets.
@@ -121,6 +146,8 @@ var generateModMetadata = tasks.register("generateModMetadata", ProcessResources
121146
mod_description : mod_description,
122147
ae2_version : ae2_version,
123148
emi_version : emi_version,
149+
refinedstorage_version : refinedstorage_version,
150+
refinedstorage_emi_integration_version : refinedstorage_emi_integration_version,
124151
]
125152
inputs.properties replaceProperties
126153
expand replaceProperties

gradle.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ parchment_mappings_version=2025.12.20
2626
mod_id=emi_patternizer
2727
mod_name=EMI Patternizer
2828
mod_license=GNU LGPL 3.0
29-
mod_version=1.0.3
29+
mod_version=1.1.0
3030
mod_group_id=io.github.linkfgfgui
3131
mod_authors=link-fgfgui
3232
mod_description=Automatically Encoding Patterns from the EMI Recipe Tree.
3333
ae2_version=19.2.17
3434
emi_version=1.1.22+1.21.1
35+
refinedstorage_version=2.0.1
36+
refinedstorage_emi_integration_version=1.0.0

src/main/java/io/github/linkfgfgui/emi_patternizer/Emi_patternizer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@
2121
@Mod(value = Emi_patternizer.MODID, dist = Dist.CLIENT)
2222
public class Emi_patternizer {
2323
public static final String MODID = "emi_patternizer";
24-
private static final Logger LOGGER = LogUtils.getLogger();
2524
public static final Lazy<KeyMapping> PATTERNIZE_MAPPING = Lazy.of(() -> new KeyMapping(
2625
"key.emi_patternizer.patternize",
2726
KeyConflictContext.GUI,
2827
InputConstants.Type.KEYSYM,
2928
GLFW.GLFW_KEY_N,
3029
"key.categories.emi_patternizer.category"
3130
));
31+
private static final Logger LOGGER = LogUtils.getLogger();
3232

3333
public Emi_patternizer(IEventBus modEventBus, ModContainer modContainer) {
3434
modEventBus.addListener(this::clientSetup);

src/main/java/io/github/linkfgfgui/emi_patternizer/Patternize.java

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package io.github.linkfgfgui.emi_patternizer;
22

3-
import appeng.client.gui.WidgetContainer;
4-
import appeng.client.gui.me.items.PatternEncodingTermScreen;
5-
import appeng.menu.SlotSemantics;
6-
import appeng.menu.me.items.PatternEncodingTermMenu;
73
import com.mojang.blaze3d.platform.InputConstants;
84
import com.mojang.logging.LogUtils;
95
import dev.emi.emi.api.recipe.EmiRecipe;
@@ -12,16 +8,15 @@
128
import dev.emi.emi.bom.BoM;
139
import dev.emi.emi.bom.MaterialNode;
1410
import dev.emi.emi.registry.EmiRecipeFiller;
15-
import io.github.linkfgfgui.emi_patternizer.mixin.AEBaseMenuAccessor;
16-
import io.github.linkfgfgui.emi_patternizer.mixin.AEBaseScreenAccessor;
17-
import io.github.linkfgfgui.emi_patternizer.mixin.WidgetContainerAccessor;
11+
import io.github.linkfgfgui.emi_patternizer.intergrated.Api;
12+
import io.github.linkfgfgui.emi_patternizer.intergrated.INTERGRATED;
1813
import net.minecraft.client.Minecraft;
19-
import net.minecraft.client.gui.components.AbstractWidget;
20-
import net.minecraft.client.gui.components.Button;
14+
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
2115
import net.minecraft.client.multiplayer.MultiPlayerGameMode;
2216
import net.minecraft.client.player.LocalPlayer;
2317
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
2418
import net.minecraft.sounds.SoundEvents;
19+
import net.minecraft.world.inventory.AbstractContainerMenu;
2520
import net.minecraft.world.inventory.ClickType;
2621
import net.neoforged.neoforge.client.event.ScreenEvent;
2722
import org.slf4j.Logger;
@@ -52,7 +47,15 @@ public static boolean containsAllItems(List<EmiStack> stackList) {
5247
return (stackList.stream().allMatch(emiStack -> EncodedItems.contains(emiStack.getId().toString())));
5348
}
5449

55-
public static void Encode(long initDelay, Minecraft minecraft, EmiRecipe recipe, PatternEncodingTermScreen<?> screen, PatternEncodingTermMenu menu, LocalPlayer player, MultiPlayerGameMode gameMode, int encodedPatternSlot) {
50+
public static void Encode(long initDelay,
51+
Minecraft minecraft,
52+
EmiRecipe recipe,
53+
AbstractContainerScreen<?> screen,
54+
AbstractContainerMenu menu,
55+
LocalPlayer player,
56+
MultiPlayerGameMode gameMode,
57+
int encodedPatternSlot,
58+
Api api) {
5659
CompletableFuture.delayedExecutor(initDelay, TimeUnit.MILLISECONDS).execute(() -> {
5760
minecraft.execute(() -> {
5861
EmiRecipeFiller.performFill(recipe, screen, EmiCraftContext.Type.FILL_BUTTON, EmiCraftContext.Destination.NONE, 1);
@@ -62,15 +65,7 @@ public static void Encode(long initDelay, Minecraft minecraft, EmiRecipe recipe,
6265
});
6366
CompletableFuture.delayedExecutor(delayPerOperation, TimeUnit.MILLISECONDS).execute(() -> {
6467
minecraft.execute(() -> {
65-
if (isSimulateClick) {
66-
WidgetContainer widgets = ((AEBaseScreenAccessor) screen).getWidgets();
67-
AbstractWidget widget = ((WidgetContainerAccessor) widgets).getWidgets().get("encodePattern");
68-
if (widget instanceof Button but) {
69-
but.onPress();
70-
}
71-
} else {
72-
menu.encode();
73-
}
68+
api.encode(isSimulateClick);
7469
});
7570
CompletableFuture.delayedExecutor(delayPerOperation, TimeUnit.MILLISECONDS).execute(() ->
7671
minecraft.execute(() ->
@@ -104,10 +99,11 @@ public static void LoadConfig() {
10499

105100
public static void onKeyPressed(ScreenEvent.KeyPressed.Post event) {
106101
if (!operating && Emi_patternizer.PATTERNIZE_MAPPING.get().isActiveAndMatches(InputConstants.getKey(event.getKeyCode(), event.getScanCode()))) {
107-
if (event.getScreen() instanceof PatternEncodingTermScreen<?> screen) {
108-
PatternEncodingTermMenu menu = screen.getMenu();
109-
// int blankPatternSlot = ((AEBaseMenuAccessor) menu).getSlotsBySemantic().get(SlotSemantics.BLANK_PATTERN).getFirst().index;
110-
int encodedPatternSlot = ((AEBaseMenuAccessor) menu).getSlotsBySemantic().get(SlotSemantics.ENCODED_PATTERN).getFirst().index;
102+
if (Api.isValidEncodingScreen(event.getScreen())) {
103+
AbstractContainerScreen<?> screen = (AbstractContainerScreen<?>) event.getScreen();
104+
AbstractContainerMenu menu = screen.getMenu();
105+
Api api = Api.getApi(screen);
106+
int encodedPatternSlot = api.getEncodedPatternSlot();
111107
if (BoM.craftingMode && !operating) {
112108
LoadConfig();
113109
Minecraft minecraft = Minecraft.getInstance();
@@ -128,7 +124,15 @@ public static void onKeyPressed(ScreenEvent.KeyPressed.Post event) {
128124
}))
129125
.forEachOrdered(node -> {
130126
if (node.recipe != null && node.recipe.getId() != null && !containsAllItems(node.recipe)) {
131-
Encode(maxDelay.get(), minecraft, node.recipe, screen, menu, player, gameMode, encodedPatternSlot);
127+
List<EmiStack> output = node.recipe.getOutputs();
128+
if (INTERGRATED.RS) {
129+
for (EmiStack emiStack : output) {
130+
if (emiStack.getItemStack().isEmpty()) {
131+
return;
132+
}
133+
}
134+
}
135+
Encode(maxDelay.get(), minecraft, node.recipe, screen, menu, player, gameMode, encodedPatternSlot, api);
132136
node.recipe.getOutputs().forEach(emiStack -> EncodedItems.add(emiStack.getId().toString()));
133137
maxDelay.addAndGet(3 * delayPerOperation + delayAdditionalPerPattern);
134138
}

src/main/java/io/github/linkfgfgui/emi_patternizer/ReloadMemory.java

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
package io.github.linkfgfgui.emi_patternizer;
22

3-
import appeng.api.crafting.IPatternDetails;
4-
import appeng.api.crafting.PatternDetailsHelper;
5-
import appeng.client.gui.me.patternaccess.PatternAccessTermScreen;
6-
import appeng.client.gui.me.patternaccess.PatternContainerRecord;
7-
import io.github.linkfgfgui.emi_patternizer.mixin.PatternAccessTermScreenAccessor;
3+
import io.github.linkfgfgui.emi_patternizer.intergrated.Api;
84
import net.minecraft.client.Minecraft;
5+
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
96
import net.minecraft.network.chat.Component;
107
import net.minecraft.world.level.Level;
118
import net.neoforged.neoforge.client.event.ScreenEvent;
129

13-
import java.util.Collection;
1410
import java.util.concurrent.CompletableFuture;
1511
import java.util.concurrent.TimeUnit;
1612

@@ -22,29 +18,16 @@ public class ReloadMemory {
2218
static long PatternCount = 0;
2319

2420
public static void onScreenOpening(ScreenEvent.Opening event) {
25-
if (event.getScreen() instanceof PatternAccessTermScreen<?> screen) {
21+
if (Api.isValidAccessScreen(event.getScreen())) {
22+
AbstractContainerScreen<?> screen = (AbstractContainerScreen<?>) event.getScreen();
23+
Api api = Api.getApi(screen);
2624
EncodedItems.clear();
2725
Minecraft minecraft = Minecraft.getInstance();
2826
Level level = minecraft.level;
29-
delayBeforeRead=Config.DELAY_BEFORE_READ.get();
27+
delayBeforeRead = Config.DELAY_BEFORE_READ.get();
3028
CompletableFuture.delayedExecutor(delayBeforeRead, TimeUnit.MILLISECONDS).execute(() -> {
3129
minecraft.execute(() -> {
32-
PatternCount = 0;
33-
Collection<PatternContainerRecord> patternContainerRecordSet = ((PatternAccessTermScreenAccessor) screen).getById().values();
34-
for (PatternContainerRecord entry : patternContainerRecordSet) {
35-
entry.getInventory().toItemContainerContents().stream().forEach((item) -> {
36-
IPatternDetails details = PatternDetailsHelper.decodePattern(item, level);
37-
PatternCount++;
38-
if (details == null) {
39-
} else {
40-
details.getOutputs().forEach(
41-
genericStack -> {
42-
EncodedItems.add(genericStack.what().getId().toString());
43-
}
44-
);
45-
}
46-
});
47-
}
30+
PatternCount = api.getPatternCount(level);
4831
if (minecraft.player != null) {
4932
minecraft.player.sendSystemMessage(Component.translatable("chat.emi_patternizer.loaded", EncodedItems.size(), PatternCount));
5033
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package io.github.linkfgfgui.emi_patternizer.intergrated;
2+
3+
import net.minecraft.client.gui.screens.Screen;
4+
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
5+
import net.minecraft.world.level.Level;
6+
7+
import java.util.HashMap;
8+
import java.util.Map;
9+
10+
11+
public interface Api {
12+
Map<String, Class<?>> CLASS_CACHE = new HashMap<>();
13+
14+
static boolean isInstanceOf(Object obj, String className) {
15+
if (obj == null) return false;
16+
Class<?> clazz = CLASS_CACHE.get(className);
17+
if (clazz == null) {
18+
try {
19+
clazz = Class.forName(className);
20+
CLASS_CACHE.put(className, clazz);
21+
} catch (ClassNotFoundException e) {
22+
CLASS_CACHE.put(className, Void.class);
23+
return false;
24+
}
25+
}
26+
if (clazz == Void.class) return false;
27+
return clazz.isInstance(obj);
28+
}
29+
30+
31+
static Api getApi(AbstractContainerScreen<?> screen) {
32+
if (INTERGRATED.AE2) {
33+
return new appliedenergistics2(screen);
34+
} else if (INTERGRATED.RS) {
35+
return new refinedstorage(screen);
36+
} else {
37+
return null;
38+
}
39+
}
40+
41+
static boolean isValidEncodingScreen(Screen screen) {
42+
if (INTERGRATED.AE2) {
43+
return isInstanceOf(screen, "appeng.client.gui.me.items.PatternEncodingTermScreen");
44+
} else if (INTERGRATED.RS) {
45+
return isInstanceOf(screen, "com.refinedmods.refinedstorage.common.autocrafting.patterngrid.PatternGridScreen");
46+
}
47+
return false;
48+
}
49+
50+
static boolean isValidAccessScreen(Screen screen) {
51+
if (INTERGRATED.AE2) {
52+
return isInstanceOf(screen, "appeng.client.gui.me.items.PatternAccessTermScreen");
53+
} else if (INTERGRATED.RS) {
54+
return isInstanceOf(screen, "com.refinedmods.refinedstorage.common.autocrafting.autocraftermanager.AutocrafterManagerScreen");
55+
}
56+
return false;
57+
}
58+
59+
void encode(boolean isSimulateClick);
60+
61+
int getEncodedPatternSlot();
62+
63+
long getPatternCount(Level level);
64+
65+
66+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.github.linkfgfgui.emi_patternizer.intergrated;
2+
3+
import net.neoforged.fml.ModList;
4+
5+
public class INTERGRATED {
6+
public static boolean AE2;
7+
public static boolean RS;
8+
9+
static {
10+
ModList list = ModList.get();
11+
if (list.isLoaded("ae2")) {
12+
AE2 = true;
13+
} else if (list.isLoaded("refinedstorage_emi_integration")) {
14+
RS = true;
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)