From 9bbd0ad61b70b6effa17358f75c10644f8a50d49 Mon Sep 17 00:00:00 2001 From: PrototypeTrousers Date: Mon, 9 Jan 2023 02:15:45 -0300 Subject: [PATCH] ASM Patch ItemStack packet size setter and getter. code from StackUp --- build.gradle | 2 + src/main/java/appeng/core/AE2ELCore.java | 58 +++++++++++ .../core/transformer/AE2ELTransformer.java | 61 ++++++++++++ .../core/transformer/ItemStackPatch.java | 98 +++++++++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 src/main/java/appeng/core/AE2ELCore.java create mode 100644 src/main/java/appeng/core/transformer/AE2ELTransformer.java create mode 100644 src/main/java/appeng/core/transformer/ItemStackPatch.java diff --git a/build.gradle b/build.gradle index 35fec2527..c327904ed 100644 --- a/build.gradle +++ b/build.gradle @@ -66,6 +66,8 @@ archivesBaseName = aebasename jar { manifest { attributes 'FMLAT': 'appeng_at.cfg' + attributes "FMLCorePlugin": "appeng.core.AE2ELCore" + attributes "FMLCorePluginContainsFMLMod": "true" } from sourceSets.api.output diff --git a/src/main/java/appeng/core/AE2ELCore.java b/src/main/java/appeng/core/AE2ELCore.java new file mode 100644 index 000000000..69ca36681 --- /dev/null +++ b/src/main/java/appeng/core/AE2ELCore.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, 2020 Adrian Siekierka + * + * This file is part of StackUp. + * + * StackUp is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * StackUp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with StackUp. If not, see . + */ + +package appeng.core; + +import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; + +import javax.annotation.Nullable; +import java.util.Map; + +@IFMLLoadingPlugin.Name("AE2ELCore") +@IFMLLoadingPlugin.MCVersion("1.12.2") +@IFMLLoadingPlugin.SortingIndex(1001) +@IFMLLoadingPlugin.TransformerExclusions("appeng.core.transformer") +public class AE2ELCore implements IFMLLoadingPlugin { + @Override + public String[] getASMTransformerClass() { + return new String[]{ + "appeng.core.transformer.AE2ELTransformer" + }; + } + + @Override + public String getModContainerClass() { + return null; + } + + @Nullable + @Override + public String getSetupClass() { + return null; + } + + @Override + public void injectData(Map data) { + } + + @Override + public String getAccessTransformerClass() { + return null; + } +} diff --git a/src/main/java/appeng/core/transformer/AE2ELTransformer.java b/src/main/java/appeng/core/transformer/AE2ELTransformer.java new file mode 100644 index 000000000..33d86cd8c --- /dev/null +++ b/src/main/java/appeng/core/transformer/AE2ELTransformer.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, 2020 Adrian Siekierka + * + * This file is part of StackUp. + * + * StackUp is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * StackUp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with StackUp. If not, see . + */ + +package appeng.core.transformer; + +import net.minecraft.launchwrapper.IClassTransformer; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.tree.ClassNode; + +import java.util.function.Consumer; + +public class AE2ELTransformer implements IClassTransformer { + + @Override + public byte[] transform(String name, String transformedName, byte[] basicClass) { + transformedName = transformedName.replace('/', '.'); + + byte[] data = basicClass; + Consumer consumer = (n) -> { + }; + Consumer emptyConsumer = consumer; + + if ("net.minecraft.item.ItemStack".equals(transformedName)) { + consumer = consumer.andThen(ItemStackPatch::patchCountGetSet); + } + + if (consumer != emptyConsumer) { + return processNode(basicClass, consumer); + } else { + return data; + } + } + + public static byte[] processNode(byte[] data, Consumer classNodeConsumer) { + ClassReader reader = new ClassReader(data); + ClassNode nodeOrig = new ClassNode(); + reader.accept(nodeOrig, 0); + classNodeConsumer.accept(nodeOrig); + ClassWriter writer = new ClassWriter(0); + nodeOrig.accept(writer); + return writer.toByteArray(); + } + +} diff --git a/src/main/java/appeng/core/transformer/ItemStackPatch.java b/src/main/java/appeng/core/transformer/ItemStackPatch.java new file mode 100644 index 000000000..80d5d3226 --- /dev/null +++ b/src/main/java/appeng/core/transformer/ItemStackPatch.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018, 2020 Adrian Siekierka + * + * This file is part of StackUp. + * + * StackUp is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * StackUp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with StackUp. If not, see . + */ + +package appeng.core.transformer; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; + +import java.util.ListIterator; + +public final class ItemStackPatch { + private ItemStackPatch() { + } + + public static void patchCountGetSet(ClassNode node) { + for (MethodNode mn : node.methods) { + if ("".equals(mn.name)) { + ListIterator it = mn.instructions.iterator(); + while (it.hasNext()) { + AbstractInsnNode in = it.next(); + if (in instanceof LdcInsnNode && "Count".equals(((LdcInsnNode) in).cst)) { + AbstractInsnNode in2 = it.next(); + if (in2.getOpcode() == Opcodes.INVOKEVIRTUAL) { + // :thinking: + boolean patched = false; + MethodInsnNode min2 = (MethodInsnNode) in2; + if (min2.name.equals("getByte")) { + min2.name = "getInteger"; + patched = true; + } else if (min2.name.equals("func_74771_c")) { + min2.name = "func_74762_e"; + patched = true; + } + + if (patched) { + min2.desc = "(Ljava/lang/String;)I"; + System.out.println("Patched ItemStack Count getter!"); + } + } + } + } + } else if ("func_77955_b".equals(mn.name) || "writeToNBT".equals(mn.name)) { + ListIterator it = mn.instructions.iterator(); + while (it.hasNext()) { + AbstractInsnNode in = it.next(); + if (in instanceof LdcInsnNode && "Count".equals(((LdcInsnNode) in).cst)) { + it.next(); + it.next(); + it.next(); + AbstractInsnNode in2 = it.next(); + if (in2.getOpcode() == Opcodes.INVOKEVIRTUAL) { + // :thinking: + boolean patched = false; + MethodInsnNode min2 = (MethodInsnNode) in2; + if (min2.name.equals("setByte")) { + min2.name = "setInteger"; + patched = true; + } else if (min2.name.equals("func_74774_a")) { + min2.name = "func_74768_a"; + patched = true; + } + + if (patched) { + min2.desc = "(Ljava/lang/String;I)V"; + System.out.println("Patched ItemStack Count setter!"); + + // Remove I2B cast + it.previous(); + it.previous(); + it.remove(); + } + } + } + } + } + } + } +}