diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/AbstractMinecraftLoader.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/AbstractMinecraftLoader.java index 42efa5cd7..acb34ddbf 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/AbstractMinecraftLoader.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/AbstractMinecraftLoader.java @@ -84,6 +84,7 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader { res.add("-XX:+CMSIncrementalMode"); res.add("-XX:-UseAdaptiveSizePolicy"); res.add("-XX:-OmitStackTraceInFastThrow"); + res.add("-Xincgc"); res.add("-Xmn128m"); } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/mod/ModpackManager.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/mod/ModpackManager.java index 26586205a..7de0115f1 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/mod/ModpackManager.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/mod/ModpackManager.java @@ -86,21 +86,9 @@ public final class ModpackManager { @Override public void executeTask() throws Throwable { String id = idFUCK; - File versions = new File(service.baseDirectory(), "versions"); - File oldFile = new File(versions, "minecraft"), newFile = null; - if (oldFile.exists()) { - newFile = new File(versions, "minecraft-" + System.currentTimeMillis()); - if (newFile.isDirectory()) - FileUtils.deleteDirectory(newFile); - else if (newFile.isFile()) - if (!newFile.delete()) - HMCLog.warn("Failed to delete file " + newFile); - if (!oldFile.renameTo(newFile)) - HMCLog.warn("Failed to rename " + oldFile + " to " + newFile); - } - String description = C.i18n("modpack.install.will_install"); + // Read modpack name and description from `modpack.json` try (ZipFile zip = new ZipFile(input)) { HashMap map = C.GSON.fromJson(new InputStreamReader(zip.getInputStream(zip.getEntry("modpack.json")), "UTF-8"), HashMap.class); if (map != null) { @@ -116,6 +104,7 @@ public final class ModpackManager { throw new IllegalStateException("Illegal modpack id!"); } + // Show a window to let the user know that what and how the modpack is. Object msgs[] = new Object[2]; msgs[0] = C.i18n("modpack.install.task"); msgs[1] = new WebPage(description); @@ -124,6 +113,25 @@ public final class ModpackManager { if (result == JOptionPane.NO_OPTION) return; + File versions = new File(service.baseDirectory(), "versions"); + + // `minecraft` folder is the existent root folder of the modpack + // Then we will decompress the modpack and there would be a folder named `minecraft` + // So if `minecraft` folder does exist, backup it and then restore it. + File oldFile = new File(versions, "minecraft"), newFile = null; + if (oldFile.exists()) { + newFile = new File(versions, "minecraft-" + System.currentTimeMillis()); + if (newFile.isDirectory()) + FileUtils.deleteDirectory(newFile); + else if (newFile.isFile()) + if (!newFile.delete()) + HMCLog.warn("Failed to delete file " + newFile); + if (!oldFile.renameTo(newFile)) + HMCLog.warn("Failed to rename " + oldFile + " to " + newFile); + } + + // If the user install the modpack into an existent version, maybe it wants to update the modpack + // So backup the game, copy the saved games. File preVersion = new File(versions, id), preVersionRenamed = null; if (preVersion.exists()) { HMCLog.log("Backing up the game"); @@ -132,6 +140,7 @@ public final class ModpackManager { HMCLog.warn("Failed to rename pre-version folder " + preVersion + " to a temp folder " + preVersionRenamed); if (!new File(preVersionRenamed, id + ".json").renameTo(new File(preVersionRenamed, preId + ".json"))) HMCLog.warn("Failed to rename pre json to new json"); + if (!new File(preVersionRenamed, id + ".jar").renameTo(new File(preVersionRenamed, preId + ".jar"))) HMCLog.warn("Failed to rename pre jar to new jar"); } @@ -144,6 +153,8 @@ public final class ModpackManager { b.incrementAndGet(); return true; }, true); + + // No pack.json here, illegal modpack. if (b.get() < 1) throw new FileNotFoundException(C.i18n("modpack.incorrect_format.no_json")); File nowFile = new File(versions, id); @@ -161,6 +172,7 @@ public final class ModpackManager { if (!json.renameTo(new File(nowFile, id + ".json"))) HMCLog.warn("Failed to rename pack.json to new id"); + // Restore the saved game from the old version. if (preVersionRenamed != null) { HMCLog.log("Restoring saves"); File presaves = new File(preVersionRenamed, "saves"); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftVersionManager.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftVersionManager.java index 662168a07..facb50e0e 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftVersionManager.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftVersionManager.java @@ -124,7 +124,7 @@ public class MinecraftVersionManager extends IMinecraftProvider { mcVersion = C.GSON.fromJson(FileUtils.readFileToString(jsonFile), MinecraftVersion.class); if (mcVersion == null) throw new GameException("Wrong json format, got null."); - } catch (IOException | GameException ex) { + } catch (IOException | GameException | JsonSyntaxException ex) { HMCLog.warn("Ignoring: " + dir + ", the json of this Minecraft is malformed.", ex); continue; } @@ -276,7 +276,7 @@ public class MinecraftVersionManager extends IMinecraftProvider { for (MinecraftVersion s : getVersions()) { FileUtils.deleteDirectoryQuietly(new File(versionRoot(s.id), s.id + "-natives")); File f = getRunDirectory(s.id); - String[] dir = { "asm", "NVIDIA", "server-resource-packs", "natives", "native" }; + String[] dir = { "natives", "native", "$native", "AMD", "crash-reports", "logs", "asm", "NVIDIA", "server-resource-packs", "natives", "native" }; for (String str : dir) FileUtils.deleteDirectoryQuietly(new File(f, str)); String[] files = { "output-client.log", "usercache.json", "usernamecache.json", "hmclmc.log" }; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/LaunchingUIDaemon.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/LaunchingUIDaemon.java index 4e3adcb92..743048c08 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/LaunchingUIDaemon.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/LaunchingUIDaemon.java @@ -76,6 +76,7 @@ public class LaunchingUIDaemon { WebFrame f = new WebFrame(jpm.getJavaProcess().getStdOutLines().toArray(new String[0])); f.setTitle("Game output"); f.setVisible(true); + checkExit((LauncherVisibility) obj.getTag()); }); jpm.jvmLaunchFailedEvent.register(t -> { HMCLog.err("Cannot create jvm, exit code: " + t); @@ -83,13 +84,9 @@ public class LaunchingUIDaemon { WebFrame f = new WebFrame(jpm.getJavaProcess().getStdOutLines().toArray(new String[0])); f.setTitle("Game output"); f.setVisible(true); + checkExit((LauncherVisibility) obj.getTag()); }); - jpm.stoppedEvent.register(() -> { - if ((LauncherVisibility) obj.getTag() == LauncherVisibility.CLOSE && !LogWindow.INSTANCE.isVisible()) { - HMCLog.log("With the option of closing the launcher anyway, the launcher will exit and will NOT catch game logs."); - System.exit(0); - } - }); + jpm.stoppedEvent.register(() -> checkExit((LauncherVisibility) obj.getTag())); jpm.start(); }); try { @@ -101,6 +98,11 @@ public class LaunchingUIDaemon { return true; }; + private static void checkExit(LauncherVisibility v) { + if (v != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible()) + System.exit(0); + } + private static final Event> LAUNCH_SCRIPT_FINISHER = (sender, str) -> { boolean flag = false; try { diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/modpack/ModpackWizard.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/modpack/ModpackWizard.java index 6aa79dfa1..86f8c1c26 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/modpack/ModpackWizard.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/modpack/ModpackWizard.java @@ -39,6 +39,7 @@ import org.jackhuang.hellominecraft.util.Pair; import org.jackhuang.hellominecraft.util.StrUtils; import org.jackhuang.hellominecraft.util.Utils; import org.jackhuang.hellominecraft.util.logging.HMCLog; +import org.jackhuang.hellominecraft.util.system.IOUtils; import org.jackhuang.hellominecraft.util.system.ZipEngine; import org.jackhuang.hellominecraft.util.ui.WebPage; import org.jackhuang.hellominecraft.util.ui.checktree.CheckBoxTreeNode; @@ -111,7 +112,8 @@ public class ModpackWizard extends WizardBranchController { boolean flag = true; ZipEngine engine = new ZipEngine(loc); Config s = new Config(); - //s.setBgpath(Settings.getInstance().getBgpath()); + if (!IOUtils.isAbsolutePath(Settings.getInstance().getBgpath())) + s.setBgpath(Settings.getInstance().getBgpath()); s.setDownloadType(Settings.getInstance().getDownloadType()); engine.putTextFile(C.GSON.toJson(s), "hmcl.json"); engine.putFile(modpack, "modpack.zip"); diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/system/IOUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/system/IOUtils.java index 8755dd8ea..d2a48286d 100755 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/system/IOUtils.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/system/IOUtils.java @@ -124,6 +124,10 @@ public class IOUtils { return realPath; } + public static boolean isAbsolutePath(String path) { + return path.startsWith("/") || path.indexOf(":") > 0; + } + public static File currentDir() { return new File("."); } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindow.form b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindow.form index b2c5c5c87..227ef10f2 100755 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindow.form +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindow.form @@ -12,7 +12,7 @@ - + diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindow.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindow.java index b085fd622..c45328ee5 100755 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindow.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindow.java @@ -83,8 +83,8 @@ public class LogWindow extends javax.swing.JFrame { setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle(C.i18n("logwindow.title")); // NOI18N addWindowListener(new java.awt.event.WindowAdapter() { - public void windowClosed(java.awt.event.WindowEvent evt) { - formWindowClosed(evt); + public void windowClosing(java.awt.event.WindowEvent evt) { + formWindowClosing(evt); } }); @@ -172,14 +172,14 @@ public class LogWindow extends javax.swing.JFrame { .addComponent(btnClear) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnClose)) - .addComponent(lblCrash, javax.swing.GroupLayout.Alignment.LEADING)) + .addComponent(lblCrash, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(lblCrash, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblCrash) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 356, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -199,33 +199,15 @@ public class LogWindow extends javax.swing.JFrame { }// //GEN-END:initComponents private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed - boolean flag = false; - for (Frame f : Frame.getFrames()) { - if (f == this) - continue; - if (f.isVisible()) - flag = true; - } - if (flag) - this.dispose(); - else - try { - Utils.shutdownForcely(0); - } catch (Exception e) { - MessageBox.Show(C.i18n("launcher.exit_failed")); - HMCLog.err("Failed to shutdown forcely", e); - } + if (listener != null && listener.apply() && terminateGameListener != null) + terminateGameListener.run(); + SwingUtils.exitIfNoWindow(this, true); }//GEN-LAST:event_btnCloseActionPerformed private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearActionPerformed this.txtLog.setText(""); }//GEN-LAST:event_btnClearActionPerformed - private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed - if (listener != null && listener.apply() && terminateGameListener != null) - terminateGameListener.run(); - }//GEN-LAST:event_formWindowClosed - private void btnCopyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCopyActionPerformed Utils.setClipborad(this.txtLog.getText()); }//GEN-LAST:event_btnCopyActionPerformed @@ -251,6 +233,12 @@ public class LogWindow extends javax.swing.JFrame { SwingUtils.openLink(C.URL_GITHUB); }//GEN-LAST:event_btnGitHubActionPerformed + private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing + if (listener != null && listener.apply() && terminateGameListener != null) + terminateGameListener.run(); + SwingUtils.exitIfNoWindow(this); + }//GEN-LAST:event_formWindowClosing + public void log(String status) { log(status, Level.INFO); } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/SwingUtils.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/SwingUtils.java index dae0d14d8..c7148279e 100755 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/SwingUtils.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/SwingUtils.java @@ -20,6 +20,7 @@ package org.jackhuang.hellominecraft.util.ui; import java.awt.Component; import java.awt.EventQueue; import java.awt.FontMetrics; +import java.awt.Frame; import java.io.File; import java.io.IOException; import java.net.URI; @@ -41,6 +42,7 @@ import org.jackhuang.hellominecraft.util.C; import org.jackhuang.hellominecraft.util.logging.HMCLog; import org.jackhuang.hellominecraft.util.MessageBox; import org.jackhuang.hellominecraft.util.StrUtils; +import org.jackhuang.hellominecraft.util.Utils; import org.jackhuang.hellominecraft.util.func.NonFunction; import org.jackhuang.hellominecraft.util.system.OS; @@ -276,4 +278,27 @@ public class SwingUtils { } component.setEnabled(t); } + + public static void exitIfNoWindow(Frame thisFrame) { + exitIfNoWindow(thisFrame, false); + } + + public static void exitIfNoWindow(Frame thisFrame, boolean neededDispose) { + boolean flag = false; + for (Frame f : Frame.getFrames()) { + if (f == thisFrame) + continue; + if (f.isVisible()) + flag = true; + } + if (!flag) + try { + Utils.shutdownForcely(0); + } catch (Exception e) { + MessageBox.Show(C.i18n("launcher.exit_failed")); + HMCLog.err("Failed to shutdown forcely", e); + } + else + thisFrame.dispose(); + } } diff --git a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/WebFrame.java b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/WebFrame.java index 2c86c1e61..ad8db1802 100644 --- a/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/WebFrame.java +++ b/HMCLAPI/src/main/java/org/jackhuang/hellominecraft/util/ui/WebFrame.java @@ -45,15 +45,7 @@ public class WebFrame extends JFrame { @Override public void windowClosing(WindowEvent e) { - boolean flag = false; - for (Frame f : Frame.getFrames()) { - if (f == WebFrame.this) - continue; - if (f.isVisible()) - flag = true; - } - if (!flag) - System.exit(0); + SwingUtils.exitIfNoWindow(WebFrame.this); } @Override