package immibis.bon.gui; import immibis.bon.ClassCollection; import immibis.bon.IProgressListener; import immibis.bon.NameSet; import immibis.bon.ReferenceDataCollection; import immibis.bon.Remapper; import immibis.bon.com.immibis.json.JsonReader; import immibis.bon.io.ClassCollectionFactory; import immibis.bon.io.JarWriter; import immibis.bon.mcp.CsvFile; import immibis.bon.mcp.ExcFile; import immibis.bon.mcp.MappingFactory; import immibis.bon.mcp.MappingLoader_MCP; import immibis.bon.mcp.MinecraftNameSet; import immibis.bon.mcp.SrgFile; import java.awt.EventQueue; import javax.swing.JFrame; import java.awt.GridBagLayout; import javax.swing.GroupLayout; import javax.swing.GroupLayout.Alignment; import javax.swing.JLabel; import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.UIManager.LookAndFeelInfo; import java.awt.Dialog.ModalityType; import java.awt.GridBagConstraints; import java.awt.Insets; import java.awt.Toolkit; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.DefaultComboBoxModel; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.JTabbedPane; import javax.swing.border.EmptyBorder; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.prefs.Preferences; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import javax.swing.JCheckBox; public class NewGUI { // The Java Preferences API is used to store the last directory the user was browsing // for the input/output files (PREFS_KEY_BROWSEDIR) // and the selected MCP directory (PREFS_KEY_MCPDIR). // Prefs are saved when the user clicks "Go" or closes the window. private final Preferences prefs = Preferences.userNodeForPackage(NewGUI.class); private final static String PREFS_KEY_BROWSEDIR = "browseDir"; private final static String PREFS_KEY_MCPDIR = "mcpDir"; private final static String PREFS_KEY_FORGEJAR = "forgeUserdevJar"; private final static String PREFS_KEY_FGCACHE = "forgegradleCacheDir"; private JFrame frmBeardedOctoNemesis; private JTextField txtInputFile; private JTextField txtOutputFile; private JButton btnBrowseOutputFile; private JTextField txtMCPDir; private JButton btnBrowseMCPDir; private JButton btnBrowseInputFile; private JComboBox mcpSideSelector; private JTabbedPane tabbedPane; private JPanel panel; private JPanel panel_1; private JButton btnGoForgeDownload; private JPanel panel_2; private JLabel label_1; private JComboBox downloadForgeVersionSelector; private JButton btnGetVersionList; private JLabel lblNoteThisWill; private JLabel lblForgeUserdevjar; private JTextField txtForgeJar; private JButton btnBrowseForgeJar; private JButton btnGoForge; private JButton btnGoMCP; private JCheckBox chckbxUseSrgNames; private JLabel lblOperation; private JComboBox operationSelector; private JLabel lblThisIsNot; private JLabel lblForgegradleCacheFolder; private JTextField txtFGCache; private JButton btnBrowseFGCache; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { for(LookAndFeelInfo lafi : UIManager.getInstalledLookAndFeels()) { //System.out.println("Installed look-and-feel: "+lafi.getName()+" @ "+lafi.getClassName()); if(lafi.getName().equals("Windows")) UIManager.setLookAndFeel(lafi.getClassName()); } NewGUI window = new NewGUI(); window.frmBeardedOctoNemesis.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the application. */ public NewGUI() { initialize(); String lastMCPDir = prefs.get(PREFS_KEY_MCPDIR, ""); if(!lastMCPDir.equals("") && new File(lastMCPDir).isDirectory()) txtMCPDir.setText(new File(lastMCPDir).getAbsolutePath()); String lastForgeJar = prefs.get(PREFS_KEY_FORGEJAR, ""); if(!lastForgeJar.equals("") && new File(lastForgeJar).exists()) txtForgeJar.setText(new File(lastForgeJar).getAbsolutePath()); String lastFGCache = prefs.get(PREFS_KEY_FGCACHE, ""); if(!lastFGCache.equals("") && new File(lastFGCache).isDirectory()) txtFGCache.setText(new File(lastFGCache).getAbsolutePath()); tabbedPane.setSelectedIndex(2); } /** * Initialize the contents of the frame. */ private void initialize() { frmBeardedOctoNemesis = new JFrame(); frmBeardedOctoNemesis.setTitle("Bearded Octo Nemesis"); frmBeardedOctoNemesis.setBounds(100, 100, 450, 285); frmBeardedOctoNemesis.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); GridBagLayout gridBagLayout = new GridBagLayout(); gridBagLayout.columnWidths = new int[]{55, 0, 0, 0}; gridBagLayout.rowHeights = new int[]{14, 14, 0, 0, 0}; gridBagLayout.columnWeights = new double[]{0.0, 1.0, 0.0, Double.MIN_VALUE}; gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, 1.0, Double.MIN_VALUE}; frmBeardedOctoNemesis.getContentPane().setLayout(gridBagLayout); JLabel lblInputFile = new JLabel("Input file:"); lblInputFile.setHorizontalAlignment(SwingConstants.TRAILING); GridBagConstraints gbc_lblInputFile = new GridBagConstraints(); gbc_lblInputFile.fill = GridBagConstraints.VERTICAL; gbc_lblInputFile.anchor = GridBagConstraints.EAST; gbc_lblInputFile.insets = new Insets(0, 0, 5, 5); gbc_lblInputFile.gridx = 0; gbc_lblInputFile.gridy = 0; frmBeardedOctoNemesis.getContentPane().add(lblInputFile, gbc_lblInputFile); txtInputFile = new JTextField(); GridBagConstraints gbc_txtInputFile = new GridBagConstraints(); gbc_txtInputFile.weightx = 1.0; gbc_txtInputFile.insets = new Insets(0, 0, 5, 5); gbc_txtInputFile.fill = GridBagConstraints.HORIZONTAL; gbc_txtInputFile.gridx = 1; gbc_txtInputFile.gridy = 0; frmBeardedOctoNemesis.getContentPane().add(txtInputFile, gbc_txtInputFile); txtInputFile.setColumns(10); btnBrowseInputFile = new JButton("Browse"); btnBrowseInputFile.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser fc = new JFileChooser(); File curDir = new File(prefs.get(PREFS_KEY_BROWSEDIR, ".")); if(!curDir.isDirectory()) curDir = new File("."); fc.setCurrentDirectory(curDir); fc.setFileFilter(new FileNameExtensionFilter("JAR files", "jar", "zip")); if(fc.showOpenDialog(frmBeardedOctoNemesis) == JFileChooser.APPROVE_OPTION) { prefs.put(PREFS_KEY_BROWSEDIR, fc.getCurrentDirectory().getAbsolutePath()); txtInputFile.setText(fc.getSelectedFile().getAbsolutePath()); if(txtOutputFile.getText().equals("")) { File inputDir = fc.getSelectedFile().getParentFile(); String inputName = fc.getSelectedFile().getName(); String outputName; if(inputName.contains(".")) { int i = inputName.lastIndexOf('.'); outputName = inputName.substring(0, i) + ".deobf." + inputName.substring(i+1); } else outputName = inputName + ".deobf.jar"; txtOutputFile.setText(new File(inputDir, outputName).getAbsolutePath()); } } } }); GridBagConstraints gbc_btnBrowseInputFile = new GridBagConstraints(); gbc_btnBrowseInputFile.anchor = GridBagConstraints.WEST; gbc_btnBrowseInputFile.insets = new Insets(0, 0, 5, 0); gbc_btnBrowseInputFile.gridx = 2; gbc_btnBrowseInputFile.gridy = 0; frmBeardedOctoNemesis.getContentPane().add(btnBrowseInputFile, gbc_btnBrowseInputFile); JLabel lblOutputFile = new JLabel("Output file:"); lblOutputFile.setHorizontalAlignment(SwingConstants.TRAILING); GridBagConstraints gbc_lblOutputFile = new GridBagConstraints(); gbc_lblOutputFile.fill = GridBagConstraints.VERTICAL; gbc_lblOutputFile.insets = new Insets(0, 0, 5, 5); gbc_lblOutputFile.anchor = GridBagConstraints.EAST; gbc_lblOutputFile.gridx = 0; gbc_lblOutputFile.gridy = 1; frmBeardedOctoNemesis.getContentPane().add(lblOutputFile, gbc_lblOutputFile); txtOutputFile = new JTextField(); GridBagConstraints gbc_txtOutputFile = new GridBagConstraints(); gbc_txtOutputFile.weightx = 1.0; gbc_txtOutputFile.insets = new Insets(0, 0, 5, 5); gbc_txtOutputFile.fill = GridBagConstraints.HORIZONTAL; gbc_txtOutputFile.gridx = 1; gbc_txtOutputFile.gridy = 1; frmBeardedOctoNemesis.getContentPane().add(txtOutputFile, gbc_txtOutputFile); txtOutputFile.setColumns(10); btnBrowseOutputFile = new JButton("Browse"); btnBrowseOutputFile.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser fc = new JFileChooser(); File curDir = new File(prefs.get(PREFS_KEY_BROWSEDIR, ".")); if(!curDir.isDirectory()) curDir = new File("."); fc.setCurrentDirectory(curDir); fc.setFileFilter(new FileNameExtensionFilter("JAR files", "jar", "zip")); if(fc.showSaveDialog(frmBeardedOctoNemesis) == JFileChooser.APPROVE_OPTION) { prefs.put(PREFS_KEY_BROWSEDIR, fc.getCurrentDirectory().getAbsolutePath()); txtOutputFile.setText(fc.getSelectedFile().getAbsolutePath()); } } }); GridBagConstraints gbc_btnBrowseOutputFile = new GridBagConstraints(); gbc_btnBrowseOutputFile.anchor = GridBagConstraints.WEST; gbc_btnBrowseOutputFile.insets = new Insets(0, 0, 5, 0); gbc_btnBrowseOutputFile.gridx = 2; gbc_btnBrowseOutputFile.gridy = 1; frmBeardedOctoNemesis.getContentPane().add(btnBrowseOutputFile, gbc_btnBrowseOutputFile); lblOperation = new JLabel("Operation:"); lblOperation.setHorizontalAlignment(SwingConstants.TRAILING); GridBagConstraints gbc_lblOperation = new GridBagConstraints(); gbc_lblOperation.anchor = GridBagConstraints.EAST; gbc_lblOperation.insets = new Insets(0, 0, 5, 5); gbc_lblOperation.gridx = 0; gbc_lblOperation.gridy = 2; frmBeardedOctoNemesis.getContentPane().add(lblOperation, gbc_lblOperation); operationSelector = new JComboBox(); operationSelector.setModel(new DefaultComboBoxModel(Operation.values())); GridBagConstraints gbc_operationSelector = new GridBagConstraints(); gbc_operationSelector.insets = new Insets(0, 0, 5, 5); gbc_operationSelector.fill = GridBagConstraints.HORIZONTAL; gbc_operationSelector.gridx = 1; gbc_operationSelector.gridy = 2; frmBeardedOctoNemesis.getContentPane().add(operationSelector, gbc_operationSelector); tabbedPane = new JTabbedPane(JTabbedPane.TOP); GridBagConstraints gbc_tabbedPane = new GridBagConstraints(); gbc_tabbedPane.gridwidth = 3; gbc_tabbedPane.insets = new Insets(0, 5, 5, 5); gbc_tabbedPane.fill = GridBagConstraints.BOTH; gbc_tabbedPane.gridx = 0; gbc_tabbedPane.gridy = 3; frmBeardedOctoNemesis.getContentPane().add(tabbedPane, gbc_tabbedPane); panel = new JPanel(); panel.setBorder(new EmptyBorder(5, 5, 5, 5)); tabbedPane.addTab("MCP", null, panel, null); GridBagLayout gbl_panel = new GridBagLayout(); gbl_panel.columnWidths = new int[]{0, 0, 0, 0}; gbl_panel.rowHeights = new int[]{0, 0, 0, 0, 0, 0}; gbl_panel.columnWeights = new double[]{0.0, 1.0, 0.0, Double.MIN_VALUE}; gbl_panel.rowWeights = new double[]{0.0, 0.0, 0.0, 1.0, 0.0, Double.MIN_VALUE}; panel.setLayout(gbl_panel); JLabel lblMcpFolder = new JLabel("MCP folder:"); GridBagConstraints gbc_lblMcpFolder = new GridBagConstraints(); gbc_lblMcpFolder.anchor = GridBagConstraints.EAST; gbc_lblMcpFolder.insets = new Insets(0, 0, 5, 5); gbc_lblMcpFolder.gridx = 0; gbc_lblMcpFolder.gridy = 0; panel.add(lblMcpFolder, gbc_lblMcpFolder); txtMCPDir = new JTextField(); GridBagConstraints gbc_txtMCPDir = new GridBagConstraints(); gbc_txtMCPDir.fill = GridBagConstraints.HORIZONTAL; gbc_txtMCPDir.insets = new Insets(0, 0, 5, 5); gbc_txtMCPDir.gridx = 1; gbc_txtMCPDir.gridy = 0; panel.add(txtMCPDir, gbc_txtMCPDir); txtMCPDir.setColumns(10); btnBrowseMCPDir = new JButton("Browse"); btnBrowseMCPDir.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser fc = new JFileChooser(); File curDir = new File(txtMCPDir.getText()); if(!curDir.isDirectory()) curDir = new File("."); fc.setCurrentDirectory(curDir); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); if(fc.showOpenDialog(frmBeardedOctoNemesis) == JFileChooser.APPROVE_OPTION) { prefs.put(PREFS_KEY_MCPDIR, fc.getSelectedFile().getAbsolutePath()); txtMCPDir.setText(fc.getSelectedFile().getAbsolutePath()); } } }); GridBagConstraints gbc_btnBrowseMCPDir = new GridBagConstraints(); gbc_btnBrowseMCPDir.insets = new Insets(0, 0, 5, 0); gbc_btnBrowseMCPDir.gridx = 2; gbc_btnBrowseMCPDir.gridy = 0; panel.add(btnBrowseMCPDir, gbc_btnBrowseMCPDir); JLabel lblSide = new JLabel("Side:"); GridBagConstraints gbc_lblSide = new GridBagConstraints(); gbc_lblSide.anchor = GridBagConstraints.EAST; gbc_lblSide.insets = new Insets(0, 0, 5, 5); gbc_lblSide.gridx = 0; gbc_lblSide.gridy = 1; panel.add(lblSide, gbc_lblSide); mcpSideSelector = new JComboBox(); GridBagConstraints gbc_mcpSideSelector = new GridBagConstraints(); gbc_mcpSideSelector.fill = GridBagConstraints.HORIZONTAL; gbc_mcpSideSelector.insets = new Insets(0, 0, 5, 5); gbc_mcpSideSelector.gridx = 1; gbc_mcpSideSelector.gridy = 1; panel.add(mcpSideSelector, gbc_mcpSideSelector); mcpSideSelector.setModel(new DefaultComboBoxModel(Side.values())); chckbxUseSrgNames = new JCheckBox("Use SRG names"); GridBagConstraints gbc_chckbxUseSrgNames = new GridBagConstraints(); gbc_chckbxUseSrgNames.anchor = GridBagConstraints.WEST; gbc_chckbxUseSrgNames.insets = new Insets(0, 0, 5, 5); gbc_chckbxUseSrgNames.gridx = 1; gbc_chckbxUseSrgNames.gridy = 2; panel.add(chckbxUseSrgNames, gbc_chckbxUseSrgNames); btnGoMCP = new JButton("Go"); btnGoMCP.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { goWithMCP(); } }); GridBagConstraints gbc_btnGoMCP = new GridBagConstraints(); gbc_btnGoMCP.fill = GridBagConstraints.HORIZONTAL; gbc_btnGoMCP.gridwidth = 3; gbc_btnGoMCP.gridx = 0; gbc_btnGoMCP.gridy = 4; panel.add(btnGoMCP, gbc_btnGoMCP); panel_1 = new JPanel(); panel_1.setBorder(new EmptyBorder(5, 5, 5, 5)); tabbedPane.addTab("Forge", null, panel_1, null); GridBagLayout gbl_panel_1 = new GridBagLayout(); gbl_panel_1.columnWidths = new int[]{0, 0, 0, 0}; gbl_panel_1.rowHeights = new int[]{0, 0, 0, 0, 0}; gbl_panel_1.columnWeights = new double[]{0.0, 1.0, 0.0, Double.MIN_VALUE}; gbl_panel_1.rowWeights = new double[]{0.0, 0.0, 1.0, 0.0, Double.MIN_VALUE}; panel_1.setLayout(gbl_panel_1); lblForgeUserdevjar = new JLabel("Forge userdev.jar:"); GridBagConstraints gbc_lblForgeUserdevjar = new GridBagConstraints(); gbc_lblForgeUserdevjar.anchor = GridBagConstraints.EAST; gbc_lblForgeUserdevjar.insets = new Insets(0, 0, 5, 5); gbc_lblForgeUserdevjar.gridx = 0; gbc_lblForgeUserdevjar.gridy = 0; panel_1.add(lblForgeUserdevjar, gbc_lblForgeUserdevjar); txtForgeJar = new JTextField(); txtForgeJar.setColumns(10); GridBagConstraints gbc_txtForgeJar = new GridBagConstraints(); gbc_txtForgeJar.insets = new Insets(0, 0, 5, 5); gbc_txtForgeJar.fill = GridBagConstraints.HORIZONTAL; gbc_txtForgeJar.gridx = 1; gbc_txtForgeJar.gridy = 0; panel_1.add(txtForgeJar, gbc_txtForgeJar); btnBrowseForgeJar = new JButton("Browse"); btnBrowseForgeJar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser fc = new JFileChooser(); File curDir = new File(txtForgeJar.getText()); if(!curDir.isDirectory()) curDir = new File("."); fc.setCurrentDirectory(curDir); fc.setFileFilter(new FileNameExtensionFilter("JAR files", "jar", "zip")); if(fc.showOpenDialog(frmBeardedOctoNemesis) == JFileChooser.APPROVE_OPTION) { prefs.put(PREFS_KEY_FORGEJAR, fc.getSelectedFile().getAbsolutePath()); txtForgeJar.setText(fc.getSelectedFile().getAbsolutePath()); } } }); GridBagConstraints gbc_btnBrowseForgeJar = new GridBagConstraints(); gbc_btnBrowseForgeJar.insets = new Insets(0, 0, 5, 0); gbc_btnBrowseForgeJar.gridx = 2; gbc_btnBrowseForgeJar.gridy = 0; panel_1.add(btnBrowseForgeJar, gbc_btnBrowseForgeJar); btnGoForge = new JButton("Go"); btnGoForge.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { goWithLocalForge(); } }); lblForgegradleCacheFolder = new JLabel("FG cache folder:"); GridBagConstraints gbc_lblForgegradleCacheFolder = new GridBagConstraints(); gbc_lblForgegradleCacheFolder.anchor = GridBagConstraints.EAST; gbc_lblForgegradleCacheFolder.insets = new Insets(0, 0, 5, 5); gbc_lblForgegradleCacheFolder.gridx = 0; gbc_lblForgegradleCacheFolder.gridy = 1; panel_1.add(lblForgegradleCacheFolder, gbc_lblForgegradleCacheFolder); txtFGCache = new JTextField(); txtFGCache.setToolTipText("The \".gradle/caches/minecraft/net/minecraftforge/forge\" folder."); txtFGCache.setColumns(10); GridBagConstraints gbc_txtFGCache = new GridBagConstraints(); gbc_txtFGCache.insets = new Insets(0, 0, 5, 5); gbc_txtFGCache.fill = GridBagConstraints.HORIZONTAL; gbc_txtFGCache.gridx = 1; gbc_txtFGCache.gridy = 1; panel_1.add(txtFGCache, gbc_txtFGCache); btnBrowseFGCache = new JButton("Browse"); btnBrowseFGCache.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser fc = new JFileChooser(); File curDir = new File(txtFGCache.getText()); if(!curDir.isDirectory()) curDir = new File("."); fc.setCurrentDirectory(curDir); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); if(fc.showOpenDialog(frmBeardedOctoNemesis) == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); if(new File(file, ".gradle").isDirectory()) file = new File(file, ".gradle"); if(new File(file, "caches").isDirectory()) file = new File(file, "caches"); if(new File(file, "minecraft").isDirectory()) file = new File(file, "minecraft"); if(new File(file, "net").isDirectory()) file = new File(file, "net"); if(new File(file, "minecraftforge").isDirectory()) file = new File(file, "minecraftforge"); if(new File(file, "forge").isDirectory()) file = new File(file, "forge"); prefs.put(PREFS_KEY_FGCACHE, file.getAbsolutePath()); txtFGCache.setText(file.getAbsolutePath()); } } }); GridBagConstraints gbc_btnBrowseFGCache = new GridBagConstraints(); gbc_btnBrowseFGCache.insets = new Insets(0, 0, 5, 0); gbc_btnBrowseFGCache.gridx = 2; gbc_btnBrowseFGCache.gridy = 1; panel_1.add(btnBrowseFGCache, gbc_btnBrowseFGCache); lblThisIsNot = new JLabel("This is not done, and will still download stuff."); GridBagConstraints gbc_lblThisIsNot = new GridBagConstraints(); gbc_lblThisIsNot.insets = new Insets(0, 0, 5, 5); gbc_lblThisIsNot.gridx = 1; gbc_lblThisIsNot.gridy = 2; panel_1.add(lblThisIsNot, gbc_lblThisIsNot); GridBagConstraints gbc_btnGoForge = new GridBagConstraints(); gbc_btnGoForge.fill = GridBagConstraints.HORIZONTAL; gbc_btnGoForge.gridwidth = 3; gbc_btnGoForge.gridx = 0; gbc_btnGoForge.gridy = 3; panel_1.add(btnGoForge, gbc_btnGoForge); panel_2 = new JPanel(); panel_2.setBorder(new EmptyBorder(5, 5, 5, 5)); tabbedPane.addTab("Forge (auto-download)", null, panel_2, null); GridBagLayout gbl_panel_2 = new GridBagLayout(); gbl_panel_2.columnWidths = new int[]{0, 0, 0, 0}; gbl_panel_2.rowHeights = new int[]{0, 0, 0, 0}; gbl_panel_2.columnWeights = new double[]{0.0, 1.0, 0.0, Double.MIN_VALUE}; gbl_panel_2.rowWeights = new double[]{0.0, 1.0, 0.0, Double.MIN_VALUE}; panel_2.setLayout(gbl_panel_2); label_1 = new JLabel("Forge version:"); GridBagConstraints gbc_label_1 = new GridBagConstraints(); gbc_label_1.anchor = GridBagConstraints.EAST; gbc_label_1.insets = new Insets(0, 0, 5, 5); gbc_label_1.gridx = 0; gbc_label_1.gridy = 0; panel_2.add(label_1, gbc_label_1); downloadForgeVersionSelector = new JComboBox(); GridBagConstraints gbc_downloadForgeVersionSelector = new GridBagConstraints(); gbc_downloadForgeVersionSelector.fill = GridBagConstraints.HORIZONTAL; gbc_downloadForgeVersionSelector.insets = new Insets(0, 0, 5, 5); gbc_downloadForgeVersionSelector.gridx = 1; gbc_downloadForgeVersionSelector.gridy = 0; panel_2.add(downloadForgeVersionSelector, gbc_downloadForgeVersionSelector); btnGetVersionList = new JButton("Get version list"); btnGetVersionList.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { getForgeVersionList(); } }); GridBagConstraints gbc_btnGetVersionList = new GridBagConstraints(); gbc_btnGetVersionList.insets = new Insets(0, 0, 5, 0); gbc_btnGetVersionList.gridx = 2; gbc_btnGetVersionList.gridy = 0; panel_2.add(btnGetVersionList, gbc_btnGetVersionList); lblNoteThisWill = new JLabel("Note: This will automatically download Minecraft Forge from the Internet."); GridBagConstraints gbc_lblNoteThisWill = new GridBagConstraints(); gbc_lblNoteThisWill.insets = new Insets(0, 0, 5, 0); gbc_lblNoteThisWill.gridwidth = 3; gbc_lblNoteThisWill.gridx = 0; gbc_lblNoteThisWill.gridy = 1; panel_2.add(lblNoteThisWill, gbc_lblNoteThisWill); btnGoForgeDownload = new JButton("Go"); GridBagConstraints gbc_btnGoForgeDownload = new GridBagConstraints(); gbc_btnGoForgeDownload.fill = GridBagConstraints.BOTH; gbc_btnGoForgeDownload.gridwidth = 3; gbc_btnGoForgeDownload.gridx = 0; gbc_btnGoForgeDownload.gridy = 2; panel_2.add(btnGoForgeDownload, gbc_btnGoForgeDownload); btnGoForgeDownload.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { goWithDownloadedForge(); } }); } private void goWithForge(final InputStream userdevJarIn) { final Operation op = (Operation)operationSelector.getSelectedItem(); if(op == Operation.ReobfuscateMod || op == Operation.SRGifyMod) { displayError("Only '"+Operation.ReobfuscateModSRG+"' and '"+Operation.DeobfuscateMod+"' are supported with Forge mods."); return; } final File fgCacheDirRoot = new File(txtFGCache.getText()); if(!fgCacheDirRoot.isDirectory()) { displayError("Not a directory: "+txtFGCache.getText()); return; } final DownloadDialog dlg = new DownloadDialog(frmBeardedOctoNemesis); dlg.setTitle("Running..."); dlg.label.setText(""); dlg.setModalityType(ModalityType.MODELESS); dlg.setVisible(true); dlg.progressBar.setValue(0); final File inputFile = new File(txtInputFile.getText()); final File outputFile = new File(txtOutputFile.getText()); Thread curTask = new Thread() { @Override public void run() { boolean crashed = false; try { IProgressListener progress = new IProgressListener() { private String currentText; @Override public void start(final int max, final String text) { currentText = text.equals("") ? " " : text; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dlg.label.setText(currentText); if(max >= 0) dlg.progressBar.setMaximum(max); dlg.progressBar.setValue(0); } }); } @Override public void set(final int value) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dlg.progressBar.setValue(value); } }); } @Override public void setMax(final int max) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dlg.progressBar.setMaximum(max); } }); } }; progress.start(1, "Reading userdev jar file"); SrgFile packagedSRG = null; ExcFile packagedEXC = null; Map<String, String> fieldsCSV = null; Map<String, String> methodsCSV = null; String forgeVer = null; try (ZipInputStream zis = new ZipInputStream(userdevJarIn)) { ZipEntry ze; while((ze = zis.getNextEntry()) != null) { if(ze.getName().equals("conf/packaged.exc")) packagedEXC = ExcFile.read(zis); if(ze.getName().equals("conf/packaged.srg")) packagedSRG = SrgFile.read(new InputStreamReader(zis, StandardCharsets.UTF_8), false); if(ze.getName().equals("conf/fields.csv")) fieldsCSV = CsvFile.read(new InputStreamReader(zis, StandardCharsets.UTF_8), new int[] {2, 1, 0}); if(ze.getName().equals("conf/methods.csv")) methodsCSV = CsvFile.read(new InputStreamReader(zis, StandardCharsets.UTF_8), new int[] {2, 1, 0}); if(ze.getName().startsWith("forge-") && ze.getName().endsWith("-changelog.txt")) forgeVer = ze.getName().substring(6, ze.getName().length()-14); } } progress.set(0); if(packagedSRG == null) throw new Exception("conf/packaged.srg not found in Forge jar file"); if(packagedEXC == null) throw new Exception("conf/packaged.exc not found in Forge jar file"); if(fieldsCSV == null) throw new Exception("conf/fields.csv not found in Forge jar file"); if(methodsCSV == null) throw new Exception("conf/methods.csv not found in Forge jar file"); if(forgeVer == null) throw new Exception("unable to determine Forge version from jar file"); File fgCacheDir = new File(fgCacheDirRoot, forgeVer); if(!fgCacheDir.isDirectory()) throw new Exception("ForgeGradle cache directory doesn't exist: "+fgCacheDir+". Is the directory set correctly, and is this version of Forge installed?"); String mcVer = "unknown"; immibis.bon.mcp.MinecraftNameSet.Side side = immibis.bon.mcp.MinecraftNameSet.Side.UNIVERSAL; MappingLoader_MCP loader = new MappingLoader_MCP(); progress.start(0, "Loading mappings and configuration"); loader.load(side, mcVer, packagedEXC, packagedSRG, fieldsCSV, methodsCSV, progress); MappingFactory.registerMCPInstance(mcVer, side, loader); MinecraftNameSet refNS = new MinecraftNameSet(MinecraftNameSet.Type.MCP, side, mcVer); Map<String, ClassCollection> refCCList = new HashMap<>(); for(File refPathFile : new File[] {new File(fgCacheDir, "forgeSrc-"+forgeVer+".jar")}) { System.err.println(refPathFile.getAbsolutePath()); progress.start(0, "Reading "+refPathFile.getName()); refCCList.put(refPathFile.getName(), ClassCollectionFactory.loadClassCollection(refNS, refPathFile, progress)); //progress.start(0, "Remapping "+s); //refs.add(Remapper.remap(mcpRefCC, inputNS, Collections.<ClassCollection>emptyList(), progress)); } MinecraftNameSet.Type[] remapTo; MinecraftNameSet.Type inputType; switch(op) { case DeobfuscateMod: inputType = MinecraftNameSet.Type.SRG; remapTo = new MinecraftNameSet.Type[] {MinecraftNameSet.Type.MCP}; break; case ReobfuscateModSRG: inputType = MinecraftNameSet.Type.MCP; remapTo = new MinecraftNameSet.Type[] {MinecraftNameSet.Type.SRG}; break; default: throw new AssertionError("operation = "+op+"?"); } NameSet inputNS = new MinecraftNameSet(inputType, side, mcVer); progress.start(0, "Reading "+inputFile.getName()); ClassCollection inputCC = ClassCollectionFactory.loadClassCollection(inputNS, inputFile, progress); // For deobfuscation: /* MCP reference * | | * | | * | | * V V * OBF reference SRG reference * | | * | | * V V * OBF input -----------> SRG input -----------> MCP input (output file) */ // remap to obf names from searge names, then searge names to MCP names, in two steps // the first will be a no-op if the mod uses searge names already for(MinecraftNameSet.Type outputType : remapTo) { MinecraftNameSet outputNS = new MinecraftNameSet(outputType, side, mcVer); List<ReferenceDataCollection> remappedRefs = new ArrayList<>(); for(Map.Entry<String, ClassCollection> e : refCCList.entrySet()) { if(inputCC.getNameSet().equals(e.getValue().getNameSet())) { // no need to remap this remappedRefs.add(ReferenceDataCollection.fromClassCollection(e.getValue())); } else { progress.start(0, "Remapping "+e.getKey()+" to "+outputType+" names"); remappedRefs.add(ReferenceDataCollection.fromClassCollection(Remapper.remap(e.getValue(), MappingFactory.getMapping((MinecraftNameSet)e.getValue().getNameSet(), (MinecraftNameSet)inputCC.getNameSet(), null), Collections.<ReferenceDataCollection>emptyList(), progress))); } } progress.start(0, "Remapping "+inputFile.getName()+" to "+outputType+" names"); inputCC = Remapper.remap(inputCC, MappingFactory.getMapping((MinecraftNameSet)inputCC.getNameSet(), outputNS, null), remappedRefs, progress); } progress.start(0, "Writing "+outputFile.getName()); JarWriter.write(outputFile, inputCC, progress); } catch(Exception e) { String s = getStackTraceMessage(e); System.err.println(s); crashed = true; final String errMsg = s; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dlg.setVisible(false); dlg.dispose(); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(errMsg), null); JOptionPane.showMessageDialog(frmBeardedOctoNemesis, errMsg, "BON - Error", JOptionPane.ERROR_MESSAGE); } }); } finally { if(!crashed) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dlg.setVisible(false); dlg.dispose(); JOptionPane.showMessageDialog(frmBeardedOctoNemesis, "Done!", "BON", JOptionPane.INFORMATION_MESSAGE); } }); } } } }; curTask.setName("remap thread"); curTask.setDaemon(true); curTask.start(); } private void displayError(String msg) { JOptionPane.showMessageDialog(frmBeardedOctoNemesis, msg, "Error - Bearded Octo Nemesis", JOptionPane.ERROR_MESSAGE); } private void goWithLocalForge() { try { goWithForge(new FileInputStream(new File(txtForgeJar.getText()))); } catch(FileNotFoundException e) { displayError("File not found: "+txtForgeJar.getText()); } } private void goWithDownloadedForge() { String selver = (String)downloadForgeVersionSelector.getSelectedItem(); if(selver == null || selver.equals("")) displayError("You must select a Forge version."); else { try { URL url = new URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/"+selver+"/forge-"+selver+"-userdev.jar"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DownloadDialog.download(frmBeardedOctoNemesis, url, baos); goWithForge(new ByteArrayInputStream(baos.toByteArray())); } catch(Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(frmBeardedOctoNemesis, e.toString(), "Error - Bearded Octo Nemesis", JOptionPane.ERROR_MESSAGE); } } } private void getForgeVersionList() { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DownloadDialog.download(frmBeardedOctoNemesis, new URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/json"), baos); Object jsonroot = JsonReader.readJSON(new InputStreamReader(new ByteArrayInputStream(baos.toByteArray()))); List<String> buildNumbers = new ArrayList<>(((Map<String,Map<String,?>>)jsonroot).get("number").keySet()); Collections.sort(buildNumbers, new Comparator<String>() { @Override public int compare(String o1, String o2) { return Integer.parseInt(o2) - Integer.parseInt(o1); } }); DefaultComboBoxModel<String> model = ((DefaultComboBoxModel<String>)downloadForgeVersionSelector.getModel()); model.removeAllElements(); for(String buildNum : buildNumbers) { Map build = ((Map<String,Map<String,Map>>)jsonroot).get("number").get(buildNum); model.addElement(build.get("mcversion")+"-"+build.get("version")); } } catch(Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(frmBeardedOctoNemesis, e.toString(), "Error - Bearded Octo Nemesis", JOptionPane.ERROR_MESSAGE); } } private void goWithMCP() { final Operation op = (Operation)operationSelector.getSelectedItem(); final Side side = (Side)mcpSideSelector.getSelectedItem(); final File mcpDir = new File(txtMCPDir.getText()); final File confDir = new File(mcpDir, "conf"); final String[] refPathList = side.referencePath.split(File.pathSeparator); String error = null; if(!mcpDir.isDirectory()) error = "MCP folder not found (at "+mcpDir+")"; else if(!confDir.isDirectory()) error = "'conf' folder not found in MCP folder (at "+confDir+")"; if(error != null) { displayError(error); return; } final DownloadDialog dlg = new DownloadDialog(frmBeardedOctoNemesis); dlg.setTitle("Running..."); dlg.label.setText(""); dlg.setModalityType(ModalityType.MODELESS); dlg.setVisible(true); dlg.progressBar.setValue(0); final File inputFile = new File(txtInputFile.getText()); final File outputFile = new File(txtOutputFile.getText()); Thread curTask = new Thread() { @Override public void run() { boolean crashed = false; try { IProgressListener progress = new IProgressListener() { private String currentText; @Override public void start(final int max, final String text) { currentText = text.equals("") ? " " : text; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dlg.label.setText(currentText); if(max >= 0) dlg.progressBar.setMaximum(max); dlg.progressBar.setValue(0); } }); } @Override public void set(final int value) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dlg.progressBar.setValue(value); } }); } @Override public void setMax(final int max) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dlg.progressBar.setMaximum(max); } }); } }; String mcVer = MappingLoader_MCP.getMCVer(mcpDir); MinecraftNameSet refNS = new MinecraftNameSet(MinecraftNameSet.Type.MCP, side.nsside, mcVer); Map<String, ClassCollection> refCCList = new HashMap<>(); for(String s : refPathList) { File refPathFile = new File(mcpDir, s); progress.start(0, "Reading "+s); refCCList.put(s, ClassCollectionFactory.loadClassCollection(refNS, refPathFile, progress)); //progress.start(0, "Remapping "+s); //refs.add(Remapper.remap(mcpRefCC, inputNS, Collections.<ClassCollection>emptyList(), progress)); } MinecraftNameSet.Type[] remapTo; MinecraftNameSet.Type inputType; switch(op) { case DeobfuscateMod: inputType = MinecraftNameSet.Type.OBF; remapTo = new MinecraftNameSet.Type[] {MinecraftNameSet.Type.SRG, MinecraftNameSet.Type.MCP}; break; case ReobfuscateMod: inputType = MinecraftNameSet.Type.MCP; remapTo = new MinecraftNameSet.Type[] {MinecraftNameSet.Type.OBF}; break; case SRGifyMod: inputType = MinecraftNameSet.Type.OBF; remapTo = new MinecraftNameSet.Type[] {MinecraftNameSet.Type.SRG}; break; case ReobfuscateModSRG: inputType = MinecraftNameSet.Type.MCP; remapTo = new MinecraftNameSet.Type[] {MinecraftNameSet.Type.SRG}; break; default: throw new AssertionError("operation = "+op+"?"); } NameSet inputNS = new MinecraftNameSet(inputType, side.nsside, mcVer); progress.start(0, "Reading "+inputFile.getName()); ClassCollection inputCC = ClassCollectionFactory.loadClassCollection(inputNS, inputFile, progress); progress.start(0, "Reading MCP configuration"); MappingFactory.registerMCPInstance(mcVer, side.nsside, mcpDir, progress); // For deobfuscation: /* MCP reference * | | * | | * | | * V V * OBF reference SRG reference * | | * | | * V V * OBF input -----------> SRG input -----------> MCP input (output file) */ // remap to obf names from searge names, then searge names to MCP names, in two steps // the first will be a no-op if the mod uses searge names already for(MinecraftNameSet.Type outputType : remapTo) { MinecraftNameSet outputNS = new MinecraftNameSet(outputType, side.nsside, mcVer); List<ReferenceDataCollection> remappedRefs = new ArrayList<>(); for(Map.Entry<String, ClassCollection> e : refCCList.entrySet()) { if(inputCC.getNameSet().equals(e.getValue().getNameSet())) { // no need to remap this remappedRefs.add(ReferenceDataCollection.fromClassCollection(e.getValue())); } else { progress.start(0, "Remapping "+e.getKey()+" to "+outputType+" names"); remappedRefs.add(ReferenceDataCollection.fromClassCollection(Remapper.remap(e.getValue(), MappingFactory.getMapping((MinecraftNameSet)e.getValue().getNameSet(), (MinecraftNameSet)inputCC.getNameSet(), null), Collections.<ReferenceDataCollection>emptyList(), progress))); } } progress.start(0, "Remapping "+inputFile.getName()+" to "+outputType+" names"); inputCC = Remapper.remap(inputCC, MappingFactory.getMapping((MinecraftNameSet)inputCC.getNameSet(), outputNS, null), remappedRefs, progress); } progress.start(0, "Writing "+outputFile.getName()); JarWriter.write(outputFile, inputCC, progress); } catch(Exception e) { String s = getStackTraceMessage(e); /*if(!new File(confDir, side.nsside.srg_name).exists()) { s = side.mcpside.srg_name+" not found in conf directory. \n"; switch(side) { case Client: case Server: s += "If you're using Forge, set the side to Universal (1.4.6+) or Universal_old (1.4.5 and earlier)"; break; case Universal: s += "If you're not using Forge, set the side to Client or Server.\n"; s += "If you're using Forge on 1.4.5 or earlier, set the side to Universal_old."; break; case Universal_old: s += "If you're not using Forge, set the side to Client or Server.\n"; break; } }*/ System.err.println(s); crashed = true; final String errMsg = s; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dlg.setVisible(false); dlg.dispose(); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(errMsg), null); JOptionPane.showMessageDialog(frmBeardedOctoNemesis, errMsg, "BON - Error", JOptionPane.ERROR_MESSAGE); } }); } finally { if(!crashed) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dlg.setVisible(false); dlg.dispose(); JOptionPane.showMessageDialog(frmBeardedOctoNemesis, "Done!", "BON", JOptionPane.INFORMATION_MESSAGE); } }); } } } }; curTask.setName("remap thread"); curTask.setDaemon(true); curTask.start(); } private static String getPrintableStackTrace(Throwable e, Set<StackTraceElement> stopAt) { String s = e.toString(); int numPrinted = 0; for(StackTraceElement ste : e.getStackTrace()) { boolean stopHere = false; if(stopAt.contains(ste) && numPrinted > 0) stopHere = true; else { s += "\n at " + ste.toString(); numPrinted++; if(ste.getClassName().startsWith("javax.swing.")) stopHere = true; } if(stopHere) { int numHidden = e.getStackTrace().length - numPrinted; s += "\n ... "+numHidden+" more"; break; } } return s; } private static String getStackTraceMessage(Throwable e) { String s = "An error has occurred - give immibis this stack trace (which has been copied to the clipboard)\n"; s += "\n" + getPrintableStackTrace(e, Collections.<StackTraceElement>emptySet()); while(e.getCause() != null) { Set<StackTraceElement> stopAt = new HashSet<StackTraceElement>(Arrays.asList(e.getStackTrace())); e = e.getCause(); s += "\nCaused by: "+getPrintableStackTrace(e, stopAt); } return s; } }