From ed99845585d4a7272c777727aabd7676b9e2fb9f Mon Sep 17 00:00:00 2001 From: htmlcsjs <46023024+htmlcsjs@users.noreply.github.com> Date: Tue, 7 May 2024 02:19:36 +0100 Subject: [PATCH] Inital Vintagium Support (#2463) Co-authored-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> (cherry picked from commit 8c2f0c6e72bb5e500552f2ec11309f763275471b) --- .gitignore | 2 + dependencies.gradle | 12 +++++ src/main/java/gregtech/GregTechMod.java | 5 +++ src/main/java/gregtech/api/util/Mods.java | 2 + .../gregtech/asm/GregTechTransformer.java | 18 ++++++++ .../asm/visitors/VintagiumManagerVistor.java | 24 ++++++++++ .../visitors/VintagiumPassManagerVisitor.java | 35 +++++++++++++++ .../utils/BloomEffectVintagiumUtil.java | 45 +++++++++++++++++++ 8 files changed, 143 insertions(+) create mode 100644 src/main/java/gregtech/asm/visitors/VintagiumManagerVistor.java create mode 100644 src/main/java/gregtech/asm/visitors/VintagiumPassManagerVisitor.java create mode 100644 src/main/java/gregtech/client/utils/BloomEffectVintagiumUtil.java diff --git a/.gitignore b/.gitignore index 755fbb2ab6d..c2fb66e1e33 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,5 @@ local.properties run/ logs/ + +libs/ diff --git a/dependencies.gradle b/dependencies.gradle index 4ab81db91bd..3ad6226cf1b 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -57,6 +57,18 @@ dependencies { compileOnly rfg.deobf("curse.maven:forestry-59751:2684780") // Forestry 5.8.2.387 compileOnly rfg.deobf("curse.maven:chisel-235279:2915375") // Chisel 1.0.2.45 + // Special Vintagium Hackery + // Vintagium is currently only distributed as a .zip containing the reobf and -dev jars on Github Actions, which is not ideal + // Using a fake Ivy repo to download it does not work, as nightly.link does not support http HEAD requests, which Gradle wants + mkdir("libs") + // Using Gradle's Ant integration seems to be the least hacky way to download an arbitrary file without a plugin + ant.get(src: "https://nightly.link/Asek3/sodium-1.12/workflows/gradle/12.x%2Fforge/Vintagium.zip", + dest: "libs", + skipexisting: 'true') + ant.unzip(src: "libs/Vintagium.zip", + dest: "libs") + compileOnly(files("libs/vintagium-mc1.12.2-0.1-dev.jar")) + // Mods with Soft compat but which have no need to be in code, such as isModLoaded() checks and getModItem() recipes. // Uncomment any of these to test them in-game. diff --git a/src/main/java/gregtech/GregTechMod.java b/src/main/java/gregtech/GregTechMod.java index 5116e9b1018..2de8b3d1fb4 100644 --- a/src/main/java/gregtech/GregTechMod.java +++ b/src/main/java/gregtech/GregTechMod.java @@ -4,7 +4,9 @@ import gregtech.api.GregTechAPI; import gregtech.api.modules.ModuleContainerRegistryEvent; import gregtech.api.persistence.PersistentData; +import gregtech.api.util.Mods; import gregtech.client.utils.BloomEffectUtil; +import gregtech.client.utils.BloomEffectVintagiumUtil; import gregtech.modules.GregTechModules; import gregtech.modules.ModuleManager; @@ -45,6 +47,9 @@ public GregTechMod() { FluidRegistry.enableUniversalBucket(); if (FMLCommonHandler.instance().getSide().isClient()) { BloomEffectUtil.init(); + if (Mods.Vintagium.isModLoaded()) { + BloomEffectVintagiumUtil.init(); + } } } diff --git a/src/main/java/gregtech/api/util/Mods.java b/src/main/java/gregtech/api/util/Mods.java index c022672f095..b06b7d9f247 100644 --- a/src/main/java/gregtech/api/util/Mods.java +++ b/src/main/java/gregtech/api/util/Mods.java @@ -68,6 +68,7 @@ public enum Mods { TOPAddons(Names.TOP_ADDONS), VoxelMap(Names.VOXEL_MAP), XaerosMinimap(Names.XAEROS_MINIMAP), + Vintagium(Names.VINTAGIUM), // Special Optifine handler, but consolidated here for simplicity Optifine(null) { @@ -135,6 +136,7 @@ public static class Names { public static final String TOP_ADDONS = "topaddons"; public static final String VOXEL_MAP = "voxelmap"; public static final String XAEROS_MINIMAP = "xaerominimap"; + public static final String VINTAGIUM = "vintagium"; } private final String ID; diff --git a/src/main/java/gregtech/asm/GregTechTransformer.java b/src/main/java/gregtech/asm/GregTechTransformer.java index 4bdf742b499..5f9d5e1ba3f 100644 --- a/src/main/java/gregtech/asm/GregTechTransformer.java +++ b/src/main/java/gregtech/asm/GregTechTransformer.java @@ -178,6 +178,24 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) ModelLoaderRegistryVisitor::new), ClassReader.EXPAND_FRAMES); return classWriter.toByteArray(); } + // TODO: Remove when vintagium has proper support for other rendering layers + case VintagiumPassManagerVisitor.TARGET_CLASS_NAME: { + ClassReader classReader = new ClassReader(basicClass); + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + classReader.accept( + new TargetClassVisitor(classWriter, VintagiumPassManagerVisitor.TARGET_METHOD, + VintagiumPassManagerVisitor::new), + ClassReader.EXPAND_FRAMES); + return classWriter.toByteArray(); + } + case VintagiumManagerVistor.TARGET_CLASS_NAME: { + ClassReader classReader = new ClassReader(basicClass); + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + classReader.accept( + new VintagiumManagerVistor(classWriter), + 0); + return classWriter.toByteArray(); + } } if (EnchantmentCanApplyVisitor.CLASS_TO_MAPPING_MAP.containsKey(internalName)) { ObfMapping methodMapping = EnchantmentCanApplyVisitor.CLASS_TO_MAPPING_MAP.get(internalName); diff --git a/src/main/java/gregtech/asm/visitors/VintagiumManagerVistor.java b/src/main/java/gregtech/asm/visitors/VintagiumManagerVistor.java new file mode 100644 index 00000000000..4d8d53edf47 --- /dev/null +++ b/src/main/java/gregtech/asm/visitors/VintagiumManagerVistor.java @@ -0,0 +1,24 @@ +package gregtech.asm.visitors; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Opcodes; + +public class VintagiumManagerVistor extends ClassVisitor implements Opcodes { + + public static final String TARGET_CLASS_NAME = "me/jellysquid/mods/sodium/client/render/chunk/passes/BlockRenderPass"; + + public VintagiumManagerVistor(ClassVisitor cv) { + super(ASM5, cv); + } + + @Override + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { + // Make BlockRenderPass.VALUES and BlockRenderPass.COUNT not final + if (name.equals("VALUES") || name.equals("COUNT")) { + return super.visitField(access & ~ACC_FINAL, name, desc, signature, value); + } else { + return super.visitField(access, name, desc, signature, value); + } + } +} diff --git a/src/main/java/gregtech/asm/visitors/VintagiumPassManagerVisitor.java b/src/main/java/gregtech/asm/visitors/VintagiumPassManagerVisitor.java new file mode 100644 index 00000000000..eb103ffb651 --- /dev/null +++ b/src/main/java/gregtech/asm/visitors/VintagiumPassManagerVisitor.java @@ -0,0 +1,35 @@ +package gregtech.asm.visitors; + +import gregtech.asm.util.ObfMapping; + +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public class VintagiumPassManagerVisitor extends MethodVisitor implements Opcodes { + + public static final String TARGET_CLASS_NAME = "me/jellysquid/mods/sodium/client/render/chunk/passes/BlockRenderPassManager"; + public static final ObfMapping TARGET_METHOD = new ObfMapping(TARGET_CLASS_NAME, "createDefaultMappings", + "()Lme/jellysquid/mods/sodium/client/render/chunk/passes/BlockRenderPassManager;"); + public static final ObfMapping GET_BLOOM_LAYER = new ObfMapping("gregtech/client/utils/BloomEffectUtil", + "getBloomLayer", "()Lnet/minecraft/util/BlockRenderLayer;"); + public static final ObfMapping GET_BLOOM_PASS = new ObfMapping("gregtech/client/utils/BloomEffectVintagiumUtil", + "getBloomPass", "()Lme/jellysquid/mods/sodium/client/render/chunk/passes/BlockRenderPass;"); + public static final ObfMapping ADD_MAPPING = new ObfMapping(TARGET_CLASS_NAME, "addMapping", + "(Lnet/minecraft/util/BlockRenderLayer;Lme/jellysquid/mods/sodium/client/render/chunk/passes/BlockRenderPass;)V"); + + public VintagiumPassManagerVisitor(MethodVisitor mv) { + super(ASM5, mv); + } + + @Override + public void visitInsn(int opcode) { + // add mapper.addMapping(BloomEffectUtil.getBloomLayer(), BloomEffectVintagiumUtil.getBloomPass()); + if (opcode == ARETURN) { + GET_BLOOM_LAYER.visitMethodInsn(this, INVOKESTATIC); + GET_BLOOM_PASS.visitMethodInsn(this, INVOKESTATIC); + ADD_MAPPING.visitMethodInsn(this, INVOKESPECIAL); + super.visitVarInsn(ALOAD, 0); + } + super.visitInsn(opcode); + } +} diff --git a/src/main/java/gregtech/client/utils/BloomEffectVintagiumUtil.java b/src/main/java/gregtech/client/utils/BloomEffectVintagiumUtil.java new file mode 100644 index 00000000000..ced8de12e03 --- /dev/null +++ b/src/main/java/gregtech/client/utils/BloomEffectVintagiumUtil.java @@ -0,0 +1,45 @@ +package gregtech.client.utils; + +import net.minecraft.util.BlockRenderLayer; +import net.minecraftforge.common.util.EnumHelper; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPass; +import me.jellysquid.mods.sodium.client.util.BufferSizeUtil; +import me.jellysquid.mods.sodium.client.util.EnumUtil; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.util.Objects; + +@SideOnly(Side.CLIENT) +public class BloomEffectVintagiumUtil { + + private static BlockRenderPass bloom; + + public static void init() { + EnumUtil.LAYERS = BlockRenderLayer.values(); + BufferSizeUtil.BUFFER_SIZES.put(BloomEffectUtil.getBloomLayer(), 131072); + bloom = EnumHelper.addEnum(BlockRenderPass.class, "BLOOM", + new Class[] { BlockRenderLayer.class, boolean.class }, BloomEffectUtil.getBloomLayer(), true); + + try { + Field values = BlockRenderPass.class.getField("VALUES"); + values.set(null, BlockRenderPass.values()); + Field count = BlockRenderPass.class.getField("COUNT"); + count.set(null, BlockRenderPass.values().length); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + /** + * @return {@link BlockRenderPass} instance for the bloom render layer. + */ + @NotNull + @SuppressWarnings("unused") + public static BlockRenderPass getBloomPass() { + return Objects.requireNonNull(bloom, "Bloom effect is not initialized yet"); + } +}