mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-10-26 14:24:30 +00:00
Use a RFB plugin for GLSM transforms when available (#329)
This commit is contained in:
1 parent
6d28df74a6
commit
c996e5e58c
8 files changed
+182
-30
No files matched your search
@@ -14,6 +14,13 @@ tasks.test {
|
||||
jvmArgs("-Djava.library.path=${tasks.extractNatives2.get().destinationFolder.asFile.get().path}")
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
inputs.property("version", project.version.toString())
|
||||
filesMatching("META-INF/rfb-plugin/*") {
|
||||
expand("version" to project.version.toString())
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register<Copy>("copyDependencies") {
|
||||
group = "Angelica"
|
||||
description = "Collect dependencies into the testDependencies folder"
|
||||
|
||||
+4
-2
@@ -51,7 +51,9 @@ configurations {
|
||||
dependencies {
|
||||
compileOnly("com.github.GTNewHorizons:Hodgepodge:2.4.4")
|
||||
|
||||
compileOnly("org.projectlombok:lombok:1.18.22") {transitive = false }
|
||||
compileOnly("com.gtnewhorizons.retrofuturabootstrap:RetroFuturaBootstrap:0.4.0") { transitive = false }
|
||||
|
||||
compileOnly("org.projectlombok:lombok:1.18.22") { transitive = false }
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.22")
|
||||
|
||||
// Iris Shaders
|
||||
@@ -71,7 +73,7 @@ dependencies {
|
||||
// Notfine Deps
|
||||
compileOnly("thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev")
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:Baubles:1.0.1.16:dev")
|
||||
compileOnly("com.github.GTNewHorizons:twilightforest:2.5.1:dev") {transitive = false }
|
||||
compileOnly("com.github.GTNewHorizons:twilightforest:2.5.1:dev") { transitive = false }
|
||||
compileOnly(rfg.deobf('curse.maven:witchery-69673:2234410'))
|
||||
|
||||
compileOnly("com.falsepattern:chunkapi-mc1.7.10:0.5.0:api")
|
||||
|
||||
@@ -21,13 +21,13 @@ public class MixinCompatHackTweaker implements ITweaker {
|
||||
@Override
|
||||
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
verifyDependencies();
|
||||
|
||||
|
||||
if(DISABLE_OPTIFINE_AND_FASTCRAFT) {
|
||||
LOGGER.info("Disabling Optifine and Fastcraft (if present)");
|
||||
disableOptifineAndFastcraft();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void verifyDependencies() {
|
||||
if(MixinCompatHackTweaker.class.getResource("/it/unimi/dsi/fastutil/ints/Int2ObjectMap.class") == null) {
|
||||
throw new RuntimeException("Missing dependency: Angelica requires GTNHLib 0.2.1 or newer! Download: https://modrinth.com/mod/gtnhlib");
|
||||
@@ -82,8 +82,12 @@ public class MixinCompatHackTweaker implements ITweaker {
|
||||
@Override
|
||||
public String[] getLaunchArguments() {
|
||||
if (FMLLaunchHandler.side().isClient()) {
|
||||
// Run after Mixins, but before LWJGl3ify
|
||||
Launch.classLoader.registerTransformer(RedirectorTransformer.class.getName());
|
||||
final boolean rfbLoaded = Launch.blackboard.getOrDefault("angelica.rfbPluginLoaded", Boolean.FALSE) == Boolean.TRUE;
|
||||
|
||||
if (!rfbLoaded) {
|
||||
// Run after Mixins, but before LWJGl3ify
|
||||
Launch.classLoader.registerTransformer(RedirectorTransformer.class.getName());
|
||||
}
|
||||
if(AngelicaConfig.enableSodium) {
|
||||
Launch.classLoader.registerTransformer(BlockTransformer.class.getName());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.gtnewhorizons.angelica.loading.rfb;
|
||||
|
||||
import com.gtnewhorizons.retrofuturabootstrap.api.PluginContext;
|
||||
import com.gtnewhorizons.retrofuturabootstrap.api.RetroFuturaBootstrap;
|
||||
import com.gtnewhorizons.retrofuturabootstrap.api.RfbClassTransformer;
|
||||
import com.gtnewhorizons.retrofuturabootstrap.api.RfbPlugin;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class AngelicaRfbPlugin implements RfbPlugin {
|
||||
|
||||
@Override
|
||||
public void onConstruction(@NotNull PluginContext ctx) {
|
||||
Launch.blackboard.put("angelica.rfbPluginLoaded", Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RfbClassTransformer @Nullable [] makeTransformers() {
|
||||
final boolean isServer = (null == RetroFuturaBootstrap.API.launchClassLoader().findClassMetadata("net.minecraft.client.main.Main"));
|
||||
if (isServer) {
|
||||
return null;
|
||||
}
|
||||
return new RfbClassTransformer[] {
|
||||
new RedirectorTransformerWrapper()
|
||||
};
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.gtnewhorizons.angelica.loading.rfb;
|
||||
|
||||
import com.gtnewhorizons.angelica.transform.RedirectorTransformer;
|
||||
import com.gtnewhorizons.retrofuturabootstrap.api.ClassNodeHandle;
|
||||
import com.gtnewhorizons.retrofuturabootstrap.api.ExtensibleClassLoader;
|
||||
import com.gtnewhorizons.retrofuturabootstrap.api.RfbClassTransformer;
|
||||
import org.intellij.lang.annotations.Pattern;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
/** RFB wrapper for {@link com.gtnewhorizons.angelica.transform.RedirectorTransformer} */
|
||||
public class RedirectorTransformerWrapper implements RfbClassTransformer {
|
||||
|
||||
public final RedirectorTransformer inner = new RedirectorTransformer();
|
||||
|
||||
@Pattern("[a-z0-9-]+")
|
||||
@Override
|
||||
public @NotNull String id() {
|
||||
return "redirector";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String @Nullable [] sortAfter() {
|
||||
return new String[] {"*", "mixin:mixin"};
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String @Nullable [] sortBefore() {
|
||||
return new String[] {"lwjgl3ify:redirect"};
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String @Nullable [] additionalExclusions() {
|
||||
return RedirectorTransformer.getTransformerExclusions().toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldTransformClass(@NotNull ExtensibleClassLoader classLoader,
|
||||
@NotNull RfbClassTransformer.Context context, @Nullable Manifest manifest, @NotNull String className,
|
||||
@NotNull ClassNodeHandle classNode) {
|
||||
if (!classNode.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
if (!classNode.isOriginal()) {
|
||||
// If a class is already a transformed ClassNode, conservatively continue processing.
|
||||
return true;
|
||||
}
|
||||
return inner.shouldRfbTransform(classNode.getOriginalBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformClass(@NotNull ExtensibleClassLoader classLoader, @NotNull RfbClassTransformer.Context context,
|
||||
@Nullable Manifest manifest, @NotNull String className, @NotNull ClassNodeHandle classNode) {
|
||||
final boolean changed = inner.transformClassNode(className, classNode.getNode());
|
||||
if (changed) {
|
||||
classNode.computeMaxs();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,9 @@ package com.gtnewhorizons.angelica.transform;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.spongepowered.asm.lib.ClassReader;
|
||||
import org.spongepowered.asm.lib.ClassWriter;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -6,24 +6,27 @@ import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import net.coderbot.iris.IrisLogging;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.spongepowered.asm.lib.ClassReader;
|
||||
import org.spongepowered.asm.lib.ClassWriter;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.lib.tree.AbstractInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
import org.spongepowered.asm.lib.tree.FieldInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.InsnList;
|
||||
import org.spongepowered.asm.lib.tree.InsnNode;
|
||||
import org.spongepowered.asm.lib.tree.IntInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.LdcInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodNode;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.tree.InsnNode;
|
||||
import org.objectweb.asm.tree.IntInsnNode;
|
||||
import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -90,6 +93,9 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
// Block owners we *shouldn't* redirect because they shadow one of our fields
|
||||
private static final Set<String> blockOwnerExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
// Needed because the config is loaded in LaunchClassLoader, but we need to access it in the parent system loader.
|
||||
private static final MethodHandle angelicaConfigSodiumEnabledGetter;
|
||||
|
||||
static {
|
||||
glCapRedirects.put(org.lwjgl.opengl.GL11.GL_ALPHA_TEST, "AlphaTest");
|
||||
glCapRedirects.put(org.lwjgl.opengl.GL11.GL_BLEND, "Blend");
|
||||
@@ -203,6 +209,22 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
methodRedirects.put(EXTBlendFunc, RedirectMap.newMap().add("glBlendFuncSeparateEXT", "tryBlendFuncSeparate"));
|
||||
methodRedirects.put(ARBMultiTexture, RedirectMap.newMap().add("glActiveTextureARB"));
|
||||
methodRedirects.put(Project, RedirectMap.newMap().add("gluPerspective"));
|
||||
|
||||
try {
|
||||
final Class<?> angelicaConfig = Class.forName("com.gtnewhorizons.angelica.config.AngelicaConfig", true, Launch.classLoader);
|
||||
final MethodHandle sodiumGetter = MethodHandles.lookup().findStaticGetter(angelicaConfig, "enableSodium", boolean.class);
|
||||
angelicaConfigSodiumEnabledGetter = sodiumGetter;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSodiumEnabled() {
|
||||
try {
|
||||
return (boolean) angelicaConfigSodiumEnabledGetter.invokeExact();
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isVanillaBlockSubclass(String className) {
|
||||
@@ -221,6 +243,14 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
return isVanillaBlockSubclass(className) || moddedBlockSubclasses.contains(className);
|
||||
}
|
||||
|
||||
public static List<String> getTransformerExclusions() {
|
||||
return Collections.unmodifiableList(TransformerExclusions);
|
||||
}
|
||||
|
||||
public boolean shouldRfbTransform(byte[] basicClass) {
|
||||
return cstPoolParser.find(basicClass, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(final String className, String transformedName, byte[] basicClass) {
|
||||
if (basicClass == null) return null;
|
||||
@@ -237,9 +267,27 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
// Keep in sync with com.gtnewhorizons.angelica.loading.rfb.RedirectorTransformerWrapper
|
||||
final ClassReader cr = new ClassReader(basicClass);
|
||||
final ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
final boolean changed = transformClassNode(transformedName, cn);
|
||||
if (changed) {
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
saveTransformedClass(bytes, transformedName);
|
||||
return bytes;
|
||||
}
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
/** @return Was the class changed? */
|
||||
public boolean transformClassNode(String transformedName, ClassNode cn)
|
||||
{
|
||||
if (cn == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Track subclasses of Block
|
||||
if (!isVanillaBlockSubclass(cn.name) && isBlockSubclass(cn.superName)) {
|
||||
@@ -338,7 +386,7 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
}
|
||||
}
|
||||
else if ((node.getOpcode() == Opcodes.GETFIELD || node.getOpcode() == Opcodes.PUTFIELD) && node instanceof FieldInsnNode fNode) {
|
||||
if(!blockOwnerExclusions.contains(fNode.owner) && isBlockSubclass(fNode.owner) && AngelicaConfig.enableSodium) {
|
||||
if(!blockOwnerExclusions.contains(fNode.owner) && isBlockSubclass(fNode.owner) && isSodiumEnabled()) {
|
||||
Pair<String, String> fieldToRedirect = null;
|
||||
for(Pair<String, String> blockPairs : BlockBoundsFields) {
|
||||
if(fNode.name.equals(blockPairs.getLeft()) || fNode.name.equals(blockPairs.getRight())) {
|
||||
@@ -384,14 +432,7 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
saveTransformedClass(bytes, transformedName);
|
||||
return bytes;
|
||||
}
|
||||
return basicClass;
|
||||
return changed;
|
||||
}
|
||||
|
||||
private File outputDir = null;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
name=Angelica
|
||||
version=${version}
|
||||
additionalVersions=
|
||||
className=com.gtnewhorizons.angelica.loading.rfb.AngelicaRfbPlugin
|
||||
transformerExclusions=com.gtnewhorizons.angelica.transform.RedirectorTransformer
|
||||
versionConstraints=
|
||||
loadBefore=
|
||||
loadAfter=mixin; lwjgl3ify
|
||||
loadRequires=
|
||||
Reference in new issue
Block a user