Open dependency floors and gate EMI, Elytra, and compiled-density fixes to the versions that need them
This commit is contained in:
parent
5c04905561
commit
17e5817faa
12 changed files with 550 additions and 8 deletions
34
server/src/main/java/dev/quorate/tune/ElytraCooldown.java
Normal file
34
server/src/main/java/dev/quorate/tune/ElytraCooldown.java
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
package dev.quorate.tune;
|
||||
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
public final class ElytraCooldown {
|
||||
private static IntSupplier read = ElytraCooldown::bind;
|
||||
|
||||
private ElytraCooldown() {}
|
||||
|
||||
public static int get() {
|
||||
return read.getAsInt();
|
||||
}
|
||||
|
||||
private static int bind() {
|
||||
try {
|
||||
var configType = Class.forName("com.kyanite.deeperdarker.DeeperDarkerConfig");
|
||||
var config = configType.getField("CONFIG").get(null);
|
||||
var setting = config.getClass().getField("soulElytraCooldown").get(config);
|
||||
var getter = setting.getClass().getMethod("getAsInt");
|
||||
IntSupplier bound =
|
||||
() -> {
|
||||
try {
|
||||
return (int) getter.invoke(setting);
|
||||
} catch (ReflectiveOperationException failure) {
|
||||
throw new IllegalStateException(failure);
|
||||
}
|
||||
};
|
||||
read = bound;
|
||||
return bound.getAsInt();
|
||||
} catch (ReflectiveOperationException failure) {
|
||||
throw new IllegalStateException(failure);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
server/src/main/java/dev/quorate/tune/mixin/DfcFallback.java
Normal file
15
server/src/main/java/dev/quorate/tune/mixin/DfcFallback.java
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package dev.quorate.tune.mixin;
|
||||
|
||||
import net.minecraft.world.level.levelgen.DensityFunction;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
// Declared on the parent. A shadow on either subclass does not see it.
|
||||
@Mixin(
|
||||
targets = "com.ishland.c2me.opts.dfc.common.gen.jvm.AbstractCompiledDensityFunction",
|
||||
remap = false)
|
||||
public interface DfcFallback {
|
||||
@Invoker(value = "getFallback", remap = false)
|
||||
DensityFunction fallback();
|
||||
}
|
||||
40
server/src/main/java/dev/quorate/tune/mixin/DfcMixin.java
Normal file
40
server/src/main/java/dev/quorate/tune/mixin/DfcMixin.java
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package dev.quorate.tune.mixin;
|
||||
|
||||
import net.minecraft.world.level.levelgen.DensityFunction;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(
|
||||
targets = {
|
||||
"com.ishland.c2me.opts.dfc.common.gen.jvm.CompiledDensityFunction",
|
||||
"com.ishland.c2me.opts.dfc.common.gen.jvm.SubCompiledDensityFunction"
|
||||
},
|
||||
remap = false)
|
||||
public abstract class DfcMixin {
|
||||
private static final Class<?> CACHING_VISITOR = cachingVisitor();
|
||||
|
||||
// Rebuilding for a foreign visitor casts every child to IFastCacheLike.
|
||||
// C2ME's own visitors implement the caching interface and stay compiled.
|
||||
@Inject(method = "mapAll", at = @At("HEAD"), cancellable = true, remap = false)
|
||||
private void mctune$fallback(
|
||||
DensityFunction.Visitor visitor, CallbackInfoReturnable<DensityFunction> cir) {
|
||||
if (CACHING_VISITOR == null || CACHING_VISITOR.isInstance(visitor)) return;
|
||||
var fallback = ((DfcFallback) (Object) this).fallback();
|
||||
if (fallback == null) return;
|
||||
cir.setReturnValue(fallback.mapAll(visitor));
|
||||
}
|
||||
|
||||
private static Class<?> cachingVisitor() {
|
||||
try {
|
||||
return Class.forName(
|
||||
"com.ishland.c2me.opts.dfc.common.ducks.ICompiledCachingAwareVisitor",
|
||||
false,
|
||||
DfcMixin.class.getClassLoader());
|
||||
} catch (ClassNotFoundException _) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
48
server/src/main/java/dev/quorate/tune/mixin/DfcPlugin.java
Normal file
48
server/src/main/java/dev/quorate/tune/mixin/DfcPlugin.java
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package dev.quorate.tune.mixin;
|
||||
|
||||
import net.neoforged.fml.loading.LoadingModList;
|
||||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public final class DfcPlugin implements IMixinConfigPlugin {
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {}
|
||||
|
||||
@Override
|
||||
public String getRefMapperConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||
var mods = LoadingModList.get();
|
||||
return mods != null && mods.getModFileById("c2me_opts_dfc") != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(
|
||||
String targetClassName,
|
||||
ClassNode targetClass,
|
||||
String mixinClassName,
|
||||
IMixinInfo mixinInfo) {}
|
||||
|
||||
@Override
|
||||
public void postApply(
|
||||
String targetClassName,
|
||||
ClassNode targetClass,
|
||||
String mixinClassName,
|
||||
IMixinInfo mixinInfo) {}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package dev.quorate.tune.mixin;
|
||||
|
||||
import dev.quorate.tune.ElytraCooldown;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(
|
||||
targets =
|
||||
"com.illusivesoulworks.elytraslot.common.integration.deeperdarker.SoulElytraBoostPayload",
|
||||
remap = false)
|
||||
public abstract class ElytraBoostMixin {
|
||||
// Both reads are in the queued lambda, not in handle. One redirect covers every read.
|
||||
@Redirect(
|
||||
method = "lambda$handle$0",
|
||||
at =
|
||||
@At(
|
||||
value = "FIELD",
|
||||
target =
|
||||
"Lcom/kyanite/deeperdarker/DeeperDarkerConfig;soulElytraCooldown:I",
|
||||
opcode = Opcodes.GETSTATIC),
|
||||
remap = false)
|
||||
private static int mctune$cooldown() {
|
||||
return ElytraCooldown.get();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package dev.quorate.tune.mixin;
|
||||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public final class ElytraPlugin implements IMixinConfigPlugin {
|
||||
// 9.0.2 reads a static int. The open 9.0.3 fix reads CONFIG instead.
|
||||
static final String ELYTRA = "[9.0.2+1.21.1,9.0.3+1.21.1)";
|
||||
|
||||
// 1.4 moved the cooldown onto CONFIG. 1.4.1 still stores an IntValue there.
|
||||
static final String DEEPER_DARKER = "[1.4,1.5)";
|
||||
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {}
|
||||
|
||||
@Override
|
||||
public String getRefMapperConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||
return ModRanges.loaded("elytraslot", ELYTRA)
|
||||
&& ModRanges.loaded("deeperdarker", DEEPER_DARKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(
|
||||
String targetClassName,
|
||||
ClassNode targetClass,
|
||||
String mixinClassName,
|
||||
IMixinInfo mixinInfo) {}
|
||||
|
||||
@Override
|
||||
public void postApply(
|
||||
String targetClassName,
|
||||
ClassNode targetClass,
|
||||
String mixinClassName,
|
||||
IMixinInfo mixinInfo) {}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package dev.quorate.tune.mixin;
|
||||
|
||||
import dev.quorate.tune.ElytraCooldown;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(
|
||||
targets =
|
||||
"com.illusivesoulworks.elytraslot.common.integration.deeperdarker.DeeperDarkerPlugin",
|
||||
remap = false)
|
||||
public abstract class ElytraTickMixin {
|
||||
@Redirect(
|
||||
method = "tick",
|
||||
at =
|
||||
@At(
|
||||
value = "FIELD",
|
||||
target =
|
||||
"Lcom/kyanite/deeperdarker/DeeperDarkerConfig;soulElytraCooldown:I",
|
||||
opcode = Opcodes.GETSTATIC),
|
||||
remap = false)
|
||||
private static int mctune$remaining() {
|
||||
return ElytraCooldown.get();
|
||||
}
|
||||
}
|
||||
31
server/src/main/java/dev/quorate/tune/mixin/ModRanges.java
Normal file
31
server/src/main/java/dev/quorate/tune/mixin/ModRanges.java
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package dev.quorate.tune.mixin;
|
||||
|
||||
import net.neoforged.fml.loading.LoadingModList;
|
||||
import net.neoforged.neoforgespi.language.MavenVersionAdapter;
|
||||
|
||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||
|
||||
public final class ModRanges {
|
||||
private ModRanges() {}
|
||||
|
||||
public static boolean contains(ArtifactVersion version, String spec) {
|
||||
return MavenVersionAdapter.createFromVersionSpec(spec).containsVersion(version);
|
||||
}
|
||||
|
||||
public static boolean loaded(String modId, String spec) {
|
||||
var mods = LoadingModList.get();
|
||||
if (mods == null) {
|
||||
return false;
|
||||
}
|
||||
var file = mods.getModFileById(modId);
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
for (var mod : file.getMods()) {
|
||||
if (modId.equals(mod.getModId())) {
|
||||
return contains(mod.getVersion(), spec);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -11,10 +11,16 @@ description="Snapshot-local inventory prediction and copy-free NBT normalization
|
|||
[[mixins]]
|
||||
config="tune.mixins.json"
|
||||
|
||||
[[mixins]]
|
||||
config="tune.dfc.mixins.json"
|
||||
|
||||
[[mixins]]
|
||||
config="tune.elytra.mixins.json"
|
||||
|
||||
[[dependencies.saltatory]]
|
||||
modId="neoforge"
|
||||
type="required"
|
||||
versionRange="[21.1.250]"
|
||||
versionRange="[21.1.250,)"
|
||||
ordering="NONE"
|
||||
side="SERVER"
|
||||
|
||||
|
|
@ -28,21 +34,21 @@ side="SERVER"
|
|||
[[dependencies.saltatory]]
|
||||
modId="mekanism"
|
||||
type="required"
|
||||
versionRange="[10.7.19]"
|
||||
versionRange="[10.7.19,)"
|
||||
ordering="AFTER"
|
||||
side="SERVER"
|
||||
|
||||
[[dependencies.saltatory]]
|
||||
modId="almanac"
|
||||
type="required"
|
||||
versionRange="[1.5.2]"
|
||||
versionRange="[1.5.2,)"
|
||||
ordering="AFTER"
|
||||
side="SERVER"
|
||||
|
||||
[[dependencies.saltatory]]
|
||||
modId="functionalstorage"
|
||||
type="required"
|
||||
versionRange="[1.21.1-1.5.8]"
|
||||
versionRange="[1.21.1-1.5.8,)"
|
||||
ordering="AFTER"
|
||||
side="SERVER"
|
||||
|
||||
|
|
@ -52,6 +58,6 @@ javaVersion="[25,)"
|
|||
[[dependencies.saltatory]]
|
||||
modId="refinedstorage"
|
||||
type="required"
|
||||
versionRange="[2.0.9]"
|
||||
versionRange="[2.0.9,)"
|
||||
ordering="AFTER"
|
||||
side="SERVER"
|
||||
|
|
|
|||
14
server/src/main/resources/tune.dfc.mixins.json
Normal file
14
server/src/main/resources/tune.dfc.mixins.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8.7",
|
||||
"package": "dev.quorate.tune.mixin",
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"plugin": "dev.quorate.tune.mixin.DfcPlugin",
|
||||
"mixins": [
|
||||
"DfcFallback",
|
||||
"DfcMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
14
server/src/main/resources/tune.elytra.mixins.json
Normal file
14
server/src/main/resources/tune.elytra.mixins.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8.7",
|
||||
"package": "dev.quorate.tune.mixin",
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"plugin": "dev.quorate.tune.mixin.ElytraPlugin",
|
||||
"mixins": [
|
||||
"ElytraBoostMixin",
|
||||
"ElytraTickMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package dev.quorate.tune.mixin;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class ModRangesTest {
|
||||
@Test
|
||||
void elytraGateMatchesTheBrokenReleaseOnly() {
|
||||
assertTrue(
|
||||
ModRanges.contains(
|
||||
new DefaultArtifactVersion("9.0.2+1.21.1"), ElytraPlugin.ELYTRA));
|
||||
assertFalse(
|
||||
ModRanges.contains(
|
||||
new DefaultArtifactVersion("9.0.1+1.21.1"), ElytraPlugin.ELYTRA));
|
||||
assertFalse(
|
||||
ModRanges.contains(
|
||||
new DefaultArtifactVersion("9.0.3+1.21.1"), ElytraPlugin.ELYTRA));
|
||||
assertTrue(
|
||||
ModRanges.contains(
|
||||
new DefaultArtifactVersion("1.4.1"), ElytraPlugin.DEEPER_DARKER));
|
||||
assertTrue(
|
||||
ModRanges.contains(new DefaultArtifactVersion("1.4"), ElytraPlugin.DEEPER_DARKER));
|
||||
assertFalse(
|
||||
ModRanges.contains(
|
||||
new DefaultArtifactVersion("1.3.9"), ElytraPlugin.DEEPER_DARKER));
|
||||
assertFalse(
|
||||
ModRanges.contains(new DefaultArtifactVersion("1.5"), ElytraPlugin.DEEPER_DARKER));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue