改进自动下载数据排序

自动下载表格加入表头排序
This commit is contained in:
南宫临风 2016-06-27 17:43:34 +08:00
parent 13c105472e
commit 9ae010a391
9 changed files with 190 additions and 144 deletions

View File

@ -30,91 +30,110 @@ import org.jackhuang.hellominecraft.util.tasks.Task;
*/ */
public abstract class InstallerVersionList { public abstract class InstallerVersionList {
/** /**
* Refresh installer versions list from the downloaded content. * Refresh installer versions list from the downloaded content.
* *
* @param versions Minecraft versions you need to refresh * @param versions Minecraft versions you need to refresh
* *
* @throws java.lang.Exception including network exceptions, IO exceptions. * @throws java.lang.Exception including network exceptions, IO exceptions.
*/ */
public abstract Task refresh(String[] versions); public abstract Task refresh(String[] versions);
/** /**
* Installer name. * Installer name.
* *
* @return installer name. * @return installer name.
*/ */
public abstract String getName(); public abstract String getName();
/** /**
* Get installers you want. * Get installers you want.
* *
* @param mcVersion the installers to this Minecraft version. * @param mcVersion the installers to this Minecraft version.
* *
* @return cached result. * @return cached result.
*/ */
protected abstract List<InstallerVersion> getVersionsImpl(String mcVersion); protected abstract List<InstallerVersion> getVersionsImpl(String mcVersion);
/** /**
* Get installers you want, please cache this method's result to save time. * Get installers you want, please cache this method's result to save time.
* *
* @param mcVersion the installers to this Minecraft version. * @param mcVersion the installers to this Minecraft version.
* *
* @return a copy of the cached data to prevent * @return a copy of the cached data to prevent
* ConcurrentModificationException. * ConcurrentModificationException.
*/ */
public List<InstallerVersion> getVersions(String mcVersion) { public List<InstallerVersion> getVersions(String mcVersion) {
List<InstallerVersion> a = getVersionsImpl(mcVersion); List<InstallerVersion> a = getVersionsImpl(mcVersion);
if (a == null) if (a == null) {
return null; return null;
else } else {
return new ArrayList<>(a); return new ArrayList<>(a);
} }
}
public static class InstallerVersion implements Comparable<InstallerVersion> { public static int compareVersion(String verOne, String verTwo) {
String[] verInfoOne = verOne.split("\\.");
String[] verInfoTwo = verTwo.split("\\.");
int idx = 0;
int minLength = Math.min(verInfoOne.length, verInfoTwo.length);
int diff = 0;
while (idx < minLength
&& (diff = verInfoOne[idx].length() - verInfoTwo[idx].length()) == 0
&& (diff = verInfoOne[idx].compareTo(verInfoTwo[idx])) == 0) {
++idx;
}
diff = (diff != 0) ? diff : verInfoOne.length - verInfoTwo.length;
return (diff == 0) ? 0 : (diff < 0 ? -1 : 1);
}
public String selfVersion, mcVersion; public static class InstallerVersion implements Comparable<InstallerVersion> {
public String installer, universal;
public String changelog;
public InstallerVersion(String selfVersion, String mcVersion) { public String selfVersion, mcVersion;
this.selfVersion = selfVersion; public String installer, universal;
this.mcVersion = mcVersion; public String changelog;
}
@Override public InstallerVersion(String selfVersion, String mcVersion) {
public int compareTo(InstallerVersion o) { this.selfVersion = selfVersion;
return selfVersion.compareTo(o.selfVersion); this.mcVersion = mcVersion;
} }
@Override @Override
public int hashCode() { public int compareTo(InstallerVersion o) {
return selfVersion.hashCode(); return compareVersion(selfVersion, o.selfVersion);
} }
@Override @Override
public boolean equals(Object obj) { public int hashCode() {
if (this == obj) return selfVersion.hashCode();
return true; }
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final InstallerVersion other = (InstallerVersion) obj;
return Objects.equals(this.selfVersion, other.selfVersion);
}
} @Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final InstallerVersion other = (InstallerVersion) obj;
return Objects.equals(this.selfVersion, other.selfVersion);
}
public static class InstallerVersionComparator implements Comparator<InstallerVersion>, Serializable { }
private static final long serialVersionUID = 3276198781795213723L; public static class InstallerVersionComparator implements Comparator<InstallerVersion>, Serializable {
public static final InstallerVersionComparator INSTANCE = new InstallerVersionComparator(); private static final long serialVersionUID = 3276198781795213723L;
@Override public static final InstallerVersionComparator INSTANCE = new InstallerVersionComparator();
public int compare(InstallerVersion o1, InstallerVersion o2) {
return o2.compareTo(o1); @Override
} public int compare(InstallerVersion o1, InstallerVersion o2) {
} return o2.compareTo(o1);
}
}
} }

