Skip to content

Commit cec9a1c

Browse files
committed
Add support for high version forge mod detection
1 parent 586005a commit cec9a1c

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ vineflower = { module = "org.vineflower:vineflower", version.ref = "vineflower"
144144

145145
sourcesolver = { module = "software.coley:source-solver", version.ref = "sourcesolver" }
146146

147+
toml4j = { module = "io.hotmoka:toml4j", version = "0.7.3" }
148+
147149
[bundles]
148150
asm = [
149151
"asm-core",

recaf-ui/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ dependencies {
2525
implementation(libs.reactfx)
2626
implementation(libs.richtextfx)
2727
implementation(libs.treemapfx)
28+
implementation(libs.toml4j)
2829
}
2930

3031
application {

recaf-ui/src/main/java/software/coley/recaf/services/info/summary/builtin/MinecraftModSummarizer.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.google.gson.JsonArray;
55
import com.google.gson.JsonObject;
66
import com.google.gson.JsonParser;
7+
import com.moandjiezana.toml.Toml;
78
import jakarta.annotation.Nonnull;
89
import jakarta.enterprise.context.ApplicationScoped;
910
import jakarta.inject.Inject;
@@ -27,6 +28,9 @@
2728
import java.io.ByteArrayInputStream;
2829
import java.util.ArrayList;
2930
import java.util.List;
31+
import java.util.Map;
32+
import java.util.Objects;
33+
import java.util.function.Supplier;
3034
import java.util.jar.Manifest;
3135

3236
/**
@@ -192,7 +196,59 @@ private boolean detectLowVersionForgeMod(@Nonnull WorkspaceResource resource) {
192196
private boolean detectHighVersionForgeMod(@Nonnull WorkspaceResource resource) {
193197
FileInfo forgeFileInfo = resource.getFileBundle().get("META-INF/mods.toml");
194198
if (forgeFileInfo != null) {
199+
loaderName = Lang.getBinding("service.analysis.is-forge-mod").get();
200+
195201
// reference: https://mcforge.readthedocs.io/en/latest/gettingstarted/modfiles/
202+
// 1. find modId in the [[mods]] section
203+
String modId = "";
204+
Toml toml = new Toml();
205+
try {
206+
toml.read(forgeFileInfo.asTextFile().getText());
207+
List<Object> mods = toml.getList("mods");
208+
if (mods != null && !mods.isEmpty()) {
209+
Object firstMod = mods.getFirst();
210+
if (firstMod instanceof Map<?, ?> map) {
211+
if (map.containsKey("modId")) {
212+
modId = map.get("modId").toString();
213+
}
214+
}
215+
}
216+
} catch (Exception e) {
217+
// Ignore TOML parsing errors
218+
}
219+
220+
// 2. find versionRange in the [[dependencies.<modId>]] section and the modId of this must is "minecraft"
221+
if (!modId.isEmpty()) {
222+
try {
223+
List<Object> dependencies = toml.getList("dependencies." + modId);
224+
if (dependencies != null && !dependencies.isEmpty()) {
225+
for (Object dep : dependencies) {
226+
if (dep instanceof Map<?, ?> map) {
227+
if (map.containsKey("modId") && map.get("modId").toString().equals("minecraft")) {
228+
if (map.containsKey("versionRange")) {
229+
mcVersion = map.get("versionRange").toString();
230+
break;
231+
}
232+
}
233+
}
234+
}
235+
}
236+
} catch (Exception e) {
237+
// Ignore TOML parsing errors
238+
}
239+
}
240+
241+
// we can not find main class in mods.toml, so we scan all class files for @Mod annotation
242+
resource.jvmClassBundleStream().forEach(bundle -> {
243+
bundle.forEach(cls -> {
244+
Supplier<JvmClassInfo> classLookup = () -> Objects.requireNonNullElse(bundle.get(cls.getName()), cls);
245+
classLookup.get().getAnnotations().forEach(annotationInfo -> {
246+
if (annotationInfo.getDescriptor().equals("Lnet/minecraftforge/fml/common/Mod;")) {
247+
mainClasses.add(cls.getName());
248+
}
249+
});
250+
});
251+
});
196252

197253
return true;
198254
}

0 commit comments

Comments
 (0)