private MethodNode fixMethod(MethodNode originalMethod) {
   CloneMap cloneMap = new CloneMap();
   MethodNode result = cloneMethodWithoutInstructions(originalMethod, cloneMap);
   result.instructions = fixInstructions(originalMethod, cloneMap);
   return result;
 }
  @Override
  boolean processMethods(List<MethodNode> methods) {
    int found = 0;
    for (MethodNode mn : methods) {
      if (mn.name.equals("<init>")) {
        logger.log(Level.INFO, "\tPatching constructor in EntityPlayer");
        ListIterator<AbstractInsnNode> it = mn.instructions.iterator();

        while (it.hasNext()) {
          AbstractInsnNode insn = it.next();
          if (insn instanceof TypeInsnNode) {
            if (((TypeInsnNode) insn).desc.equals(inventoryClassName)) {
              ((TypeInsnNode) insn).desc = "mods/battlegear2/api/core/InventoryPlayerBattle";
            }

          } else if (insn instanceof MethodInsnNode) {
            if (((MethodInsnNode) insn).owner.equals(inventoryClassName)) {
              ((MethodInsnNode) insn).owner = "mods/battlegear2/api/core/InventoryPlayerBattle";
            }
          }
        }
        found++;
      } else if (mn.name.equals(onItemFinishMethodName) && mn.desc.equals(SIMPLEST_METHOD_DESC)) {
        sendPatchLog("onItemUseFinish");
        InsnList newList = new InsnList();
        ListIterator<AbstractInsnNode> it = mn.instructions.iterator();
        while (it.hasNext()) {
          AbstractInsnNode next = it.next();
          if (next instanceof MethodInsnNode
              && ((MethodInsnNode) next)
                  .owner.equals("net/minecraftforge/event/ForgeEventFactory")) {
            found++;
            int index = ((MethodInsnNode) next).desc.indexOf(")");
            String newDesc =
                ((MethodInsnNode) next).desc.substring(0, index)
                    + "I"
                    + ((MethodInsnNode) next).desc.substring(index);
            newList.add(new VarInsnNode(ILOAD, 1));
            newList.add(
                new MethodInsnNode(INVOKESTATIC, UTILITY_CLASS, "beforeFinishUseEvent", newDesc));
          } else {
            newList.add(next);
          }
        }
        mn.instructions = newList;
      } else if (mn.name.equals(onUpdateMethodName) && mn.desc.equals(SIMPLEST_METHOD_DESC)) {
        sendPatchLog("onUpdate");
        InsnList newList = new InsnList();
        ListIterator<AbstractInsnNode> it = mn.instructions.iterator();
        while (it.hasNext()) {
          AbstractInsnNode next = it.next();
          if (next instanceof FieldInsnNode
              && ((FieldInsnNode) next).owner.equals(entityPlayerClassName)
              && ((FieldInsnNode) next).name.equals(playerInventoryFieldName)) {
            found++;
            newList.add(new VarInsnNode(ALOAD, 0));
            newList.add(
                new FieldInsnNode(
                    GETFIELD,
                    entityPlayerClassName,
                    playerItemInUseField,
                    "L" + itemStackClassName + ";"));
            newList.add(
                new MethodInsnNode(
                    INVOKESTATIC,
                    UTILITY_CLASS,
                    "getCurrentItemOnUpdate",
                    "(L"
                        + entityPlayerClassName
                        + ";L"
                        + itemStackClassName
                        + ";)L"
                        + itemStackClassName
                        + ";"));
            next = it.next();
          } else {
            newList.add(next);
          }
        }
        mn.instructions = newList;
      } else if (mn.name.equals(setCurrentItemArmourMethodName)
          && mn.desc.equals(setCurrentItemArmourMethodDesc)) {

        sendPatchLog("setCurrentItemOrArmor");
        replaceInventoryArrayAccess(
            mn, entityPlayerClassName, playerInventoryFieldName, mn.maxStack, mn.maxLocals);
        found++;
      } else if (mn.name.equals(interactWithMethodName) && mn.desc.equals(interactWithMethodDesc)) {
        sendPatchLog("interactWith");
        MethodNode mv =
            new MethodNode(ACC_PUBLIC, interactWithMethodName, interactWithMethodDesc, null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(
            INVOKESTATIC,
            UTILITY_CLASS,
            "interactWith",
            "(L" + entityPlayerClassName + ";L" + entityClassName + ";)Z");
        mv.visitInsn(IRETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + entityPlayerClassName + ";", null, l0, l1, 0);
        mv.visitLocalVariable("p_70998_1_", "L" + entityClassName + ";", null, l0, l1, 1);
        mv.visitMaxs(2, 2);
        mv.visitEnd();
        mn.instructions = mv.instructions;
        found++;
      }
    }

    logger.log(Level.INFO, "\tCreating new methods in EntityPlayer");
    methods.add(methods.size(), generateAttackOffhandMethod());
    methods.add(methods.size(), generateSwingOffhand());
    methods.add(methods.size(), generateGetOffSwingMethod());
    methods.add(methods.size(), generateUpdateSwingArm());
    methods.add(methods.size(), generateIsBattleMode());
    methods.add(methods.size(), generateIsBlockingWithShield());
    methods.add(methods.size(), generateSetBlockingWithShield());
    methods.add(
        methods.size(),
        generateGetter(entityPlayerClassName, "getSpecialActionTimer", "specialActionTimer", "I"));
    methods.add(
        methods.size(),
        generateSetter(entityPlayerClassName, "setSpecialActionTimer", "specialActionTimer", "I"));
    return found == 5;
  }