View File

@ -76,10 +76,13 @@ public class MinecraftForgeVersionList extends InstallerVersionList {
for (Map.Entry<String, int[]> arr : root.mcversion.entrySet()) { for (Map.Entry<String, int[]> arr : root.mcversion.entrySet()) {
String mcver = StrUtils.formatVersion(arr.getKey()); String mcver = StrUtils.formatVersion(arr.getKey());
if (mcver == null) {
mcver = arr.getKey();
}
ArrayList<InstallerVersion> al = new ArrayList<>(); ArrayList<InstallerVersion> al = new ArrayList<>();
for (int num : arr.getValue()) { for (int num : arr.getValue()) {
MinecraftForgeVersion v = root.number.get(num); MinecraftForgeVersion v = root.number.get(num);
InstallerVersion iv = new InstallerVersion(v.version, StrUtils.formatVersion(v.mcversion)); InstallerVersion iv = new InstallerVersion(v.version, v.mcversion);
for (String[] f : v.files) { for (String[] f : v.files) {
String ver = v.mcversion + "-" + v.version; String ver = v.mcversion + "-" + v.version;
@ -108,7 +111,7 @@ public class MinecraftForgeVersionList extends InstallerVersionList {
versions.add(iv); versions.add(iv);
} }
versionMap.put(StrUtils.formatVersion(mcver), al); versionMap.put(mcver, al);
} }
Collections.sort(versions, new InstallerVersionComparator()); Collections.sort(versions, new InstallerVersionComparator());

View File

@ -17,9 +17,13 @@
*/ */
package org.jackhuang.hellominecraft.launcher.ui; package org.jackhuang.hellominecraft.launcher.ui;
import java.util.Comparator;
import java.util.List; import java.util.List;
import javax.swing.RowSorter;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel; import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import org.jackhuang.hellominecraft.util.C; import org.jackhuang.hellominecraft.util.C;
import org.jackhuang.hellominecraft.launcher.setting.Settings; import org.jackhuang.hellominecraft.launcher.setting.Settings;
import org.jackhuang.hellominecraft.launcher.core.install.InstallerType; import org.jackhuang.hellominecraft.launcher.core.install.InstallerType;
@ -36,29 +40,45 @@ import org.jackhuang.hellominecraft.util.ui.SwingUtils;
*/ */
public class InstallerPanel extends AnimatedPanel { public class InstallerPanel extends AnimatedPanel {
GameSettingsPanel gsp; GameSettingsPanel gsp;
/** private static class VerComparator implements Comparator<String> {
* Creates new form InstallerPanel
*
* @param gsp To get the minecraft version
* @param installerType load which installer
*/
public InstallerPanel(GameSettingsPanel gsp, InstallerType installerType) {
initComponents();
setOpaque(false); @Override
this.gsp = gsp; public int compare(String o1, String o2) {
id = installerType; return InstallerVersionList.compareVersion(o1, o2);
list = Settings.getInstance().getDownloadSource().getProvider().getInstallerByType(id); }
} };
/** /**
* This method is called from within the constructor to initialize the form. * Creates new form InstallerPanel
* WARNING: Do NOT modify this code. The content of this method is always *
* regenerated by the Form Editor. * @param gsp To get the minecraft version
*/ * @param installerType load which installer
@SuppressWarnings("unchecked") */
public InstallerPanel(GameSettingsPanel gsp, InstallerType installerType) {
initComponents();
//表格排序
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(lstInstallers.getModel());
VerComparator verComparator = new VerComparator();
for (int i = 0; i < lstInstallers.getColumnCount(); i++) {
sorter.setComparator(i, verComparator);
}
lstInstallers.setRowSorter(sorter);
setOpaque(false);
this.gsp = gsp;
id = installerType;
list = Settings.getInstance().getDownloadSource().getProvider().getInstallerByType(id);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() { private void initComponents() {
@ -109,60 +129,64 @@ public class InstallerPanel extends AnimatedPanel {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void btnInstallActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnInstallActionPerformed private void btnInstallActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnInstallActionPerformed
downloadSelectedRow(); downloadSelectedRow();
}//GEN-LAST:event_btnInstallActionPerformed }//GEN-LAST:event_btnInstallActionPerformed
private void btnRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshActionPerformed private void btnRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshActionPerformed
refreshVersions(); refreshVersions();
}//GEN-LAST:event_btnRefreshActionPerformed }//GEN-LAST:event_btnRefreshActionPerformed
transient List<InstallerVersionList.InstallerVersion> versions; transient List<InstallerVersionList.InstallerVersion> versions;
transient InstallerVersionList list; transient InstallerVersionList list;
InstallerType id; InstallerType id;
void refreshVersions() { void refreshVersions() {
if (TaskWindow.execute(list.refresh(new String[] { gsp.getMinecraftVersionFormatted() }))) if (TaskWindow.execute(list.refresh(new String[]{gsp.getMinecraftVersionFormatted()}))) {
loadVersions(); loadVersions();
} }
}
public synchronized InstallerVersionList.InstallerVersion getVersion(int idx) { public synchronized InstallerVersionList.InstallerVersion getVersion(int idx) {
return versions.get(idx); return versions.get(idx);
} }
synchronized void downloadSelectedRow() { synchronized void downloadSelectedRow() {
int idx = lstInstallers.getSelectedRow(); int idx = lstInstallers.getSelectedRow();
if (versions == null || idx < 0 || idx >= versions.size()) { if (versions == null || idx < 0 || idx >= versions.size()) {
MessageBox.Show(C.i18n("install.not_refreshed")); MessageBox.Show(C.i18n("install.not_refreshed"));
return; return;
} }
TaskWindow.execute(Settings.getLastProfile().service().install().download(Settings.getLastProfile().getSelectedVersion(), getVersion(idx), id), TaskWindow.execute(Settings.getLastProfile().service().install().download(Settings.getLastProfile().getSelectedVersion(), getVersion(idx), id),
new TaskRunnable(this::refreshVersions)); new TaskRunnable(this::refreshVersions));
} }
public void loadVersions() { public void loadVersions() {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
synchronized (InstallerPanel.this) { synchronized (InstallerPanel.this) {
DefaultTableModel model = (DefaultTableModel) lstInstallers.getModel(); DefaultTableModel model = (DefaultTableModel) lstInstallers.getModel();
String mcver = StrUtils.formatVersion(gsp.getMinecraftVersionFormatted()); String mcver = StrUtils.formatVersion(gsp.getMinecraftVersionFormatted());
versions = list.getVersions(mcver); versions = list.getVersions(mcver);
SwingUtils.clearDefaultTable(lstInstallers); SwingUtils.clearDefaultTable(lstInstallers);
if (versions != null) if (versions != null) {
for (InstallerVersionList.InstallerVersion v : versions) for (InstallerVersionList.InstallerVersion v : versions) {
if (v != null) if (v != null) {
model.addRow(new Object[] { v.selfVersion == null ? "null" : v.selfVersion, v.mcVersion == null ? "null" : v.mcVersion }); model.addRow(new Object[]{v.selfVersion == null ? "null" : v.selfVersion, v.mcVersion == null ? "null" : v.mcVersion});
} }
}); }
} }
}
});
}
boolean refreshed = false; boolean refreshed = false;
@Override @Override
public void onSelect() { public void onSelect() {
if (!refreshed) { if (!refreshed) {
refreshVersions(); refreshVersions();
refreshed = true; refreshed = true;
} }
} }
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnInstall; private javax.swing.JButton btnInstall;

View File

@ -131,7 +131,7 @@
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="lblRestart" min="-2" max="-2" attributes="0"/> <Component id="lblRestart" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="65" max="32767" attributes="0"/> <EmptySpace pref="80" max="32767" attributes="0"/>
<Component id="lblModpack" min="-2" max="-2" attributes="0"/> <Component id="lblModpack" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="lblAbout" min="-2" max="-2" attributes="0"/> <Component id="lblAbout" min="-2" max="-2" attributes="0"/>

View File

@ -349,7 +349,7 @@ public class LauncherSettingsPanel extends AnimatedPanel {
.addComponent(btnMCBBS)) .addComponent(btnMCBBS))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblRestart) .addComponent(lblRestart)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 65, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 80, Short.MAX_VALUE)
.addComponent(lblModpack, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lblModpack, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblAbout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lblAbout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)

