55import it .unimi .dsi .fastutil .chars .Char2ObjectOpenHashMap ;
66import it .unimi .dsi .fastutil .objects .Object2ObjectMaps ;
77import it .unimi .dsi .fastutil .objects .Object2ObjectOpenHashMap ;
8- import org . apache . commons . lang3 . tuple . Pair ;
8+ import it . unimi . dsi . fastutil . objects . ObjectOpenHashSet ;
99import org .codehaus .groovy .ast .ClassHelper ;
1010import org .codehaus .groovy .ast .ClassNode ;
1111import org .codehaus .groovy .ast .Parameter ;
1515import java .io .BufferedReader ;
1616import java .io .InputStream ;
1717import java .io .InputStreamReader ;
18- import java .util .ArrayList ;
19- import java .util .Arrays ;
20- import java .util .List ;
21- import java .util .Map ;
22- import java .util .stream .Collectors ;
18+ import java .util .*;
19+ import java .util .function .Function ;
2320
2421public class GroovyDeobfMapper {
2522
@@ -113,23 +110,60 @@ public static Map<String, String> getDeobfFields(Class<?> clazz) {
113110
114111 public static String getObfuscatedMethodName (ClassNode receiver , String method , Parameter [] args ) {
115112 ClassNode objClass = ClassHelper .OBJECT_TYPE ;
116- Map <String , MethodInfo > obfNames ;
117- String obfName = null ;
113+ Set <String > searched = new ObjectOpenHashSet <>() ;
114+ String obfName ;
118115
119116 do {
120- obfNames = OBF_METHOD_NAMES .get (receiver .getName ());
121- if (obfNames != null ) {
122- MethodInfo methodInfo = obfNames .get (method );
123- if (methodInfo != null ) {
124- obfName = methodInfo .findMethod (args );
125- }
117+ obfName = getObfMethodInClass (receiver , method , args );
118+ if (obfName == null ) {
119+ searched .add (receiver .getName ());
120+ obfName = forAllInterfaces (receiver , searched , i -> getObfMethodInClass (i , method , args ));
126121 }
127122 receiver = receiver .getSuperClass ();
128123 } while (obfName == null && receiver != null && receiver != objClass );
129124
130125 return obfName ;
131126 }
132127
128+ private static <T > T forAllInterfaces (ClassNode clz , Set <String > searched , Function <ClassNode , T > consumer ) {
129+ ClassNode [] interfaces = clz .getInterfaces ();
130+ if (interfaces == null || interfaces .length == 0 ) return null ;
131+ List <ClassNode > queue = new ArrayList <>();
132+ Collections .addAll (queue , interfaces );
133+ while (!queue .isEmpty ()) {
134+ ClassNode current = queue .remove (0 );
135+ T t = consumer .apply (current );
136+ if (t != null ) return t ;
137+ ClassNode superClass = current .getSuperClass ();
138+ if (superClass != null && !searched .contains (superClass .getName ())) {
139+ queue .add (superClass ); // idk if interfaces can have super classes or if its counted as interfaces everytime
140+ searched .add (superClass .getName ());
141+ }
142+ interfaces = current .getInterfaces ();
143+ if (interfaces != null ) {
144+ for (ClassNode i : interfaces ) {
145+ if (!searched .contains (i .getName ())) {
146+ queue .add (i );
147+ searched .add (i .getName ());
148+ }
149+ }
150+ }
151+ }
152+ return null ;
153+ }
154+
155+ @ Nullable
156+ private static String getObfMethodInClass (ClassNode clz , String method , Parameter [] args ) {
157+ Map <String , MethodInfo > obfNames = OBF_METHOD_NAMES .get (clz .getName ());
158+ if (obfNames != null ) {
159+ MethodInfo methodInfo = obfNames .get (method );
160+ if (methodInfo != null ) {
161+ return methodInfo .findMethod (args );
162+ }
163+ }
164+ return null ;
165+ }
166+
133167 public static String getObfuscatedFieldName (Class <?> receiver , String field ) {
134168 Class <Object > objClass = Object .class ;
135169 Map <String , String > obfNames ;
@@ -149,8 +183,8 @@ public static String getObfuscatedFieldName(Class<?> receiver, String field) {
149183 private static class MethodInfo {
150184
151185 private final String deobfName ;
152- // private Object2ObjectOpenCustomHashMap<Object[], String> obfNames;
153- private List <Pair < String [], String >> obfNames ;
186+ private List < String > obfNames ;
187+ private List <String []> obfArgs ;
154188 private final String defObfName ;
155189 private final String defArgs ;
156190
@@ -163,35 +197,45 @@ private MethodInfo(String deobfName, String defObfName, String defArgs) {
163197 public void registerOverloadedMethod (String obfName , String args ) {
164198 if (obfName .equals (defObfName )) return ;
165199 if (obfNames == null ) {
166- //obfNames = new Object2ObjectOpenCustomHashMap<>(PARAM_HASH_STRATEGY);
167- //obfNames.put(makeClassArray(defArgs), defObfName);
168200 obfNames = new ArrayList <>();
169- obfNames .add (Pair .of (makeClassArray (defArgs ), defObfName ));
201+ obfArgs = new ArrayList <>();
202+ obfNames .add (defObfName );
203+ obfArgs .add (makeClassArray (defArgs ));
170204 }
171- obfNames .add (Pair .of (makeClassArray (args ), obfName ));
205+ obfNames .add (obfName );
206+ obfArgs .add (makeClassArray (args ));
172207 }
173208
209+ @ Nullable
174210 public String findMethod (Parameter [] args ) {
175211 if (this .obfNames == null ) {
176212 return this .defObfName ;
177213 }
178- List <String > results = this .obfNames .stream ()
179- .filter (pair -> pair .getKey ().length == args .length )
180- .filter (pair -> {
181- for (int i = 0 ; i < args .length ; i ++) {
182- String origParam = pair .getKey ()[i ];
183- if (!matches (origParam , args [i ])) {
184- return false ;
185- }
186- }
187- return true ;
188- })
189- .map (Pair ::getValue )
190- .collect (Collectors .toList ());
191- if (results .isEmpty ()) return null ;
192- if (results .size () == 1 ) return results .get (0 );
193- GroovyLog .get ().errorMC ("Multiple methods match the name {} and params {}" , this .deobfName , Arrays .toString (args ));
194- return results .get (0 );
214+ String result = null ;
215+ for (int i = 0 ; i < this .obfNames .size (); i ++) {
216+ String obfName = this .obfNames .get (i );
217+ String [] obfArgs = this .obfArgs .get (i );
218+ if (matches (obfArgs , args )) {
219+ if (result == null ) {
220+ result = obfName ;
221+ } else {
222+ GroovyLog .get ().errorMC ("Multiple methods match the name {} and params {}" , this .deobfName , Arrays .toString (args ));
223+ return result ;
224+ }
225+ }
226+ }
227+ return result ;
228+ }
229+
230+ public static boolean matches (String [] original , Parameter [] parameters ) {
231+ if (original .length != parameters .length ) return false ;
232+ for (int j = 0 ; j < parameters .length ; j ++) {
233+ String origParam = original [j ];
234+ if (!matches (origParam , parameters [j ])) {
235+ return false ;
236+ }
237+ }
238+ return true ;
195239 }
196240
197241 public static boolean matches (String original , Parameter param ) {
0 commit comments