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
20 changed files with 550 additions and 8 deletions
|
|
@ -20,6 +20,7 @@ configurations { testImplementation.extendsFrom compileOnly }
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly('net.createmod.ponder:ponder-neoforge:1.0.82+mc1.21.1') { transitive = false }
|
compileOnly('net.createmod.ponder:ponder-neoforge:1.0.82+mc1.21.1') { transitive = false }
|
||||||
compileOnly('maven.modrinth:iris:t3ruzodq') { transitive = false }
|
compileOnly('maven.modrinth:iris:t3ruzodq') { transitive = false }
|
||||||
|
compileOnly('maven.modrinth:jei:Tn0dgwL0') { transitive = false }
|
||||||
compileOnly('dev.engine-room.flywheel:flywheel-neoforge-1.21.1:1.0.6') { transitive = false }
|
compileOnly('dev.engine-room.flywheel:flywheel-neoforge-1.21.1:1.0.6') { transitive = false }
|
||||||
testImplementation 'org.ow2.asm:asm-tree:9.8'
|
testImplementation 'org.ow2.asm:asm-tree:9.8'
|
||||||
testImplementation 'org.ow2.asm:asm-commons:9.8'
|
testImplementation 'org.ow2.asm:asm-commons:9.8'
|
||||||
|
|
|
||||||
51
client/src/main/java/dev/quorate/client/mixin/EmiPlugin.java
Normal file
51
client/src/main/java/dev/quorate/client/mixin/EmiPlugin.java
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
package dev.quorate.client.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 EmiPlugin implements IMixinConfigPlugin {
|
||||||
|
// 1.1.24 leaves JEI's aligned setPosition abstract. 1.1.25 is the next release.
|
||||||
|
static final String EMI = "[1.1.24+1.21.1+neoforge,1.1.25+1.21.1+neoforge)";
|
||||||
|
|
||||||
|
// 19.57.0.450 declares the aligned method and places through getXPos/getYPos.
|
||||||
|
static final String JEI = "[19.57.0.450,19.58)";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad(String mixinPackage) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRefMapperConfig() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||||
|
return ModRanges.loaded("emi", EMI) && ModRanges.loaded("jei", JEI);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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,33 @@
|
||||||
|
package dev.quorate.client.mixin;
|
||||||
|
|
||||||
|
import mezz.jei.api.gui.builder.IRecipeSlotBuilder;
|
||||||
|
import mezz.jei.api.gui.placement.HorizontalAlignment;
|
||||||
|
import mezz.jei.api.gui.placement.VerticalAlignment;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
@Mixin(targets = "dev.emi.emi.jemi.impl.JemiRecipeSlotBuilder", remap = false)
|
||||||
|
public abstract class EmiSlotMixin {
|
||||||
|
@Shadow(remap = false)
|
||||||
|
public abstract IRecipeSlotBuilder setPosition(int x, int y);
|
||||||
|
|
||||||
|
@Shadow(remap = false)
|
||||||
|
public abstract int getWidth();
|
||||||
|
|
||||||
|
@Shadow(remap = false)
|
||||||
|
public abstract int getHeight();
|
||||||
|
|
||||||
|
// Same placement as JEI PlaceableUtil: origin plus alignment inside the area.
|
||||||
|
public IRecipeSlotBuilder setPosition(
|
||||||
|
int areaX,
|
||||||
|
int areaY,
|
||||||
|
int areaWidth,
|
||||||
|
int areaHeight,
|
||||||
|
HorizontalAlignment horizontal,
|
||||||
|
VerticalAlignment vertical) {
|
||||||
|
return setPosition(
|
||||||
|
areaX + horizontal.getXPos(areaWidth, getWidth()),
|
||||||
|
areaY + vertical.getYPos(areaHeight, getHeight()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package dev.quorate.client.mixin;
|
||||||
|
|
||||||
|
import mezz.jei.api.gui.placement.HorizontalAlignment;
|
||||||
|
import mezz.jei.api.gui.placement.VerticalAlignment;
|
||||||
|
import mezz.jei.api.gui.widgets.ITextWidget;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
@Mixin(targets = "dev.emi.emi.jemi.impl.extras.JemiTextWidget", remap = false)
|
||||||
|
public abstract class EmiTextMixin {
|
||||||
|
@Shadow(remap = false)
|
||||||
|
public int x;
|
||||||
|
|
||||||
|
@Shadow(remap = false)
|
||||||
|
public int y;
|
||||||
|
|
||||||
|
@Shadow(remap = false)
|
||||||
|
public abstract int getWidth();
|
||||||
|
|
||||||
|
@Shadow(remap = false)
|
||||||
|
public abstract int getHeight();
|
||||||
|
|
||||||
|
// ITextWidget.setPosition returns ITextWidget. The parent method returns IPlaceable.
|
||||||
|
public ITextWidget setPosition(int x, int y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
return (ITextWidget) (Object) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITextWidget setPosition(
|
||||||
|
int areaX,
|
||||||
|
int areaY,
|
||||||
|
int areaWidth,
|
||||||
|
int areaHeight,
|
||||||
|
HorizontalAlignment horizontal,
|
||||||
|
VerticalAlignment vertical) {
|
||||||
|
return setPosition(
|
||||||
|
areaX + horizontal.getXPos(areaWidth, getWidth()),
|
||||||
|
areaY + vertical.getYPos(areaHeight, getHeight()));
|
||||||
|
}
|
||||||
|
}
|
||||||
31
client/src/main/java/dev/quorate/client/mixin/ModRanges.java
Normal file
31
client/src/main/java/dev/quorate/client/mixin/ModRanges.java
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
package dev.quorate.client.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,13 @@ description="Create rendering and collision query optimizations."
|
||||||
[[mixins]]
|
[[mixins]]
|
||||||
config="client.mixins.json"
|
config="client.mixins.json"
|
||||||
|
|
||||||
|
[[mixins]]
|
||||||
|
config="client.jemi.mixins.json"
|
||||||
|
|
||||||
[[dependencies.saltatory_client]]
|
[[dependencies.saltatory_client]]
|
||||||
modId="neoforge"
|
modId="neoforge"
|
||||||
type="required"
|
type="required"
|
||||||
versionRange="[21.1.250]"
|
versionRange="[21.1.250,)"
|
||||||
ordering="NONE"
|
ordering="NONE"
|
||||||
side="CLIENT"
|
side="CLIENT"
|
||||||
|
|
||||||
|
|
@ -31,13 +34,13 @@ javaVersion="[25,)"
|
||||||
[[dependencies.saltatory_client]]
|
[[dependencies.saltatory_client]]
|
||||||
modId="ponder"
|
modId="ponder"
|
||||||
type="required"
|
type="required"
|
||||||
versionRange="[1.0.82+mc1.21.1]"
|
versionRange="[1.0.82+mc1.21.1,)"
|
||||||
ordering="AFTER"
|
ordering="AFTER"
|
||||||
side="CLIENT"
|
side="CLIENT"
|
||||||
|
|
||||||
[[dependencies.saltatory_client]]
|
[[dependencies.saltatory_client]]
|
||||||
modId="iris"
|
modId="iris"
|
||||||
type="required"
|
type="required"
|
||||||
versionRange="[1.8.12-snapshot+mc1.21.1-local]"
|
versionRange="[1.8.12-snapshot+mc1.21.1-local,)"
|
||||||
ordering="AFTER"
|
ordering="AFTER"
|
||||||
side="CLIENT"
|
side="CLIENT"
|
||||||
|
|
|
||||||
14
client/src/main/resources/client.jemi.mixins.json
Normal file
14
client/src/main/resources/client.jemi.mixins.json
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"required": true,
|
||||||
|
"minVersion": "0.8.7",
|
||||||
|
"package": "dev.quorate.client.mixin",
|
||||||
|
"compatibilityLevel": "JAVA_21",
|
||||||
|
"plugin": "dev.quorate.client.mixin.EmiPlugin",
|
||||||
|
"client": [
|
||||||
|
"EmiSlotMixin",
|
||||||
|
"EmiTextMixin"
|
||||||
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package dev.quorate.client.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 jemiGateMatchesTheBrokenPairOnly() {
|
||||||
|
assertTrue(
|
||||||
|
ModRanges.contains(
|
||||||
|
new DefaultArtifactVersion("1.1.24+1.21.1+neoforge"), EmiPlugin.EMI));
|
||||||
|
assertFalse(
|
||||||
|
ModRanges.contains(
|
||||||
|
new DefaultArtifactVersion("1.1.23+1.21.1+neoforge"), EmiPlugin.EMI));
|
||||||
|
assertFalse(
|
||||||
|
ModRanges.contains(
|
||||||
|
new DefaultArtifactVersion("1.1.25+1.21.1+neoforge"), EmiPlugin.EMI));
|
||||||
|
assertTrue(ModRanges.contains(new DefaultArtifactVersion("19.57.0.450"), EmiPlugin.JEI));
|
||||||
|
assertTrue(ModRanges.contains(new DefaultArtifactVersion("19.57.0.451"), EmiPlugin.JEI));
|
||||||
|
assertFalse(ModRanges.contains(new DefaultArtifactVersion("19.56.0.1"), EmiPlugin.JEI));
|
||||||
|
assertFalse(ModRanges.contains(new DefaultArtifactVersion("19.58"), EmiPlugin.JEI));
|
||||||
|
}
|
||||||
|
}
|
||||||
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]]
|
[[mixins]]
|
||||||
config="tune.mixins.json"
|
config="tune.mixins.json"
|
||||||
|
|
||||||
|
[[mixins]]
|
||||||
|
config="tune.dfc.mixins.json"
|
||||||
|
|
||||||
|
[[mixins]]
|
||||||
|
config="tune.elytra.mixins.json"
|
||||||
|
|
||||||
[[dependencies.saltatory]]
|
[[dependencies.saltatory]]
|
||||||
modId="neoforge"
|
modId="neoforge"
|
||||||
type="required"
|
type="required"
|
||||||
versionRange="[21.1.250]"
|
versionRange="[21.1.250,)"
|
||||||
ordering="NONE"
|
ordering="NONE"
|
||||||
side="SERVER"
|
side="SERVER"
|
||||||
|
|
||||||
|
|
@ -28,21 +34,21 @@ side="SERVER"
|
||||||
[[dependencies.saltatory]]
|
[[dependencies.saltatory]]
|
||||||
modId="mekanism"
|
modId="mekanism"
|
||||||
type="required"
|
type="required"
|
||||||
versionRange="[10.7.19]"
|
versionRange="[10.7.19,)"
|
||||||
ordering="AFTER"
|
ordering="AFTER"
|
||||||
side="SERVER"
|
side="SERVER"
|
||||||
|
|
||||||
[[dependencies.saltatory]]
|
[[dependencies.saltatory]]
|
||||||
modId="almanac"
|
modId="almanac"
|
||||||
type="required"
|
type="required"
|
||||||
versionRange="[1.5.2]"
|
versionRange="[1.5.2,)"
|
||||||
ordering="AFTER"
|
ordering="AFTER"
|
||||||
side="SERVER"
|
side="SERVER"
|
||||||
|
|
||||||
[[dependencies.saltatory]]
|
[[dependencies.saltatory]]
|
||||||
modId="functionalstorage"
|
modId="functionalstorage"
|
||||||
type="required"
|
type="required"
|
||||||
versionRange="[1.21.1-1.5.8]"
|
versionRange="[1.21.1-1.5.8,)"
|
||||||
ordering="AFTER"
|
ordering="AFTER"
|
||||||
side="SERVER"
|
side="SERVER"
|
||||||
|
|
||||||
|
|
@ -52,6 +58,6 @@ javaVersion="[25,)"
|
||||||
[[dependencies.saltatory]]
|
[[dependencies.saltatory]]
|
||||||
modId="refinedstorage"
|
modId="refinedstorage"
|
||||||
type="required"
|
type="required"
|
||||||
versionRange="[2.0.9]"
|
versionRange="[2.0.9,)"
|
||||||
ordering="AFTER"
|
ordering="AFTER"
|
||||||
side="SERVER"
|
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