View File

@ -89,7 +89,7 @@ public final class MainFrame extends DraggableFrame {
setContentSize(834, 542); setContentSize(834, 542);
else else
setContentSize(802, 511); setContentSize(802, 511);
setDefaultCloseOperation(3); setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle(Main.makeTitle()); setTitle(Main.makeTitle());
initComponents(); initComponents();
loadBackground(); loadBackground();

View File

@ -298,7 +298,7 @@ mainwindow.enter_script_name=输入要生成脚本的文件名
mainwindow.make_launch_succeed=启动脚本已生成完毕: mainwindow.make_launch_succeed=启动脚本已生成完毕:
mainwindow.no_version=未找到任何版本,是否进入游戏下载? mainwindow.no_version=未找到任何版本,是否进入游戏下载?
launcher.about=<html>默认背景图感谢gamerteam提供。<br><a href="http://huangyuhui.duapp.com/link.php?type=sponsor">如果您希望本软件继续发展,请赞助</a><br/>关于作者:<br/>百度IDhuanghongxun20<br/>mcbbshuanghongxun<br/>邮箱huanghongxun2008@126.com<br/>Minecraft Forum ID: klkl6523<br/>欢迎提交Bug哦<br/>Copyright (c) 2013-2016 huangyuhui.<br/>免责声明Minecraft软件版权归Mojang AB所有使用本软件产生的版权问题本软件制作方概不负责。<br/>本启动器在GPLv3协议下开源:https://github.com/huanghongxun/HMCL/ ,感谢issues和pull requests贡献者<br/>本软件使用了基于Apache License 2.0的Gson项目感谢贡献者。</html> launcher.about=<html>默认背景图感谢gamerteam提供。<br/>关于作者:<br/>百度IDhuanghongxun20<br/>mcbbshuanghongxun<br/>邮箱huanghongxun2008@126.com<br/>Minecraft Forum ID: klkl6523<br/>欢迎提交Bug哦<br/>Copyright (c) 2013-2016 huangyuhui.<br/>免责声明Minecraft软件版权归Mojang AB所有使用本软件产生的版权问题本软件制作方概不负责。<br/>本启动器在GPLv3协议下开源:https://github.com/huanghongxun/HMCL/ ,感谢issues和pull requests贡献者<br/>本软件使用了基于Apache License 2.0的Gson项目感谢贡献者。</html>
launcher.download_source=下载源 launcher.download_source=下载源
launcher.background_location=背景地址 launcher.background_location=背景地址
launcher.exit_failed=强制退出失败可能是Forge 1.7.10及更高版本导致的,无法解决。 launcher.exit_failed=强制退出失败可能是Forge 1.7.10及更高版本导致的,无法解决。

View File

@ -298,7 +298,7 @@ mainwindow.enter_script_name=\u8f93\u5165\u8981\u751f\u6210\u811a\u672c\u7684\u6
mainwindow.make_launch_succeed=\u542f\u52a8\u811a\u672c\u5df2\u751f\u6210\u5b8c\u6bd5: mainwindow.make_launch_succeed=\u542f\u52a8\u811a\u672c\u5df2\u751f\u6210\u5b8c\u6bd5:
mainwindow.no_version=\u672a\u627e\u5230\u4efb\u4f55\u7248\u672c\uff0c\u662f\u5426\u8fdb\u5165\u6e38\u620f\u4e0b\u8f7d\uff1f mainwindow.no_version=\u672a\u627e\u5230\u4efb\u4f55\u7248\u672c\uff0c\u662f\u5426\u8fdb\u5165\u6e38\u620f\u4e0b\u8f7d\uff1f
launcher.about=<html>\u9ed8\u8ba4\u80cc\u666f\u56fe\u611f\u8c22gamerteam\u63d0\u4f9b\u3002<br><a href="http://huangyuhui.duapp.com/link.php?type=sponsor">\u5982\u679c\u60a8\u5e0c\u671b\u672c\u8f6f\u4ef6\u7ee7\u7eed\u53d1\u5c55\uff0c\u8bf7\u8d5e\u52a9</a><br/>\u5173\u4e8e\u4f5c\u8005\uff1a<br/>\u767e\u5ea6ID\uff1ahuanghongxun20<br/>mcbbs\uff1ahuanghongxun<br/>\u90ae\u7bb1\uff1ahuanghongxun2008@126.com<br/>Minecraft Forum ID: klkl6523<br/>\u6b22\u8fce\u63d0\u4ea4Bug\u54e6<br/>Copyright (c) 2013-2016 huangyuhui.<br/>\u514d\u8d23\u58f0\u660e\uff1aMinecraft\u8f6f\u4ef6\u7248\u6743\u5f52Mojang AB\u6240\u6709\uff0c\u4f7f\u7528\u672c\u8f6f\u4ef6\u4ea7\u751f\u7684\u7248\u6743\u95ee\u9898\u672c\u8f6f\u4ef6\u5236\u4f5c\u65b9\u6982\u4e0d\u8d1f\u8d23\u3002<br/>\u672c\u542f\u52a8\u5668\u5728GPLv3\u534f\u8bae\u4e0b\u5f00\u6e90:https://github.com/huanghongxun/HMCL/ ,\u611f\u8c22issues\u548cpull requests\u8d21\u732e\u8005<br/>\u672c\u8f6f\u4ef6\u4f7f\u7528\u4e86\u57fa\u4e8eApache License 2.0\u7684Gson\u9879\u76ee\uff0c\u611f\u8c22\u8d21\u732e\u8005\u3002</html> launcher.about=<html>\u9ed8\u8ba4\u80cc\u666f\u56fe\u611f\u8c22gamerteam\u63d0\u4f9b\u3002<br>\u5173\u4e8e\u4f5c\u8005\uff1a<br/>\u767e\u5ea6ID\uff1ahuanghongxun20<br/>mcbbs\uff1ahuanghongxun<br/>\u90ae\u7bb1\uff1ahuanghongxun2008@126.com<br/>Minecraft Forum ID: klkl6523<br/>\u6b22\u8fce\u63d0\u4ea4Bug\u54e6<br/>Copyright (c) 2013-2016 huangyuhui.<br/>\u514d\u8d23\u58f0\u660e\uff1aMinecraft\u8f6f\u4ef6\u7248\u6743\u5f52Mojang AB\u6240\u6709\uff0c\u4f7f\u7528\u672c\u8f6f\u4ef6\u4ea7\u751f\u7684\u7248\u6743\u95ee\u9898\u672c\u8f6f\u4ef6\u5236\u4f5c\u65b9\u6982\u4e0d\u8d1f\u8d23\u3002<br/>\u672c\u542f\u52a8\u5668\u5728GPLv3\u534f\u8bae\u4e0b\u5f00\u6e90:https://github.com/huanghongxun/HMCL/ ,\u611f\u8c22issues\u548cpull requests\u8d21\u732e\u8005<br/>\u672c\u8f6f\u4ef6\u4f7f\u7528\u4e86\u57fa\u4e8eApache License 2.0\u7684Gson\u9879\u76ee\uff0c\u611f\u8c22\u8d21\u732e\u8005\u3002</html>
launcher.download_source=\u4e0b\u8f7d\u6e90 launcher.download_source=\u4e0b\u8f7d\u6e90
launcher.background_location=\u80cc\u666f\u5730\u5740 launcher.background_location=\u80cc\u666f\u5730\u5740
launcher.exit_failed=\u5f3a\u5236\u9000\u51fa\u5931\u8d25\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5bfc\u81f4\u7684\uff0c\u65e0\u6cd5\u89e3\u51b3\u3002 launcher.exit_failed=\u5f3a\u5236\u9000\u51fa\u5931\u8d25\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5bfc\u81f4\u7684\uff0c\u65e0\u6cd5\u89e3\u51b3\u3002

View File

@ -298,7 +298,7 @@ mainwindow.enter_script_name=輸入要生成腳本的資料名
mainwindow.make_launch_succeed=啟動腳本已生成完畢: mainwindow.make_launch_succeed=啟動腳本已生成完畢:
mainwindow.no_version=未找到任何版本,是否進入遊戲下載? mainwindow.no_version=未找到任何版本,是否進入遊戲下載?
launcher.about=<html>默認背景圖感謝gamerteam提供。<br><a href="http://huangyuhui.duapp.com/link.php?type=sponsor">如果您希望本軟件繼續發展,請贊助</a><br>關於作者:<br>百度IDhuanghongxun20<br>mcbbshuanghongxun<br>郵箱huanghongxun2008@126.com<br>Minecraft Forum ID: klkl6523<br>歡迎提交Bug哦<br/>Copyright (c) 2013-2016 huangyuhui.<br>免責聲明Minecraft軟體版權歸Mojang AB所有遊戲由於誤操作本啟動器而丟失數據的概不負責。<br>本啟動器在GPLv3協議下開源:http://github.com/huanghongxun/HMCL/ ,感谢issues和pull requests贡献者<br>本軟體使用了基於Apache License 2.0的Gson項目感謝貢獻者。</html> launcher.about=<html>默認背景圖感謝gamerteam提供。<br>關於作者:<br>百度IDhuanghongxun20<br>mcbbshuanghongxun<br>郵箱huanghongxun2008@126.com<br>Minecraft Forum ID: klkl6523<br>歡迎提交Bug哦<br/>Copyright (c) 2013-2016 huangyuhui.<br>免責聲明Minecraft軟體版權歸Mojang AB所有遊戲由於誤操作本啟動器而丟失數據的概不負責。<br>本啟動器在GPLv3協議下開源:http://github.com/huanghongxun/HMCL/ ,感谢issues和pull requests贡献者<br>本軟體使用了基於Apache License 2.0的Gson項目感謝貢獻者。</html>
launcher.download_source=下載源 launcher.download_source=下載源
launcher.background_location=背景地址 launcher.background_location=背景地址
launcher.exit_failed=強制退出失敗可能是Forge 1.7.10及更高版本導致的,無法解決。 launcher.exit_failed=強制退出失敗可能是Forge 1.7.10及更高版本導致的,無法解決。