/* * Copyright (c) 2017 NOVA, All rights reserved. * This library is free software, licensed under GNU Lesser General Public License version 3 * * This file is part of NOVA. * * NOVA is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NOVA 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NOVA. If not, see <http://www.gnu.org/licenses/>. */ package nova.core.wrapper.mc.forge.v18.asm.transformers; import nova.core.wrapper.mc.forge.v18.asm.lib.ASMHelper; import nova.core.wrapper.mc.forge.v18.asm.lib.ObfMapping; import nova.internal.core.Game; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.VarInsnNode; /** * @author ExE Boss */ public class GameDataTransformer implements Transformer { @Override public void transform(ClassNode cnode) { Game.logger().info("Transforming GameData class for correct NOVA mod id mapping."); transformAddPrefix(cnode); transformRegisterBlock(cnode); transformRegisterItem(cnode); } private void transformAddPrefix(ClassNode cnode) { ObfMapping mapping = new ObfMapping("net/minecraftforge/fml/common/registry/GameData", "addPrefix", "(Ljava/lang/String;)Ljava/lang/String;"); MethodNode method = ASMHelper.findMethod(mapping, cnode); if (method == null) { throw new IllegalStateException("[NOVA] Lookup " + mapping + " failed!"); } Game.logger().info("Transforming method {}", method.name); @SuppressWarnings("unchecked") JumpInsnNode prev = (JumpInsnNode) method.instructions.get(49); InsnList list = new InsnList(); list.add(new VarInsnNode(ALOAD, 4)); list.add(new MethodInsnNode(INVOKESTATIC, "nova/core/wrapper/mc/forge/v18/asm/StaticForwarder", "isNovaPrefix", "(Ljava/lang/String;)Z", false)); list.add(new JumpInsnNode(IFNE, prev.label)); method.instructions.insert(prev, list); Game.logger().info("Injected instruction to method: {}", method.name); } private void transformRegisterBlock(ClassNode cnode) { ObfMapping obfMap = new ObfMapping("net/minecraftforge/fml/common/registry/GameData", "registerBlock", "(Latr;Ljava/lang/String;)I"); ObfMapping deobfMap = new ObfMapping("net/minecraftforge/fml/common/registry/GameData", "registerBlock", "(Lnet/minecraft/block/Block;Ljava/lang/String;)I"); MethodNode method = ASMHelper.findMethod(obfMap, cnode); if (method == null) { Game.logger().warn("Lookup {} failed. You are probably in a deobf environment.", obfMap); method = ASMHelper.findMethod(deobfMap, cnode); if (method == null) { throw new IllegalStateException("[NOVA] Lookup " + deobfMap + " failed!"); } } Game.logger().info("Transforming method {}", method.name); @SuppressWarnings("unchecked") JumpInsnNode prev = (JumpInsnNode) method.instructions.get(12); InsnList list = new InsnList(); list.add(new VarInsnNode(ALOAD, 2)); list.add(new MethodInsnNode(INVOKESTATIC, "nova/core/wrapper/mc/forge/v18/asm/StaticForwarder", "hasNovaPrefix", "(Ljava/lang/String;)Z", false)); list.add(new JumpInsnNode(IFNE, prev.label)); method.instructions.insert(prev, list); Game.logger().info("Injected instruction to method: {}", method.name); } private void transformRegisterItem(ClassNode cnode) { ObfMapping obfMap = new ObfMapping("net/minecraftforge/fml/common/registry/GameData", "registerItem", "(Lalq;Ljava/lang/String;)I"); ObfMapping deobfMap = new ObfMapping("net/minecraftforge/fml/common/registry/GameData", "registerItem", "(Lnet/minecraft/item/Item;Ljava/lang/String;)I"); MethodNode method = ASMHelper.findMethod(obfMap, cnode); if (method == null) { Game.logger().warn("Lookup {} failed. You are probably in a deobf environment.", obfMap); method = ASMHelper.findMethod(deobfMap, cnode); if (method == null) { throw new IllegalStateException("[NOVA] Lookup " + deobfMap + " failed!"); } } Game.logger().info("Transforming method {}", method.name); @SuppressWarnings("unchecked") JumpInsnNode prev = (JumpInsnNode) method.instructions.get(12); InsnList list = new InsnList(); list.add(new VarInsnNode(ALOAD, 2)); list.add(new MethodInsnNode(INVOKESTATIC, "nova/core/wrapper/mc/forge/v18/asm/StaticForwarder", "hasNovaPrefix", "(Ljava/lang/String;)Z", false)); list.add(new JumpInsnNode(IFNE, prev.label)); method.instructions.insert(prev, list); Game.logger().info("Injected instruction to method: {}", method.name); } }