KajetansTransformer.java 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package me.ktcm;
  2. import net.minecraft.launchwrapper.IClassTransformer;
  3. import net.minecraft.launchwrapper.Launch;
  4. import org.objectweb.asm.ClassReader;
  5. import org.objectweb.asm.ClassWriter;
  6. import org.objectweb.asm.Opcodes;
  7. import org.objectweb.asm.tree.AbstractInsnNode;
  8. import org.objectweb.asm.tree.ClassNode;
  9. import org.objectweb.asm.tree.FieldInsnNode;
  10. import org.objectweb.asm.tree.FrameNode;
  11. import org.objectweb.asm.tree.InsnList;
  12. import org.objectweb.asm.tree.InsnNode;
  13. import org.objectweb.asm.tree.LineNumberNode;
  14. import org.objectweb.asm.tree.MethodInsnNode;
  15. import org.objectweb.asm.tree.MethodNode;
  16. import org.objectweb.asm.tree.VarInsnNode;
  17. public class KajetansTransformer implements IClassTransformer
  18. {
  19. private final boolean obfuscated;
  20. public KajetansTransformer()
  21. {
  22. Boolean ldev = (Boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment");
  23. if(ldev == null)
  24. {
  25. obfuscated = true;
  26. }
  27. else
  28. {
  29. obfuscated = !ldev;
  30. }
  31. }
  32. @Override
  33. public byte[] transform(String old, String searge, byte[] bytes)
  34. {
  35. if(searge.equals("net.minecraft.client.gui.FontRenderer"))
  36. {
  37. //net.minecraft.client.gui.FontRenderer;
  38. System.out.println("|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾");
  39. System.out.println("| Patching net.minecraft.client.gui.FontRenderer");
  40. System.out.println("|___________________________________________________");
  41. return patchColorHook(old, bytes);
  42. }
  43. return bytes;
  44. }
  45. public byte[] patchColorHook(String c, byte[] bytes)
  46. {
  47. try
  48. {
  49. ClassNode classNode = new ClassNode();
  50. ClassReader classReader = new ClassReader(bytes);
  51. classReader.accept(classNode, 0);
  52. // net/minecraft/client/gui/FontRenderer bip
  53. // func_78255_a renderStringAtPos Render a single line string at the current (posX,posY) and update posX
  54. // MD: net/minecraft/client/gui/FontRenderer/renderStringAtPos (Ljava/lang/String;Z)V bip/a (Ljava/lang/String;Z)V
  55. MethodNode mn;
  56. if(obfuscated)
  57. {
  58. mn = classNode.methods.stream().filter(me -> me.name.equals("a")).filter(me -> "(Ljava/lang/String;Z)V".equals(me.desc)).findAny().get();
  59. }
  60. else
  61. {
  62. mn = classNode.methods.stream().filter(me -> me.name.equals("renderStringAtPos")).findAny().get();
  63. }
  64. InsnList ins = mn.instructions;
  65. int index = 0;
  66. boolean found = false;
  67. AbstractInsnNode next;
  68. while(index < ins.size())
  69. {
  70. next = ins.get(index);
  71. if(next instanceof MethodInsnNode)
  72. {
  73. MethodInsnNode mnode = (MethodInsnNode) next;
  74. if(mnode.name.equals("valueOf") && mnode.desc.equals("(C)Ljava/lang/String;"))
  75. {
  76. found = true;
  77. // LdcInsnNode 18 9 - loading of string constant "0123456789abcdefklmnor", must be removed
  78. // VarInsnNode 25 2 1
  79. // VarInsnNode 21 2 3
  80. // InsnNode 4 0
  81. // InsnNode 96 0
  82. // MethodInsnNode 182 5 (I)C false charAt java/lang/String
  83. // insert new instruction here
  84. // MethodInsnNode 184 5 (C)Ljava/lang/String; false valueOf java/lang/String - search for this instruction, its not obfuscated
  85. // FieldInsnNode 178 4 Ljava/util/Locale; ROOT java/util/Locale - must be removed
  86. // MethodInsnNode 182 5 (Ljava/util/Locale;)Ljava/lang/String; false toLowerCase java/lang/String - must be removed
  87. // InsnNode 3 0 - must be removed
  88. // MethodInsnNode 182 5 (I)C false charAt java/lang/String - must be removed
  89. // MethodInsnNode 182 5 (I)I false indexOf java/lang/String - must be removed
  90. // VarInsnNode 54 2 5
  91. // LabelNode -1 8
  92. index--;
  93. ins.remove(ins.get(index - 5)); // remove "0123456789abcdefklmnor"
  94. ins.remove(ins.get(index));
  95. ins.remove(ins.get(index));
  96. ins.remove(ins.get(index));
  97. ins.remove(ins.get(index));
  98. ins.remove(ins.get(index));
  99. ins.remove(ins.get(index));
  100. ins.insert(ins.get(index - 1), new MethodInsnNode(Opcodes.INVOKESTATIC, "me/ktcm/events/Hooks", "onColorCodeChosen", "(CZ)I", false));
  101. ins.insert(ins.get(index - 1), new VarInsnNode(Opcodes.ILOAD, 2)); // push boolean shadow on the stack, inverted order
  102. break;
  103. }
  104. }
  105. index++;
  106. }
  107. if(!found)
  108. {
  109. System.out.println("Start of color hook was not found");
  110. return bytes;
  111. }
  112. /*java.util.ListIterator<AbstractInsnNode> list = ins.iterator();
  113. while(list.hasNext())
  114. {
  115. System.out.println(getString(list.next()));
  116. }*/
  117. ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
  118. classNode.accept(writer);
  119. return writer.toByteArray();
  120. }
  121. catch(Exception ex)
  122. {
  123. ex.printStackTrace();
  124. }
  125. return bytes;
  126. }
  127. public String getString(AbstractInsnNode node)
  128. {
  129. StringBuilder sb = new StringBuilder();
  130. sb.append(node.getClass().getSimpleName());
  131. sb.append(" ");
  132. sb.append(node.getOpcode());
  133. sb.append(" ");
  134. sb.append(node.getType());
  135. sb.append(" ");
  136. if(node instanceof LineNumberNode)
  137. {
  138. LineNumberNode n = (LineNumberNode) node;
  139. sb.append(n.line);
  140. sb.append(" ");
  141. sb.append(n.start);
  142. }
  143. else if(node instanceof VarInsnNode)
  144. {
  145. VarInsnNode n = (VarInsnNode) node;
  146. sb.append(n.var);
  147. }
  148. else if(node instanceof MethodInsnNode)
  149. {
  150. MethodInsnNode n = (MethodInsnNode) node;
  151. sb.append(n.desc);
  152. sb.append(" ");
  153. sb.append(n.itf);
  154. sb.append(" ");
  155. sb.append(n.name);
  156. sb.append(" ");
  157. sb.append(n.owner);
  158. }
  159. else if(node instanceof FrameNode)
  160. {
  161. FrameNode n = (FrameNode) node;
  162. if(n.local != null)
  163. {
  164. n.local.forEach(s -> {sb.append(s); sb.append(" ");});
  165. }
  166. if(n.stack != null)
  167. {
  168. n.stack.forEach(s -> {sb.append(s); sb.append(" ");});
  169. }
  170. }
  171. else if(node instanceof InsnNode)
  172. {
  173. }
  174. else if(node instanceof FieldInsnNode)
  175. {
  176. FieldInsnNode n = (FieldInsnNode) node;
  177. sb.append(n.desc);
  178. sb.append(" ");
  179. sb.append(n.name);
  180. sb.append(" ");
  181. sb.append(n.owner);
  182. }
  183. return sb.toString();
  184. }
  185. }