1414import java .nio .file .Files ;
1515import java .util .ArrayList ;
1616import java .util .Arrays ;
17- import java .util .Collections ;
17+ import java .util .Enumeration ;
1818import java .util .HashMap ;
1919import java .util .HashSet ;
2020import java .util .List ;
@@ -39,14 +39,14 @@ public class Generator {
3939 public static final String EXTENSION = ".lzma" ;
4040 private static final byte [] EMPTY_DATA = new byte [0 ];
4141
42- private final Map <String , String > o2m = new HashMap <>();
43- private final Map <String , String > m2o = new HashMap <>();
4442 private final Set <String > patches = new TreeSet <>();
4543
4644 private final File output ;
4745 private final List <PatchSet > sets = new ArrayList <>();
4846 private boolean pack200 = false ;
4947 private boolean legacy = false ;
48+ private IMappingFile o2m = null ;
49+ private IMappingFile m2o = null ;
5050
5151 public Generator (File output ) {
5252 this .output = output ;
@@ -85,12 +85,21 @@ public Generator legacy(boolean value) {
8585 return this ;
8686 }
8787
88- public void loadMappings (File srg ) throws IOException {
88+ /*
89+ * This is used when we do obfed binary patches
90+ * This should be the obf2srg mapping
91+ * We only use the class names and this is only used
92+ * to map the patch file class names to the obfed class files
93+ */
94+ public void loadMappings (File srg , boolean reverse ) throws IOException {
8995 IMappingFile map = IMappingFile .load (srg );
90- map .getClasses ().forEach (cls -> {
91- o2m .put (cls .getOriginal (), cls .getMapped ());
92- m2o .put (cls .getOriginal (), cls .getMapped ());
93- });
96+ if (reverse ) {
97+ o2m = map .reverse ();
98+ m2o = map ;
99+ } else {
100+ o2m = map ;
101+ m2o = map .reverse ();
102+ }
94103 }
95104
96105 public void loadPatches (File root ) throws IOException {
@@ -138,33 +147,39 @@ public void create() throws IOException {
138147 }
139148 }
140149
150+ private void gatherClasses (Map <String , Set <String >> entries , ZipFile archive ) {
151+ for (Enumeration <? extends ZipEntry > itr = archive .entries (); itr .hasMoreElements ();) {
152+ String name = itr .nextElement ().getName ();
153+ if (!name .endsWith (".class" ))
154+ continue ;
155+ name = name .substring (0 , name .length () - 6 );
156+ int idx = name .indexOf ('$' );
157+ String outer = idx == -1 ? name : name .substring (0 , idx );
158+ entries .computeIfAbsent (outer , k -> new HashSet <>()).add (name );
159+ }
160+ }
161+
141162 private Map <String , byte []> gatherPatches (File clean , File dirty ) throws IOException {
142163 Map <String , byte []> binpatches = new TreeMap <>();
143164 try (ZipFile zclean = new ZipFile (clean );
144165 ZipFile zdirty = new ZipFile (dirty )){
145166
167+ // This is a map of all classes to their 'sibling' classes.
168+ // Specifically all outer classes grouped with their inner classes.
169+ // This is done because when we modify a class, it could have durastic changes to the synthetic inner classes.
170+ // So we jus assume that if we patch one thing, we patch all inner classes
146171 Map <String , Set <String >> entries = new HashMap <>();
147- Collections .list (zclean .entries ()).stream ().map (e -> e .getName ()).filter (e -> e .endsWith (".class" )).map (e -> e .substring (0 , e .length () - 6 )).forEach (e -> {
148- int idx = e .indexOf ('$' );
149- if (idx != -1 )
150- entries .computeIfAbsent (e .substring (0 , idx ), k -> new HashSet <>()).add (e );
151- else
152- entries .computeIfAbsent (e , k -> new HashSet <>()).add (e );
153- });
154- Collections .list (zdirty .entries ()).stream ().map (e -> e .getName ()).filter (e -> e .endsWith (".class" )).map (e -> e .substring (0 , e .length () - 6 )).forEach (e -> {
155- int idx = e .indexOf ('$' );
156- if (idx != -1 )
157- entries .computeIfAbsent (e .substring (0 , idx ), k -> new HashSet <>()).add (e );
158- else
159- entries .computeIfAbsent (e , k -> new HashSet <>()).add (e );
160- });
172+ gatherClasses (entries , zclean );
173+ gatherClasses (entries , zdirty );
161174
162175 log ("Creating patches:" );
163176 log (" Clean: " + clean );
164177 log (" Dirty: " + dirty );
165178 if (patches .isEmpty ()) { //No patches, assume full set!
166179 for (String cls : entries .keySet ()) {
167- String srg = m2o .getOrDefault (cls , cls );
180+ // We use the srg name to make the names in the archive readable.
181+ // Doesn't actually effect the functionality, so is optional
182+ String srg = o2m == null ? cls : o2m .remapClass (cls );
168183 byte [] cleanData = getData (zclean , cls );
169184 byte [] dirtyData = getData (zdirty , cls );
170185 if (!Arrays .equals (cleanData , dirtyData )) {
@@ -175,17 +190,12 @@ private Map<String, byte[]> gatherPatches(File clean, File dirty) throws IOExcep
175190 }
176191 } else {
177192 for (String path : patches ) {
178- String obf = o2m .getOrDefault (path , path );
193+ // Map the patch dev name, to prodution name
194+ String obf = m2o == null ? path : m2o .remapClass (path );
195+
179196 if (entries .containsKey (obf )) {
180197 for (String cls : entries .get (obf )) {
181- String srg = m2o .get (cls );
182- if (srg == null ) {
183- int idx = cls .indexOf ('$' );
184- if (idx == -1 )
185- srg = path ;
186- else
187- srg = path + '$' + cls .substring (idx + 1 );
188- }
198+ String srg = o2m == null ? cls : o2m .remapClass (cls );
189199
190200 byte [] cleanData = getData (zclean , cls );
191201 byte [] dirtyData = getData (zdirty , cls );
0 commit comments