diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..438e81f --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.class +*.jar +MANIFEST.MF diff --git a/Converter.java b/Converter.java new file mode 100644 index 0000000..51086ae --- /dev/null +++ b/Converter.java @@ -0,0 +1,245 @@ +import java.util.Scanner; +import javax.swing.JTextArea; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; + + +// not completely finished, but hopefully it's close. + +public class Converter { + private String pathIn; + private String pathOut; + private String levelData; + private String levelDataBackup; + private int laserCount; + private int replacedLaserCount; + private final String rLaserType = "\"_type\":13"; + private final String lLaserType = "\"_type\":12"; + + public Converter(String path) { + this.pathIn = path; + this.pathOut = this.pathIn; + this.levelData = loadLevelData(); + } + + public Converter(String pathIn, String pathOut) { + this.pathIn = pathIn; + this.pathOut = pathOut; + this.levelData = loadLevelData(); + } + + public int getLaserCount() { + return laserCount; + } + + public int getReplacedLaserCount() { + return replacedLaserCount; + } + + private String loadLevelData() { + try { + FileReader reader = new FileReader(pathIn); + Scanner scan = new Scanner(reader); + String localLevelData = scan.nextLine(); + scan.close(); + levelDataBackup = localLevelData; + return localLevelData; + } catch (Exception e) { + return "Error"; + } + } + + public void backupLevelData(JTextArea log) { + String backupLocation = pathIn.substring(0, pathIn.indexOf(".dat")) + "_backup.dat"; + try { + File file = new File(backupLocation); + FileWriter fileWriter = new FileWriter(file); + fileWriter.write(levelDataBackup); + fileWriter.flush(); + fileWriter.close(); + } catch (Exception e) { + log.append("ERROR: idk wtf when worng lol"); + } + } + + public void outputLevelData(JTextArea log) { + try { + File file = new File(pathOut); + FileWriter fileWriter = new FileWriter(file); + fileWriter.write(levelData); + fileWriter.flush(); + fileWriter.close(); + } catch (Exception e) { + log.append("ERROR: idk wtf when worng lol"); + } + } + + public void checkEvents(JTextArea log) { + laserCount = 0; + log.append("Looking for Laser events... \n"); + + for (int i = 0; i < (levelData.length() - rLaserType.length() - 5); i++) { + if (levelData.substring(i, (i + rLaserType.length())).equals(rLaserType)) { + log.append("Looking for " + lLaserType + " and " + rLaserType + ". Found: " + laserCount + " PROGRESS: " + i + "/" + levelData.length() + "\n"); + laserCount++; + } else if (levelData.substring(i, (i + lLaserType.length())).equals(lLaserType)) { + log.append("Looking for " + lLaserType + " and " + rLaserType + ". Found: " + laserCount + " PROGRESS: " + i + "/" + levelData.length() + "\n"); + laserCount++; + } + } + + log.append("Found " + laserCount + " matches for laser speed events. \n"); + } + + public void replaceEvents(JTextArea log) { + replacedLaserCount = 0; + // Start replacing based on type 13's value + for (int i = 0; i < (levelData.length() - rLaserType.length() - 5); i++) { + if (levelData.substring(i, (i + rLaserType.length())).equals(rLaserType)) { + String event = levelData.substring(i, levelData.indexOf("}", i)); + int eventValue = Integer.parseInt(event.substring(event.lastIndexOf(":") + 1)); + int eventType = Integer.parseInt(event.substring(event.indexOf(":") + 1, event.indexOf(","))); + switch (eventValue) { + // Switch event into 360 event + case 0: case 1: case 2: case 3: + case 4: case 5: case 6: case 7: + eventType = 15; + break; + // keep event as laser + default: + eventValue = Math.abs(eventValue - 8); + break; + } + event = "\"_type\":" + eventType + ",\"_value\":" + eventValue; + levelData = levelData.substring(0, i) + event + levelData.substring(levelData.indexOf("}", i)); + replacedLaserCount++; + log.append("Converting laser events... Currently on " + replacedLaserCount + "/" + laserCount + "\n"); + + // Start replacing based on type 12's value + } else if (levelData.substring(i, (i + lLaserType.length())).equals(lLaserType)) { + String event = levelData.substring(i, levelData.indexOf("}", i)); + int eventValue = Integer.parseInt(event.substring(event.lastIndexOf(":") + 1)); + int eventType = Integer.parseInt(event.substring(event.indexOf(":") + 1, event.indexOf(","))); + switch (eventValue) { + // Switch event into 360 event + case 0: case 1: case 2: case 3: + case 4: case 5: case 6: case 7: + eventType = 14; + break; + // keep event as laser + default: + eventValue = Math.abs(eventValue - 8); + break; + } + event = "\"_type\":" + eventType + ",\"_value\":" + eventValue; + levelData = levelData.substring(0, i) + event + levelData.substring(levelData.indexOf("}", i)); + replacedLaserCount++; + log.append("Converting laser events... Currently on " + replacedLaserCount + "/" + laserCount + "\n"); + } + } + log.append("Converting laser events... Done. " + replacedLaserCount + "/" + laserCount + "\n"); + } +/* Used for holding old method, as I would still like to keep it in the branch for refrence for now. + private static void prototype() throws FileNotFoundException, IOException { + // Call for user file loc. + Scanner userPrompt = new Scanner(System.in); + System.out.println("Only run this once per file. Do not open files generated with this tool in MMA2."); + System.out.println("Where is the level.dat located?"); + String oFile = userPrompt.nextLine().trim(); + System.out.println("Where do you want your want your level.dat to be exported to?\nNOTE: Blank will overwrite the existing file."); + String nFileInput = userPrompt.nextLine(); + String nFile; + if (nFileInput.isBlank()) { + nFile = oFile; + } else { + nFile = nFileInput.trim(); + } + nFileInput = null; + + // Read file + FileReader reader = new FileReader(oFile); + Scanner scan = new Scanner(reader); + String levelData = scan.nextLine(); + scan.close(); + + //For error checking later + final String rLaserType = "\"_type\":13"; + final String lLaserType = "\"_type\":12"; + int LaserCount = 0; + System.out.print("Looking for Laser events... \r"); + + for (int i = 0; i < (levelData.length() - rLaserType.length() - 5); i++) { + if (levelData.substring(i,(i + rLaserType.length())).equals(rLaserType)) { + System.out.print("Looking for " + lLaserType + " and " + rLaserType +". Found: " + LaserCount + " PROGRESS: " + i + "/" + levelData.length() + "\r"); + LaserCount++; + } else if (levelData.substring(i,(i + lLaserType.length())).equals(lLaserType)) { + System.out.print("Looking for " + lLaserType + " and " + rLaserType +". Found: " + LaserCount + " PROGRESS: " + i + "/" + levelData.length() + "\r"); + LaserCount++; + } + } + + System.out.println("Found " + LaserCount + " matches for laser speed events. "); + + // confirm details with the user, if not exit. + System.out.println("Would you like to continue? Y/n (Default is Y)"); + String confirm = userPrompt.nextLine(); + if (confirm.equals("Y") || confirm.isBlank()) { + } else { + userPrompt.close(); + System.exit(0); + } + + int replaceCount = 0; + // Start replacing based on type 13's value + for (int i = 0; i < (levelData.length() - rLaserType.length() - 5); i++) { + if (levelData.substring(i,(i + rLaserType.length())).equals(rLaserType)) { + String event = levelData.substring(i,levelData.indexOf("}", i)); + int eventValue = Integer.parseInt(event.substring(event.lastIndexOf(":") + 1)); + int eventType = Integer.parseInt(event.substring(event.indexOf(":") + 1, event.indexOf(","))); + switch (eventValue) { + // Switch event into 360 event + case 0: case 1: case 2: case 3: + case 4: case 5: case 6: case 7: + eventType = 15; break; + // keep event as laser + default: + eventValue = Math.abs(eventValue - 8); break; + } + event = "\"_type\":" + eventType + ",\"_value\":" + eventValue; + levelData = levelData.substring(0,i) + event + levelData.substring(levelData.indexOf("}", i)); + replaceCount++; + + + // Start replacing based on type 12's value + } else if (levelData.substring(i,(i + lLaserType.length())).equals(lLaserType)) { + String event = levelData.substring(i,levelData.indexOf("}", i)); + int eventValue = Integer.parseInt(event.substring(event.lastIndexOf(":") + 1)); + int eventType = Integer.parseInt(event.substring(event.indexOf(":") + 1, event.indexOf(","))); + switch (eventValue) { + // Switch event into 360 event + case 0: case 1: case 2: case 3: + case 4: case 5: case 6: case 7: + eventType = 14; break; + // keep event as laser + default: + eventValue = Math.abs(eventValue - 8); break; + } + event = "\"_type\":" + eventType + ",\"_value\":" + eventValue; + levelData = levelData.substring(0,i) + event + levelData.substring(levelData.indexOf("}", i)); + replaceCount++; + } + System.out.print("Converting laser events... Currently on " + replaceCount + "/" + LaserCount + "\r"); + } + System.out.println("Converting laser events... Done. " + replaceCount + "/" + LaserCount + " "); + System.out.println("Outputting file at " + nFile); + + File file = new File(nFile); + FileWriter fileWriter = new FileWriter(file); + fileWriter.write(levelData); + fileWriter.flush(); + fileWriter.close(); + userPrompt.close(); + } + */ +} diff --git a/Main.java b/Main.java index 3123ccf..d3e9539 100644 --- a/Main.java +++ b/Main.java @@ -1,118 +1,10 @@ - // This will be the worst code you have ever seen. Sorry but I don't care. -import java.util.Scanner; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.FileNotFoundException; -import java.io.IOException; - -/** - * Converts type 12 & type 13 events into laser & 360 events based on their value - * (0-7 for 360 and 8 - * for laser speed) - * @author TM0D - * - */ public class Main { - public static void main(String[] args) throws FileNotFoundException, IOException { - // Call for user file loc. - Scanner userPrompt = new Scanner(System.in); - System.out.println("Only run this once per file. Do not open files generated with this tool in MMA2."); - System.out.println("Where is the level.dat located?"); - String oFile = userPrompt.nextLine().trim(); - System.out.println("Where do you want your want your level.dat to be exported to?\nNOTE: Blank will overwrite the existing file."); - String nFileInput = userPrompt.nextLine(); - String nFile; - if (nFileInput.isBlank()) { - nFile = oFile; - } else { - nFile = nFileInput.trim(); - } - nFileInput = null; - - // Read file - FileReader reader = new FileReader(oFile); - Scanner scan = new Scanner(reader); - String levelData = scan.nextLine(); - scan.close(); - - //For error checking later - final String rLaserType = "\"_type\":13"; - final String lLaserType = "\"_type\":12"; - int LaserCount = 0; - System.out.print("Looking for Laser events... \r"); - - for (int i = 0; i < (levelData.length() - rLaserType.length() - 5); i++) { - if (levelData.substring(i,(i + rLaserType.length())).equals(rLaserType)) { - System.out.print("Looking for " + lLaserType + " and " + rLaserType +". Found: " + LaserCount + " PROGRESS: " + i + "/" + levelData.length() + "\r"); - LaserCount++; - } else if (levelData.substring(i,(i + lLaserType.length())).equals(lLaserType)) { - System.out.print("Looking for " + lLaserType + " and " + rLaserType +". Found: " + LaserCount + " PROGRESS: " + i + "/" + levelData.length() + "\r"); - LaserCount++; - } - } - - System.out.println("Found " + LaserCount + " matches for laser speed events. "); - - // confirm details with the user, if not exit. - System.out.println("Would you like to continue? Y/n (Default is Y)"); - String confirm = userPrompt.nextLine(); - if (confirm.equals("Y") || confirm.isBlank()) { - } else { - userPrompt.close(); - System.exit(0); - } - - int replaceCount = 0; - // Start replacing based on type 13's value - for (int i = 0; i < (levelData.length() - rLaserType.length() - 5); i++) { - if (levelData.substring(i,(i + rLaserType.length())).equals(rLaserType)) { - String event = levelData.substring(i,levelData.indexOf("}", i)); - int eventValue = Integer.parseInt(event.substring(event.lastIndexOf(":") + 1)); - int eventType = Integer.parseInt(event.substring(event.indexOf(":") + 1, event.indexOf(","))); - switch (eventValue) { - // Switch event into 360 event - case 0: case 1: case 2: case 3: - case 4: case 5: case 6: case 7: - eventType = 15; break; - // keep event as laser - default: - eventValue = Math.abs(eventValue - 8); break; - } - event = "\"_type\":" + eventType + ",\"_value\":" + eventValue; - levelData = levelData.substring(0,i) + event + levelData.substring(levelData.indexOf("}", i)); - replaceCount++; - - - // Start replacing based on type 12's value - } else if (levelData.substring(i,(i + lLaserType.length())).equals(lLaserType)) { - String event = levelData.substring(i,levelData.indexOf("}", i)); - int eventValue = Integer.parseInt(event.substring(event.lastIndexOf(":") + 1)); - int eventType = Integer.parseInt(event.substring(event.indexOf(":") + 1, event.indexOf(","))); - switch (eventValue) { - // Switch event into 360 event - case 0: case 1: case 2: case 3: - case 4: case 5: case 6: case 7: - eventType = 14; break; - // keep event as laser - default: - eventValue = Math.abs(eventValue - 8); break; - } - event = "\"_type\":" + eventType + ",\"_value\":" + eventValue; - levelData = levelData.substring(0,i) + event + levelData.substring(levelData.indexOf("}", i)); - replaceCount++; - } - System.out.print("Converting laser events... Currently on " + replaceCount + "/" + LaserCount + "\r"); - } - System.out.println("Converting laser events... Done. " + replaceCount + "/" + LaserCount + " "); - System.out.println("Outputting file at " + nFile); - - File file = new File(nFile); - FileWriter fileWriter = new FileWriter(file); - fileWriter.write(levelData); - fileWriter.flush(); - fileWriter.close(); - userPrompt.close(); + private static Converter converter; + private static Window frame; + public static void main(String[] args) { + frame = new Window(converter); + frame.setupFrame(); } } diff --git a/README.md b/README.md index bd6bfcc..f539e3f 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,19 @@ # MMA2Converter Made to easily make 360 Beat Saber maps in MMA2 without losing a event track. +### Releases +So I've got it running, should just need Java 8 (which you probably have installed). + +### Other +Currently the output file names aren't the best, but I'll fix that later. + +When mapping in MMA2: + Left Laser - event 14 (0-7) Right Laser - event 15 (0-7) +Laser speed: 8 = 0, 9 = 1, 10 = 2, etc.. -Laser speed: 8 = 0, 9 = 1, 10 = 2, etc.. +See the [BSMG Wiki](https://bsmg.wiki/mapping/extended-mapping.html#rotation-events-and-values) for more info as to what this all means diff --git a/Window.java b/Window.java new file mode 100644 index 0000000..04fb2a9 --- /dev/null +++ b/Window.java @@ -0,0 +1,159 @@ +import java.io.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + + +// Just yoinked the code from my ScuffedWalls Project +public class Window implements ActionListener { + private static JFrame frame; + private JTextField inField; + private JButton checkButton, loadButton, backupButton, outputButton, checkLevelButton, convertButton; + private JTextArea log; + private JScrollPane logScrollPane; + private Converter converter; + private boolean loadFlag = false; + + public Window(Converter converter) { + this.converter = converter; + frame = new JFrame("MMA2 360 Converter"); + frame.setSize(600,400); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + + + public void setupFrame() { + setupFrameFileSelect(); + setupFrameLog(); + setupFrameButtons(); + + frame.getContentPane().setBackground(new Color(100,100,100)); + frame.setLayout(null); + frame.setVisible(true); + } + + /** + * Setup Menu Bar + */ + private void setupFrameFileSelect() { + inField = new JTextField(" Full File Path"); + inField.setBounds(5,5,480,25); + inField.setBackground(new Color(50,50,50)); + inField.setForeground(Color.WHITE); + + frame.add(inField); + } + + private void setupFrameLog() { + log = new JTextArea(); + log.setMargin(new Insets(5,5,5,5)); + log.setEditable(false); + logScrollPane = new JScrollPane(log); + logScrollPane.setBounds(5, 35, 480, 320); + log.setBackground(new Color(50,50,50)); + log.setForeground(Color.WHITE); + + frame.add(logScrollPane); + } + + private void setupFrameButtons() { + checkButton = new JButton("Check"); + checkButton.setBounds(490, 5, 90, 25); + checkButton.setBackground(new Color(50,50,50)); + checkButton.setForeground(Color.WHITE); + + loadButton = new JButton("Load"); + loadButton.setBounds(490, 35, 90, 25); + loadButton.setBackground(new Color(50,50,50)); + loadButton.setForeground(Color.WHITE); + + backupButton = new JButton("Backup"); + backupButton.setBounds(490, 300, 90, 25); + backupButton.setBackground(new Color(50,50,50)); + backupButton.setForeground(Color.WHITE); + + + convertButton = new JButton("Convert"); + convertButton.setBounds(490, 170, 90, 25); + convertButton.setBackground(new Color(50,50,50)); + convertButton.setForeground(Color.ORANGE); + + outputButton = new JButton("Output"); + outputButton.setBounds(490, 330, 90, 25); + outputButton.setBackground(new Color(50,50,50)); + outputButton.setForeground(Color.WHITE); + + + checkLevelButton = new JButton("Check lvl"); + checkLevelButton.setBounds(490, 140, 90, 25); + checkLevelButton.setBackground(new Color(50,50,50)); + checkLevelButton.setForeground(Color.GREEN); + + loadButton.setEnabled(false); convertButton.setEnabled(false); + backupButton.setEnabled(false); checkLevelButton.setEnabled(false); + outputButton.setEnabled(false); + loadButton.addActionListener(this); convertButton.addActionListener(this); + checkButton.addActionListener(this); backupButton.addActionListener(this); + outputButton.addActionListener(this); checkLevelButton.addActionListener(this); + + + frame.add(checkButton); frame.add(loadButton); + frame.add(convertButton); frame.add(backupButton); + frame.add(checkLevelButton); frame.add(outputButton); + } + + /* + * ***************** + * ** After-Setup ** + * ***************** + */ + + public void actionPerformed(ActionEvent e) { + // CHECK + if (e.getSource() == checkButton) { + try { + File test = new File(inField.getText()); + if (test.exists() && test.isFile()) { // && test.getPath().indexOf(".dat") != -1 && true + inField.setEditable(false); + checkButton.setEnabled(false); + loadButton.setEnabled(true); + log.append("Valid File Found!\n"); + } else { + log.append("ERROR: INVALID FILE PATH\n"); + log.append("\n"); + log.append("Please input a valid file. (e.g. ExpertStandard.dat\n"); + checkButton.setForeground(Color.RED); + } + } catch (Exception err) { + log.append("ERROR: " + err); + log.append(" \n"); + log.append("Please input a valid file.\n"); + checkButton.setForeground(Color.RED); + } + + } else if (e.getSource() == loadButton) { + converter = new Converter(inField.getText()); + log.append("File Loaded!"); + checkLevelButton.setEnabled(true); backupButton.setEnabled(true); + convertButton.setEnabled(true); loadButton.setEnabled(false); + } else if (e.getSource() == checkLevelButton) { + converter.checkEvents(log); + convertButton.setForeground(Color.GREEN); + loadFlag = true; + } else if (e.getSource() == convertButton) { + convertButton.setEnabled(false); + if (loadFlag) { + converter.replaceEvents(log); + } else { + converter.checkEvents(log); + converter.replaceEvents(log); + } + checkLevelButton.setEnabled(false); convertButton.setEnabled(false); + outputButton.setEnabled(true); + } else if (e.getSource() == backupButton) { + converter.backupLevelData(log); + } else if (e.getSource() == outputButton) { + converter.outputLevelData(log); + } + } +} \ No newline at end of file