From 636e404973ec5cc5e6dff7d8d3027a28d8f51a4b Mon Sep 17 00:00:00 2001 From: KatatsumuriPan Date: Sat, 9 Dec 2023 21:41:22 +0900 Subject: [PATCH 1/3] =?UTF-8?q?ASM=E6=9B=B4=E6=96=B0(+import=E4=B8=A6?= =?UTF-8?q?=E3=81=B3=E6=9B=BF=E3=81=88)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../asm/core/AccessTransformerForMixin.java | 36 ++ .../uti_alsofluids/asm/core/AsmTypes.java | 59 +-- .../kpan/uti_alsofluids/asm/core/AsmUtil.java | 20 +- .../asm/core/MyAsmNameRemapper.java | 186 ++------ .../uti_alsofluids/asm/core/MyTextifier.java | 7 +- .../adapters/AddFieldAccessorAdapter.java | 100 ----- .../asm/core/adapters/AddFieldAdapter.java | 46 -- .../asm/core/adapters/AddMethodAdapter.java | 44 -- .../core/adapters/AddRefMethodAdapter.java | 71 ---- .../asm/core/adapters/FieldPublicAdapter.java | 29 -- .../adapters/InjectInstructionsAdapter.java | 37 +- .../asm/core/adapters/Instructions.java | 201 ++++----- .../core/adapters/MixinAccessorAdapter.java | 397 ++++++++++++++++++ .../asm/core/adapters/MyClassVisitor.java | 24 +- .../asm/core/adapters/MyMethodVisitor.java | 6 +- .../adapters/ReplaceInstructionsAdapter.java | 12 +- .../core/adapters/ReplaceMethodAdapter.java | 39 +- .../adapters/ReplaceRefMethodAdapter.java | 28 +- .../kpan/uti_alsofluids/asm/tf/TF_Fluid.java | 3 +- .../uti_alsofluids/asm/tf/TF_FluidStack.java | 3 +- .../asm/tf/integration/ae2/TF_GuiCraft__.java | 5 +- .../gregtech/TF_PhantomFluidWidget.java | 7 +- .../jei/TF_FluidStackRenderer.java | 7 +- .../p455w0rd/wct/TF_GuiCraft__.java | 5 +- .../integration/p455w0rd/wft/TF_GuiWFT.java | 7 +- .../p455w0rd/wpt/TF_GuiCraft__.java | 5 +- .../theoneprobe/TF_OverlayRenderer.java | 5 +- 27 files changed, 719 insertions(+), 670 deletions(-) create mode 100644 src/main/java/kpan/uti_alsofluids/asm/core/AccessTransformerForMixin.java delete mode 100644 src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddFieldAccessorAdapter.java delete mode 100644 src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddFieldAdapter.java delete mode 100644 src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddMethodAdapter.java delete mode 100644 src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddRefMethodAdapter.java delete mode 100644 src/main/java/kpan/uti_alsofluids/asm/core/adapters/FieldPublicAdapter.java create mode 100644 src/main/java/kpan/uti_alsofluids/asm/core/adapters/MixinAccessorAdapter.java diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/AccessTransformerForMixin.java b/src/main/java/kpan/uti_alsofluids/asm/core/AccessTransformerForMixin.java new file mode 100644 index 0000000..6687802 --- /dev/null +++ b/src/main/java/kpan/uti_alsofluids/asm/core/AccessTransformerForMixin.java @@ -0,0 +1,36 @@ +package kpan.uti_alsofluids.asm.core; + +import com.google.common.io.CharSource; +import net.minecraftforge.fml.common.asm.transformers.AccessTransformer; + +import java.io.IOException; + +public class AccessTransformerForMixin extends AccessTransformer { + + private static AccessTransformerForMixin INSTANCE; + private static boolean callSuper = false; + + + public static void toPublic(String deobfOwner, String srgMethodName, String deobfMethodDesc) { + String rule = "public " + deobfOwner + " " + srgMethodName + deobfMethodDesc; + callSuper = true; + INSTANCE.processATFile(CharSource.wrap(rule)); + callSuper = false; + } + + public AccessTransformerForMixin() throws IOException { + super(); + INSTANCE = this; + } + + @Override + protected void processATFile(CharSource rulesResource) { + if (!callSuper) + return; + try { + super.processATFile(rulesResource); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/AsmTypes.java b/src/main/java/kpan/uti_alsofluids/asm/core/AsmTypes.java index 240717f..4ed88e0 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/AsmTypes.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/AsmTypes.java @@ -1,13 +1,15 @@ package kpan.uti_alsofluids.asm.core; +import kpan.uti_alsofluids.ModReference; + import java.util.ArrayList; import java.util.List; -import kpan.uti_alsofluids.ModReference; - +@SuppressWarnings("unused") public class AsmTypes { public static final String HOOK = ModReference.SRC_DIR.replace('.', '/') + "/asm/hook/"; + public static final String ACC = ModReference.SRC_DIR.replace('.', '/') + "/asm/acc/"; public static final String VOID = "V"; public static final String BOOL = "Z"; public static final String CHAR = "C"; @@ -40,6 +42,7 @@ public class AsmTypes { public static final String IBLOCKACCESS = "net/minecraft/world/IBlockAccess"; public static final String FLUID = "net/minecraftforge/fluids/Fluid"; public static final String FLUIDSTACK = "net/minecraftforge/fluids/FluidStack"; + public static final String CONTAINER = "net/minecraft/inventory/Container"; public static final String METHOD_VOID = "()V"; @@ -74,34 +77,34 @@ public static MethodDesc fromMethodDesc(String methodDesc) { if (c == ')') break; switch (c) { - case 'Z': - case 'C': - case 'B': - case 'S': - case 'I': - case 'J': - case 'F': - case 'D': - sb.append(c); - params.add(sb.toString()); - sb.setLength(0); - index++; - break; - case '[': - sb.append('['); - index++; - break; - case 'L': { - int end_index = methodDesc.indexOf(';', index); - params.add(methodDesc.substring(index + 1, end_index)); - index = end_index + 1; - break; - } - default: - throw new RuntimeException("Invalid Char:" + c); + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + case 'J': + case 'F': + case 'D': + sb.append(c); + params.add(sb.toString()); + sb.setLength(0); + index++; + break; + case '[': + sb.append('['); + index++; + break; + case 'L': { + int end_index = methodDesc.indexOf(';', index); + params.add(methodDesc.substring(index + 1, end_index)); + index = end_index + 1; + break; + } + default: + throw new RuntimeException("Invalid Char:" + c); } } - return new MethodDesc(methodDesc.substring(index + 1), params.toArray(new String[params.size()])); + return new MethodDesc(methodDesc.substring(index + 1), params.toArray(new String[0])); } public final String returnDesc; diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/AsmUtil.java b/src/main/java/kpan/uti_alsofluids/asm/core/AsmUtil.java index 1a9865c..b308ed1 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/AsmUtil.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/AsmUtil.java @@ -130,8 +130,7 @@ public static String toDesc(Object raw) { @SuppressWarnings("unused") public static MethodVisitor traceMethod(MethodVisitor mv, @Nullable String methodName) { Textifier p = new MyTextifier(methodName); - TraceMethodVisitor tracemv = new TraceMethodVisitor(mv, p); - return tracemv; + return new TraceMethodVisitor(mv, p); } //MethodDescにも使用可能 @@ -154,8 +153,8 @@ public static String[] runtimeExceptions(String[] deobfExceptions) { throw new NotImplementedException("TODO");//TODO } - public static int loadOpcode(String type) { - switch (type) { + public static int toLoadOpcode(String desc) { + switch (desc) { case AsmTypes.BOOL: case AsmTypes.CHAR: case AsmTypes.BYTE: @@ -172,8 +171,19 @@ public static int loadOpcode(String type) { return Opcodes.ALOAD; } } + public static int loadLocals(MethodVisitor mv, String[] descs, int offset) { + for (String desc : descs) { + int opcode = AsmUtil.toLoadOpcode(desc); + mv.visitVarInsn(opcode, offset); + if (opcode == Opcodes.LLOAD || opcode == Opcodes.DOUBLE) + offset += 2; + else + offset += 1; + } + return offset; + } - public static int returnOpcode(String type) { + public static int toReturnOpcode(String type) { switch (type) { case AsmTypes.VOID: return Opcodes.RETURN; diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/MyAsmNameRemapper.java b/src/main/java/kpan/uti_alsofluids/asm/core/MyAsmNameRemapper.java index 7da171c..c5865b3 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/MyAsmNameRemapper.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/MyAsmNameRemapper.java @@ -12,14 +12,12 @@ import net.minecraftforge.fml.common.FMLLog; import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; import net.minecraftforge.fml.common.patcher.ClassPatchManager; +import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.objectweb.asm.ClassReader; import javax.annotation.Nullable; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -29,13 +27,9 @@ public class MyAsmNameRemapper { private static LaunchClassLoader classLoader; - private static Map> fieldSrgMcpMap = Maps.newHashMap(); - private static Map> methodSrgMcpMap = Maps.newHashMap(); - private static Map> rawFieldSrgMcpMap = Maps.newHashMap(); - private static Map> rawMethodSrgMcpMap = Maps.newHashMap(); - private static Map> fieldObfSrgMap = Maps.newHashMap(); - private static Map> methodObfSrgMap = Maps.newHashMap(); - private static Set srgMcpLoadedSet = Sets.newHashSet(); + private static final Map> fieldObfSrgMap = Maps.newHashMap(); + private static final Map> methodObfSrgMap = Maps.newHashMap(); + private static final Set srgMcpLoadedSet = Sets.newHashSet(); //FMLDeobfuscatingRemapper private static Map> rawFieldMaps; @@ -45,90 +39,35 @@ public static void init() { if (classLoader == null) { classLoader = MyReflectionHelper.getPrivateField(FMLDeobfuscatingRemapper.INSTANCE, "classLoader"); loadDeobfMap(); - //loadMcpMap(); - LogManager.getLogger().info("Srg Rename Mapping Loaded Completely"); + LogManager.getLogger().info("Obf Rename Mapping Loaded Completely"); } } private static void loadDeobfMap() { rawFieldMaps = MyReflectionHelper.getPrivateField(FMLDeobfuscatingRemapper.INSTANCE, "rawFieldMaps"); rawMethodMaps = MyReflectionHelper.getPrivateField(FMLDeobfuscatingRemapper.INSTANCE, "rawMethodMaps"); } - private static void loadMcpMap() throws IOException { - InputStream stream = MyAsmNameRemapper.class.getResourceAsStream("/nameremapper/output.srg"); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {//readerがcloseされれば全部closeされる(はず) - String line; - while ((line = reader.readLine()) != null) { - String[] split = line.split(" "); - switch (split[0]) { - case "CL:": - //CL: deobfName deobfName - break; - case "FD:": { - //FD: srgFullName mcpFullName - int srg_name_idx = split[1].lastIndexOf('/') + 1; - String srg_class = split[1].substring(0, srg_name_idx - 1); - String srg_name = split[1].substring(srg_name_idx); - int mcp_name_idx = split[2].lastIndexOf('/') + 1; - String mcp_class = split[2].substring(0, mcp_name_idx - 1); - String mcp_name = split[2].substring(mcp_name_idx); - if (!srg_class.equals(mcp_class)) { - System.out.println("not same class?"); - System.out.println(srg_class + "," + mcp_class); - } - if (!rawFieldSrgMcpMap.containsKey(srg_class)) - rawFieldSrgMcpMap.put(srg_class, HashBiMap.create()); - rawFieldSrgMcpMap.get(srg_class).put(srg_name, mcp_name); - break; - } - case "MD:": { - //MD: srgFullName desc mcpFullName desc - int srg_name_idx = split[1].lastIndexOf('/') + 1; - String srg_class = split[1].substring(0, srg_name_idx - 1); - String srg_name = split[1].substring(srg_name_idx); - String srg_desc = split[2]; - int mcp_name_idx = split[3].lastIndexOf('/') + 1; - String mcp_class = split[3].substring(0, mcp_name_idx - 1); - String mcp_name = split[3].substring(mcp_name_idx); - String mcp_desc = split[4]; - if (!srg_class.equals(mcp_class)) { - System.out.println("not same class?"); - System.out.println(srg_class + "," + mcp_class); - } - if (!srg_desc.equals(mcp_desc)) { - System.out.println("not same desc?"); - System.out.println(srg_desc + "," + mcp_desc); - } - if (!rawMethodSrgMcpMap.containsKey(srg_class)) - rawMethodSrgMcpMap.put(srg_class, HashBiMap.create()); - rawMethodSrgMcpMap.get(srg_class).put(new NameDescPair(srg_name, srg_desc), new NameDescPair(mcp_name, mcp_desc)); - break; - } - } - } - } - } public static String runtimeClass(String deobfName) { if (AsmUtil.isDeobfEnvironment()) return deobfName.replace('.', '/'); else - return getClassDeobfName(deobfName); + return getClassObfName(deobfName); } public static String runtimeField(FieldRemap fieldRemap) { if (AsmUtil.isDeobfEnvironment()) return fieldRemap.mcpFieldName; - String obf_owner = getClassDeobfName(fieldRemap.deobfOwner); - String srg_name = mcp2SrgFieldName(obf_owner, fieldRemap.mcpFieldName); - return obf2SrgFieldName(obf_owner, srg_name); + String obf_owner = getClassObfName(fieldRemap.deobfOwner); + String srg_name = fieldRemap.srgFieldName; + return srg2ObfFieldName(obf_owner, srg_name); } public static String runtimeMethod(MethodRemap methodRemap) { if (AsmUtil.isDeobfEnvironment()) return methodRemap.mcpMethodName; - String obf_owner = getClassDeobfName(methodRemap.deobfOwner); - String srg_name = mcp2SrgMethodName(obf_owner, methodRemap.mcpMethodName, methodRemap.deobfMethodDesc); - return obf2SrgMethodName(obf_owner, srg_name, AsmUtil.obfDesc(methodRemap.deobfMethodDesc)); + String obf_owner = getClassObfName(methodRemap.deobfOwner); + String srg_name = methodRemap.srgMethodName; + return srg2ObfMethodName(obf_owner, srg_name, AsmUtil.obfDesc(methodRemap.deobfMethodDesc)); } public static String getClassDeobfName(String obfName) { @@ -140,12 +79,6 @@ public static String getClassObfName(String deobfName) { return FMLDeobfuscatingRemapper.INSTANCE.unmap(deobfName); } - public static String tryGetFieldDeobfName(String owner, String obfName) { - String obf_owner = getClassObfName(owner); - String srg_name = obf2SrgFieldName(obf_owner, obfName); - return srg2McpFieldName(obf_owner, srg_name); - } - public static String obf2SrgMethodName(String obfOwner, String obfName, String obfDesc) { BiMap map = getMethodObf2SrgMap(obfOwner); if (map == null) @@ -183,43 +116,6 @@ public static String srg2ObfFieldName(String obfOwner, String srgName) { return obf_name; } - public static String srg2McpMethodName(String obfOwner, String srgName, String deobfDesc) { - BiMap map = getMethodSrg2McpMap(obfOwner); - if (map == null) - return srgName; - NameDescPair mcp_pair = map.get(new NameDescPair(srgName, deobfDesc)); - if (mcp_pair == null) - return srgName; - return mcp_pair.name; - } - public static String mcp2SrgMethodName(String obfOwner, String mcpName, String deobfDesc) { - BiMap map = getMethodSrg2McpMap(obfOwner); - if (map == null) - return mcpName; - NameDescPair srg_pair = map.inverse().get(new NameDescPair(mcpName, deobfDesc)); - if (srg_pair == null) - return mcpName; - return srg_pair.name; - } - public static String srg2McpFieldName(String obfOwner, String srgName) { - BiMap map = getFieldSrg2McpMap(obfOwner); - if (map == null) - return srgName; - String mcp_name = map.get(srgName); - if (mcp_name == null) - return srgName; - return mcp_name; - } - public static String mcp2SrgFieldName(String obfOwner, String mcpName) { - BiMap map = getFieldSrg2McpMap(obfOwner); - if (map == null) - return mcpName; - String srg_name = map.inverse().get(mcpName); - if (srg_name == null) - return mcpName; - return srg_name; - } - private static @Nullable BiMap getMethodObf2SrgMap(String obfOwner) { if (!srgMcpLoadedSet.contains(obfOwner)) { findAndMergeSuperMaps(obfOwner); @@ -232,20 +128,6 @@ public static String mcp2SrgFieldName(String obfOwner, String mcpName) { } return fieldObfSrgMap.get(obfOwner); } - public static @Nullable BiMap getMethodSrg2McpMap(String obfOwner) { - String deobf = getClassDeobfName(obfOwner); - if (!srgMcpLoadedSet.contains(obfOwner)) { - findAndMergeSuperMaps(obfOwner); - } - return methodSrgMcpMap.get(deobf); - } - private static @Nullable BiMap getFieldSrg2McpMap(String obfOwner) { - String deobf = getClassDeobfName(obfOwner); - if (!srgMcpLoadedSet.contains(obfOwner)) { - findAndMergeSuperMaps(obfOwner); - } - return fieldSrgMcpMap.get(deobf); - } private static void findAndMergeSuperMaps(String obfName) { try { String superName = null; @@ -271,14 +153,12 @@ private static void mergeSuperMaps(String obfName, @Nullable String superName, S List allParents = ImmutableList.builder().add(superName).addAll(Arrays.asList(interfaces)).build(); // generate maps for all parent objects for (String parentThing : allParents) { - if (!fieldSrgMcpMap.containsKey(parentThing)) { + if (!fieldObfSrgMap.containsKey(parentThing)) { findAndMergeSuperMaps(parentThing); } } BiMap method_obfsrg_map = HashBiMap.create(); - BiMap method_srgmcp_map = HashBiMap.create(); BiMap field_obfsrg_map = HashBiMap.create(); - BiMap field_srgmcp_map = HashBiMap.create(); for (String parentThing : allParents) { String deobf_parent = getClassDeobfName(parentThing); if (methodObfSrgMap.containsKey(parentThing)) { @@ -288,12 +168,6 @@ private static void mergeSuperMaps(String obfName, @Nullable String superName, S field_obfsrg_map.putAll(fieldObfSrgMap.get(parentThing)); } - if (methodSrgMcpMap.containsKey(deobf_parent)) { - method_srgmcp_map.putAll(methodSrgMcpMap.get(deobf_parent)); - } - if (fieldSrgMcpMap.containsKey(deobf_parent)) { - field_srgmcp_map.putAll(fieldSrgMcpMap.get(deobf_parent)); - } } if (rawMethodMaps.containsKey(obfName)) { for (Entry entry : rawMethodMaps.get(obfName).entrySet()) { @@ -312,23 +186,10 @@ private static void mergeSuperMaps(String obfName, @Nullable String superName, S } } - if (rawMethodSrgMcpMap.containsKey(deobf)) { - for (Entry entry : rawMethodSrgMcpMap.get(deobf).entrySet()) { - method_srgmcp_map.forcePut(entry.getKey(), entry.getValue()); - } - } - if (rawFieldSrgMcpMap.containsKey(deobf)) { - for (Entry entry : rawFieldSrgMcpMap.get(deobf).entrySet()) { - field_srgmcp_map.forcePut(entry.getKey(), entry.getValue()); - } - } methodObfSrgMap.put(obfName, ImmutableBiMap.copyOf(method_obfsrg_map)); fieldObfSrgMap.put(obfName, ImmutableBiMap.copyOf(field_obfsrg_map)); - methodSrgMcpMap.put(deobf, ImmutableBiMap.copyOf(method_srgmcp_map)); - fieldSrgMcpMap.put(deobf, ImmutableBiMap.copyOf(field_srgmcp_map)); - - LogManager.getLogger().debug("map : " + deobf + " count : " + method_obfsrg_map.size() + "," + method_srgmcp_map.size() + "," + field_obfsrg_map.size() + "," + field_srgmcp_map.size()); + LogManager.getLogger().debug("map : " + deobf + " count : " + method_obfsrg_map.size() + "," + field_obfsrg_map.size()); } public static class NameDescPair { @@ -364,19 +225,20 @@ public static class FieldRemap { public final String deobfOwner; public final String mcpFieldName; public final String deobfDesc; + public final String srgFieldName; - public FieldRemap(String deobfOwner, String mcpFieldName, String deobfDesc) { + public FieldRemap(String deobfOwner, String mcpFieldName, String deobfDesc, @Nullable String srgFieldName) { this.deobfOwner = deobfOwner.replace('.', '/'); this.mcpFieldName = mcpFieldName; - this.deobfDesc = deobfDesc; + this.deobfDesc = AsmUtil.toDesc(deobfDesc); + this.srgFieldName = StringUtils.isEmpty(srgFieldName) ? mcpFieldName : srgFieldName; } public Object[] toRuntime() { if (AsmUtil.isDeobfEnvironment()) return new Object[]{deobfOwner, mcpFieldName, deobfDesc}; String obf_owner = getClassObfName(deobfOwner); - String srg_name = mcp2SrgFieldName(obf_owner, mcpFieldName); - String obf_name = srg2ObfFieldName(obf_owner, srg_name); + String obf_name = srg2ObfFieldName(obf_owner, srgFieldName); return new Object[]{obf_owner, obf_name, AsmUtil.obfDesc(deobfDesc)}; } @@ -386,11 +248,13 @@ public static class MethodRemap { public final String deobfOwner; public final String mcpMethodName; public final String deobfMethodDesc; + public final String srgMethodName; - public MethodRemap(String deobfOwner, String mcpMethodName, String deobfMethodDesc) { + public MethodRemap(String deobfOwner, String mcpMethodName, String deobfMethodDesc, @Nullable String srgMethodName) { this.deobfOwner = deobfOwner.replace('.', '/'); this.mcpMethodName = mcpMethodName; this.deobfMethodDesc = deobfMethodDesc; + this.srgMethodName = StringUtils.isEmpty(srgMethodName) ? mcpMethodName : srgMethodName; } public boolean isTarget(String runtimeName, String runtimeDesc) { @@ -399,8 +263,7 @@ public boolean isTarget(String runtimeName, String runtimeDesc) { } else { String obf_owner = getClassObfName(deobfOwner); String obf_methoddesc = AsmUtil.obfDesc(deobfMethodDesc); - String srg_name = mcp2SrgMethodName(obf_owner, mcpMethodName, deobfMethodDesc); - String obf_name = srg2ObfMethodName(obf_owner, srg_name, obf_methoddesc); + String obf_name = srg2ObfMethodName(obf_owner, srgMethodName, obf_methoddesc); return runtimeName.equals(obf_name) && runtimeDesc.equals(obf_methoddesc); } } @@ -411,8 +274,7 @@ public Object[] toRuntime() { } else { String obf_owner = getClassObfName(deobfOwner); String obf_methoddesc = AsmUtil.obfDesc(deobfMethodDesc); - String srg_name = mcp2SrgMethodName(obf_owner, mcpMethodName, deobfMethodDesc); - String obf_name = srg2ObfMethodName(obf_owner, srg_name, obf_methoddesc); + String obf_name = srg2ObfMethodName(obf_owner, srgMethodName, obf_methoddesc); return new Object[]{obf_owner, obf_name, obf_methoddesc}; } } diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/MyTextifier.java b/src/main/java/kpan/uti_alsofluids/asm/core/MyTextifier.java index e7446e7..2afd060 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/MyTextifier.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/MyTextifier.java @@ -1,13 +1,12 @@ package kpan.uti_alsofluids.asm.core; -import javax.annotation.Nullable; - import org.objectweb.asm.util.Textifier; +import javax.annotation.Nullable; + public class MyTextifier extends Textifier { private final @Nullable String methodName; - public MyTextifier() { this(null); } public MyTextifier(@Nullable String methodName) { super(AsmUtil.ASM_VER);//引数アリじゃないとException投げる this.methodName = methodName; @@ -24,7 +23,7 @@ public void visitFieldInsn(int opcode, String owner, String name, String desc) { buf.append("//"); buf.append(MyAsmNameRemapper.getClassDeobfName(owner)); buf.append('.'); - buf.append(MyAsmNameRemapper.tryGetFieldDeobfName(owner, name)); + buf.append(MyAsmNameRemapper.obf2SrgFieldName(owner, name)); buf.append(' '); buf.append(AsmUtil.deobfDesc(desc)); } diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddFieldAccessorAdapter.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddFieldAccessorAdapter.java deleted file mode 100644 index 9b6b8e4..0000000 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddFieldAccessorAdapter.java +++ /dev/null @@ -1,100 +0,0 @@ -package kpan.uti_alsofluids.asm.core.adapters; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -import kpan.uti_alsofluids.asm.core.AsmTypes; -import kpan.uti_alsofluids.asm.core.AsmUtil; -import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper; -import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper.FieldRemap; - -public class AddFieldAccessorAdapter extends MyClassVisitor { - - protected final String runtimeInstanceClassName; - protected final String fieldNameForAccessorName; - protected final String runtimeFieldName; - protected final String runtimeDesc; - private String runtimeGenerics; - private boolean found = false; - - public AddFieldAccessorAdapter(ClassVisitor cv, String accessorClassName, FieldRemap field) { - super(cv, accessorClassName); - runtimeInstanceClassName = MyAsmNameRemapper.runtimeClass(field.deobfOwner); - fieldNameForAccessorName = field.mcpFieldName; - runtimeFieldName = MyAsmNameRemapper.runtimeField(field); - runtimeDesc = AsmUtil.runtimeDesc(field.deobfDesc); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - if (name.equals("get_" + fieldNameForAccessorName) || name.equals("set_" + fieldNameForAccessorName)) { - if (access != (Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC)) - throw new RuntimeException("Invalid access value:" + name); - runtimeGenerics = signature; - found = true; - return null;//既存のを削除、visitEndで追加 - } else - return super.visitMethod(access, name, desc, signature, exceptions); - } - - @Override - public void visitEnd() { - if (found) { - String signature = runtimeGenerics; - MethodVisitor get_mv = super.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "get_" + fieldNameForAccessorName, AsmUtil.toMethodDesc(runtimeDesc, runtimeInstanceClassName), signature, - null); - if (get_mv != null) { - get_mv.visitCode(); - get_mv.visitVarInsn(Opcodes.ALOAD, 0); - get_mv.visitFieldInsn(Opcodes.GETFIELD, runtimeInstanceClassName, runtimeFieldName, runtimeDesc); - get_mv.visitInsn(returnOpcode(runtimeDesc)); - get_mv.visitMaxs(0, 0);//引数は無視され、再計算される(Write時に再計算されるのでtrace時点では0,0のまま) - get_mv.visitEnd(); - } - MethodVisitor set_mv = super.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "set_" + fieldNameForAccessorName, - AsmUtil.toMethodDesc(AsmTypes.VOID, runtimeInstanceClassName, runtimeDesc), - signature, - null); - if (set_mv != null) { - set_mv.visitCode(); - set_mv.visitVarInsn(Opcodes.ALOAD, 0); - set_mv.visitVarInsn(loadOpcode(runtimeDesc), 1); - set_mv.visitFieldInsn(Opcodes.PUTFIELD, runtimeInstanceClassName, runtimeFieldName, runtimeDesc); - set_mv.visitInsn(Opcodes.RETURN); - set_mv.visitMaxs(0, 0);//引数は無視され、再計算される(Write時に再計算されるのでtrace時点では0,0のまま) - set_mv.visitEnd(); - } - success(); - } - super.visitEnd(); - } - - protected int loadOpcode(String type) { - if (type.equals(AsmTypes.BOOL) || type.equals(AsmTypes.CHAR) || type.equals(AsmTypes.BYTE) || type.equals(AsmTypes.SHORT) || type.equals(AsmTypes.INT)) - return Opcodes.ILOAD; - else if (type.equals(AsmTypes.LONG)) - return Opcodes.LLOAD; - else if (type.equals(AsmTypes.FLOAT)) - return Opcodes.FLOAD; - else if (type.equals(AsmTypes.DOUBLE)) - return Opcodes.DLOAD; - else - return Opcodes.ALOAD; - } - - protected static int returnOpcode(String type) { - if (type.equals(AsmTypes.VOID)) - return Opcodes.RETURN; - else if (type.equals(AsmTypes.BOOL) || type.equals(AsmTypes.CHAR) || type.equals(AsmTypes.BYTE) || type.equals(AsmTypes.SHORT) || type.equals(AsmTypes.INT)) - return Opcodes.IRETURN; - else if (type.equals(AsmTypes.LONG)) - return Opcodes.LRETURN; - else if (type.equals(AsmTypes.FLOAT)) - return Opcodes.FRETURN; - else if (type.equals(AsmTypes.DOUBLE)) - return Opcodes.DRETURN; - else - return Opcodes.ARETURN; - } -} diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddFieldAdapter.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddFieldAdapter.java deleted file mode 100644 index 43132f3..0000000 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddFieldAdapter.java +++ /dev/null @@ -1,46 +0,0 @@ -package kpan.uti_alsofluids.asm.core.adapters; - -import javax.annotation.Nullable; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.Opcodes; - -import kpan.uti_alsofluids.asm.core.AsmUtil; - -public class AddFieldAdapter extends MyClassVisitor { - - protected final int access; - protected final String runtimeName; - protected final String runtimeDesc; - @Nullable protected final String runtimeGenerics; - @Nullable protected final Object initValue; - - public AddFieldAdapter(ClassVisitor cv, String runtimeName, String deobfDesc) { - this(cv, Opcodes.ACC_PUBLIC, runtimeName, deobfDesc, null, null); - } - public AddFieldAdapter(ClassVisitor cv, int access, String runtimeName, String deobfDesc) { - this(cv, access, runtimeName, deobfDesc, null, null); - } - public AddFieldAdapter(ClassVisitor cv, int access, String runtimeName, String deobfDesc, Object initValue) { - this(cv, access, runtimeName, deobfDesc, null, initValue); - } - public AddFieldAdapter(ClassVisitor cv, int access, String runtimeName, String deobfDesc, @Nullable String deobfGenerics, @Nullable Object initValue) { - super(cv, runtimeName + " " + deobfDesc); - this.access = access; - this.runtimeName = runtimeName; - runtimeDesc = AsmUtil.runtimeDesc(deobfDesc); - runtimeGenerics = AsmUtil.runtimeDesc(deobfGenerics); - this.initValue = initValue; - } - - @Override - public void visitEnd() { - FieldVisitor fv = visitField(access, runtimeName, runtimeDesc, runtimeGenerics, initValue); - if (fv != null) - fv.visitEnd(); - success(); - super.visitEnd(); - } - -} diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddMethodAdapter.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddMethodAdapter.java deleted file mode 100644 index 3c5bb8b..0000000 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddMethodAdapter.java +++ /dev/null @@ -1,44 +0,0 @@ -package kpan.uti_alsofluids.asm.core.adapters; - -import javax.annotation.Nullable; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; - -public abstract class AddMethodAdapter extends MyClassVisitor { - - protected final int access; - protected final String runtimeName; - protected final String runtimeDesc; - @Nullable protected final String runtimeGenerics; - @Nullable protected final String[] runtimeExceptions; - - public AddMethodAdapter(ClassVisitor cv, int access, String runtimeName, String runtimeDesc) { - this(cv, access, runtimeName, runtimeDesc, null, null); - } - public AddMethodAdapter(ClassVisitor cv, int access, String runtimeName, String runtimeDesc, @Nullable String runtimeGenerics, @Nullable String[] runtimeExceptions) { - super(cv, runtimeName + " " + runtimeDesc); - this.access = access; - this.runtimeName = runtimeName; - this.runtimeDesc = runtimeDesc; - this.runtimeGenerics = runtimeGenerics; - this.runtimeExceptions = runtimeExceptions; - } - - @Override - public void visitEnd() { - - MethodVisitor mv = visitMethod(access, runtimeName, runtimeDesc, runtimeGenerics, runtimeExceptions); - if (mv != null) { - mv.visitCode(); - methodBody(mv); - mv.visitMaxs(0, 0);//引数は無視され、再計算される(Write時に再計算されるのでtrace時点では0,0のまま) - mv.visitEnd(); - success(); - } - - super.visitEnd(); - } - - protected abstract void methodBody(MethodVisitor mv); -} diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddRefMethodAdapter.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddRefMethodAdapter.java deleted file mode 100644 index 93fd050..0000000 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/AddRefMethodAdapter.java +++ /dev/null @@ -1,71 +0,0 @@ -package kpan.uti_alsofluids.asm.core.adapters; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -import kpan.uti_alsofluids.asm.core.AsmTypes; -import kpan.uti_alsofluids.asm.core.AsmTypes.MethodDesc; -import kpan.uti_alsofluids.asm.core.AsmUtil; -import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper; -import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper.MethodRemap; - -public class AddRefMethodAdapter extends AddMethodAdapter { - - private final String runtimeTarget; - private final String refMethodName; - private final String runtimeRefMethodOwner; - private final String runtimeReturnType; - private final String[] runtimeParams; - - public AddRefMethodAdapter(ClassVisitor cv, String runtimeRefMethodOwner, int access, MethodRemap method) { - super(cv, access, MyAsmNameRemapper.runtimeMethod(method), AsmUtil.runtimeDesc(method.deobfMethodDesc)); - refMethodName = method.mcpMethodName; - runtimeTarget = MyAsmNameRemapper.runtimeClass(method.deobfOwner); - this.runtimeRefMethodOwner = runtimeRefMethodOwner; - MethodDesc md = MethodDesc.fromMethodDesc(AsmUtil.runtimeDesc(method.deobfMethodDesc)); - runtimeReturnType = md.returnDesc; - runtimeParams = md.paramsDesc; - } - - @Override - protected void methodBody(MethodVisitor mv) { - - //java7との互換性のため、文字列switchを使用していない - //this - mv.visitVarInsn(Opcodes.ALOAD, 0); - //params - for (int i = 0; i < runtimeParams.length; i++) { - if (runtimeParams[i].equals(AsmTypes.BOOL) || runtimeParams[i].equals(AsmTypes.CHAR) || runtimeParams[i].equals(AsmTypes.BYTE) || runtimeParams[i].equals(AsmTypes.SHORT) - || runtimeParams[i].equals(AsmTypes.INT)) - mv.visitVarInsn(Opcodes.ILOAD, i + 1); - else if (runtimeParams[i].equals(AsmTypes.LONG)) - mv.visitVarInsn(Opcodes.LLOAD, i + 1); - else if (runtimeParams[i].equals(AsmTypes.FLOAT)) - mv.visitVarInsn(Opcodes.FLOAD, i + 1); - else if (runtimeParams[i].equals(AsmTypes.DOUBLE)) - mv.visitVarInsn(Opcodes.DLOAD, i + 1); - else - mv.visitVarInsn(Opcodes.ALOAD, i + 1); - } - - //invoke - mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeRefMethodOwner, refMethodName, AsmUtil.toMethodDesc(runtimeReturnType, runtimeTarget, runtimeParams), false); - - //return - if (runtimeReturnType.equals(AsmTypes.VOID)) - mv.visitInsn(Opcodes.RETURN); - else if (runtimeReturnType.equals(AsmTypes.BOOL) || runtimeReturnType.equals(AsmTypes.CHAR) || runtimeReturnType.equals(AsmTypes.BYTE) || runtimeReturnType.equals(AsmTypes.SHORT) - || runtimeReturnType.equals(AsmTypes.INT)) - mv.visitInsn(Opcodes.IRETURN); - else if (runtimeReturnType.equals(AsmTypes.LONG)) - mv.visitInsn(Opcodes.LRETURN); - else if (runtimeReturnType.equals(AsmTypes.FLOAT)) - mv.visitInsn(Opcodes.FRETURN); - else if (runtimeReturnType.equals(AsmTypes.DOUBLE)) - mv.visitInsn(Opcodes.DRETURN); - else - mv.visitInsn(Opcodes.ARETURN); - } - -} diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/FieldPublicAdapter.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/FieldPublicAdapter.java deleted file mode 100644 index f5dec6f..0000000 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/FieldPublicAdapter.java +++ /dev/null @@ -1,29 +0,0 @@ -package kpan.uti_alsofluids.asm.core.adapters; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.Opcodes; - -import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper; -import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper.FieldRemap; - -public class FieldPublicAdapter extends MyClassVisitor { - - protected final String runtimeName; - - public FieldPublicAdapter(ClassVisitor cv, FieldRemap field) { - super(cv, field.deobfOwner); - runtimeName = MyAsmNameRemapper.runtimeField(field); - } - - @Override - public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { - if (name.equals(runtimeName)) { - access &= ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED); - access |= Opcodes.ACC_PUBLIC; - success(); - } - return super.visitField(access, name, desc, signature, value); - } - -} diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/InjectInstructionsAdapter.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/InjectInstructionsAdapter.java index 0220388..f1f801a 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/InjectInstructionsAdapter.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/InjectInstructionsAdapter.java @@ -1,8 +1,8 @@ package kpan.uti_alsofluids.asm.core.adapters; -import org.objectweb.asm.MethodVisitor; - import kpan.uti_alsofluids.asm.core.adapters.Instructions.Instr; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; public class InjectInstructionsAdapter extends ReplaceInstructionsAdapter { @@ -34,6 +34,18 @@ public static InjectInstructionsAdapter after(MethodVisitor mv, String name, Ins return new InjectInstructionsAdapter(mv, name, targets, instructions, -1); } + public static ReplaceInstructionsAdapter beforeAfter(MethodVisitor mv, String name, Instructions targets, Instructions before, Instructions after) { + return new InjectInstructionsAdapter(mv, name, targets, before, 0) { + @Override + protected void visitAllInstructions() { + super.visitAllInstructions(); + for (Instr instruction : after) { + instruction.visit(mv, this); + } + + } + }; + } public static MethodVisitor injectFirst(MethodVisitor mv, String nameForDebug, final Instructions instructions) { return new MyMethodVisitor(mv, nameForDebug) { @Override @@ -46,16 +58,25 @@ public void visitCode() { } }; } - @Deprecated - public static MethodVisitor injectLast(MethodVisitor mv, String nameForDebug, final Instructions instructions) { + public static MethodVisitor injectBeforeReturns(MethodVisitor mv, String nameForDebug, final Instructions instructions) { return new MyMethodVisitor(mv, nameForDebug) { + @Override + public void visitInsn(int opcode) { + if (opcode == Opcodes.IRETURN || opcode == Opcodes.LRETURN || opcode == Opcodes.FRETURN || opcode == Opcodes.DRETURN || opcode == Opcodes.ARETURN || opcode == Opcodes.RETURN) { + for (Instr instruction : instructions) { + instruction.visit(mv, this); + } + success(); + } + super.visitInsn(opcode); + } + @Override public void visitEnd() { - for (Instr instruction : instructions) { - instruction.visit(mv, this); + //RETURN�����‚����Ă��ǂ��̂ŃV���[�g�J�b�g + if (mv != null) { + mv.visitEnd(); } - success(); - super.visitEnd(); } }; } diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/Instructions.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/Instructions.java index e1036c4..bb6a64b 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/Instructions.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/Instructions.java @@ -1,31 +1,29 @@ package kpan.uti_alsofluids.asm.core.adapters; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -import javax.annotation.Nullable; - -import org.apache.commons.lang3.StringUtils; -import org.objectweb.asm.Handle; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - import com.google.common.collect.Lists; - import kpan.uti_alsofluids.asm.core.AsmUtil; import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper; import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper.FieldRemap; import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper.MethodRemap; import kpan.uti_alsofluids.asm.core.adapters.Instructions.Instr; +import org.apache.commons.lang3.StringUtils; +import org.objectweb.asm.Handle; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Objects; public class Instructions implements List { private final List instructions; - public Instructions() { this(Lists. newArrayList()); } + public Instructions() { this(Lists.newArrayList()); } public Instructions(List instructions) { this.instructions = instructions; } public Instructions addInstr(Instr instr) { @@ -115,39 +113,45 @@ public Instructions varInsn(OpcodeVar opcode, int varIndex) { public Instructions fload(int varIndex) { return varInsn(OpcodeVar.FLOAD, varIndex); } public Instructions dload(int varIndex) { return varInsn(OpcodeVar.DLOAD, varIndex); } public Instructions aload(int varIndex) { return varInsn(OpcodeVar.ALOAD, varIndex); } + public Instructions istore(int varIndex) { return varInsn(OpcodeVar.ISTORE, varIndex); } + public Instructions lstore(int varIndex) { return varInsn(OpcodeVar.LSTORE, varIndex); } + public Instructions fstore(int varIndex) { return varInsn(OpcodeVar.FSTORE, varIndex); } + public Instructions dstore(int varIndex) { return varInsn(OpcodeVar.DSTORE, varIndex); } + public Instructions astore(int varIndex) { return varInsn(OpcodeVar.ASTORE, varIndex); } + public Instructions rep() { return addInstr(Instr.REP); } public static Instructions create(Instr... instructions) { return new Instructions(Lists.newArrayList(instructions)); } public static class Instr { - public static final Instr REP = new Instr(0, null, new Object[0]) { + public static final Instr REP = new Instr(0, null) { @Override - public void visit(MethodVisitor mv, MyMethodVisitor adapter) {} + public void visit(MethodVisitor mv, MyMethodVisitor adapter) { } @Override protected boolean isRep() { return true; } @Override protected boolean repEquals(Instr other) { return true; } }; - private static final Instr LDC_REP = new Instr(0, VisitType.LDC, new Object[0]) { + private static final Instr LDC_REP = new Instr(0, VisitType.LDC) { @Override - public void visit(MethodVisitor mv, MyMethodVisitor adapter) {} + public void visit(MethodVisitor mv, MyMethodVisitor adapter) { } @Override protected boolean isRep() { return true; } @Override protected boolean repEquals(Instr other) { return other.type == VisitType.LDC; } }; - private static final Instr LABEL_REP = new Instr(0, VisitType.LABEL, new Object[0]) { + private static final Instr LABEL_REP = new Instr(0, VisitType.LABEL) { @Override - public void visit(MethodVisitor mv, MyMethodVisitor adapter) {} + public void visit(MethodVisitor mv, MyMethodVisitor adapter) { } @Override protected boolean isRep() { return true; } @Override protected boolean repEquals(Instr other) { return other.type == VisitType.LABEL; } }; - private static final Instr JUMP_REP = new Instr(0, VisitType.JUMP, new Object[0]) { + private static final Instr JUMP_REP = new Instr(0, VisitType.JUMP) { @Override - public void visit(MethodVisitor mv, MyMethodVisitor adapter) {} + public void visit(MethodVisitor mv, MyMethodVisitor adapter) { } @Override protected boolean isRep() { return true; } @Override @@ -160,14 +164,14 @@ public static class InvokeRep extends Instr { private final String runtimeMethodName; public InvokeRep(OpcodeMethod opcode, String runtimeOwner, String runtimeMethodName) { - super(opcode.opcode, VisitType.METHOD, new Object[0]); + super(opcode.opcode, VisitType.METHOD); this.opcode = opcode; this.runtimeOwner = runtimeOwner.replace('.', '/'); this.runtimeMethodName = runtimeMethodName; } @Override - public void visit(MethodVisitor mv, MyMethodVisitor adapter) {} + public void visit(MethodVisitor mv, MyMethodVisitor adapter) { } @Override protected boolean isRep() { return true; } @Override @@ -178,13 +182,21 @@ protected boolean repEquals(Instr other) { return false; if (!runtimeOwner.equals(other.params[0])) return false; - if (!runtimeMethodName.equals(other.params[1])) - return false; - return true; + return runtimeMethodName.equals(other.params[1]); } - public boolean equals(InvokeRep other) { + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + InvokeRep other = (InvokeRep) o; return opcode == other.opcode && runtimeOwner.equals(other.runtimeOwner) && runtimeMethodName.equals(other.runtimeMethodName); } + @Override + public int hashCode() { + return Objects.hash(opcode, runtimeOwner, runtimeMethodName); + } } public static Instr dynamicInsn(String runtimeName, String runtimeDesc, Handle bsm, Object... bsmArgs) { @@ -281,11 +293,11 @@ public static Instr varInsn(int opcode, int varIndex) { return new Instr(opcode, VisitType.VAR, varIndex); } - private int opcode; - private Object[] params; - private VisitType type; + private final int opcode; + private final Object[] params; + private final VisitType type; - public Instr(int opcode, VisitType type, Object... params) { + Instr(int opcode, VisitType type, Object... params) { this.opcode = opcode; this.type = type; this.params = params; @@ -295,53 +307,53 @@ public void visit(@Nullable MethodVisitor mv, @Nullable MyMethodVisitor adapter) if (mv == null) return; switch (type) { - case DYNAMIC: - mv.visitInvokeDynamicInsn((String) params[0], (String) params[1], (Handle) params[2], (Object[]) params[3]); - break; - case FIELD: - mv.visitFieldInsn(opcode, (String) params[0], (String) params[1], (String) params[2]); - break; - case IINC: - mv.visitIincInsn((Integer) params[0], (Integer) params[1]);//なんかのエラーを防ぐためにintではなくInteger - break; - case INT: - mv.visitIntInsn(opcode, (Integer) params[0]); - break; - case INSN: - mv.visitInsn(opcode); - break; - case JUMP: - if (params[0] instanceof Label) { - mv.visitJumpInsn(opcode, (Label) params[0]); - } else { - if (adapter == null) - throw new IllegalArgumentException("the adapter must not be null to solve the label"); - mv.visitJumpInsn(opcode, adapter.getLabel((Integer) params[0])); - } - break; - case LABEL: - if (params[0] instanceof Label) { - mv.visitLabel((Label) params[0]); - } else { - if (adapter == null) - throw new IllegalArgumentException("the adapter must not be null to solve the label"); - mv.visitLabel(adapter.getLabel((Integer) params[0])); - } - break; - case LDC: - mv.visitLdcInsn(params[0]); - break; - case METHOD: - mv.visitMethodInsn(opcode, (String) params[0], (String) params[1], (String) params[2], (Boolean) params[3]); - break; - case TYPE: - mv.visitTypeInsn(opcode, (String) params[0]); - break; - case VAR: - mv.visitVarInsn(opcode, (Integer) params[0]); - break; - default: - throw new RuntimeException("Invalid Type:" + type); + case DYNAMIC: + mv.visitInvokeDynamicInsn((String) params[0], (String) params[1], (Handle) params[2], (Object[]) params[3]); + break; + case FIELD: + mv.visitFieldInsn(opcode, (String) params[0], (String) params[1], (String) params[2]); + break; + case IINC: + mv.visitIincInsn((Integer) params[0], (Integer) params[1]);//なんかのエラーを防ぐためにintではなくInteger + break; + case INT: + mv.visitIntInsn(opcode, (Integer) params[0]); + break; + case INSN: + mv.visitInsn(opcode); + break; + case JUMP: + if (params[0] instanceof Label) { + mv.visitJumpInsn(opcode, (Label) params[0]); + } else { + if (adapter == null) + throw new IllegalArgumentException("the adapter must not be null to solve the label"); + mv.visitJumpInsn(opcode, adapter.getLabel((Integer) params[0])); + } + break; + case LABEL: + if (params[0] instanceof Label) { + mv.visitLabel((Label) params[0]); + } else { + if (adapter == null) + throw new IllegalArgumentException("the adapter must not be null to solve the label"); + mv.visitLabel(adapter.getLabel((Integer) params[0])); + } + break; + case LDC: + mv.visitLdcInsn(params[0]); + break; + case METHOD: + mv.visitMethodInsn(opcode, (String) params[0], (String) params[1], (String) params[2], (Boolean) params[3]); + break; + case TYPE: + mv.visitTypeInsn(opcode, (String) params[0]); + break; + case VAR: + mv.visitVarInsn(opcode, (Integer) params[0]); + break; + default: + throw new RuntimeException("Invalid Type:" + type); } } @@ -389,13 +401,6 @@ private static boolean equals(Instr a, Instr b) { return false; if (a.opcode != b.opcode) return false; - if (a.type == VisitType.FIELD) { - // System.out.println("A"); - // System.out.println(a.opcode + "\t" + a.params[0] + "." + a.params[1] + "\t" + a.params[2]); - // System.out.println("B"); - // System.out.println(b.opcode + "\t" + b.params[0] + "." + b.params[1] + "\t" + b.params[2]); - // System.out.println("Result:" + Arrays.equals(a.params, b.params)); - } return Arrays.equals(a.params, b.params); } @@ -415,12 +420,10 @@ private enum VisitType { @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(type); - sb.append("("); - sb.append(StringUtils.join(params, ",")); - sb.append(")"); - return sb.toString(); + return type + + "(" + + StringUtils.join(params, ",") + + ")"; } } @@ -439,7 +442,7 @@ public enum OpcodeVar { public final int opcode; - private OpcodeVar(int opcode) { this.opcode = opcode; } + OpcodeVar(int opcode) { this.opcode = opcode; } } public enum OpcodeField { @@ -451,7 +454,7 @@ public enum OpcodeField { public final int opcode; - private OpcodeField(int opcode) { this.opcode = opcode; } + OpcodeField(int opcode) { this.opcode = opcode; } } public enum OpcodeMethod { @@ -463,7 +466,7 @@ public enum OpcodeMethod { public final int opcode; - private OpcodeMethod(int opcode) { this.opcode = opcode; } + OpcodeMethod(int opcode) { this.opcode = opcode; } } public enum OpcodeInt { @@ -474,7 +477,7 @@ public enum OpcodeInt { public final int opcode; - private OpcodeInt(int opcode) { this.opcode = opcode; } + OpcodeInt(int opcode) { this.opcode = opcode; } } public enum OpcodeJump { @@ -500,7 +503,7 @@ public enum OpcodeJump { public final int opcode; - private OpcodeJump(int opcode) { this.opcode = opcode; } + OpcodeJump(int opcode) { this.opcode = opcode; } } //Listインターフェース diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/MixinAccessorAdapter.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/MixinAccessorAdapter.java new file mode 100644 index 0000000..8d7b8eb --- /dev/null +++ b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/MixinAccessorAdapter.java @@ -0,0 +1,397 @@ +package kpan.uti_alsofluids.asm.core.adapters; + +import kpan.uti_alsofluids.ModReference; +import kpan.uti_alsofluids.asm.core.AccessTransformerForMixin; +import kpan.uti_alsofluids.asm.core.AsmTypes; +import kpan.uti_alsofluids.asm.core.AsmTypes.MethodDesc; +import kpan.uti_alsofluids.asm.core.AsmUtil; +import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper; +import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper.FieldRemap; +import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper.MethodRemap; +import org.apache.commons.lang3.ArrayUtils; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Handle; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.TypePath; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; + +public class MixinAccessorAdapter extends MyClassVisitor { + + private final String deobfTargetClassName; + private final Class accessor; + private final HashMap fieldInfoMap = new HashMap<>(); + private final HashMap methodInfoMap = new HashMap<>(); + public MixinAccessorAdapter(ClassVisitor cv, String deobfTargetClassName, String accessorClassName) { + super(cv, deobfTargetClassName); + this.deobfTargetClassName = deobfTargetClassName; + mixinTarget = deobfTargetClassName; + try { + accessor = Class.forName(accessorClassName.replace('/', '.')); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + mixinTarget = null; + } + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + super.visit(version, access, name, signature, superName, ArrayUtils.add(interfaces, accessor.getName().replace('.', '/'))); + } + + @Override + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { + fieldInfoMap.put(name, new RuntimeInfo(desc, (access & Opcodes.ACC_STATIC) != 0)); + return super.visitField(access, name, desc, signature, value); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + methodInfoMap.put(name, new MethodInfo(desc, (access & Opcodes.ACC_STATIC) != 0, (access & Opcodes.ACC_PRIVATE) != 0)); + return super.visitMethod(access, name, desc, signature, exceptions); + } + + @Override + public void visitEnd() { + for (Method method : accessor.getMethods()) { + String methodName = method.getName(); + if (methodName.startsWith("get_")) { + //getter + String deobf_name = methodName.substring("get_".length()); + Class type = method.getReturnType(); + boolean is_static = Modifier.isStatic(method.getModifiers()); + if (type == void.class) + throw new IllegalStateException("return type of getter is void!:" + methodName); + if (method.getParameterCount() != 0) + throw new IllegalStateException("parameters of getter are empty!:" + methodName); + + String srg_name = method.getAnnotation(SrgName.class) != null ? method.getAnnotation(SrgName.class).value() : deobf_name; + String runtime_name = MyAsmNameRemapper.runtimeField(new FieldRemap(deobfTargetClassName, deobf_name, type.getName(), srg_name)); + String runtime_desc = AsmUtil.runtimeDesc(AsmUtil.toDesc(type)); + if (method.getAnnotation(NewField.class) != null) { + if ((srg_name != null && !deobf_name.equals(srg_name)) || !deobf_name.equals(runtime_name)) + throw new IllegalStateException("Field duplicated!:" + methodName); + if (!fieldInfoMap.containsKey(runtime_name)) { + String runtimeGenerics = null;//TODO + FieldVisitor fv = visitField(Opcodes.ACC_PUBLIC | (is_static ? Opcodes.ACC_STATIC : 0), runtime_name, runtime_desc, runtimeGenerics, null); + if (fv != null) + fv.visitEnd(); + } + } + RuntimeInfo fieldInfo = fieldInfoMap.get(runtime_name); + if (fieldInfo == null) + throw new IllegalStateException("Unknown field:" + runtime_name + "(" + methodName + ")"); + if (!fieldInfo.runtimeDesc.equals(runtime_desc)) + throw new IllegalStateException("Unmatched field type:" + runtime_name + "(" + methodName + ")"); + if (fieldInfo.isStatic != is_static) + throw new IllegalStateException("Unmatched field access(static):" + runtime_name + "(" + methodName + ")"); + + MethodVisitor mv = visitMethod(Opcodes.ACC_PUBLIC | (is_static ? Opcodes.ACC_STATIC : 0), methodName, AsmUtil.toMethodDesc(runtime_desc), null, null); + if (mv != null) { + mv.visitCode(); + if (is_static) { + mv.visitFieldInsn(Opcodes.GETSTATIC, MyAsmNameRemapper.runtimeClass(deobfTargetClassName), runtime_name, runtime_desc); + } else { + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitFieldInsn(Opcodes.GETFIELD, MyAsmNameRemapper.runtimeClass(deobfTargetClassName), runtime_name, runtime_desc); + } + mv.visitInsn(AsmUtil.toReturnOpcode(runtime_desc)); + mv.visitMaxs(0, 0);//引数は無視され、再計算される(Write時に再計算されるのでtrace時点では0,0のまま) + mv.visitEnd(); + } + + } else if (methodName.startsWith("set_")) { + //setter + String deobf_name = methodName.substring("set_".length()); + Class type = method.getParameterTypes()[0]; + boolean is_static = Modifier.isStatic(method.getModifiers()); + if (method.getReturnType() != void.class) + throw new IllegalStateException("return type of getter is not void!:" + methodName); + if (method.getParameterCount() != 1) + throw new IllegalStateException("parameters num of getter is not 1!:" + methodName); + + String srg_name = method.getAnnotation(SrgName.class) != null ? method.getAnnotation(SrgName.class).value() : null; + String runtime_name = MyAsmNameRemapper.runtimeField(new FieldRemap(deobfTargetClassName, deobf_name, type.getName(), srg_name)); + String runtime_desc = AsmUtil.runtimeDesc(AsmUtil.toDesc(type)); + if (method.getAnnotation(NewField.class) != null) { + if ((srg_name != null && !deobf_name.equals(srg_name)) || !deobf_name.equals(runtime_name)) + throw new IllegalStateException("Field duplicated!:" + methodName); + if (!fieldInfoMap.containsKey(runtime_name)) { + String runtimeGenerics = null;//TODO + FieldVisitor fv = visitField(Opcodes.ACC_PUBLIC | (is_static ? Opcodes.ACC_STATIC : 0), runtime_name, runtime_desc, runtimeGenerics, null); + if (fv != null) + fv.visitEnd(); + } + } + RuntimeInfo fieldInfo = fieldInfoMap.get(runtime_name); + if (fieldInfo == null) + throw new IllegalStateException("Unknown field:" + runtime_name + "(" + methodName + ")"); + if (!fieldInfo.runtimeDesc.equals(runtime_desc)) + throw new IllegalStateException("Unmatched field type:" + runtime_name + "(" + methodName + ")"); + if (fieldInfo.isStatic != is_static) + throw new IllegalStateException("Unmatched field access(static):" + runtime_name + "(" + methodName + ")"); + + MethodVisitor mv = visitMethod(Opcodes.ACC_PUBLIC | (is_static ? Opcodes.ACC_STATIC : 0), methodName, AsmUtil.toMethodDesc(AsmTypes.VOID, runtime_desc), null, null); + if (mv != null) { + mv.visitCode(); + if (is_static) { + mv.visitVarInsn(AsmUtil.toLoadOpcode(runtime_desc), 0); + mv.visitFieldInsn(Opcodes.PUTSTATIC, MyAsmNameRemapper.runtimeClass(deobfTargetClassName), runtime_name, runtime_desc); + } else { + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitVarInsn(AsmUtil.toLoadOpcode(runtime_desc), 1); + mv.visitFieldInsn(Opcodes.PUTFIELD, MyAsmNameRemapper.runtimeClass(deobfTargetClassName), runtime_name, runtime_desc); + } + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0);//引数は無視され、再計算される(Write時に再計算されるのでtrace時点では0,0のまま) + mv.visitEnd(); + } + } else if (method.getAnnotation(NewMethod.class) != null) { + //staticじゃないならinterfaceがメソッドを持ってるので問題ない + //staticなものは無効とする + } else { + //bridge + String method_desc = AsmUtil.toDesc(method); + boolean is_static = Modifier.isStatic(method.getModifiers()); + + String runtime_name; + if (method.getAnnotation(SrgName.class) != null) { + String srg_name = method.getAnnotation(SrgName.class).value(); + runtime_name = MyAsmNameRemapper.runtimeMethod(new MethodRemap(deobfTargetClassName, methodName, method_desc, srg_name)); + } else { + runtime_name = methodName; + } + + if (methodName.equals(runtime_name)) { + AccessTransformerForMixin.toPublic(deobfTargetClassName, methodName, method_desc); + } else { + String runtime_desc = AsmUtil.runtimeDesc(method_desc); + MethodInfo methodInfo = methodInfoMap.get(runtime_name); + if (methodInfo == null) + throw new IllegalStateException("Unknown method:" + runtime_name + "(" + methodName + ")"); + if (!methodInfo.runtimeDesc.equals(runtime_desc)) + throw new IllegalStateException("Unknown method desc:" + runtime_name + "(" + methodName + ")"); + if (methodInfo.isStatic != is_static) + throw new IllegalStateException("Unknown method access(static):" + runtime_name + "(" + methodName + ")"); + if (methodInfoMap.containsKey(methodName)) + throw new IllegalStateException("Duplicated method:" + runtime_name + "(" + methodName + ")"); + boolean is_private = methodInfo.isPrivate; + + MethodVisitor mv = visitMethod(Opcodes.ACC_PUBLIC | (is_static ? Opcodes.ACC_STATIC : 0), methodName, runtime_desc, null, null); + if (mv != null) { + mv.visitCode(); + int offset = 0; + //this + if (!is_static) { + mv.visitVarInsn(Opcodes.ALOAD, 0); + offset = 1; + } + //params + for (int i = 0; i < method.getParameterCount(); i++) { + int opcode = AsmUtil.toLoadOpcode(AsmUtil.toDesc(method.getParameterTypes()[i])); + mv.visitVarInsn(opcode, offset); + if (opcode == Opcodes.LLOAD || opcode == Opcodes.DOUBLE) + offset += 2; + else + offset += 1; + } + //invoke + if (is_static) + mv.visitMethodInsn(Opcodes.INVOKESTATIC, MyAsmNameRemapper.runtimeClass(deobfTargetClassName), runtime_name, runtime_desc, false); + else if (is_private) + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, MyAsmNameRemapper.runtimeClass(deobfTargetClassName), runtime_name, runtime_desc, false); + else + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MyAsmNameRemapper.runtimeClass(deobfTargetClassName), runtime_name, runtime_desc, false); + //return + mv.visitInsn(AsmUtil.toReturnOpcode(AsmUtil.toDesc(method.getReturnType()))); + + mv.visitMaxs(0, 0);//引数は無視され、再計算される(Write時に再計算されるのでtrace時点では0,0のまま) + mv.visitEnd(); + } + } + } + } + success(); + super.visitEnd(); + } + + private static String mixinTarget = null; + + public static ClassVisitor transformAccessor(ClassVisitor cv, String transformedName) { + if (mixinTarget == null || !transformedName.startsWith(ModReference.SRC_DIR + ".asm.acc.")) + return cv; + + cv = new MyClassVisitor(cv, transformedName, 0) { + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + if ((access & Opcodes.ACC_STATIC) != 0) { + mv = new MethodVisitor(AsmUtil.ASM_VER, mv) { + @Override + public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { + } + @Override + public void visitInsn(int opcode) { + } + @Override + public void visitIntInsn(int opcode, int operand) { + } + @Override + public void visitVarInsn(int opcode, int var) { + } + @Override + public void visitTypeInsn(int opcode, String type) { + } + @Override + public void visitFieldInsn(int opcode, String owner, String name, String desc) { + } + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc) { + } + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { + } + @Override + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { + } + @Override + public void visitJumpInsn(int opcode, Label label) { + } + @Override + public void visitLabel(Label label) { + } + @Override + public void visitLdcInsn(Object cst) { + } + @Override + public void visitIincInsn(int var, int increment) { + } + @Override + public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { + } + @Override + public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { + } + @Override + public void visitMultiANewArrayInsn(String desc, int dims) { + } + @Override + public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { + return null; + } + @Override + public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { + } + @Override + public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { + return null; + } + @Override + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { + } + @Override + public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) { + return null; + } + @Override + public void visitLineNumber(int line, Label start) { + } + @Override + public void visitMaxs(int maxStack, int maxLocals) { + } + @Override + public void visitEnd() { + if (name.startsWith("get_")) { + //invoke + mv.visitMethodInsn(Opcodes.INVOKESTATIC, mixinTarget.replace('.', '/'), name, desc, false); + //return + mv.visitInsn(AsmUtil.toReturnOpcode(desc.substring("()".length()))); + } else if (name.startsWith("set_")) { + //params + mv.visitVarInsn(AsmUtil.toLoadOpcode(desc.substring(1, desc.length() - 2)), 0); + //invoke + mv.visitMethodInsn(Opcodes.INVOKESTATIC, mixinTarget.replace('.', '/'), name, desc, false); + //return + mv.visitInsn(Opcodes.RETURN); + } else { + MethodDesc md = MethodDesc.fromMethodDesc(desc); + //params + AsmUtil.loadLocals(mv, md.paramsDesc, 0); + //invoke + mv.visitMethodInsn(Opcodes.INVOKESTATIC, mixinTarget.replace('.', '/'), name, desc, false); + //return + mv.visitInsn(AsmUtil.toReturnOpcode(md.returnDesc)); + } + mv.visitMaxs(0, 0);//引数は無視され、再計算される(Write時に再計算されるのでtrace時点では0,0のまま) + super.visitEnd(); + } + }; + } + return mv; + } + }; + + return cv; + } + + /** + * ターゲットクラスに新しいフィールドとして追加する。 + * getterとsetterの両方で重複して付ける必要がある + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface NewField { + } + + /** + * ターゲットクラスに新しいメソッドとして追加する。 + * staticメソッドに対しては使用できない。 + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface NewMethod { + } + + /** + * 難読化されているバニラのコードなどで、フィールドやメソッドのsrg名を指定するために使う。 + * メソッドの名前を元からget_field_71432_Pのようにしても良いが、それだと分かりづらいので、 + * メソッドの名前をget_instanceにしたまま実行時にはget_field_71432_Pに変換するためにこのアノテーションを用いる。 + * ただ、バニラのコードに対してはForgeが用意しているAccessTransformerを使った方が良い。 + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface SrgName { + String value() default ""; + } + + private static class RuntimeInfo { + public final String runtimeDesc; + public final boolean isStatic; + + private RuntimeInfo(String runtimeDesc, boolean isStatic) { + this.runtimeDesc = runtimeDesc; + this.isStatic = isStatic; + } + } + + private static class MethodInfo { + public final String runtimeDesc; + public final boolean isStatic; + public final boolean isPrivate; + + private MethodInfo(String runtimeDesc, boolean isStatic, boolean isPrivate) { + this.runtimeDesc = runtimeDesc; + this.isStatic = isStatic; + this.isPrivate = isPrivate; + } + } +} diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/MyClassVisitor.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/MyClassVisitor.java index 6b41b98..6074c9c 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/MyClassVisitor.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/MyClassVisitor.java @@ -1,8 +1,7 @@ package kpan.uti_alsofluids.asm.core.adapters; -import org.objectweb.asm.ClassVisitor; - import kpan.uti_alsofluids.asm.core.AsmUtil; +import org.objectweb.asm.ClassVisitor; public class MyClassVisitor extends ClassVisitor { @@ -19,8 +18,19 @@ public MyClassVisitor(ClassVisitor cv, String nameForDebug, int successExpectedM this.successExpectedMinInclusive = Math.max(successExpectedMinInclusive, 0); this.successExpectedMaxInclusive = Math.max(successExpectedMaxInclusive, 0); } - public void setSuccessExpectedMin(int minInclusive) { successExpectedMinInclusive = Math.max(minInclusive, 0); } - public void setSuccessExpectedMax(int maxInclusive) { successExpectedMaxInclusive = Math.max(maxInclusive, 0); } + public MyClassVisitor setSuccessExpected(int successExpected) { + setSuccessExpectedMin(successExpected); + setSuccessExpectedMax(successExpected); + return this; + } + public MyClassVisitor setSuccessExpectedMin(int minInclusive) { + successExpectedMinInclusive = Math.max(minInclusive, 0); + return this; + } + public MyClassVisitor setSuccessExpectedMax(int maxInclusive) { + successExpectedMaxInclusive = Math.max(maxInclusive, 0); + return this; + } protected void success() { successed++; } @@ -30,11 +40,11 @@ public void visitEnd() { super.visitEnd(); if (successed < successExpectedMinInclusive || successed > successExpectedMaxInclusive) { if (successExpectedMinInclusive == successExpectedMaxInclusive) - throw new RuntimeException("transform failed:" + nameForDebug + "\nexpected:" + successExpectedMinInclusive + "\nactual:" + successed); + throw new RuntimeException("class transform failed:" + nameForDebug + "\nexpected:" + successExpectedMinInclusive + "\nactual:" + successed); else if (successExpectedMaxInclusive == Integer.MAX_VALUE) - throw new RuntimeException("transform failed:" + nameForDebug + "\nexpected: " + successExpectedMinInclusive + "~\nactual:" + successed); + throw new RuntimeException("class transform failed:" + nameForDebug + "\nexpected: " + successExpectedMinInclusive + "~\nactual:" + successed); else - throw new RuntimeException("transform failed:" + nameForDebug + "\nexpected: " + successExpectedMinInclusive + "~" + successExpectedMaxInclusive + "\nactual:" + successed); + throw new RuntimeException("class transform failed:" + nameForDebug + "\nexpected: " + successExpectedMinInclusive + "~" + successExpectedMaxInclusive + "\nactual:" + successed); } } } diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/MyMethodVisitor.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/MyMethodVisitor.java index fcab70a..d020e00 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/MyMethodVisitor.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/MyMethodVisitor.java @@ -112,11 +112,11 @@ public void visitEnd() { super.visitEnd(); if (success < successExpectedMinInclusive || success > successExpectedMaxInclusive) { if (successExpectedMinInclusive == successExpectedMaxInclusive) - throw new RuntimeException("transform failed:" + nameForDebug + "\nexpected:" + successExpectedMinInclusive + "\nactual:" + success); + throw new RuntimeException("method transform failed:" + nameForDebug + "\nexpected:" + successExpectedMinInclusive + "\nactual:" + success); else if (successExpectedMaxInclusive == Integer.MAX_VALUE) - throw new RuntimeException("transform failed:" + nameForDebug + "\nexpected: " + successExpectedMinInclusive + "~\nactual:" + success); + throw new RuntimeException("method transform failed:" + nameForDebug + "\nexpected: " + successExpectedMinInclusive + "~\nactual:" + success); else - throw new RuntimeException("transform failed:" + nameForDebug + "\nexpected: " + successExpectedMinInclusive + "~" + successExpectedMaxInclusive + "\nactual:" + success); + throw new RuntimeException("method transform failed:" + nameForDebug + "\nexpected: " + successExpectedMinInclusive + "~" + successExpectedMaxInclusive + "\nactual:" + success); } } diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceInstructionsAdapter.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceInstructionsAdapter.java index 1760664..0c82d6b 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceInstructionsAdapter.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceInstructionsAdapter.java @@ -1,17 +1,14 @@ package kpan.uti_alsofluids.asm.core.adapters; -import java.util.ArrayList; - -import javax.annotation.Nonnull; - +import com.google.common.collect.Lists; +import kpan.uti_alsofluids.asm.core.adapters.Instructions.Instr; import org.objectweb.asm.Handle; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; -import com.google.common.collect.Lists; - -import kpan.uti_alsofluids.asm.core.adapters.Instructions.Instr; +import javax.annotation.Nonnull; +import java.util.ArrayList; public class ReplaceInstructionsAdapter extends MyMethodVisitor { @@ -148,7 +145,6 @@ public void visitMethodInsn(int opcode, String owner, String name, String desc, if (api < Opcodes.ASM5 || !check(Instr.methodInsn(opcode, owner, name, desc, itf))) super.visitMethodInsn(opcode, owner, name, desc, itf); } - @SuppressWarnings("deprecation") @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { if (api >= Opcodes.ASM5 || !check(Instr.methodInsn(opcode, owner, name, desc, opcode == Opcodes.INVOKEINTERFACE))) diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceMethodAdapter.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceMethodAdapter.java index 24b0e00..399b4e1 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceMethodAdapter.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceMethodAdapter.java @@ -1,23 +1,24 @@ package kpan.uti_alsofluids.asm.core.adapters; -import java.util.Arrays; - -import javax.annotation.Nullable; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; - import kpan.uti_alsofluids.asm.core.AsmUtil; import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper; import kpan.uti_alsofluids.asm.core.MyAsmNameRemapper.MethodRemap; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; + +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Objects; public abstract class ReplaceMethodAdapter extends MyClassVisitor { protected final String runtimeName; protected final String runtimeDesc; protected int access; - @Nullable protected String runtimeGenerics; - @Nullable protected String[] runtimeExceptions;//RuntimeExceptionではなくExceptionのRuntime名 + @Nullable + protected String runtimeGenerics; + @Nullable + protected String[] runtimeExceptions;//RuntimeExceptionではなくExceptionのRuntime名 protected boolean useAccess = false; protected boolean useGenerics = false; protected boolean useExceptions = false; @@ -34,9 +35,21 @@ public ReplaceMethodAdapter(ClassVisitor cv, String runtimeMethodName, String ru runtimeName = runtimeMethodName; this.runtimeDesc = runtimeDesc; } - public void setAccess(int access) { this.access = access; useAccess = true; } - public void setGenerics(String deobfGenerics) { runtimeGenerics = AsmUtil.runtimeMethodGenerics(deobfGenerics); useGenerics = true; } - public void setExceptions(String[] deobfExceptions) { runtimeExceptions = AsmUtil.runtimeExceptions(deobfExceptions); useExceptions = true; } + @SuppressWarnings("unused") + public void setAccess(int access) { + this.access = access; + useAccess = true; + } + @SuppressWarnings("unused") + public void setGenerics(String deobfGenerics) { + runtimeGenerics = AsmUtil.runtimeMethodGenerics(deobfGenerics); + useGenerics = true; + } + @SuppressWarnings("unused") + public void setExceptions(String[] deobfExceptions) { + runtimeExceptions = AsmUtil.runtimeExceptions(deobfExceptions); + useExceptions = true; + } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { @@ -93,7 +106,7 @@ private boolean isTarget(int access, String name, String desc, String signature, } //Java7との互換性のために、Objects.equalsを使用してない private static boolean equals(Object a, Object b) { - return a == b || a != null && a.equals(b); + return Objects.equals(a, b); } } diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceRefMethodAdapter.java b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceRefMethodAdapter.java index 257bcb7..ae8785c 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceRefMethodAdapter.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/adapters/ReplaceRefMethodAdapter.java @@ -13,52 +13,50 @@ public class ReplaceRefMethodAdapter extends ReplaceMethodAdapter { private final String runtimeClassForRefMethodParam; private final String originalName; private final String refClass; - private final String returnType; - private final String[] params; + private final String runtimeReturnType; + private final String[] runtimeParams; public ReplaceRefMethodAdapter(ClassVisitor cv, String refClass, MethodRemap method) { super(cv, method); - originalName = runtimeName; + originalName = method.mcpMethodName; runtimeClassForRefMethodParam = MyAsmNameRemapper.runtimeClass(method.deobfOwner); this.refClass = refClass; MethodDesc md = MethodDesc.fromMethodDesc(AsmUtil.runtimeDesc(method.deobfMethodDesc)); - returnType = md.returnDesc; - params = md.paramsDesc; + runtimeReturnType = md.returnDesc; + runtimeParams = md.paramsDesc; } public ReplaceRefMethodAdapter(ClassVisitor cv, String refClass, String runtimeClassForRefMethodParam, String runtimeMethodName, String runtimeDesc) { super(cv, runtimeMethodName, runtimeDesc); - originalName = runtimeName; + originalName = runtimeMethodName; this.runtimeClassForRefMethodParam = runtimeClassForRefMethodParam; this.refClass = refClass; MethodDesc md = MethodDesc.fromMethodDesc(runtimeDesc); - returnType = md.returnDesc; - params = md.paramsDesc; + runtimeReturnType = md.returnDesc; + runtimeParams = md.paramsDesc; } @Override protected void methodBody(MethodVisitor mv) { - - //java7との互換性のため、文字列switchを使用していない boolean is_static = (access & Opcodes.ACC_STATIC) != 0; int offset = 0; + //this if (!is_static) { mv.visitVarInsn(Opcodes.ALOAD, 0); offset = 1; } + //params - for (int i = 0; i < params.length; i++) { - mv.visitVarInsn(AsmUtil.loadOpcode(params[i]), i + offset); - } + AsmUtil.loadLocals(mv, runtimeParams, offset); //invoke if (is_static) mv.visitMethodInsn(Opcodes.INVOKESTATIC, refClass, originalName, runtimeDesc, false); else - mv.visitMethodInsn(Opcodes.INVOKESTATIC, refClass, originalName, AsmUtil.runtimeDesc(AsmUtil.toMethodDesc(returnType, runtimeClassForRefMethodParam, params)), false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, refClass, originalName, AsmUtil.toMethodDesc(runtimeReturnType, runtimeClassForRefMethodParam, runtimeParams), false); //return - mv.visitInsn(AsmUtil.returnOpcode(returnType)); + mv.visitInsn(AsmUtil.toReturnOpcode(runtimeReturnType)); } } diff --git a/src/main/java/kpan/uti_alsofluids/asm/tf/TF_Fluid.java b/src/main/java/kpan/uti_alsofluids/asm/tf/TF_Fluid.java index 02bf7fc..a2b577c 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/tf/TF_Fluid.java +++ b/src/main/java/kpan/uti_alsofluids/asm/tf/TF_Fluid.java @@ -1,10 +1,9 @@ package kpan.uti_alsofluids.asm.tf; -import org.objectweb.asm.ClassVisitor; - import kpan.uti_alsofluids.asm.core.AsmTypes; import kpan.uti_alsofluids.asm.core.AsmUtil; import kpan.uti_alsofluids.asm.core.adapters.ReplaceRefMethodAdapter; +import org.objectweb.asm.ClassVisitor; public class TF_Fluid { diff --git a/src/main/java/kpan/uti_alsofluids/asm/tf/TF_FluidStack.java b/src/main/java/kpan/uti_alsofluids/asm/tf/TF_FluidStack.java index 1856174..03da0d8 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/tf/TF_FluidStack.java +++ b/src/main/java/kpan/uti_alsofluids/asm/tf/TF_FluidStack.java @@ -1,10 +1,9 @@ package kpan.uti_alsofluids.asm.tf; -import org.objectweb.asm.ClassVisitor; - import kpan.uti_alsofluids.asm.core.AsmTypes; import kpan.uti_alsofluids.asm.core.AsmUtil; import kpan.uti_alsofluids.asm.core.adapters.ReplaceRefMethodAdapter; +import org.objectweb.asm.ClassVisitor; public class TF_FluidStack { diff --git a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/ae2/TF_GuiCraft__.java b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/ae2/TF_GuiCraft__.java index b8a449c..65aee8b 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/ae2/TF_GuiCraft__.java +++ b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/ae2/TF_GuiCraft__.java @@ -1,14 +1,13 @@ package kpan.uti_alsofluids.asm.tf.integration.ae2; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; - import kpan.uti_alsofluids.asm.core.AsmTypes; import kpan.uti_alsofluids.asm.core.AsmUtil; import kpan.uti_alsofluids.asm.core.adapters.Instructions; import kpan.uti_alsofluids.asm.core.adapters.MyClassVisitor; import kpan.uti_alsofluids.asm.core.adapters.ReplaceInstructionsAdapter; import net.minecraftforge.fml.common.Loader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; public class TF_GuiCraft__ { diff --git a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/gregtech/TF_PhantomFluidWidget.java b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/gregtech/TF_PhantomFluidWidget.java index 168cbc0..c1e85af 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/gregtech/TF_PhantomFluidWidget.java +++ b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/gregtech/TF_PhantomFluidWidget.java @@ -1,14 +1,13 @@ package kpan.uti_alsofluids.asm.tf.integration.gregtech; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - import kpan.uti_alsofluids.asm.core.AsmTypes; import kpan.uti_alsofluids.asm.core.AsmUtil; import kpan.uti_alsofluids.asm.core.adapters.Instructions; import kpan.uti_alsofluids.asm.core.adapters.MyClassVisitor; import kpan.uti_alsofluids.asm.core.adapters.ReplaceInstructionsAdapter; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; public class TF_PhantomFluidWidget { diff --git a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/jei/TF_FluidStackRenderer.java b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/jei/TF_FluidStackRenderer.java index c3b6458..565f145 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/jei/TF_FluidStackRenderer.java +++ b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/jei/TF_FluidStackRenderer.java @@ -1,15 +1,14 @@ package kpan.uti_alsofluids.asm.tf.integration.jei; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - import kpan.uti_alsofluids.asm.core.AsmTypes; import kpan.uti_alsofluids.asm.core.AsmUtil; import kpan.uti_alsofluids.asm.core.adapters.Instructions; import kpan.uti_alsofluids.asm.core.adapters.Instructions.OpcodeVar; import kpan.uti_alsofluids.asm.core.adapters.MyClassVisitor; import kpan.uti_alsofluids.asm.core.adapters.ReplaceInstructionsAdapter; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; public class TF_FluidStackRenderer { diff --git a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wct/TF_GuiCraft__.java b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wct/TF_GuiCraft__.java index c6bfec9..0088bc7 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wct/TF_GuiCraft__.java +++ b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wct/TF_GuiCraft__.java @@ -1,14 +1,13 @@ package kpan.uti_alsofluids.asm.tf.integration.p455w0rd.wct; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; - import kpan.uti_alsofluids.asm.core.AsmTypes; import kpan.uti_alsofluids.asm.core.AsmUtil; import kpan.uti_alsofluids.asm.core.adapters.Instructions; import kpan.uti_alsofluids.asm.core.adapters.MyClassVisitor; import kpan.uti_alsofluids.asm.core.adapters.ReplaceInstructionsAdapter; import net.minecraftforge.fml.common.Loader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; public class TF_GuiCraft__ { diff --git a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wft/TF_GuiWFT.java b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wft/TF_GuiWFT.java index abe4568..0ca29cb 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wft/TF_GuiWFT.java +++ b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wft/TF_GuiWFT.java @@ -1,14 +1,13 @@ package kpan.uti_alsofluids.asm.tf.integration.p455w0rd.wft; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - import kpan.uti_alsofluids.asm.core.AsmTypes; import kpan.uti_alsofluids.asm.core.AsmUtil; import kpan.uti_alsofluids.asm.core.adapters.Instructions; import kpan.uti_alsofluids.asm.core.adapters.MyClassVisitor; import kpan.uti_alsofluids.asm.core.adapters.ReplaceInstructionsAdapter; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; public class TF_GuiWFT { diff --git a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wpt/TF_GuiCraft__.java b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wpt/TF_GuiCraft__.java index 99b479a..d4326e2 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wpt/TF_GuiCraft__.java +++ b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/p455w0rd/wpt/TF_GuiCraft__.java @@ -1,14 +1,13 @@ package kpan.uti_alsofluids.asm.tf.integration.p455w0rd.wpt; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; - import kpan.uti_alsofluids.asm.core.AsmTypes; import kpan.uti_alsofluids.asm.core.AsmUtil; import kpan.uti_alsofluids.asm.core.adapters.Instructions; import kpan.uti_alsofluids.asm.core.adapters.MyClassVisitor; import kpan.uti_alsofluids.asm.core.adapters.ReplaceInstructionsAdapter; import net.minecraftforge.fml.common.Loader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; public class TF_GuiCraft__ { diff --git a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/theoneprobe/TF_OverlayRenderer.java b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/theoneprobe/TF_OverlayRenderer.java index dcfec06..7983c13 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/theoneprobe/TF_OverlayRenderer.java +++ b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/theoneprobe/TF_OverlayRenderer.java @@ -1,14 +1,13 @@ package kpan.uti_alsofluids.asm.tf.integration.theoneprobe; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; - import kpan.uti_alsofluids.asm.core.AsmTypes; import kpan.uti_alsofluids.asm.core.AsmUtil; import kpan.uti_alsofluids.asm.core.adapters.InjectInstructionsAdapter; import kpan.uti_alsofluids.asm.core.adapters.Instructions; import kpan.uti_alsofluids.asm.core.adapters.Instructions.OpcodeVar; import kpan.uti_alsofluids.asm.core.adapters.MyClassVisitor; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; public class TF_OverlayRenderer { From b7f6ae8b849e6c706da61543c78310666c4fab3c Mon Sep 17 00:00:00 2001 From: KatatsumuriPan Date: Sat, 9 Dec 2023 22:06:43 +0900 Subject: [PATCH 2/3] =?UTF-8?q?FTBQuests=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 ++ .../integration/ftbquests/ACC_ButtonTask.java | 19 +++++++ .../asm/core/ASMTransformer.java | 2 + .../integration/ftbquests/HK_ButtonTask.java | 40 ++++++++++++++ .../integration/ftbquests/TF_ButtonTask.java | 53 +++++++++++++++++++ .../uti_alsofluids/config/ConfigHolder.java | 9 +++- 6 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/main/java/kpan/uti_alsofluids/asm/acc/integration/ftbquests/ACC_ButtonTask.java create mode 100644 src/main/java/kpan/uti_alsofluids/asm/hook/integration/ftbquests/HK_ButtonTask.java create mode 100644 src/main/java/kpan/uti_alsofluids/asm/tf/integration/ftbquests/TF_ButtonTask.java diff --git a/build.gradle b/build.gradle index 342b853..001ebad 100644 --- a/build.gradle +++ b/build.gradle @@ -152,4 +152,8 @@ dependencies { implementation fg.deobf("curse.maven:gregtech-ce-unofficial-557242:4904269") implementation fg.deobf("curse.maven:the-one-probe-245211:2667280") runtimeOnly fg.deobf("curse.maven:codechicken-lib-1-8-242818:2779848") + + implementation fg.deobf("curse.maven:item-filters-309674:3003364") + implementation fg.deobf("curse.maven:ftb-library-legacy-forge-237167:2985811") + implementation fg.deobf("curse.maven:ftb-quests-forge-289412:3156637") } diff --git a/src/main/java/kpan/uti_alsofluids/asm/acc/integration/ftbquests/ACC_ButtonTask.java b/src/main/java/kpan/uti_alsofluids/asm/acc/integration/ftbquests/ACC_ButtonTask.java new file mode 100644 index 0000000..5b64023 --- /dev/null +++ b/src/main/java/kpan/uti_alsofluids/asm/acc/integration/ftbquests/ACC_ButtonTask.java @@ -0,0 +1,19 @@ +package kpan.uti_alsofluids.asm.acc.integration.ftbquests; + + +import kpan.uti_alsofluids.asm.core.adapters.MixinAccessorAdapter.NewField; + +public interface ACC_ButtonTask { + + //新しいインスタンスフィールドの追加&getter作成 + //getterとsetterの両方を作成する必要はないが、初期化する方法が無いので両方作るのが基本 + //@NewFieldはgetterとsetterの両方に必要 + @NewField + String get_localizedLine(); + + //新しいインスタンスフィールドの追加&setter作成 + //説明はgetter同様 + @NewField + void set_localizedLine(String value); + +} diff --git a/src/main/java/kpan/uti_alsofluids/asm/core/ASMTransformer.java b/src/main/java/kpan/uti_alsofluids/asm/core/ASMTransformer.java index 94d48fa..4b0492c 100644 --- a/src/main/java/kpan/uti_alsofluids/asm/core/ASMTransformer.java +++ b/src/main/java/kpan/uti_alsofluids/asm/core/ASMTransformer.java @@ -8,6 +8,7 @@ import kpan.uti_alsofluids.asm.tf.integration.ae2.TF_GuiFluidSlot; import kpan.uti_alsofluids.asm.tf.integration.ae2.TF_GuiFluidTank; import kpan.uti_alsofluids.asm.tf.integration.ae2.TF_GuiFluidTerminal; +import kpan.uti_alsofluids.asm.tf.integration.ftbquests.TF_ButtonTask; import kpan.uti_alsofluids.asm.tf.integration.gregtech.TF_AEFluidConfigSlot; import kpan.uti_alsofluids.asm.tf.integration.gregtech.TF_AEFluidDisplayWidget; import kpan.uti_alsofluids.asm.tf.integration.gregtech.TF_GTFluid$GTMaterialFluid; @@ -55,6 +56,7 @@ public byte[] transform(String name, String transformedName, byte[] bytes) { ClassVisitor cv = cw; cv = TF_AEFluidConfigSlot.appendVisitor(cv, transformedName); cv = TF_AEFluidDisplayWidget.appendVisitor(cv, transformedName); + cv = TF_ButtonTask.appendVisitor(cv, transformedName); cv = TF_Fluid.appendVisitor(cv, transformedName); cv = TF_FluidRegistry_LAVA.appendVisitor(cv, transformedName); cv = TF_FluidRegistry_WATER.appendVisitor(cv, transformedName); diff --git a/src/main/java/kpan/uti_alsofluids/asm/hook/integration/ftbquests/HK_ButtonTask.java b/src/main/java/kpan/uti_alsofluids/asm/hook/integration/ftbquests/HK_ButtonTask.java new file mode 100644 index 0000000..6a7934d --- /dev/null +++ b/src/main/java/kpan/uti_alsofluids/asm/hook/integration/ftbquests/HK_ButtonTask.java @@ -0,0 +1,40 @@ +package kpan.uti_alsofluids.asm.hook.integration.ftbquests; + +import com.feed_the_beast.ftbquests.gui.tree.ButtonTask; +import com.feed_the_beast.ftbquests.quest.task.FluidTask; +import com.feed_the_beast.ftbquests.quest.task.ItemTask; +import com.feed_the_beast.ftbquests.quest.task.Task; +import kpan.uti_alsofluids.asm.acc.integration.ftbquests.ACC_ButtonTask; +import kpan.uti_alsofluids.asm.hook.LocalizedName; +import kpan.uti_alsofluids.config.ConfigHolder; +import net.minecraft.util.text.TextFormatting; + +import java.util.List; + +public class HK_ButtonTask { + + public static void onConstruct(ButtonTask self, Task t) { + if (t instanceof ItemTask || t instanceof FluidTask) { + t.clearCachedData(); + synchronized (LocalizedName.langmapus.localizedLock) { + try { + LocalizedName.langmapus.localizedThread = Thread.currentThread(); + ((ACC_ButtonTask) self).set_localizedLine(t.getTitle()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + LocalizedName.langmapus.localizedThread = null; + } + } + t.clearCachedData(); + } + } + + public static void addLocalizedLine(ButtonTask self, List list) { + if (LocalizedName.showLocalize() && ConfigHolder.client.FTBQuests.showLocalizedName) { + String localized = ((ACC_ButtonTask) self).get_localizedLine(); + if (!list.get(list.size() - 1).equals(localized)) + list.add(TextFormatting.GRAY + localized); + } + } +} diff --git a/src/main/java/kpan/uti_alsofluids/asm/tf/integration/ftbquests/TF_ButtonTask.java b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/ftbquests/TF_ButtonTask.java new file mode 100644 index 0000000..c4b6325 --- /dev/null +++ b/src/main/java/kpan/uti_alsofluids/asm/tf/integration/ftbquests/TF_ButtonTask.java @@ -0,0 +1,53 @@ +package kpan.uti_alsofluids.asm.tf.integration.ftbquests; + +import kpan.uti_alsofluids.asm.core.AsmTypes; +import kpan.uti_alsofluids.asm.core.AsmUtil; +import kpan.uti_alsofluids.asm.core.adapters.InjectInstructionsAdapter; +import kpan.uti_alsofluids.asm.core.adapters.Instructions; +import kpan.uti_alsofluids.asm.core.adapters.MixinAccessorAdapter; +import kpan.uti_alsofluids.asm.core.adapters.MyClassVisitor; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public class TF_ButtonTask { + + private static final String TARGET = "com.feed_the_beast.ftbquests.gui.tree.ButtonTask"; + private static final String HOOK = AsmTypes.HOOK + "integration/ftbquests/" + "HK_" + "ButtonTask"; + private static final String ACC = AsmTypes.ACC + "integration/ftbquests/" + "ACC_" + "ButtonTask"; + + public static ClassVisitor appendVisitor(ClassVisitor cv, String className) { + if (!TARGET.equals(className)) + return cv; + ClassVisitor newcv = new MyClassVisitor(cv, className) { + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + if ("".equals(name)) { + mv = InjectInstructionsAdapter.injectBeforeReturns(mv, name, + Instructions.create() + .aload(0) + .aload(2) + .invokeStatic(HOOK, "onConstruct", AsmUtil.composeRuntimeMethodDesc(AsmTypes.VOID, TARGET, "com.feed_the_beast.ftbquests.quest.task.Task"))); + success(); + } + if ("addMouseOverText".equals(name)) { + mv = InjectInstructionsAdapter.after(mv, name + , Instructions.create() + .invokeVirtual(TARGET, "getTitle", AsmUtil.composeRuntimeMethodDesc(AsmTypes.STRING)) + .invokeInterface(AsmTypes.LIST, "add", AsmUtil.composeRuntimeMethodDesc(AsmTypes.BOOL, AsmTypes.OBJECT)) + .insn(Opcodes.POP) + , Instructions.create() + .aload(0) + .aload(1) + .invokeStatic(HOOK, "addLocalizedLine", AsmUtil.composeRuntimeMethodDesc(AsmTypes.VOID, TARGET, AsmTypes.LIST)) + ); + success(); + } + return mv; + } + }.setSuccessExpected(2); + newcv = new MixinAccessorAdapter(newcv, className, ACC); + return newcv; + } +} diff --git a/src/main/java/kpan/uti_alsofluids/config/ConfigHolder.java b/src/main/java/kpan/uti_alsofluids/config/ConfigHolder.java index 17a5255..7a6a412 100644 --- a/src/main/java/kpan/uti_alsofluids/config/ConfigHolder.java +++ b/src/main/java/kpan/uti_alsofluids/config/ConfigHolder.java @@ -22,6 +22,7 @@ public static class Client { @BooleanValue(defaultValue = true) public boolean showLocalizedName = true; public AppliedEnergistcs2_ AppliedEnergistcs2 = new AppliedEnergistcs2_(); + public FTBQuests_ FTBQuests = new FTBQuests_(); public GregTechCEu_ GregTechCEu = new GregTechCEu_(); public JustEnoughItems_ JEI = new JustEnoughItems_(); public TheOneProbe_ TheOneProbe = new TheOneProbe_(); @@ -41,6 +42,12 @@ public static class GregTechCEu_ { public boolean showLocalizedName = true; } + public static class FTBQuests_ { + @Comment("Show the localized name of the item and the fluid.") // + @BooleanValue(defaultValue = true) + public boolean showLocalizedName = true; + } + public static class JustEnoughItems_ { @Comment("Show the localized name of the fluid.") // @BooleanValue(defaultValue = true) @@ -86,5 +93,5 @@ public static void updateVersion(Configuration config) { } } - public static String getVersion() {return "2";} + public static String getVersion() { return "2"; } } From ebd9d93eea0d2b56b54f9140185b8e47c4e453ab Mon Sep 17 00:00:00 2001 From: KatatsumuriPan Date: Sat, 9 Dec 2023 22:21:45 +0900 Subject: [PATCH 3/3] =?UTF-8?q?1.6.0=E3=81=B8=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/changelog.txt | 2 ++ version.properties | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt index 8b8b549..c3a6e6c 100644 --- a/src/main/resources/changelog.txt +++ b/src/main/resources/changelog.txt @@ -1,3 +1,5 @@ +version 1.6.0 : + Add FTBQuests compatibility. version 1.5.1 : Add ja_jp forge universal forge bucket localization. Fix bug that no localized name(obviously water) was displayed in Reservoir Hatch(GTCEu). diff --git a/version.properties b/version.properties index eb68571..cce7ba4 100644 --- a/version.properties +++ b/version.properties @@ -1,3 +1,3 @@ majorVersion=1 -minorVersion=5 -patchVersion=1 +minorVersion=6 +patchVersion=0