Skip to content

Commit

Permalink
Merge pull request #463 from NebelNidas/mapping-io
Browse files Browse the repository at this point in the history
Initial Mapping-IO support
  • Loading branch information
modmuss50 authored Nov 28, 2023
2 parents c675acf + 5df82c3 commit 7622b75
Show file tree
Hide file tree
Showing 19 changed files with 556 additions and 122 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ subprojects {
dependencies {
implementation 'com.google.guava:guava:32.1.2-jre'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'net.fabricmc:mapping-io:0.5.0'

compileOnly 'org.jetbrains:annotations:24.0.1'

testImplementation 'junit:junit:4.13.2'
testImplementation 'org.hamcrest:hamcrest:2.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import cuchaz.enigma.analysis.index.JarIndex;
import cuchaz.enigma.classprovider.ClasspathClassProvider;
import cuchaz.enigma.translation.mapping.EntryMapping;
import cuchaz.enigma.translation.mapping.serde.MappingFormat;
import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters;
import cuchaz.enigma.translation.mapping.tree.EntryTree;
import cuchaz.enigma.translation.representation.entry.ClassEntry;
Expand Down Expand Up @@ -38,15 +37,12 @@ public void run(String... args) throws Exception {
Enigma enigma = Enigma.create();

System.out.println("Reading JAR...");

EnigmaProject project = enigma.openJar(fileJarIn, new ClasspathClassProvider(), ProgressListener.none());

System.out.println("Reading mappings...");

MappingFormat format = chooseEnigmaFormat(fileMappings);
MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters();

EntryTree<EntryMapping> mappings = format.read(fileMappings, ProgressListener.none(), saveParameters);
EntryTree<EntryMapping> mappings = readMappings(fileMappings, ProgressListener.none(), saveParameters);
project.setMappings(mappings);

JarIndex idx = project.getJarIndex();
Expand Down
26 changes: 18 additions & 8 deletions enigma-cli/src/main/java/cuchaz/enigma/command/Command.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
package cuchaz.enigma.command;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import com.google.common.io.MoreFiles;
import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
import net.fabricmc.mappingio.tree.VisitableMappingTree;

import cuchaz.enigma.Enigma;
import cuchaz.enigma.EnigmaProject;
import cuchaz.enigma.ProgressListener;
import cuchaz.enigma.classprovider.ClasspathClassProvider;
import cuchaz.enigma.translation.mapping.EntryMapping;
import cuchaz.enigma.translation.mapping.serde.MappingFormat;
import cuchaz.enigma.translation.mapping.serde.MappingIoConverter;
import cuchaz.enigma.translation.mapping.serde.MappingParseException;
import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters;
import cuchaz.enigma.translation.mapping.tree.EntryTree;

Expand Down Expand Up @@ -41,22 +47,26 @@ protected static EnigmaProject openProject(Path fileJarIn, Path fileMappings) th
System.out.println("Reading mappings...");

MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters();
EntryTree<EntryMapping> mappings = chooseEnigmaFormat(fileMappings).read(fileMappings, progress, saveParameters);
EntryTree<EntryMapping> mappings = readMappings(fileMappings, progress, saveParameters);

project.setMappings(mappings);
}

return project;
}

protected static MappingFormat chooseEnigmaFormat(Path path) {
if (Files.isDirectory(path)) {
return MappingFormat.ENIGMA_DIRECTORY;
} else if ("zip".equalsIgnoreCase(MoreFiles.getFileExtension(path))) {
return MappingFormat.ENIGMA_ZIP;
} else {
return MappingFormat.ENIGMA_FILE;
protected static EntryTree<EntryMapping> readMappings(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException {
// Legacy
if ("zip".equalsIgnoreCase(MoreFiles.getFileExtension(path))) {
return MappingFormat.ENIGMA_ZIP.read(path, progress, saveParameters, null);
}

net.fabricmc.mappingio.format.MappingFormat format = MappingReader.detectFormat(path);
if (format == null) throw new IllegalArgumentException("Unknown mapping format!");

VisitableMappingTree tree = new MemoryMappingTree();
MappingReader.read(path, format, tree);
return MappingIoConverter.fromMappingIo(tree, progress, null);
}

protected static File getWritableFile(String path) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package cuchaz.enigma.command;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;

import net.fabricmc.mappingio.MappingWriter;
import net.fabricmc.mappingio.tree.VisitableMappingTree;

import cuchaz.enigma.ProgressListener;
import cuchaz.enigma.translation.mapping.EntryMapping;
import cuchaz.enigma.translation.mapping.serde.MappingFormat;
import cuchaz.enigma.translation.mapping.serde.MappingIoConverter;
import cuchaz.enigma.translation.mapping.serde.MappingParseException;
import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters;
import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsReader;
import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsWriter;
import cuchaz.enigma.translation.mapping.serde.tiny.TinyMappingsReader;
import cuchaz.enigma.translation.mapping.serde.tiny.TinyMappingsWriter;
import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Writer;
import cuchaz.enigma.translation.mapping.tree.EntryTree;
Expand All @@ -22,11 +24,11 @@ private MappingCommandsUtil() {

public static EntryTree<EntryMapping> read(String type, Path path, MappingSaveParameters saveParameters) throws MappingParseException, IOException {
if (type.equals("enigma")) {
return (Files.isDirectory(path) ? EnigmaMappingsReader.DIRECTORY : EnigmaMappingsReader.ZIP).read(path, ProgressListener.none(), saveParameters);
return (Files.isDirectory(path) ? MappingFormat.ENIGMA_DIRECTORY : MappingFormat.ENIGMA_ZIP).read(path, ProgressListener.none(), saveParameters, null);
}

if (type.equals("tiny")) {
return TinyMappingsReader.INSTANCE.read(path, ProgressListener.none(), saveParameters);
return MappingFormat.TINY_FILE.read(path, ProgressListener.none(), saveParameters, null);
}

MappingFormat format = null;
Expand All @@ -40,15 +42,15 @@ public static EntryTree<EntryMapping> read(String type, Path path, MappingSavePa
}

if (format != null) {
return format.getReader().read(path, ProgressListener.none(), saveParameters);
return format.read(path, ProgressListener.none(), saveParameters, null);
}

throw new IllegalArgumentException("no reader for " + type);
}

public static void write(EntryTree<EntryMapping> mappings, String type, Path path, MappingSaveParameters saveParameters) {
if (type.equals("enigma")) {
EnigmaMappingsWriter.DIRECTORY.write(mappings, path, ProgressListener.none(), saveParameters);
MappingFormat.ENIGMA_DIRECTORY.write(mappings, path, ProgressListener.none(), saveParameters);
return;
}

Expand All @@ -59,7 +61,18 @@ public static void write(EntryTree<EntryMapping> mappings, String type, Path pat
throw new IllegalArgumentException("specify column names as 'tinyv2:from_namespace:to_namespace'");
}

new TinyV2Writer(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters);
if (!System.getProperty("enigma.use_mappingio", "true").equals("true")) {
new TinyV2Writer(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters);
return;
}

try {
VisitableMappingTree tree = MappingIoConverter.toMappingIo(mappings, ProgressListener.none(), split[1], split[2]);
tree.accept(MappingWriter.create(path, net.fabricmc.mappingio.format.MappingFormat.TINY_2_FILE));
} catch (IOException e) {
throw new UncheckedIOException(e);
}

return;
}

Expand All @@ -70,7 +83,18 @@ public static void write(EntryTree<EntryMapping> mappings, String type, Path pat
throw new IllegalArgumentException("specify column names as 'tiny:from_column:to_column'");
}

new TinyMappingsWriter(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters);
if (!System.getProperty("enigma.use_mappingio", "true").equals("true")) {
new TinyMappingsWriter(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters);
return;
}

try {
VisitableMappingTree tree = MappingIoConverter.toMappingIo(mappings, ProgressListener.none(), split[1], split[2]);
tree.accept(MappingWriter.create(path, net.fabricmc.mappingio.format.MappingFormat.TINY_FILE));
} catch (IOException e) {
throw new UncheckedIOException(e);
}

return;
}

Expand All @@ -83,7 +107,7 @@ public static void write(EntryTree<EntryMapping> mappings, String type, Path pat
}

if (format != null) {
format.getWriter().write(mappings, path, ProgressListener.none(), saveParameters);
format.write(mappings, path, ProgressListener.none(), saveParameters);
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public static void main(String[] args) {
mappingFormat = MappingFormat.ENIGMA_FILE;
}

mappings = EntryRemapper.mapped(project.getJarIndex(), mappingFormat.read(mappingsFile, ProgressListener.none(), profile.getMappingSaveParameters()));
mappings = EntryRemapper.mapped(project.getJarIndex(), mappingFormat.read(mappingsFile, ProgressListener.none(), profile.getMappingSaveParameters(), project.getJarIndex()));
}

PrintWriter log = new PrintWriter(Files.newBufferedWriter(logFile));
Expand Down
17 changes: 14 additions & 3 deletions enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import javax.swing.SwingUtilities;

import com.google.common.collect.Lists;
import org.jetbrains.annotations.ApiStatus;

import cuchaz.enigma.Enigma;
import cuchaz.enigma.EnigmaProfile;
Expand Down Expand Up @@ -139,6 +140,12 @@ public void closeJar() {
this.gui.onCloseJar();
}

@ApiStatus.Internal
public CompletableFuture<Void> openMappings(MappingFormat format, Path path, boolean useMappingIo) {
System.getProperties().setProperty("enigma.use_mappingio", useMappingIo ? "true" : "false");
return openMappings(format, path);
}

public CompletableFuture<Void> openMappings(MappingFormat format, Path path) {
if (project == null) {
return CompletableFuture.completedFuture(null);
Expand All @@ -149,9 +156,7 @@ public CompletableFuture<Void> openMappings(MappingFormat format, Path path) {
return ProgressDialog.runOffThread(gui.getFrame(), progress -> {
try {
MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters();

EntryTree<EntryMapping> mappings = format.read(path, progress, saveParameters);
project.setMappings(mappings);
project.setMappings(format.read(path, progress, saveParameters, project.getJarIndex()));

loadedMappingFormat = format;
loadedMappingPath = path;
Expand Down Expand Up @@ -179,6 +184,12 @@ public CompletableFuture<Void> saveMappings(Path path) {
return saveMappings(path, loadedMappingFormat);
}

@ApiStatus.Internal
public CompletableFuture<Void> saveMappings(Path path, MappingFormat format, boolean useMappingIo) {
System.getProperties().setProperty("enigma.use_mappingio", useMappingIo ? "true" : "false");
return saveMappings(path, format);
}

/**
* Saves the mappings, with a dialog popping up, showing the progress.
*
Expand Down
88 changes: 57 additions & 31 deletions enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class MenuBar {
private final JMenu fileMenu = new JMenu();
private final JMenuItem jarOpenItem = new JMenuItem();
private final JMenuItem jarCloseItem = new JMenuItem();
private final JMenu openMenu = new JMenu();
private final JMenu openMappingsMenu = new JMenu();
private final JMenuItem saveMappingsItem = new JMenuItem();
private final JMenu saveMappingsAsMenu = new JMenu();
private final JMenuItem closeMappingsItem = new JMenuItem();
Expand Down Expand Up @@ -88,7 +88,7 @@ public MenuBar(Gui gui) {

this.retranslateUi();

prepareOpenMenu(this.openMenu, gui);
prepareOpenMappingsMenu(this.openMappingsMenu, gui);
prepareSaveMappingsAsMenu(this.saveMappingsAsMenu, this.saveMappingsItem, gui);
prepareDecompilerMenu(this.decompilerMenu, gui);
prepareThemesMenu(this.themesMenu, gui);
Expand All @@ -98,7 +98,7 @@ public MenuBar(Gui gui) {
this.fileMenu.add(this.jarOpenItem);
this.fileMenu.add(this.jarCloseItem);
this.fileMenu.addSeparator();
this.fileMenu.add(this.openMenu);
this.fileMenu.add(this.openMappingsMenu);
this.fileMenu.add(this.saveMappingsItem);
this.fileMenu.add(this.saveMappingsAsMenu);
this.fileMenu.add(this.closeMappingsItem);
Expand Down Expand Up @@ -174,7 +174,7 @@ public void updateUiState() {
this.startServerItem.setText(I18n.translate(connectionState != ConnectionState.HOSTING ? "menu.collab.server.start" : "menu.collab.server.stop"));

this.jarCloseItem.setEnabled(jarOpen);
this.openMenu.setEnabled(jarOpen);
this.openMappingsMenu.setEnabled(jarOpen);
this.saveMappingsItem.setEnabled(jarOpen && this.gui.enigmaMappingsFileChooser.getSelectedFile() != null && connectionState != ConnectionState.CONNECTED);
this.saveMappingsAsMenu.setEnabled(jarOpen);
this.closeMappingsItem.setEnabled(jarOpen);
Expand All @@ -189,7 +189,7 @@ public void retranslateUi() {
this.fileMenu.setText(I18n.translate("menu.file"));
this.jarOpenItem.setText(I18n.translate("menu.file.jar.open"));
this.jarCloseItem.setText(I18n.translate("menu.file.jar.close"));
this.openMenu.setText(I18n.translate("menu.file.mappings.open"));
this.openMappingsMenu.setText(I18n.translate("menu.file.mappings.open"));
this.saveMappingsItem.setText(I18n.translate("menu.file.mappings.save"));
this.saveMappingsAsMenu.setText(I18n.translate("menu.file.mappings.save_as"));
this.closeMappingsItem.setText(I18n.translate("menu.file.mappings.close"));
Expand Down Expand Up @@ -402,45 +402,71 @@ private void onGithubClicked() {
GuiUtil.openUrl("https://github.com/FabricMC/Enigma");
}

private static void prepareOpenMenu(JMenu openMenu, Gui gui) {
private static void prepareOpenMappingsMenu(JMenu openMappingsMenu, Gui gui) {
// Mapping-IO readers
MappingFormat.getReadableFormats().stream()
.filter(format -> format.getMappingIoCounterpart() != null)
.forEach(format -> addOpenMappingsMenuEntry(I18n.translate(format.getMappingIoCounterpart().name),
format, true, openMappingsMenu, gui));
openMappingsMenu.addSeparator();

// Enigma's own readers
for (MappingFormat format : MappingFormat.values()) {
if (format.getReader() != null) {
JMenuItem item = new JMenuItem(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT)));
item.addActionListener(event -> {
gui.enigmaMappingsFileChooser.setCurrentDirectory(new File(UiConfig.getLastSelectedDir()));

if (gui.enigmaMappingsFileChooser.showOpenDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
File selectedFile = gui.enigmaMappingsFileChooser.getSelectedFile();
gui.getController().openMappings(format, selectedFile.toPath());
UiConfig.setLastSelectedDir(gui.enigmaMappingsFileChooser.getCurrentDirectory().toString());
}
});
openMenu.add(item);
addOpenMappingsMenuEntry(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT)) + " (legacy)",
format, false, openMappingsMenu, gui);
}
}
}

private static void addOpenMappingsMenuEntry(String text, MappingFormat format, boolean mappingIo, JMenu openMappingsMenu, Gui gui) {
JMenuItem item = new JMenuItem(text);
item.addActionListener(event -> {
gui.enigmaMappingsFileChooser.setCurrentDirectory(new File(UiConfig.getLastSelectedDir()));

if (gui.enigmaMappingsFileChooser.showOpenDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
File selectedFile = gui.enigmaMappingsFileChooser.getSelectedFile();
gui.getController().openMappings(format, selectedFile.toPath(), mappingIo);
UiConfig.setLastSelectedDir(gui.enigmaMappingsFileChooser.getCurrentDirectory().toString());
}
});
openMappingsMenu.add(item);
}

private static void prepareSaveMappingsAsMenu(JMenu saveMappingsAsMenu, JMenuItem saveMappingsItem, Gui gui) {
// Mapping-IO writers
MappingFormat.getWritableFormats().stream()
.filter(format -> format.hasMappingIoWriter())
.forEach(format -> addSaveMappingsAsMenuEntry(format.getMappingIoCounterpart().name,
format, true, saveMappingsAsMenu, saveMappingsItem, gui));
saveMappingsAsMenu.addSeparator();

// Enigma's own writers
for (MappingFormat format : MappingFormat.values()) {
if (format.getWriter() != null) {
JMenuItem item = new JMenuItem(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT)));
item.addActionListener(event -> {
// TODO: Use a specific file chooser for it
if (gui.enigmaMappingsFileChooser.getCurrentDirectory() == null) {
gui.enigmaMappingsFileChooser.setCurrentDirectory(new File(UiConfig.getLastSelectedDir()));
}

if (gui.enigmaMappingsFileChooser.showSaveDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
gui.getController().saveMappings(gui.enigmaMappingsFileChooser.getSelectedFile().toPath(), format);
saveMappingsItem.setEnabled(true);
UiConfig.setLastSelectedDir(gui.enigmaMappingsFileChooser.getCurrentDirectory().toString());
}
});
saveMappingsAsMenu.add(item);
addSaveMappingsAsMenuEntry(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT)) + " (legacy)",
format, false, saveMappingsAsMenu, saveMappingsItem, gui);
}
}
}

private static void addSaveMappingsAsMenuEntry(String text, MappingFormat format, boolean mappingIo, JMenu saveMappingsAsMenu, JMenuItem saveMappingsItem, Gui gui) {
JMenuItem item = new JMenuItem(text);
item.addActionListener(event -> {
// TODO: Use a specific file chooser for it
if (gui.enigmaMappingsFileChooser.getCurrentDirectory() == null) {
gui.enigmaMappingsFileChooser.setCurrentDirectory(new File(UiConfig.getLastSelectedDir()));
}

if (gui.enigmaMappingsFileChooser.showSaveDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
gui.getController().saveMappings(gui.enigmaMappingsFileChooser.getSelectedFile().toPath(), format, mappingIo);
saveMappingsItem.setEnabled(true);
UiConfig.setLastSelectedDir(gui.enigmaMappingsFileChooser.getCurrentDirectory().toString());
}
});
saveMappingsAsMenu.add(item);
}

private static void prepareDecompilerMenu(JMenu decompilerMenu, Gui gui) {
ButtonGroup decompilerGroup = new ButtonGroup();

Expand Down
Loading

0 comments on commit 7622b75

Please sign in to comment.