|
3 | 3 | import java.lang.reflect.InvocationHandler; |
4 | 4 | import java.lang.reflect.Method; |
5 | 5 |
|
| 6 | +import javassist.CannotCompileException; |
6 | 7 | import javassist.ClassPool; |
7 | 8 | import javassist.CtClass; |
8 | 9 | import javassist.CtMethod; |
9 | 10 | import javassist.CtPrimitiveType; |
10 | 11 | import javassist.NotFoundException; |
11 | | -import javassist.bytecode.BadBytecode; |
12 | | -import javassist.bytecode.Bytecode; |
13 | | -import javassist.bytecode.CodeAttribute; |
14 | | -import javassist.bytecode.CodeIterator; |
15 | | -import javassist.bytecode.ConstPool; |
16 | 12 | import javassist.bytecode.Descriptor; |
17 | | -import javassist.bytecode.LocalVariableAttribute; |
18 | | -import javassist.bytecode.MethodInfo; |
| 13 | +import javassist.expr.ExprEditor; |
| 14 | +import javassist.expr.FieldAccess; |
19 | 15 |
|
20 | 16 | import org.gotti.wurmunlimited.modloader.classhooks.HookException; |
21 | 17 | import org.gotti.wurmunlimited.modloader.classhooks.HookManager; |
@@ -89,56 +85,31 @@ private void registerOnMessageHook() { |
89 | 85 | CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator"); |
90 | 86 |
|
91 | 87 | CtClass[] paramTypes = { |
92 | | - CtPrimitiveType.intType, |
93 | 88 | classPool.get("java.nio.ByteBuffer") |
94 | 89 | }; |
95 | 90 |
|
96 | | - String descriptor = Descriptor.ofMethod(CtClass.booleanType, new CtClass[] { |
97 | | - classPool.get("com.wurmonline.server.creatures.Communicator"), |
98 | | - classPool.get(String.class.getName()) |
99 | | - }); |
100 | | - |
101 | | - CtMethod method = ctCommunicator.getMethod("reallyHandle", Descriptor.ofMethod(CtPrimitiveType.voidType, paramTypes)); |
102 | | - MethodInfo methodInfo = method.getMethodInfo(); |
103 | | - CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); |
104 | | - ConstPool constPool = methodInfo.getConstPool(); |
105 | | - |
106 | | - LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag); |
107 | | - int messageIndex = -1; |
108 | | - for (int i = 0; i < attr.tableLength(); i++) { |
109 | | - if ("message".equals(attr.variableName(i))) { |
110 | | - messageIndex = attr.index(i); |
111 | | - } |
| 91 | + // com.wurmonline.server.creatures.Communicator.reallyHandle_CMD_MESSAGE(ByteBuffer) |
| 92 | + CtMethod method; |
| 93 | + try { |
| 94 | + method = ctCommunicator.getMethod("reallyHandle_CMD_MESSAGE", Descriptor.ofMethod(CtPrimitiveType.voidType, paramTypes)); |
| 95 | + } catch (NotFoundException e) { |
| 96 | + // Backward compatible |
| 97 | + method = ctCommunicator.getMethod("reallyHandle", Descriptor.ofMethod(CtPrimitiveType.voidType, paramTypes)); |
112 | 98 | } |
113 | 99 |
|
114 | | - if (messageIndex == -1) { |
115 | | - throw new HookException("Message variable can not be resolved"); |
116 | | - } |
117 | | - |
118 | | - CodeIterator codeIterator = codeAttribute.iterator(); |
119 | | - int lastOp = 0; |
120 | | - while (codeIterator.hasNext()) { |
121 | | - int pos = codeIterator.next(); |
122 | | - int op = codeIterator.byteAt(pos); |
123 | | - if (op == CodeIterator.PUTSTATIC) { |
124 | | - int indexByte1 = codeIterator.byteAt(pos + 1); |
125 | | - int indexByte2 = codeIterator.byteAt(pos + 2); |
126 | | - int constPoolIndex = indexByte1 << 8 | indexByte2; |
127 | | - if ("commandMessage".equals(constPool.getFieldrefName(constPoolIndex)) && lastOp == CodeIterator.ALOAD) { |
128 | | - Bytecode bytecode = new Bytecode(constPool); |
129 | | - bytecode.add(Bytecode.ALOAD_0); |
130 | | - bytecode.addAload(codeIterator.byteAt(pos - 1)); |
131 | | - bytecode.addInvokestatic(classPool.get(this.getClass().getName()), "communicatorMessageHook", descriptor); |
132 | | - bytecode.add(Bytecode.IFEQ, 0, 4, Bytecode.RETURN); |
133 | | - codeIterator.insertAt(pos + 3, bytecode.get()); |
134 | | - break; |
| 100 | + method.instrument(new ExprEditor() { |
| 101 | + @Override |
| 102 | + public void edit(FieldAccess f) throws CannotCompileException { |
| 103 | + if (f.isWriter() && f.getClassName().equals("com.wurmonline.server.creatures.Communicator") && f.getFieldName().equals("commandMessage")) { |
| 104 | + StringBuffer code = new StringBuffer(); |
| 105 | + code.append("$proceed($$);\n"); |
| 106 | + code.append(String.format("if (%s#communicatorMessageHook(this, $1)) { return; };\n", ProxyServerHook.class.getName())); |
| 107 | + f.replace(code.toString()); |
135 | 108 | } |
136 | 109 | } |
137 | | - lastOp = op; |
138 | | - } |
| 110 | + }); |
139 | 111 |
|
140 | | - methodInfo.rebuildStackMap(classPool); |
141 | | - } catch (NotFoundException | BadBytecode e) { |
| 112 | + } catch (NotFoundException | CannotCompileException e) { |
142 | 113 | throw new HookException(e); |
143 | 114 | } |
144 | 115 | } |
|
0 commit comments