summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--enigma-cli/src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java6
-rw-r--r--enigma-cli/src/main/java/cuchaz/enigma/command/Command.java26
-rw-r--r--enigma-cli/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java35
-rw-r--r--enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java48
-rw-r--r--enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java42
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java107
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingIoConverter.java10
-rw-r--r--enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java6
8 files changed, 168 insertions, 112 deletions
diff --git a/enigma-cli/src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java b/enigma-cli/src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java
index 922d668..5e64b2c 100644
--- a/enigma-cli/src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java
+++ b/enigma-cli/src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java
@@ -10,7 +10,6 @@ import cuchaz.enigma.ProgressListener;
10import cuchaz.enigma.analysis.index.JarIndex; 10import cuchaz.enigma.analysis.index.JarIndex;
11import cuchaz.enigma.classprovider.ClasspathClassProvider; 11import cuchaz.enigma.classprovider.ClasspathClassProvider;
12import cuchaz.enigma.translation.mapping.EntryMapping; 12import cuchaz.enigma.translation.mapping.EntryMapping;
13import cuchaz.enigma.translation.mapping.serde.MappingFormat;
14import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; 13import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters;
15import cuchaz.enigma.translation.mapping.tree.EntryTree; 14import cuchaz.enigma.translation.mapping.tree.EntryTree;
16import cuchaz.enigma.translation.representation.entry.ClassEntry; 15import cuchaz.enigma.translation.representation.entry.ClassEntry;
@@ -38,15 +37,12 @@ public class CheckMappingsCommand extends Command {
38 Enigma enigma = Enigma.create(); 37 Enigma enigma = Enigma.create();
39 38
40 System.out.println("Reading JAR..."); 39 System.out.println("Reading JAR...");
41
42 EnigmaProject project = enigma.openJar(fileJarIn, new ClasspathClassProvider(), ProgressListener.none()); 40 EnigmaProject project = enigma.openJar(fileJarIn, new ClasspathClassProvider(), ProgressListener.none());
43 41
44 System.out.println("Reading mappings..."); 42 System.out.println("Reading mappings...");
45
46 MappingFormat format = chooseEnigmaFormat(fileMappings);
47 MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters(); 43 MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters();
48 44
49 EntryTree<EntryMapping> mappings = format.read(fileMappings, ProgressListener.none(), saveParameters); 45 EntryTree<EntryMapping> mappings = readMappings(fileMappings, ProgressListener.none(), saveParameters);
50 project.setMappings(mappings); 46 project.setMappings(mappings);
51 47
52 JarIndex idx = project.getJarIndex(); 48 JarIndex idx = project.getJarIndex();
diff --git a/enigma-cli/src/main/java/cuchaz/enigma/command/Command.java b/enigma-cli/src/main/java/cuchaz/enigma/command/Command.java
index 04d49f2..ef7cfaa 100644
--- a/enigma-cli/src/main/java/cuchaz/enigma/command/Command.java
+++ b/enigma-cli/src/main/java/cuchaz/enigma/command/Command.java
@@ -1,11 +1,15 @@
1package cuchaz.enigma.command; 1package cuchaz.enigma.command;
2 2
3import java.io.File; 3import java.io.File;
4import java.io.IOException;
4import java.nio.file.Files; 5import java.nio.file.Files;
5import java.nio.file.Path; 6import java.nio.file.Path;
6import java.nio.file.Paths; 7import java.nio.file.Paths;
7 8
8import com.google.common.io.MoreFiles; 9import com.google.common.io.MoreFiles;
10import net.fabricmc.mappingio.MappingReader;
11import net.fabricmc.mappingio.tree.MemoryMappingTree;
12import net.fabricmc.mappingio.tree.VisitableMappingTree;
9 13
10import cuchaz.enigma.Enigma; 14import cuchaz.enigma.Enigma;
11import cuchaz.enigma.EnigmaProject; 15import cuchaz.enigma.EnigmaProject;
@@ -13,6 +17,8 @@ import cuchaz.enigma.ProgressListener;
13import cuchaz.enigma.classprovider.ClasspathClassProvider; 17import cuchaz.enigma.classprovider.ClasspathClassProvider;
14import cuchaz.enigma.translation.mapping.EntryMapping; 18import cuchaz.enigma.translation.mapping.EntryMapping;
15import cuchaz.enigma.translation.mapping.serde.MappingFormat; 19import cuchaz.enigma.translation.mapping.serde.MappingFormat;
20import cuchaz.enigma.translation.mapping.serde.MappingIoConverter;
21import cuchaz.enigma.translation.mapping.serde.MappingParseException;
16import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; 22import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters;
17import cuchaz.enigma.translation.mapping.tree.EntryTree; 23import cuchaz.enigma.translation.mapping.tree.EntryTree;
18 24
@@ -41,7 +47,7 @@ public abstract class Command {
41 System.out.println("Reading mappings..."); 47 System.out.println("Reading mappings...");
42 48
43 MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters(); 49 MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters();
44 EntryTree<EntryMapping> mappings = chooseEnigmaFormat(fileMappings).read(fileMappings, progress, saveParameters); 50 EntryTree<EntryMapping> mappings = readMappings(fileMappings, progress, saveParameters);
45 51
46 project.setMappings(mappings); 52 project.setMappings(mappings);
47 } 53 }
@@ -49,14 +55,18 @@ public abstract class Command {
49 return project; 55 return project;
50 } 56 }
51 57
52 protected static MappingFormat chooseEnigmaFormat(Path path) { 58 protected static EntryTree<EntryMapping> readMappings(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException {
53 if (Files.isDirectory(path)) { 59 // Legacy
54 return MappingFormat.ENIGMA_DIRECTORY; 60 if ("zip".equalsIgnoreCase(MoreFiles.getFileExtension(path))) {
55 } else if ("zip".equalsIgnoreCase(MoreFiles.getFileExtension(path))) { 61 return MappingFormat.ENIGMA_ZIP.read(path, progress, saveParameters);
56 return MappingFormat.ENIGMA_ZIP;
57 } else {
58 return MappingFormat.ENIGMA_FILE;
59 } 62 }
63
64 net.fabricmc.mappingio.format.MappingFormat format = MappingReader.detectFormat(path);
65 if (format == null) throw new IllegalArgumentException("Unknown mapping format!");
66
67 VisitableMappingTree tree = new MemoryMappingTree();
68 MappingReader.read(path, format, tree);
69 return MappingIoConverter.fromMappingIo(tree, progress);
60 } 70 }
61 71
62 protected static File getWritableFile(String path) { 72 protected static File getWritableFile(String path) {
diff --git a/enigma-cli/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java b/enigma-cli/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java
index 787625b..c452d8c 100644
--- a/enigma-cli/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java
+++ b/enigma-cli/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java
@@ -4,14 +4,15 @@ import java.io.IOException;
4import java.nio.file.Files; 4import java.nio.file.Files;
5import java.nio.file.Path; 5import java.nio.file.Path;
6 6
7import net.fabricmc.mappingio.MappingWriter;
8import net.fabricmc.mappingio.tree.VisitableMappingTree;
9
7import cuchaz.enigma.ProgressListener; 10import cuchaz.enigma.ProgressListener;
8import cuchaz.enigma.translation.mapping.EntryMapping; 11import cuchaz.enigma.translation.mapping.EntryMapping;
9import cuchaz.enigma.translation.mapping.serde.MappingFormat; 12import cuchaz.enigma.translation.mapping.serde.MappingFormat;
13import cuchaz.enigma.translation.mapping.serde.MappingIoConverter;
10import cuchaz.enigma.translation.mapping.serde.MappingParseException; 14import cuchaz.enigma.translation.mapping.serde.MappingParseException;
11import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; 15import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters;
12import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsReader;
13import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsWriter;
14import cuchaz.enigma.translation.mapping.serde.tiny.TinyMappingsReader;
15import cuchaz.enigma.translation.mapping.serde.tiny.TinyMappingsWriter; 16import cuchaz.enigma.translation.mapping.serde.tiny.TinyMappingsWriter;
16import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Writer; 17import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Writer;
17import cuchaz.enigma.translation.mapping.tree.EntryTree; 18import cuchaz.enigma.translation.mapping.tree.EntryTree;
@@ -22,11 +23,11 @@ public final class MappingCommandsUtil {
22 23
23 public static EntryTree<EntryMapping> read(String type, Path path, MappingSaveParameters saveParameters) throws MappingParseException, IOException { 24 public static EntryTree<EntryMapping> read(String type, Path path, MappingSaveParameters saveParameters) throws MappingParseException, IOException {
24 if (type.equals("enigma")) { 25 if (type.equals("enigma")) {
25 return (Files.isDirectory(path) ? EnigmaMappingsReader.DIRECTORY : EnigmaMappingsReader.ZIP).read(path, ProgressListener.none(), saveParameters); 26 return (Files.isDirectory(path) ? MappingFormat.ENIGMA_DIRECTORY : MappingFormat.ENIGMA_ZIP).read(path, ProgressListener.none(), saveParameters);
26 } 27 }
27 28
28 if (type.equals("tiny")) { 29 if (type.equals("tiny")) {
29 return TinyMappingsReader.INSTANCE.read(path, ProgressListener.none(), saveParameters); 30 return MappingFormat.TINY_FILE.read(path, ProgressListener.none(), saveParameters);
30 } 31 }
31 32
32 MappingFormat format = null; 33 MappingFormat format = null;
@@ -40,15 +41,15 @@ public final class MappingCommandsUtil {
40 } 41 }
41 42
42 if (format != null) { 43 if (format != null) {
43 return format.getReader().read(path, ProgressListener.none(), saveParameters); 44 return format.read(path, ProgressListener.none(), saveParameters);
44 } 45 }
45 46
46 throw new IllegalArgumentException("no reader for " + type); 47 throw new IllegalArgumentException("no reader for " + type);
47 } 48 }
48 49
49 public static void write(EntryTree<EntryMapping> mappings, String type, Path path, MappingSaveParameters saveParameters) { 50 public static void write(EntryTree<EntryMapping> mappings, String type, Path path, MappingSaveParameters saveParameters) throws IOException {
50 if (type.equals("enigma")) { 51 if (type.equals("enigma")) {
51 EnigmaMappingsWriter.DIRECTORY.write(mappings, path, ProgressListener.none(), saveParameters); 52 MappingFormat.ENIGMA_DIRECTORY.write(mappings, path, ProgressListener.none(), saveParameters);
52 return; 53 return;
53 } 54 }
54 55
@@ -59,7 +60,13 @@ public final class MappingCommandsUtil {
59 throw new IllegalArgumentException("specify column names as 'tinyv2:from_namespace:to_namespace'"); 60 throw new IllegalArgumentException("specify column names as 'tinyv2:from_namespace:to_namespace'");
60 } 61 }
61 62
62 new TinyV2Writer(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters); 63 if (!System.getProperty("enigma.use_mappingio", "true").equals("true")) {
64 new TinyV2Writer(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters);
65 return;
66 }
67
68 VisitableMappingTree tree = MappingIoConverter.toMappingIo(mappings, ProgressListener.none(), split[1], split[2]);
69 tree.accept(MappingWriter.create(path, net.fabricmc.mappingio.format.MappingFormat.TINY_2_FILE));
63 return; 70 return;
64 } 71 }
65 72
@@ -70,7 +77,13 @@ public final class MappingCommandsUtil {
70 throw new IllegalArgumentException("specify column names as 'tiny:from_column:to_column'"); 77 throw new IllegalArgumentException("specify column names as 'tiny:from_column:to_column'");
71 } 78 }
72 79
73 new TinyMappingsWriter(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters); 80 if (!System.getProperty("enigma.use_mappingio", "true").equals("true")) {
81 new TinyMappingsWriter(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters);
82 return;
83 }
84
85 VisitableMappingTree tree = MappingIoConverter.toMappingIo(mappings, ProgressListener.none(), split[1], split[2]);
86 tree.accept(MappingWriter.create(path, net.fabricmc.mappingio.format.MappingFormat.TINY_FILE));
74 return; 87 return;
75 } 88 }
76 89
@@ -83,7 +96,7 @@ public final class MappingCommandsUtil {
83 } 96 }
84 97
85 if (format != null) { 98 if (format != null) {
86 format.getWriter().write(mappings, path, ProgressListener.none(), saveParameters); 99 format.write(mappings, path, ProgressListener.none(), saveParameters);
87 return; 100 return;
88 } 101 }
89 102
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java
index 2c15305..88dc070 100644
--- a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java
+++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java
@@ -29,11 +29,6 @@ import javax.swing.JOptionPane;
29import javax.swing.SwingUtilities; 29import javax.swing.SwingUtilities;
30 30
31import com.google.common.collect.Lists; 31import com.google.common.collect.Lists;
32import net.fabricmc.mappingio.MappingReader;
33import net.fabricmc.mappingio.MappingWriter;
34import net.fabricmc.mappingio.tree.MemoryMappingTree;
35import net.fabricmc.mappingio.tree.VisitOrder;
36import net.fabricmc.mappingio.tree.VisitableMappingTree;
37 32
38import cuchaz.enigma.Enigma; 33import cuchaz.enigma.Enigma;
39import cuchaz.enigma.EnigmaProfile; 34import cuchaz.enigma.EnigmaProfile;
@@ -82,7 +77,6 @@ import cuchaz.enigma.translation.mapping.EntryUtil;
82import cuchaz.enigma.translation.mapping.MappingDelta; 77import cuchaz.enigma.translation.mapping.MappingDelta;
83import cuchaz.enigma.translation.mapping.ResolutionStrategy; 78import cuchaz.enigma.translation.mapping.ResolutionStrategy;
84import cuchaz.enigma.translation.mapping.serde.MappingFormat; 79import cuchaz.enigma.translation.mapping.serde.MappingFormat;
85import cuchaz.enigma.translation.mapping.serde.MappingIoConverter;
86import cuchaz.enigma.translation.mapping.serde.MappingParseException; 80import cuchaz.enigma.translation.mapping.serde.MappingParseException;
87import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; 81import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters;
88import cuchaz.enigma.translation.mapping.tree.EntryTree; 82import cuchaz.enigma.translation.mapping.tree.EntryTree;
@@ -105,7 +99,6 @@ public class GuiController implements ClientPacketHandler {
105 99
106 private Path loadedMappingPath; 100 private Path loadedMappingPath;
107 private MappingFormat loadedMappingFormat; 101 private MappingFormat loadedMappingFormat;
108 public boolean useMappingIo = true;
109 102
110 private ClassHandleProvider chp; 103 private ClassHandleProvider chp;
111 104
@@ -146,6 +139,11 @@ public class GuiController implements ClientPacketHandler {
146 this.gui.onCloseJar(); 139 this.gui.onCloseJar();
147 } 140 }
148 141
142 public CompletableFuture<Void> openMappings(MappingFormat format, Path path, boolean useMappingIo) {
143 System.getProperties().setProperty("enigma.use_mappingio", useMappingIo ? "true" : "false");
144 return openMappings(format, path);
145 }
146
149 public CompletableFuture<Void> openMappings(MappingFormat format, Path path) { 147 public CompletableFuture<Void> openMappings(MappingFormat format, Path path) {
150 if (project == null) { 148 if (project == null) {
151 return CompletableFuture.completedFuture(null); 149 return CompletableFuture.completedFuture(null);
@@ -156,26 +154,7 @@ public class GuiController implements ClientPacketHandler {
156 return ProgressDialog.runOffThread(gui.getFrame(), progress -> { 154 return ProgressDialog.runOffThread(gui.getFrame(), progress -> {
157 try { 155 try {
158 MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters(); 156 MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters();
159 EntryTree<EntryMapping> mappings; 157 project.setMappings(format.read(path, progress, saveParameters));
160
161 if (useMappingIo) {
162 String loadingMessage;
163
164 if (format.getMappingIoCounterpart().hasSingleFile()) {
165 loadingMessage = I18n.translate("progress.mappings.loading_file");
166 } else {
167 loadingMessage = I18n.translate("progress.mappings.loading_directory");
168 }
169
170 progress.init(1, loadingMessage);
171 VisitableMappingTree mappingTree = new MemoryMappingTree();
172 MappingReader.read(path, format.getMappingIoCounterpart(), mappingTree);
173 mappings = MappingIoConverter.fromMappingIo(mappingTree, progress);
174 } else {
175 mappings = format.read(path, progress, saveParameters);
176 }
177
178 project.setMappings(mappings);
179 158
180 loadedMappingFormat = format; 159 loadedMappingFormat = format;
181 loadedMappingPath = path; 160 loadedMappingPath = path;
@@ -203,6 +182,11 @@ public class GuiController implements ClientPacketHandler {
203 return saveMappings(path, loadedMappingFormat); 182 return saveMappings(path, loadedMappingFormat);
204 } 183 }
205 184
185 public CompletableFuture<Void> saveMappings(Path path, MappingFormat format, boolean useMappingIo) {
186 System.getProperties().setProperty("enigma.use_mappingio", useMappingIo ? "true" : "false");
187 return saveMappings(path, format);
188 }
189
206 /** 190 /**
207 * Saves the mappings, with a dialog popping up, showing the progress. 191 * Saves the mappings, with a dialog popping up, showing the progress.
208 * 192 *
@@ -229,15 +213,7 @@ public class GuiController implements ClientPacketHandler {
229 loadedMappingFormat = format; 213 loadedMappingFormat = format;
230 loadedMappingPath = path; 214 loadedMappingPath = path;
231 215
232 if (useMappingIo) { 216 if (saveAll) {
233 VisitableMappingTree mappingTree = MappingIoConverter.toMappingIo(mapper.getObfToDeobf(), progress);
234
235 progress.init(1, I18n.translate("progress.mappings.writing"));
236 MappingWriter writer = MappingWriter.create(path, format.getMappingIoCounterpart());
237 mappingTree.accept(writer, VisitOrder.createByName());
238 writer.close();
239 progress.step(1, I18n.translate("progress.done"));
240 } else if (saveAll) {
241 format.write(mapper.getObfToDeobf(), path, progress, saveParameters); 217 format.write(mapper.getObfToDeobf(), path, progress, saveParameters);
242 } else { 218 } else {
243 format.write(mapper.getObfToDeobf(), delta, path, progress, saveParameters); 219 format.write(mapper.getObfToDeobf(), delta, path, progress, saveParameters);
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
index 59362e5..30e3586 100644
--- a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
+++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
@@ -7,7 +7,6 @@ import java.io.IOException;
7import java.nio.file.Files; 7import java.nio.file.Files;
8import java.nio.file.Path; 8import java.nio.file.Path;
9import java.util.Arrays; 9import java.util.Arrays;
10import java.util.List;
11import java.util.Locale; 10import java.util.Locale;
12import java.util.Map; 11import java.util.Map;
13import java.util.stream.Collectors; 12import java.util.stream.Collectors;
@@ -404,22 +403,11 @@ public class MenuBar {
404 } 403 }
405 404
406 private static void prepareOpenMappingsMenu(JMenu openMappingsMenu, Gui gui) { 405 private static void prepareOpenMappingsMenu(JMenu openMappingsMenu, Gui gui) {
407 List<MappingFormat> readableMappingIoFormats = Arrays.asList(
408 MappingFormat.ENIGMA_DIRECTORY,
409 MappingFormat.ENIGMA_FILE,
410 MappingFormat.TINY_FILE,
411 MappingFormat.TINY_V2,
412 MappingFormat.SRG_FILE,
413 MappingFormat.TSRG_FILE,
414 MappingFormat.TSRG_2_FILE,
415 MappingFormat.PROGUARD);
416
417 // Mapping-IO readers 406 // Mapping-IO readers
418 for (MappingFormat format : readableMappingIoFormats) { 407 MappingFormat.getReadableFormats().stream()
419 addOpenMappingsMenuEntry(I18n.translate(format.getMappingIoCounterpart().name), 408 .filter(format -> format.getMappingIoCounterpart() != null)
420 format, true, openMappingsMenu, gui); 409 .forEach(format -> addOpenMappingsMenuEntry(I18n.translate(format.getMappingIoCounterpart().name),
421 } 410 format, true, openMappingsMenu, gui));
422
423 openMappingsMenu.addSeparator(); 411 openMappingsMenu.addSeparator();
424 412
425 // Enigma's own readers 413 // Enigma's own readers
@@ -438,8 +426,7 @@ public class MenuBar {
438 426
439 if (gui.enigmaMappingsFileChooser.showOpenDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) { 427 if (gui.enigmaMappingsFileChooser.showOpenDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
440 File selectedFile = gui.enigmaMappingsFileChooser.getSelectedFile(); 428 File selectedFile = gui.enigmaMappingsFileChooser.getSelectedFile();
441 gui.getController().useMappingIo = mappingIo; 429 gui.getController().openMappings(format, selectedFile.toPath(), mappingIo);
442 gui.getController().openMappings(format, selectedFile.toPath());
443 UiConfig.setLastSelectedDir(gui.enigmaMappingsFileChooser.getCurrentDirectory().toString()); 430 UiConfig.setLastSelectedDir(gui.enigmaMappingsFileChooser.getCurrentDirectory().toString());
444 } 431 }
445 }); 432 });
@@ -447,19 +434,11 @@ public class MenuBar {
447 } 434 }
448 435
449 private static void prepareSaveMappingsAsMenu(JMenu saveMappingsAsMenu, JMenuItem saveMappingsItem, Gui gui) { 436 private static void prepareSaveMappingsAsMenu(JMenu saveMappingsAsMenu, JMenuItem saveMappingsItem, Gui gui) {
450 List<MappingFormat> writableMappingIoFormats = Arrays.asList(
451 MappingFormat.ENIGMA_DIRECTORY,
452 MappingFormat.ENIGMA_FILE,
453 MappingFormat.TINY_FILE,
454 MappingFormat.TINY_V2,
455 MappingFormat.PROGUARD);
456
457 // Mapping-IO writers 437 // Mapping-IO writers
458 for (MappingFormat format : writableMappingIoFormats) { 438 MappingFormat.getWritableFormats().stream()
459 addSaveMappingsAsMenuEntry(format.getMappingIoCounterpart().name, 439 .filter(format -> format.hasMappingIoWriter())
460 format, true, saveMappingsAsMenu, saveMappingsItem, gui); 440 .forEach(format -> addSaveMappingsAsMenuEntry(format.getMappingIoCounterpart().name,
461 } 441 format, true, saveMappingsAsMenu, saveMappingsItem, gui));
462
463 saveMappingsAsMenu.addSeparator(); 442 saveMappingsAsMenu.addSeparator();
464 443
465 // Enigma's own writers 444 // Enigma's own writers
@@ -480,8 +459,7 @@ public class MenuBar {
480 } 459 }
481 460
482 if (gui.enigmaMappingsFileChooser.showSaveDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) { 461 if (gui.enigmaMappingsFileChooser.showSaveDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
483 gui.getController().useMappingIo = mappingIo; 462 gui.getController().saveMappings(gui.enigmaMappingsFileChooser.getSelectedFile().toPath(), format, mappingIo);
484 gui.getController().saveMappings(gui.enigmaMappingsFileChooser.getSelectedFile().toPath(), format);
485 saveMappingsItem.setEnabled(true); 463 saveMappingsItem.setEnabled(true);
486 UiConfig.setLastSelectedDir(gui.enigmaMappingsFileChooser.getCurrentDirectory().toString()); 464 UiConfig.setLastSelectedDir(gui.enigmaMappingsFileChooser.getCurrentDirectory().toString());
487 } 465 }
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java
index f402c19..4d34720 100644
--- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java
+++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java
@@ -1,10 +1,19 @@
1package cuchaz.enigma.translation.mapping.serde; 1package cuchaz.enigma.translation.mapping.serde;
2 2
3import java.io.IOException; 3import java.io.IOException;
4import java.io.UncheckedIOException;
4import java.nio.file.Path; 5import java.nio.file.Path;
6import java.util.Arrays;
7import java.util.List;
5 8
6import javax.annotation.Nullable; 9import javax.annotation.Nullable;
7 10
11import net.fabricmc.mappingio.MappingReader;
12import net.fabricmc.mappingio.MappingWriter;
13import net.fabricmc.mappingio.tree.MemoryMappingTree;
14import net.fabricmc.mappingio.tree.VisitOrder;
15import net.fabricmc.mappingio.tree.VisitableMappingTree;
16
8import cuchaz.enigma.ProgressListener; 17import cuchaz.enigma.ProgressListener;
9import cuchaz.enigma.translation.mapping.EntryMapping; 18import cuchaz.enigma.translation.mapping.EntryMapping;
10import cuchaz.enigma.translation.mapping.MappingDelta; 19import cuchaz.enigma.translation.mapping.MappingDelta;
@@ -19,27 +28,30 @@ import cuchaz.enigma.translation.mapping.serde.tiny.TinyMappingsWriter;
19import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Reader; 28import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Reader;
20import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Writer; 29import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Writer;
21import cuchaz.enigma.translation.mapping.tree.EntryTree; 30import cuchaz.enigma.translation.mapping.tree.EntryTree;
31import cuchaz.enigma.utils.I18n;
22 32
23public enum MappingFormat { 33public enum MappingFormat {
24 ENIGMA_FILE(EnigmaMappingsWriter.FILE, EnigmaMappingsReader.FILE, net.fabricmc.mappingio.format.MappingFormat.ENIGMA_FILE), 34 ENIGMA_FILE(EnigmaMappingsWriter.FILE, EnigmaMappingsReader.FILE, net.fabricmc.mappingio.format.MappingFormat.ENIGMA_FILE, true),
25 ENIGMA_DIRECTORY(EnigmaMappingsWriter.DIRECTORY, EnigmaMappingsReader.DIRECTORY, net.fabricmc.mappingio.format.MappingFormat.ENIGMA_DIR), 35 ENIGMA_DIRECTORY(EnigmaMappingsWriter.DIRECTORY, EnigmaMappingsReader.DIRECTORY, net.fabricmc.mappingio.format.MappingFormat.ENIGMA_DIR, true),
26 ENIGMA_ZIP(EnigmaMappingsWriter.ZIP, EnigmaMappingsReader.ZIP, null), 36 ENIGMA_ZIP(EnigmaMappingsWriter.ZIP, EnigmaMappingsReader.ZIP, null, false),
27 TINY_V2(new TinyV2Writer("intermediary", "named"), new TinyV2Reader(), net.fabricmc.mappingio.format.MappingFormat.TINY_2_FILE), 37 TINY_V2(new TinyV2Writer("intermediary", "named"), new TinyV2Reader(), net.fabricmc.mappingio.format.MappingFormat.TINY_2_FILE, true),
28 TINY_FILE(TinyMappingsWriter.INSTANCE, TinyMappingsReader.INSTANCE, net.fabricmc.mappingio.format.MappingFormat.TINY_FILE), 38 TINY_FILE(TinyMappingsWriter.INSTANCE, TinyMappingsReader.INSTANCE, net.fabricmc.mappingio.format.MappingFormat.TINY_FILE, true),
29 SRG_FILE(SrgMappingsWriter.INSTANCE, null, net.fabricmc.mappingio.format.MappingFormat.SRG_FILE), 39 SRG_FILE(SrgMappingsWriter.INSTANCE, null, net.fabricmc.mappingio.format.MappingFormat.SRG_FILE, false),
30 TSRG_FILE(null, null, net.fabricmc.mappingio.format.MappingFormat.TSRG_FILE), 40 TSRG_FILE(null, null, net.fabricmc.mappingio.format.MappingFormat.TSRG_FILE, false),
31 TSRG_2_FILE(null, null, net.fabricmc.mappingio.format.MappingFormat.TSRG_2_FILE), 41 TSRG_2_FILE(null, null, net.fabricmc.mappingio.format.MappingFormat.TSRG_2_FILE, false),
32 PROGUARD(null, ProguardMappingsReader.INSTANCE, net.fabricmc.mappingio.format.MappingFormat.PROGUARD_FILE), 42 PROGUARD(null, ProguardMappingsReader.INSTANCE, net.fabricmc.mappingio.format.MappingFormat.PROGUARD_FILE, true),
33 RECAF(RecafMappingsWriter.INSTANCE, RecafMappingsReader.INSTANCE, null); 43 RECAF(RecafMappingsWriter.INSTANCE, RecafMappingsReader.INSTANCE, null, false);
34 44
35 private final MappingsWriter writer; 45 private final MappingsWriter writer;
36 private final MappingsReader reader; 46 private final MappingsReader reader;
37 private final net.fabricmc.mappingio.format.MappingFormat mappingIoCounterpart; 47 private final net.fabricmc.mappingio.format.MappingFormat mappingIoCounterpart;
48 private final boolean hasMappingIoWriter;
38 49
39 MappingFormat(MappingsWriter writer, MappingsReader reader, net.fabricmc.mappingio.format.MappingFormat mappingIoCounterpart) { 50 MappingFormat(MappingsWriter writer, MappingsReader reader, net.fabricmc.mappingio.format.MappingFormat mappingIoCounterpart, boolean hasMappingIoWriter) {
40 this.writer = writer; 51 this.writer = writer;
41 this.reader = reader; 52 this.reader = reader;
42 this.mappingIoCounterpart = mappingIoCounterpart; 53 this.mappingIoCounterpart = mappingIoCounterpart;
54 this.hasMappingIoWriter = hasMappingIoWriter;
43 } 55 }
44 56
45 public void write(EntryTree<EntryMapping> mappings, Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) { 57 public void write(EntryTree<EntryMapping> mappings, Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) {
@@ -47,19 +59,49 @@ public enum MappingFormat {
47 } 59 }
48 60
49 public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) { 61 public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) {
50 if (writer == null) { 62 if (!hasMappingIoWriter || !useMappingIo()) {
51 throw new IllegalStateException(name() + " does not support writing"); 63 if (writer == null) {
64 throw new IllegalStateException(name() + " does not support writing");
65 }
66
67 writer.write(mappings, delta, path, progressListener, saveParameters);
68 return;
52 } 69 }
53 70
54 writer.write(mappings, delta, path, progressListener, saveParameters); 71 try {
72 VisitableMappingTree tree = MappingIoConverter.toMappingIo(mappings, progressListener);
73 progressListener.init(1, I18n.translate("progress.mappings.writing"));
74 progressListener.step(1, null); // Reset message
75
76 tree.accept(MappingWriter.create(path, mappingIoCounterpart), VisitOrder.createByName());
77 progressListener.step(1, I18n.translate("progress.done"));
78 } catch (IOException e) {
79 throw new UncheckedIOException(e);
80 }
55 } 81 }
56 82
57 public EntryTree<EntryMapping> read(Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) throws IOException, MappingParseException { 83 public EntryTree<EntryMapping> read(Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) throws IOException, MappingParseException {
58 if (reader == null) { 84 if (!useMappingIo()) {
59 throw new IllegalStateException(name() + " does not support reading"); 85 if (reader == null) {
86 throw new IllegalStateException(name() + " does not support reading");
87 }
88
89 return reader.read(path, progressListener, saveParameters);
60 } 90 }
61 91
62 return reader.read(path, progressListener, saveParameters); 92 String loadingMessage;
93
94 if (mappingIoCounterpart.hasSingleFile()) {
95 loadingMessage = I18n.translate("progress.mappings.loading_file");
96 } else {
97 loadingMessage = I18n.translate("progress.mappings.loading_directory");
98 }
99
100 progressListener.init(1, loadingMessage);
101
102 VisitableMappingTree mappingTree = new MemoryMappingTree();
103 MappingReader.read(path, mappingIoCounterpart, mappingTree);
104 return MappingIoConverter.fromMappingIo(mappingTree, progressListener);
63 } 105 }
64 106
65 @Nullable 107 @Nullable
@@ -76,4 +118,35 @@ public enum MappingFormat {
76 public net.fabricmc.mappingio.format.MappingFormat getMappingIoCounterpart() { 118 public net.fabricmc.mappingio.format.MappingFormat getMappingIoCounterpart() {
77 return mappingIoCounterpart; 119 return mappingIoCounterpart;
78 } 120 }
121
122 public boolean hasMappingIoWriter() {
123 return hasMappingIoWriter;
124 }
125
126 public boolean isReadable() {
127 return reader != null || mappingIoCounterpart != null;
128 }
129
130 public boolean isWritable() {
131 return writer != null || hasMappingIoWriter;
132 }
133
134 private boolean useMappingIo() {
135 if (mappingIoCounterpart == null) return false;
136 return System.getProperty("enigma.use_mappingio", "true").equals("true");
137 }
138
139 public static List<MappingFormat> getReadableFormats() {
140 return Arrays.asList(values())
141 .stream()
142 .filter(MappingFormat::isReadable)
143 .toList();
144 }
145
146 public static List<MappingFormat> getWritableFormats() {
147 return Arrays.asList(values())
148 .stream()
149 .filter(MappingFormat::isWritable)
150 .toList();
151 }
79} 152}
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingIoConverter.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingIoConverter.java
index a0912fa..4372585 100644
--- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingIoConverter.java
+++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingIoConverter.java
@@ -33,19 +33,23 @@ import cuchaz.enigma.utils.I18n;
33 33
34public class MappingIoConverter { 34public class MappingIoConverter {
35 public static VisitableMappingTree toMappingIo(EntryTree<EntryMapping> mappings, ProgressListener progress) { 35 public static VisitableMappingTree toMappingIo(EntryTree<EntryMapping> mappings, ProgressListener progress) {
36 return toMappingIo(mappings, progress, "intermediary", "named");
37 }
38
39 public static VisitableMappingTree toMappingIo(EntryTree<EntryMapping> mappings, ProgressListener progress, String fromNs, String toNs) {
36 try { 40 try {
37 List<EntryTreeNode<EntryMapping>> classes = StreamSupport.stream(mappings.spliterator(), false) 41 List<EntryTreeNode<EntryMapping>> classes = StreamSupport.stream(mappings.spliterator(), false)
38 .filter(node -> node.getEntry() instanceof ClassEntry) 42 .filter(node -> node.getEntry() instanceof ClassEntry)
39 .toList(); 43 .toList();
40 44
41 progress.init(classes.size(), I18n.translate("progress.mappings.converting.to_mappingio")); 45 progress.init(classes.size(), I18n.translate("progress.mappings.converting.to_mappingio"));
42 int steps = 0; 46 int stepsDone = 0;
43 47
44 MemoryMappingTree mappingTree = new MemoryMappingTree(); 48 MemoryMappingTree mappingTree = new MemoryMappingTree();
45 mappingTree.visitNamespaces("intermediary", List.of("named")); 49 mappingTree.visitNamespaces(fromNs, List.of(toNs));
46 50
47 for (EntryTreeNode<EntryMapping> classNode : classes) { 51 for (EntryTreeNode<EntryMapping> classNode : classes) {
48 progress.step(steps++, classNode.getEntry().getFullName()); 52 progress.step(++stepsDone, classNode.getEntry().getFullName());
49 writeClass(classNode, mappings, mappingTree); 53 writeClass(classNode, mappings, mappingTree);
50 } 54 }
51 55
diff --git a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java
index 681fd3f..34d5a6e 100644
--- a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java
+++ b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java
@@ -4,6 +4,7 @@ import java.io.File;
4import java.io.IOException; 4import java.io.IOException;
5 5
6import org.junit.Assert; 6import org.junit.Assert;
7import org.junit.BeforeClass;
7import org.junit.Test; 8import org.junit.Test;
8 9
9import cuchaz.enigma.ProgressListener; 10import cuchaz.enigma.ProgressListener;
@@ -87,6 +88,11 @@ public class TestReadWriteCycle {
87 tempFile.delete(); 88 tempFile.delete();
88 } 89 }
89 90
91 @BeforeClass
92 public static void setup() {
93 System.getProperties().setProperty("enigma.use_mappingio", "false");
94 }
95
90 @Test 96 @Test
91 public void testEnigmaFile() throws IOException, MappingParseException { 97 public void testEnigmaFile() throws IOException, MappingParseException {
92 testReadWriteCycle(MappingFormat.ENIGMA_FILE, true, ".enigma"); 98 testReadWriteCycle(MappingFormat.ENIGMA_FILE, true, ".enigma");