Skip to content

Commit 4655556

Browse files
committed
Fix MoulConfig compat
1 parent 0722965 commit 4655556

14 files changed

Lines changed: 401 additions & 47 deletions

File tree

minecraft/build.gradle.kts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,22 @@ val skyhanniRelocatedConfiguration: Configuration by configurations.creating {
159159
attributes { attribute(skyhanniRelocated, true) }
160160
}
161161

162+
val firmamentRelocated = registerRelocationAttribute("relocate-firmament-moulconfig") {
163+
relocate("io.github.notenoughupdates.moulconfig", "moe.nea.firmament.deps.moulconfig")
164+
}
165+
166+
val firmamentRelocatedConfiguration: Configuration by configurations.creating {
167+
attributes { attribute(firmamentRelocated, true) }
168+
}
169+
170+
val dandelionBpRelocated = registerRelocationAttribute("relocate-dandelion-bp-moulconfig") {
171+
relocate("io.github.notenoughupdates.moulconfig", "net.azureaaron.dandelion_bp.deps.moulconfig")
172+
}
173+
174+
val dandelionBpRelocatedConfiguration: Configuration by configurations.creating {
175+
attributes { attribute(dandelionBpRelocated, true) }
176+
}
177+
162178
dependencies {
163179
data class CompatDependency(
164180
val all: String? = null,
@@ -191,6 +207,10 @@ dependencies {
191207
compileOnlyCompat("org.notenoughupdates.moulconfig:common:3.11.0")
192208
skyhanniRelocatedConfiguration("org.notenoughupdates.moulconfig:common:3.11.0")
193209
compileOnly(prebundle(skyhanniRelocatedConfiguration))
210+
firmamentRelocatedConfiguration("org.notenoughupdates.moulconfig:common:3.11.0")
211+
compileOnly(prebundle(firmamentRelocatedConfiguration))
212+
dandelionBpRelocatedConfiguration("org.notenoughupdates.moulconfig:common:3.11.0")
213+
compileOnly(prebundle(dandelionBpRelocatedConfiguration))
194214

195215
fun rconfig(mcVersion: String, modVersion: String, mcVersionOverride: String = mcVersion) =
196216
mcVersion to CompatDependency("com.teamresourceful.resourcefulconfig:resourcefulconfig-common-$mcVersionOverride:$modVersion")

minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfigMixinInit.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ public List<String> getMixins() {
6767
mixins.add(e);
6868
return Unit.INSTANCE;
6969
});
70+
mixins.add("compat.moulconfig.Mixin_MCConfigEditorIntegration_Firmament");
71+
mixins.add("compat.moulconfig.Mixin_MoulConfigAdapter_DandelionBp");
7072

7173
//#if MC>=1.19.2
7274
//$$mixins.add("Mixin_MinecraftClientResourceStuff");

minecraft/src/main/java/org/polyfrost/oneconfig/internal/mixin/compat/moulconfig/Mixin_GuiOptionEditorDropdown.java

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
import org.spongepowered.asm.mixin.Mixin;
88
import org.spongepowered.asm.mixin.Pseudo;
99
import org.spongepowered.asm.mixin.Shadow;
10+
import org.spongepowered.asm.mixin.Unique;
11+
12+
import java.lang.reflect.Field;
13+
import java.lang.reflect.Method;
14+
import java.util.List;
1015

1116
@Pseudo
1217
@MoulConfig
@@ -15,16 +20,48 @@
1520
//#endif
1621
@Mixin(value = GuiOptionEditorDropdown.class, remap = false)
1722
public class Mixin_GuiOptionEditorDropdown implements MoulConfigGuiOptionEditorDropdownAccessor {
18-
19-
@Shadow
20-
private String[] values;
2123
@Shadow
2224
private boolean useOrdinal;
2325
@Shadow
2426
private Enum<?>[] constants;
2527

28+
@Unique
29+
private String[] oneconfig$resolvedValues;
30+
31+
// MoulConfig 3.x uses String[] for this field, 4.x uses List<StructuredText>.
32+
// Reflection avoids the @Shadow descriptor mismatch that breaks mixin application.
2633
public String[] oneconfig$values() {
27-
return this.values;
34+
if (oneconfig$resolvedValues != null) return oneconfig$resolvedValues;
35+
try {
36+
Field f = this.getClass().getDeclaredField("values");
37+
f.setAccessible(true);
38+
Object val = f.get(this);
39+
if (val instanceof String[]) {
40+
oneconfig$resolvedValues = (String[]) val;
41+
} else if (val instanceof List<?>) {
42+
List<?> list = (List<?>) val;
43+
String[] result = new String[list.size()];
44+
for (int i = 0; i < list.size(); i++) {
45+
Object item = list.get(i);
46+
if (item instanceof String) {
47+
result[i] = (String) item;
48+
} else {
49+
try {
50+
Method getText = item.getClass().getMethod("getText");
51+
result[i] = (String) getText.invoke(item);
52+
} catch (Exception e) {
53+
result[i] = item.toString();
54+
}
55+
}
56+
}
57+
oneconfig$resolvedValues = result;
58+
} else {
59+
oneconfig$resolvedValues = new String[0];
60+
}
61+
} catch (Exception e) {
62+
oneconfig$resolvedValues = new String[0];
63+
}
64+
return oneconfig$resolvedValues;
2865
}
2966

3067
public boolean oneconfig$useOrdinal() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.polyfrost.oneconfig.internal.mixin.compat.moulconfig;
2+
3+
import org.polyfrost.oneconfig.internal.compat.MoulConfigCompat;
4+
import org.spongepowered.asm.mixin.Mixin;
5+
import org.spongepowered.asm.mixin.Pseudo;
6+
import org.spongepowered.asm.mixin.injection.At;
7+
import org.spongepowered.asm.mixin.injection.Inject;
8+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
9+
10+
import java.lang.reflect.Field;
11+
import java.util.Collection;
12+
13+
@Pseudo
14+
@Mixin(targets = "moe.nea.firmament.compat.moulconfig.MCConfigEditorIntegration", remap = false)
15+
public class Mixin_MCConfigEditorIntegration_Firmament {
16+
@Inject(method = "<init>()V", at = @At("TAIL"))
17+
private void oneconfig$onInit(CallbackInfo ci) {
18+
try {
19+
Field categoriesField = this.getClass().getDeclaredField("categories");
20+
Field configField = this.getClass().getDeclaredField("configObject");
21+
categoriesField.setAccessible(true);
22+
configField.setAccessible(true);
23+
24+
Object categoriesValue = categoriesField.get(this);
25+
Object configValue = configField.get(this);
26+
27+
if (categoriesValue instanceof Collection<?> && configValue != null) {
28+
MoulConfigCompat.parseMoulconfigFromUnknownEditor((Collection<?>) categoriesValue, configValue);
29+
}
30+
} catch (Throwable ignored) {}
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.polyfrost.oneconfig.internal.mixin.compat.moulconfig;
2+
3+
import org.polyfrost.oneconfig.internal.compat.MoulConfigCompat;
4+
import org.spongepowered.asm.mixin.Mixin;
5+
import org.spongepowered.asm.mixin.Pseudo;
6+
import org.spongepowered.asm.mixin.injection.At;
7+
import org.spongepowered.asm.mixin.injection.Coerce;
8+
import org.spongepowered.asm.mixin.injection.Inject;
9+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
10+
11+
import java.lang.reflect.Field;
12+
import java.lang.reflect.Method;
13+
import java.util.Collection;
14+
import java.util.List;
15+
16+
@Pseudo
17+
@Mixin(targets = "net.azureaaron.dandelion_bp.impl.moulconfig.MoulConfigAdapter", remap = false)
18+
public class Mixin_MoulConfigAdapter_DandelionBp {
19+
@Inject(method = "generateMoulConfigScreen", at = @At("RETURN"))
20+
private void oneconfig$onGenerateMoulConfigScreen(List<?> categories, @Coerce Object parent, String search, CallbackInfoReturnable<?> cir) {
21+
try {
22+
Method generateProcessedCategories = this.getClass().getDeclaredMethod("generateProcessedCategories", List.class);
23+
generateProcessedCategories.setAccessible(true);
24+
Object processed = generateProcessedCategories.invoke(this, categories);
25+
26+
Field configDefinitionField = this.getClass().getDeclaredField("configDefinition");
27+
configDefinitionField.setAccessible(true);
28+
Object configDefinition = configDefinitionField.get(this);
29+
30+
if (processed instanceof Collection<?> && configDefinition != null) {
31+
MoulConfigCompat.parseMoulconfigFromUnknownEditor((Collection<?>) processed, configDefinition);
32+
}
33+
} catch (Throwable ignored) {}
34+
}
35+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.polyfrost.oneconfig.internal.mixin.compat.moulconfig;
2+
3+
import io.github.notenoughupdates.moulconfig.Config;
4+
import io.github.notenoughupdates.moulconfig.gui.MoulConfigEditor;
5+
import io.github.notenoughupdates.moulconfig.processor.ProcessedCategory;
6+
import org.polyfrost.oneconfig.internal.compat.MoulConfigCompat;
7+
import org.polyfrost.oneconfig.relocator.annotations.MoulConfig;
8+
import org.polyfrost.oneconfig.relocator.annotations.RelocatedMixin;
9+
import org.spongepowered.asm.mixin.Final;
10+
import org.spongepowered.asm.mixin.Mixin;
11+
import org.spongepowered.asm.mixin.Pseudo;
12+
import org.spongepowered.asm.mixin.Shadow;
13+
import org.spongepowered.asm.mixin.injection.At;
14+
import org.spongepowered.asm.mixin.injection.Inject;
15+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
16+
17+
import java.util.LinkedHashMap;
18+
19+
@Pseudo
20+
@MoulConfig
21+
//#if MC==1.8.9||MC>=1.21.4
22+
@RelocatedMixin
23+
//#endif
24+
@Mixin(value = MoulConfigEditor.class, remap = false)
25+
public class Mixin_MoulConfigEditor<T extends Config> {
26+
@Shadow
27+
@Final
28+
private LinkedHashMap<String, ProcessedCategory> allCategories;
29+
30+
@Shadow
31+
@Final
32+
private T configObject;
33+
34+
@Inject(at = @At("TAIL"), method = "<init>(Ljava/util/LinkedHashMap;Lio/github/notenoughupdates/moulconfig/Config;)V")
35+
public void oneconfig$init(CallbackInfo ci) {
36+
MoulConfigCompat.parseMoulconfigFromEditor(this.allCategories.values(), this.configObject);
37+
}
38+
}

minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/CompatLoader.kt

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import org.polyfrost.oneconfig.internal.ui.OneConfigUI
99
import java.net.URI
1010

1111
object CompatLoader {
12+
private val forcedModId = ThreadLocal<String?>()
1213

1314
private var bypassDelay = false
1415

@@ -25,11 +26,18 @@ object CompatLoader {
2526
"org.polyfrost.oneconfig",
2627
"java.lang",
2728
"net.fabric",
28-
"net.azureaaron.dandelion",
29+
"net.azureaaron.dandelion.deps.moulconfig",
30+
"net.azureaaron.dandelion_bp.deps.moulconfig",
31+
"net.azureaaron.dandelion_bp.impl.moulconfig",
32+
"moe.nea.firmament.deps.moulconfig",
2933
"kotlin"
3034
)
3135

3236
fun findFirstMod(): ModInfo? {
37+
forcedModId.get()?.let { forcedId ->
38+
val forcedMod = OmniLoader.mods.firstOrNull { it.id == forcedId }
39+
if (forcedMod != null) return forcedMod
40+
}
3341
Thread.currentThread().stackTrace.firstOrNull {
3442
illegalPaths.none { path -> it.className.startsWith(path) }
3543
}?.let { element ->
@@ -45,9 +53,27 @@ object CompatLoader {
4553
}
4654

4755
fun markFirstModAsSkip() {
48-
findFirstMod()?.let { nativeLoadedConfigs.add(it.id)}
56+
val mod = findFirstMod()
57+
if (mod == null) return
58+
nativeLoadedConfigs.add(mod.id)
4959
}
5060

61+
fun withForcedModId(modId: String?, block: () -> Unit) {
62+
if (modId == null) {
63+
block()
64+
return
65+
}
66+
val prev = forcedModId.get()
67+
forcedModId.set(modId)
68+
try {
69+
block()
70+
} finally {
71+
forcedModId.set(prev)
72+
}
73+
}
74+
75+
fun hasMod(id: String): Boolean = OmniLoader.mods.any { it.id == id }
76+
5177
val extraCompatConfigs get() = OneConfigUI.extraConfigTrees
5278

5379
private val list: MutableList<Pair<Int, () -> Unit>> = mutableListOf()

0 commit comments

Comments
 (0)