summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/translation/mapping
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/translation/mapping')
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsWriter.java144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsWriter.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsWriter.java
new file mode 100644
index 0000000..0a52dad
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsWriter.java
@@ -0,0 +1,144 @@
1package cuchaz.enigma.translation.mapping.serde;
2
3import com.google.common.base.Joiner;
4import com.google.common.collect.Lists;
5import cuchaz.enigma.ProgressListener;
6import cuchaz.enigma.translation.MappingTranslator;
7import cuchaz.enigma.translation.Translator;
8import cuchaz.enigma.translation.mapping.EntryMapping;
9import cuchaz.enigma.translation.mapping.MappingDelta;
10import cuchaz.enigma.translation.mapping.VoidEntryResolver;
11import cuchaz.enigma.translation.mapping.tree.EntryTree;
12import cuchaz.enigma.translation.mapping.tree.EntryTreeNode;
13import cuchaz.enigma.translation.representation.entry.ClassEntry;
14import cuchaz.enigma.translation.representation.entry.Entry;
15import cuchaz.enigma.translation.representation.entry.FieldEntry;
16import cuchaz.enigma.translation.representation.entry.MethodEntry;
17
18import java.io.BufferedWriter;
19import java.io.IOException;
20import java.io.Writer;
21import java.nio.charset.StandardCharsets;
22import java.nio.file.Files;
23import java.nio.file.Path;
24import java.util.Comparator;
25import java.util.HashSet;
26import java.util.Set;
27
28public class TinyMappingsWriter implements MappingsWriter {
29 private static final String VERSION_CONSTANT = "v1";
30 private static final Joiner TAB_JOINER = Joiner.on('\t');
31
32 // HACK: as of enigma 0.13.1, some fields seem to appear duplicated?
33 private final Set<String> writtenLines = new HashSet<>();
34 private final String nameObf;
35 private final String nameDeobf;
36
37 public TinyMappingsWriter(String nameObf, String nameDeobf) {
38 this.nameObf = nameObf;
39 this.nameDeobf = nameDeobf;
40 }
41
42 @Override
43 public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress) {
44 try {
45 Files.deleteIfExists(path);
46 Files.createFile(path);
47 } catch (IOException e) {
48 e.printStackTrace();
49 }
50
51 try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
52 writeLine(writer, new String[]{VERSION_CONSTANT, nameObf, nameDeobf});
53
54 Lists.newArrayList(mappings).stream()
55 .map(EntryTreeNode::getEntry).sorted(Comparator.comparing(Object::toString))
56 .forEach(entry -> writeEntry(writer, mappings, entry));
57 } catch (IOException e) {
58 e.printStackTrace();
59 }
60 }
61
62 private void writeEntry(Writer writer, EntryTree<EntryMapping> mappings, Entry<?> entry) {
63 EntryTreeNode<EntryMapping> node = mappings.findNode(entry);
64 if (node == null) {
65 return;
66 }
67
68 Translator translator = new MappingTranslator(mappings, VoidEntryResolver.INSTANCE);
69
70 EntryMapping mapping = mappings.get(entry);
71 if (mapping != null && !entry.getName().equals(mapping.getTargetName())) {
72 if (entry instanceof ClassEntry) {
73 writeClass(writer, (ClassEntry) entry, translator);
74 } else if (entry instanceof FieldEntry) {
75 writeLine(writer, serializeEntry(entry, mapping.getTargetName()));
76 } else if (entry instanceof MethodEntry) {
77 writeLine(writer, serializeEntry(entry, mapping.getTargetName()));
78 }
79 }
80
81 writeChildren(writer, mappings, node);
82 }
83
84 private void writeChildren(Writer writer, EntryTree<EntryMapping> mappings, EntryTreeNode<EntryMapping> node) {
85 node.getChildren().stream()
86 .filter(e -> e instanceof FieldEntry).sorted()
87 .forEach(child -> writeEntry(writer, mappings, child));
88
89 node.getChildren().stream()
90 .filter(e -> e instanceof MethodEntry).sorted()
91 .forEach(child -> writeEntry(writer, mappings, child));
92
93 node.getChildren().stream()
94 .filter(e -> e instanceof ClassEntry).sorted()
95 .forEach(child -> writeEntry(writer, mappings, child));
96 }
97
98 private void writeClass(Writer writer, ClassEntry entry, Translator translator) {
99 ClassEntry translatedEntry = translator.translate(entry);
100
101 String obfClassName = entry.getFullName();
102 String deobfClassName = translatedEntry.getFullName();
103 writeLine(writer, new String[]{"CLASS", obfClassName, deobfClassName});
104 }
105
106 private void writeLine(Writer writer, String[] data) {
107 try {
108 String line = TAB_JOINER.join(data) + "\n";
109 if (writtenLines.add(line)) {
110 writer.write(line);
111 }
112 } catch (IOException e) {
113 throw new RuntimeException(e);
114 }
115 }
116
117 private String[] serializeEntry(Entry<?> entry, String... extraFields) {
118 String[] data = null;
119
120 if (entry instanceof FieldEntry) {
121 data = new String[4 + extraFields.length];
122 data[0] = "FIELD";
123 data[1] = entry.getContainingClass().getFullName();
124 data[2] = ((FieldEntry) entry).getDesc().toString();
125 data[3] = entry.getName();
126 } else if (entry instanceof MethodEntry) {
127 data = new String[4 + extraFields.length];
128 data[0] = "METHOD";
129 data[1] = entry.getContainingClass().getFullName();
130 data[2] = ((MethodEntry) entry).getDesc().toString();
131 data[3] = entry.getName();
132 } else if (entry instanceof ClassEntry) {
133 data = new String[2 + extraFields.length];
134 data[0] = "CLASS";
135 data[1] = ((ClassEntry) entry).getFullName();
136 }
137
138 if (data != null) {
139 System.arraycopy(extraFields, 0, data, data.length - extraFields.length, extraFields.length);
140 }
141
142 return data;
143 }
144}