private static void stringEncryptionTransformer(ClassNode classNode) { if (classNode.superName.equals("org/bukkit/plugin/java/JavaPlugin") || classNode.superName.equals("net/md_5/bungee/api/plugin/Plugin")) { for (MethodNode methodNode : classNode.methods) { InsnList nodes = methodNode.instructions; for (int i = 0; i < nodes.size(); i++) { AbstractInsnNode instruction = nodes.get(i); if (instruction instanceof LdcInsnNode) { if (instruction.getNext() instanceof MethodInsnNode) { LdcInsnNode ldc = (LdcInsnNode) instruction; MethodInsnNode methodinsnnode = (MethodInsnNode) ldc.getNext(); if (ldc.cst instanceof String) { if (methodinsnnode.name.equalsIgnoreCase("\u0972") && methodinsnnode.desc.equalsIgnoreCase("(Ljava/lang/String;)Ljava/lang/String;")) { methodNode.instructions.remove(methodinsnnode); ldc.cst = decryptionArray((String)ldc.cst); } } } } } } } }
public static InsnList toNumericalValue(String what) { Objects.requireNonNull(what); InsnList il = new InsnList(); il.add(new LdcInsnNode(what)); il.add(new MethodInsnNode( INVOKESTATIC, Type.getInternalName(Conversions.class), "toNumericalValue", Type.getMethodDescriptor( Type.getType(Number.class), Type.getType(Object.class), Type.getType(String.class)), false)); return il; }
@Override public MethodTransformer[] getMethodTransformers() { MethodTransformer loadWorldTransformer = new MethodTransformer() { public String getMethodName() {return CoreLoader.isObfuscated ? "a" : "loadWorld";} public String getDescName() {return "(L" + (CoreLoader.isObfuscated ? "bnq" : Type.getInternalName(WorldClient.class)) + ";Ljava/lang/String;)V";} public void transform(ClassNode classNode, MethodNode method, boolean obfuscated) { CLTLog.info("Found method: " + method.name + " " + method.desc); CLTLog.info("begining at start of method " + getMethodName()); //TransformerUtil.onWorldLoad(WorldClient worldClientIn) InsnList toInsert = new InsnList(); toInsert.add(new VarInsnNode(ALOAD, 1)); //worldClientIn toInsert.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(TransformerUtil.class), "onWorldLoad", "(L" + Type.getInternalName(WorldClient.class) + ";)V", false)); method.instructions.insertBefore(method.instructions.getFirst(), toInsert); } }; return new MethodTransformer[] {loadWorldTransformer}; }
private Invoke.Type invokeType(MethodInsnNode method) { switch (method.getOpcode()) { case Opcodes.INVOKEVIRTUAL: if (isCallToPolymorphicSignatureMethod(method)) { return Invoke.Type.POLYMORPHIC; } return Invoke.Type.VIRTUAL; case Opcodes.INVOKESTATIC: return Invoke.Type.STATIC; case Opcodes.INVOKEINTERFACE: return Invoke.Type.INTERFACE; case Opcodes.INVOKESPECIAL: { DexType owner = application.getTypeFromName(method.owner); if (owner == clazz || method.name.equals(Constants.INSTANCE_INITIALIZER_NAME)) { return Invoke.Type.DIRECT; } else { return Invoke.Type.SUPER; } } default: throw new Unreachable("Unexpected MethodInsnNode opcode: " + method.getOpcode()); } }
private void build(MethodInsnNode insn, IRBuilder builder) { // Resolve the target method of the invoke. DexMethod method = application.getMethod(insn.owner, insn.name, insn.desc); buildInvoke( insn.desc, Type.getObjectType(insn.owner), insn.getOpcode() != Opcodes.INVOKESTATIC, builder, (types, registers) -> { Invoke.Type invokeType = invokeType(insn); DexProto callSiteProto = null; DexMethod targetMethod = method; if (invokeType == Invoke.Type.POLYMORPHIC) { targetMethod = application.getMethod( insn.owner, insn.name, METHODHANDLE_INVOKE_OR_INVOKEEXACT_DESC); callSiteProto = application.getProto(insn.desc); } builder.addInvoke(invokeType, targetMethod, callSiteProto, types, registers); }); }
private void checkArrayArgs(MethodNode methodNode, Frame<BasicValue> logMessageFrame, Frame<BasicValue> arraySizeFrame, int lineNumber, MethodInsnNode methodInsn, int messageIndex, int arrayIndex) { BasicValue arraySizeObject = getStackValue(arraySizeFrame, methodInsn, arrayIndex); if (arraySizeObject instanceof ArraySizeBasicValue == false) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "Could not determine size of array")); return; } ArraySizeBasicValue arraySize = (ArraySizeBasicValue) arraySizeObject; PlaceHolderStringBasicValue logMessageLength = checkLogMessageConsistency(methodNode, logMessageFrame, lineNumber, methodInsn, messageIndex, arraySize.minValue); if (logMessageLength == null) { return; } if (arraySize.minValue != arraySize.maxValue) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "Multiple parameter arrays with conflicting sizes")); return; } assert logMessageLength.minValue == logMessageLength.maxValue && arraySize.minValue == arraySize.maxValue; if (logMessageLength.minValue != arraySize.minValue) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "Expected " + logMessageLength.minValue + " arguments but got " + arraySize.minValue)); return; } }
private PlaceHolderStringBasicValue checkLogMessageConsistency(MethodNode methodNode, Frame<BasicValue> logMessageFrame, int lineNumber, MethodInsnNode methodInsn, int messageIndex, int argsSize) { BasicValue logMessageLengthObject = getStackValue(logMessageFrame, methodInsn, messageIndex); if (logMessageLengthObject instanceof PlaceHolderStringBasicValue == false) { if (argsSize > 0) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "First argument must be a string constant so that we can statically ensure proper place holder usage")); } else { // don't check logger usage for logger.warn(someObject) } return null; } PlaceHolderStringBasicValue logMessageLength = (PlaceHolderStringBasicValue) logMessageLengthObject; if (logMessageLength.minValue != logMessageLength.maxValue) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "Multiple log messages with conflicting number of place holders")); return null; } return logMessageLength; }
private void replaceInvokeSpecial(ClassNode clazz, List<MethodNode> toReplace) { for (MethodNode method : clazz.methods) { for (Iterator<AbstractInsnNode> it = method.instructions.iterator(); it.hasNext();) { AbstractInsnNode insn = it.next(); if (insn.getOpcode() == INVOKESPECIAL) { MethodInsnNode mInsn = (MethodInsnNode) insn; for (MethodNode n : toReplace) { if (n.name.equals(mInsn.name) && n.desc.equals(mInsn.desc)) { mInsn.setOpcode(INVOKEVIRTUAL); break; } } } } } }
@Override public void transform(ClassNode clazz, MethodNode method, InsnMatcher matcher) { method.tryCatchBlocks.clear(); method.localVariables.clear(); method.instructions.clear(); /* this.loginHandlerList.put(SteamIdAsString, loginHandler); */ method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); method.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "com/wurmonline/server/steam/SteamHandler", "loginHandlerList", "Ljava/util/Map;")); method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); method.instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "java/util/Map", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true)); method.instructions.add(new InsnNode(Opcodes.POP)); /* return true; */ method.instructions.add(new InsnNode(Opcodes.ICONST_1)); method.instructions.add(new InsnNode(Opcodes.IRETURN)); }
public static InsnList newTable(int array, int hash) { InsnList il = new InsnList(); il.add(ASMUtils.loadInt(array)); il.add(ASMUtils.loadInt(hash)); il.add(new MethodInsnNode( INVOKEINTERFACE, selfTpe().getInternalName(), "newTable", Type.getMethodType( Type.getType(Table.class), Type.INT_TYPE, Type.INT_TYPE).getDescriptor(), true)); return il; }
public static InsnList get(int index) { Check.nonNegative(index); InsnList il = new InsnList(); if (index <= 4) { String methodName = "get" + index; il.add(new MethodInsnNode( INVOKEINTERFACE, selfTpe().getInternalName(), methodName, Type.getMethodType( Type.getType(Object.class)).getDescriptor(), true)); } else { il.add(ASMUtils.loadInt(index)); il.add(get()); } return il; }
protected InsnList resumptionHandler(LabelNode label) { InsnList il = new InsnList(); il.add(label); il.add(ASMUtils.frameSame1(UnresolvedControlThrowable.class)); il.add(createSnapshot()); // register snapshot with the control exception il.add(new MethodInsnNode( INVOKEVIRTUAL, Type.getInternalName(UnresolvedControlThrowable.class), "resolve", Type.getMethodType( Type.getType(ResolvedControlThrowable.class), Type.getType(Resumable.class), Type.getType(Object.class)).getDescriptor(), false)); // rethrow il.add(new InsnNode(ATHROW)); return il; }
private Detour callDetour(ClassNode cn, MethodNode mn, AnnotationNode a) { String owner = getFirstParameter(mn); if (owner == null) { _log.debug("Could not get parameter type for detour " + mn.name + mn.desc); return null; } MethodInsnNode mi = getMethodInstruction(mn, owner, mn.name); if (mi == null) { _log.debug("Could not get method instruction for detour " + mn.name + mn.desc); return null; } CallDetour detour = new CallDetour(_log); detour.matchMethod = mn.name; detour.matchDesc = mi.desc; detour.owner = owner.replace('/', '.'); detour.detourOwner = cn.name; detour.detourDesc = mn.desc; return detour; }
@SuppressWarnings("unchecked") boolean analyze() { for (final Iterator<AbstractInsnNode> it = methodNode.instructions.iterator(); it .hasNext();) { //CHECKSTYLE:OFF final AbstractInsnNode instruction = it.next(); //CHECKSTYLE:ON if (instruction instanceof MethodInsnNode) { final MethodInsnNode methodInsnNode = (MethodInsnNode) instruction; if (STRING_INTERNAL_NAME.equals(methodInsnNode.owner) && "toString".equals(methodInsnNode.name)) { // il n'y a qu'une méthode toString dans la classe String, inutile de vérifier desc return true; } } } return false; }
public void populateClassGraph() { String className = Type.getObjectType(classNode.name).getClassName(); logger.debug("Creating graph for class {}" , className); for (MethodNode methodNode : classNode.methods) { String methodName = methodNode.name; MethodGraph caller = new MethodGraph(className, methodName); InsnList instructions = methodNode.instructions; for (int i = 0; i < instructions.size(); i++) { AbstractInsnNode insnNode = instructions.get(i); if (insnNode.getType() == AbstractInsnNode.METHOD_INSN) { MethodInsnNode methodInsnNode = (MethodInsnNode)insnNode; String calledOwner = Type.getObjectType(methodInsnNode.owner).getClassName(); String calledName = methodInsnNode.name; MethodGraph called = new MethodGraph(calledOwner, calledName); Call call = new Call(caller, called); if (!called.getOwner().equals("java.lang.Object") && !called.getName().equals("<init>")) { logger.trace("Adding call graph: {}", call.toString()); GraphHolder.addCallGraph(call); } } } } }
@Override public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values) throws AnalyzerException { if (insn instanceof MethodInsnNode) { boolean skipOne = insn.getOpcode() != Opcodes.INVOKESTATIC; // Note if the argument is a holder, and is used as a function argument for(BasicValue value : values) { // if non-static method, skip over the receiver if (skipOne) { skipOne = false; continue; } if (value instanceof ReplacingBasicValue) { final ReplacingBasicValue argument = (ReplacingBasicValue) value; argument.setFunctionArgument(); } } } return super.naryOperation(insn, values); }
@Override public MethodTransformer[] getMethodTransformers() { MethodTransformer transformLoadWorld = new MethodTransformer() { @Override public MethodName getName() { return Names.Minecraft_loadWorld; } @Override public void transform(ClassNode classNode, MethodNode method, boolean obfuscated) { CLTLog.info("Found method: " + method.name + " " + method.desc); CLTLog.info("begining at start of method " + getName().all()); InsnList toInsert = new InsnList(); toInsert.add(new VarInsnNode(ALOAD, 1)); //worldClientIn toInsert.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(RenderUtil.class), "onWorldLoad", "(L" + Type.getInternalName(WorldClient.class) + ";)V", false)); method.instructions.insertBefore(method.instructions.getFirst(), toInsert); } }; return new MethodTransformer[] {transformLoadWorld}; }
public static void setSuper(ClassNode node, String superClass) { String replacedSuper = ""; if (node.superName != "") { replacedSuper = node.superName; } if (replacedSuper != "") { ListIterator<?> mli = node.methods.listIterator(); while (mli.hasNext()) { MethodNode mn = (MethodNode) mli.next(); ListIterator<?> ili = mn.instructions.iterator(); while (ili.hasNext()) { AbstractInsnNode ain = (AbstractInsnNode) ili.next(); if (ain.getOpcode() == Opcodes.INVOKESPECIAL) { MethodInsnNode min = (MethodInsnNode) ain; if (min.owner.equals(replacedSuper)) { min.owner = superClass; } } } } } node.superName = superClass; }
public static boolean areNodesEqual(AbstractInsnNode node, AbstractInsnNode node2) { if (node.getClass() == node2.getClass() && node.getOpcode() == node2.getOpcode()) { if (node instanceof MethodInsnNode) { return ((MethodInsnNode) node).name.equals(((MethodInsnNode) node2).name) && ((MethodInsnNode) node).desc.equals(((MethodInsnNode) node2).desc) && ((MethodInsnNode) node).owner.equals(((MethodInsnNode) node2).owner); } else if (node instanceof VarInsnNode) { return ((VarInsnNode) node).var == ((VarInsnNode) node2).var; } else if (node instanceof InsnNode) { return true; } else if (node instanceof TypeInsnNode) { return ((TypeInsnNode) node).desc.equals(((TypeInsnNode) node2).desc); } else if (node instanceof JumpInsnNode) { return ((JumpInsnNode) node).label == ((JumpInsnNode) node2).label; } else if (node instanceof LabelNode) { return node == node2; } else if (node instanceof LineNumberNode) { return ((LineNumberNode) node).line == ((LineNumberNode) node2).line; } else if (node instanceof FieldInsnNode) { return ((FieldInsnNode) node).name.equals(((FieldInsnNode) node2).name) && ((FieldInsnNode) node).desc.equals(((FieldInsnNode) node2).desc) && ((FieldInsnNode) node).owner.equals(((FieldInsnNode) node2).owner); } else if (node instanceof LdcInsnNode) { return ((LdcInsnNode) node).cst.equals(((LdcInsnNode) node2).cst); } } return false; }
public static boolean isCallToInterface(MethodInsnNode insn) { assert insn.itf || insn.getOpcode() != Opcodes.INVOKEINTERFACE; return insn.itf; /*return insn.getOpcode() == Opcodes.INVOKEINTERFACE || (insn.getOpcode() == Opcodes.INVOKESPECIAL || insn.getOpcode() == Opcodes.INVOKESTATIC) && insn.itf;*/ }
/** * Replaces class references in super constructor invocations. * Must not replace references in this() constructor invocations. * * @param theClass the class being patched * @param extenderClass the injected superclass * @param mn method to process */ private static void replaceSuperCtorCalls(final ClassNode theClass, final ClassNode extenderClass, MethodNode mn) { for (Iterator it = mn.instructions.iterator(); it.hasNext(); ) { AbstractInsnNode aIns = (AbstractInsnNode)it.next(); if (aIns.getOpcode() == Opcodes.INVOKESPECIAL) { MethodInsnNode mins = (MethodInsnNode)aIns; if (CONSTRUCTOR_NAME.equals(mins.name) && mins.owner.equals(extenderClass.superName)) { // replace with the extender class name mins.owner = extenderClass.name; } break; } } }
@Override public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values) throws AnalyzerException { int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); } else if (opcode == INVOKEDYNAMIC) { return newValue(Type .getReturnType(((InvokeDynamicInsnNode) insn).desc)); } else { return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); } }
@Override public MethodTransformer[] getMethodTransformers() { MethodTransformer transformSetBlockState = new MethodTransformer() { public String getMethodName() {return CoreLoader.isObfuscated ? "a" : "setBlockState";} public String getDescName() { if (CoreLoader.isObfuscated) { return "(Lco;Latl;)Latl;"; } else { return "(L" + Type.getInternalName(BlockPos.class) + ";L" + Type.getInternalName(IBlockState.class) + ";)L" + Type.getInternalName(IBlockState.class) + ";"; } } @Override public void transform(ClassNode classNode, MethodNode method, boolean obfuscated) { CLTLog.info("Found method: " + method.name + " " + method.desc); InsnList toInsert = new InsnList(); //TransformerUtil.onChunkModified(this); toInsert.add(new VarInsnNode(ALOAD, 0)); //this toInsert.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(TransformerUtil.class), "onChunkModified", "(L" + classNode.name + ";)V", false)); //onChunkModified method.instructions.insert(toInsert); } }; return new MethodTransformer[] {transformSetBlockState}; }
@Override public MethodTransformer[] getMethodTransformers() { MethodTransformer transformDoStitch = new MethodTransformer() { public String getMethodName() {return CoreLoader.isObfuscated ? "c" : "doStitch";} public String getDescName() {return "()V";} @Override public void transform(ClassNode classNode, MethodNode method, boolean obfuscated) { CLTLog.info("Found method: " + method.name + " " + method.desc); AbstractInsnNode instruction = method.instructions.getLast(); //find ProgressManager.pop for (int i = 0; i < 5; i++) { instruction = instruction.getPrevious(); } InsnList toInsert = new InsnList(); //TransformerUtil.createTextureMap(stitchSlots); toInsert.add(new VarInsnNode(ALOAD, 0)); //this toInsert.add(new FieldInsnNode(GETFIELD, classNode.name, obfuscated ? "field_94317_b" : "stitchSlots", "Ljava/util/List;")); //stitchSlots toInsert.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(TransformerUtil.class), "createTextureMap", "(Ljava/util/List;)V", false)); //TransformerUtil.createTextureMap method.instructions.insertBefore(instruction, toInsert); } }; return new MethodTransformer[] {transformDoStitch}; }
@Override public MethodTransformer[] getMethodTransformers() { MethodTransformer transformSetupCameraTransform = new MethodTransformer() { public String getMethodName() {return CoreLoader.isObfuscated ? "a" : "setupCameraTransform";} public String getDescName() {return "(FI)V";} /** * Transforms {@link net.minecraft.client.renderer.EntityRenderer#setupCameraTransform()} */ public void transform(ClassNode classNode, MethodNode method, boolean obfuscated) { CLTLog.info("Found method: " + method.name + " " + method.desc); for (AbstractInsnNode instruction : method.instructions.toArray()) { if (instruction.getOpcode() == TABLESWITCH) { CLTLog.info("Found tableswitch in method " + getMethodName()); //Go back to orientCamera for (int i = 0; i < 8+4; i++) { instruction = instruction.getPrevious(); } InsnList toInsert = new InsnList(); //GlStateManager.translate(0, 0, -0.05F); toInsert.add(new InsnNode(FCONST_0)); //0 toInsert.add(new InsnNode(FCONST_0)); //0 toInsert.add(new LdcInsnNode(-0.05f)); //-0.05 toInsert.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(GlStateManager.class), obfuscated ? "func_179109_b" : "translate", "(FFF)V", false)); method.instructions.insertBefore(instruction, toInsert); break; } } } }; return new MethodTransformer[] {transformSetupCameraTransform}; }
private void checkFixedArityArgs(MethodNode methodNode, Frame<BasicValue> logMessageFrame, int lineNumber, MethodInsnNode methodInsn, int messageIndex, int positionalArgsLength) { PlaceHolderStringBasicValue logMessageLength = checkLogMessageConsistency(methodNode, logMessageFrame, lineNumber, methodInsn, messageIndex, positionalArgsLength); if (logMessageLength == null) { return; } if (logMessageLength.minValue != positionalArgsLength) { wrongUsageCallback.accept(new WrongLoggerUsage(className, methodNode.name, methodInsn.name, lineNumber, "Expected " + logMessageLength.minValue + " arguments but got " + positionalArgsLength)); return; } }
@Override public SourceValue naryOperation(final AbstractInsnNode insn, final List<? extends SourceValue> values) { int size; int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { size = 1; } else { String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc : ((MethodInsnNode) insn).desc; size = Type.getReturnType(desc).getSize(); } return new SourceValue(size, insn); }
public MethodDefinition invokeSpecial( ParameterizedType type, String name, ParameterizedType returnType, List<ParameterizedType> parameterTypes) { instructionList.add( new MethodInsnNode( INVOKESPECIAL, type.getClassName(), name, methodDescription(returnType, parameterTypes), false)); return this; }
public MethodDefinition invokeStatic(Method method) { instructionList.add( new MethodInsnNode( INVOKESTATIC, Type.getInternalName(method.getDeclaringClass()), method.getName(), Type.getMethodDescriptor(method), false)); return this; }
public MethodDefinition invokeVirtual( Class<?> type, String name, Class<?> returnType, Class<?>... parameterTypes) { instructionList.add( new MethodInsnNode( INVOKEVIRTUAL, type(type).getClassName(), name, methodDescription(returnType, parameterTypes), false)); return this; }
public MethodDefinition invokeVirtual( ParameterizedType type, String name, ParameterizedType returnType, ParameterizedType... parameterTypes) { instructionList.add( new MethodInsnNode( INVOKEVIRTUAL, type.getClassName(), name, methodDescription(returnType, parameterTypes), false)); return this; }
public static AbstractInsnNode numeric(String methodName, int numArgs) { Type[] args = new Type[numArgs]; Arrays.fill(args, Type.getType(Number.class)); return new MethodInsnNode( INVOKESTATIC, Type.getInternalName(Dispatch.class), methodName, Type.getMethodDescriptor( Type.getType(Number.class), args), false); }
public static AbstractInsnNode continueLoop() { return new MethodInsnNode( INVOKESTATIC, Type.getInternalName(Dispatch.class), "signed_le", Type.getMethodDescriptor( Type.BOOLEAN_TYPE, Type.getType(Number.class), Type.getType(Number.class), Type.getType(Number.class)), false); }
public static MethodInsnNode ctor(Type of, Type... args) { return new MethodInsnNode( INVOKESPECIAL, of.getInternalName(), "<init>", Type.getMethodDescriptor( Type.VOID_TYPE, args), false); }
@Override public void transform(ClassNode clazz, MethodNode method, InsnMatcher matcher) { InsnList list = new InsnList(); /* PluginManager.getPluginManager().init(new ClientPluginContext(this)); */ list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/wyverngame/anvil/api/PluginManager", "getInstance", "()Lcom/wyverngame/anvil/api/PluginManager;", false)); list.add(new TypeInsnNode(Opcodes.NEW, "com/wyverngame/anvil/api/client/ClientPluginContext")); list.add(new InsnNode(Opcodes.DUP)); list.add(new VarInsnNode(Opcodes.ALOAD, 0)); list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "com/wyverngame/anvil/api/client/ClientPluginContext", "<init>", "(Lcom/wurmonline/client/WurmClientBase;)V", false)); list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "com/wyverngame/anvil/api/PluginManager", "init", "(Lcom/wyverngame/anvil/api/PluginContext;)V", false)); method.instructions.insertBefore(method.instructions.getFirst(), list); }
public static AbstractInsnNode rawBinaryOperator(String methodName, Type returnType, Type argType) { return new MethodInsnNode( INVOKESTATIC, Type.getInternalName(LuaMathOperators.class), methodName, Type.getMethodDescriptor( returnType, argType, argType), false); }
public static AbstractInsnNode stringLen() { return new MethodInsnNode( INVOKESTATIC, Type.getInternalName(LuaMathOperators.class), "stringLen", Type.getMethodDescriptor( Type.INT_TYPE, Type.getType(String.class)), false); }