Add: Common folder to save libraries and assets

This commit is contained in:
huangyuhui
2017-02-13 13:10:11 +08:00
parent eb311abe83
commit 20be2f76c6
25 changed files with 388 additions and 179 deletions

View File

@@ -0,0 +1,52 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.launcher.api.event.version;
import java.io.File;
import java.util.EventObject;
import org.jackhuang.hellominecraft.util.Wrapper;
/**
* This event gets fired when we getting minecraft library path.
* <br>
* This event is fired on the {@link org.jackhuang.hellominecraft.api.HMCLAPI#EVENT_BUS}
* @param source {@link org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary}
* @param {@code Wrapper<File>} modify this thing to change to your wanted mc lib.
* @author huangyuhui
*/
public class MinecraftLibraryPathEvent extends EventObject {
String location;
Wrapper<File> file;
public MinecraftLibraryPathEvent(Object source, String location, Wrapper<File> value) {
super(source);
this.location = location;
this.file = value;
}
public String getLocation() {
return location;
}
public Wrapper<File> getFile() {
return file;
}
}

View File

@@ -50,9 +50,9 @@ public class AssetsMojangLoader extends IAssetsHandler {
public Task getList(final MinecraftVersion mv, final IMinecraftAssetService mp) {
Objects.requireNonNull(mv);
String assetsId = mv.getAssetsIndex().getId();
File assets = mp.getAssets();
File assets = mp.getAssets(assetsId);
HMCLog.log("Gathering asset index: " + assetsId);
File f = IOUtils.tryGetCanonicalFile(new File(assets, "indexes/" + assetsId + ".json"));
File f = mp.getIndexFile(assetsId);
return new TaskInfo("Gather asset index") {
@Override
public Collection<Task> getDependTasks() {
@@ -72,7 +72,7 @@ public class AssetsMojangLoader extends IAssetsHandler {
AssetsIndex o = C.GSON.fromJson(result, AssetsIndex.class);
assetsDownloadURLs = new ArrayList<>();
assetsLocalNames = new ArrayList<>();
contents = new ArrayList<>();
assetsObjects = new ArrayList<>();
HashSet<String> loadedHashes = new HashSet<>();
int pgs = 0;
if (o != null && o.getFileMap() != null)
@@ -80,13 +80,9 @@ public class AssetsMojangLoader extends IAssetsHandler {
if (loadedHashes.contains(e.getValue().getHash()))
continue;
loadedHashes.add(e.getValue().getHash());
Contents c = new Contents();
c.eTag = e.getValue().getHash();
c.key = c.eTag.substring(0, 2) + "/" + e.getValue().getHash();
c.size = e.getValue().getSize();
contents.add(c);
assetsDownloadURLs.add(c.key);
assetsLocalNames.add(new File(assets, "objects" + File.separator + c.key.replace("/", File.separator)));
assetsObjects.add(e.getValue());
assetsDownloadURLs.add(e.getValue().getLocation());
assetsLocalNames.add(mp.getAssetObject(assetsId, e.getValue()));
if (ppl != null)
ppl.setProgress(this, ++pgs, o.getFileMap().size());
}

View File

@@ -34,7 +34,9 @@ public class AssetsObject {
this.size = size;
}
public AssetsObject() {
public AssetsObject(String hash, long size) {
this.hash = hash;
this.size = size;
}
public String getHash() {
@@ -44,6 +46,10 @@ public class AssetsObject {
public long getSize() {
return this.size;
}
public String getLocation() {
return hash.substring(0, 2) + "/" + hash;
}
@Override
public boolean equals(Object o) {

View File

@@ -1,72 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.launcher.core.asset;
/**
*
* @author huangyuhui
*/
public class Contents {
public String key, eTag, lastModified, storageClass;
public Contents() {
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String geteTag() {
return eTag;
}
public void seteTag(String eTag) {
this.eTag = eTag;
}
public String getLastModified() {
return lastModified;
}
public void setLastModified(String lastModified) {
this.lastModified = lastModified;
}
public String getStorageClass() {
return storageClass;
}
public void setStorageClass(String storageClass) {
this.storageClass = storageClass;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public long size;
}

View File

@@ -45,7 +45,7 @@ public abstract class IAssetsHandler {
protected ArrayList<String> assetsDownloadURLs;
protected ArrayList<File> assetsLocalNames;
protected final String name;
protected List<Contents> contents;
protected List<AssetsObject> assetsObjects;
public IAssetsHandler(String name) {
this.name = name;
@@ -98,7 +98,7 @@ public abstract class IAssetsHandler {
@Override
public void executeTask(boolean areDependTasksSucceeded) {
if (assetsDownloadURLs == null || assetsLocalNames == null || contents == null)
if (assetsDownloadURLs == null || assetsLocalNames == null || assetsObjects == null)
throw new IllegalStateException(C.i18n("assets.not_refreshed"));
int max = assetsDownloadURLs.size();
al = new ArrayList<>();
@@ -117,7 +117,7 @@ public abstract class IAssetsHandler {
FileInputStream fis = FileUtils.openInputStream(location);
String sha = DigestUtils.sha1Hex(IOUtils.toByteArray(fis));
IOUtils.closeQuietly(fis);
if (contents.get(i).geteTag().equals(sha)) {
if (assetsObjects.get(i).getHash().equals(sha)) {
++hasDownloaded;
HMCLog.log("File " + assetsLocalNames.get(i) + " has been downloaded successfully, skipped downloading.");
if (ppl != null)
@@ -130,7 +130,7 @@ public abstract class IAssetsHandler {
need = !location.exists();
}
if (need)
al.add(new FileDownloadTask(url, location).setTag(contents.get(i).geteTag()));
al.add(new FileDownloadTask(url, location).setTag(assetsObjects.get(i).getHash()));
}
}

View File

@@ -70,7 +70,7 @@ public class MinecraftAssetService extends IMinecraftAssetService {
@Override
public Task downloadMinecraftAssetsIndex(AssetIndexDownloadInfo assetIndex) {
File assetsLocation = getAssets();
File assetsLocation = getAssets(assetIndex.getId());
if (!FileUtils.makeDirectory(assetsLocation))
HMCLog.warn("Failed to make directories: " + assetsLocation);
File assetsIndex = getIndexFile(assetIndex.getId());
@@ -100,7 +100,7 @@ public class MinecraftAssetService extends IMinecraftAssetService {
@Override
public boolean downloadMinecraftAssetsIndexAsync(AssetIndexDownloadInfo assetIndex) {
File assetsDir = getAssets();
File assetsDir = getAssets(assetIndex.getId());
if (!FileUtils.makeDirectory(assetsDir))
HMCLog.warn("Failed to make directories: " + assetsDir);
File assetsIndex = getIndexFile(assetIndex.getId());
@@ -111,8 +111,8 @@ public class MinecraftAssetService extends IMinecraftAssetService {
HMCLog.warn("Failed to rename " + assetsIndex + " to " + renamed);
}
if (TaskWindow.factory()
.append(new FileDownloadTask(assetIndex.getUrl(service.getDownloadType()), IOUtils.tryGetCanonicalFile(assetsIndex), assetIndex.sha1).setTag(assetIndex.getId() + ".json"))
.execute()) {
.append(new FileDownloadTask(assetIndex.getUrl(service.getDownloadType()), IOUtils.tryGetCanonicalFile(assetsIndex), assetIndex.sha1).setTag(assetIndex.getId() + ".json"))
.execute()) {
if (renamed != null && !renamed.delete())
HMCLog.warn("Failed to delete " + renamed + ", maybe you should do it.");
return true;
@@ -123,30 +123,31 @@ public class MinecraftAssetService extends IMinecraftAssetService {
}
@Override
public File getAssets() {
public File getAssets(String assetId) {
return new File(service.baseDirectory(), "assets");
}
private File getIndexFile(String assetVersion) {
return new File(getAssets(), "indexes/" + assetVersion + ".json");
}
@Override
public File getAssetObject(String assetVersion, String name) throws IOException {
try {
AssetsIndex index = (AssetsIndex) C.GSON.fromJson(FileUtils.read(getIndexFile(assetVersion), "UTF-8"), AssetsIndex.class);
public File getIndexFile(String assetId) {
return new File(getAssets(assetId), "indexes/" + assetId + ".json");
}
String hash = ((AssetsObject) index.getFileMap().get(name)).getHash();
return new File(getAssets(), "objects/" + hash.substring(0, 2) + "/" + hash);
@Override
public File getAssetObject(String assetId, String name) throws IOException {
try {
AssetsIndex index = (AssetsIndex) C.GSON.fromJson(FileUtils.read(getIndexFile(assetId), "UTF-8"), AssetsIndex.class);
return getAssetObject(assetId, (AssetsObject) index.getFileMap().get(name));
} catch (JsonSyntaxException e) {
throw new IOException("Assets file format malformed.", e);
}
}
private boolean checkAssetsExistance(AssetIndexDownloadInfo assetIndex) {
File indexFile = getIndexFile(assetIndex.getId());
protected boolean checkAssetsExistance(AssetIndexDownloadInfo assetIndex) {
String assetId = assetIndex.getId();
File indexFile = getIndexFile(assetId);
File assetDir = getAssets(assetId);
if (!getAssets().exists() || !indexFile.isFile())
if (!getAssets(assetId).exists() || !indexFile.isFile())
return false;
try {
@@ -156,7 +157,7 @@ public class MinecraftAssetService extends IMinecraftAssetService {
if (index == null)
return false;
for (Map.Entry<String, AssetsObject> entry : index.getFileMap().entrySet())
if (!new File(getAssets(), "objects/" + ((AssetsObject) entry.getValue()).getHash().substring(0, 2) + "/" + ((AssetsObject) entry.getValue()).getHash()).exists())
if (!assetObjectPath(assetDir, (AssetsObject) entry.getValue()).exists())
return false;
return true;
} catch (IOException | JsonSyntaxException e) {
@@ -164,8 +165,8 @@ public class MinecraftAssetService extends IMinecraftAssetService {
}
}
private File reconstructAssets(AssetIndexDownloadInfo assetIndex) {
File assetsDir = getAssets();
protected File reconstructAssets(AssetIndexDownloadInfo assetIndex) {
File assetsDir = getAssets(assetIndex.getId());
String assetVersion = assetIndex.getId();
File indexFile = getIndexFile(assetVersion);
File virtualRoot = new File(new File(assetsDir, "virtual"), assetVersion);
@@ -187,7 +188,7 @@ public class MinecraftAssetService extends IMinecraftAssetService {
int tot = index.getFileMap().entrySet().size();
for (Map.Entry<String, AssetsObject> entry : index.getFileMap().entrySet()) {
File target = new File(virtualRoot, (String) entry.getKey());
File original = new File(assetsDir, "objects/" + ((AssetsObject) entry.getValue()).getHash().substring(0, 2) + "/" + ((AssetsObject) entry.getValue()).getHash());
File original = assetObjectPath(assetsDir, (AssetsObject) entry.getValue());
if (original.exists()) {
cnt++;
if (!target.isFile())
@@ -205,6 +206,15 @@ public class MinecraftAssetService extends IMinecraftAssetService {
return virtualRoot;
}
@Override
public File getAssetObject(String assetId, AssetsObject object) {
return assetObjectPath(getAssets(assetId), object);
}
public File assetObjectPath(File assetDir, AssetsObject object) {
return new File(assetDir, "objects/" + object.getLocation());
}
public final IAssetProvider ASSET_PROVIDER_IMPL = (t, allow) -> {
if (allow && !checkAssetsExistance(t.getAssetsIndex()))
if (MessageBox.show(C.i18n("assets.no_assets"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)

View File

@@ -85,7 +85,7 @@ public class MinecraftLoader extends AbstractMinecraftLoader {
t = t.replace("${version_type}", options.getType());
t = t.replace("${game_directory}", service.version().getRunDirectory(version.id).getAbsolutePath());
t = t.replace("${game_assets}", game_assets);
t = t.replace("${assets_root}", service.asset().getAssets().getAbsolutePath());
t = t.replace("${assets_root}", service.asset().getAssets(version.getAssetsIndex().getId()).getAbsolutePath());
t = t.replace("${auth_access_token}", lr.getAccessToken());
t = t.replace("${user_type}", lr.getUserType());
t = t.replace("${assets_index_name}", version.getAssetsIndex().getId());

View File

@@ -20,6 +20,7 @@ package org.jackhuang.hellominecraft.launcher.core.service;
import java.io.File;
import java.io.IOException;
import org.jackhuang.hellominecraft.launcher.core.GameException;
import org.jackhuang.hellominecraft.launcher.core.asset.AssetsObject;
import org.jackhuang.hellominecraft.launcher.core.version.AssetIndexDownloadInfo;
import org.jackhuang.hellominecraft.util.task.Task;
@@ -35,20 +36,24 @@ public abstract class IMinecraftAssetService extends IMinecraftBasicService {
public abstract Task downloadAssets(String mcVersion) throws GameException;
public abstract File getAssets();
public abstract File getAssets(String assetId);
public abstract File getIndexFile(String assetId);
/**
* Redownload the Asset index json of the given version.
*
* @param a the given version name
* @param mcVersion the given version name
*
* @return Is the action successful?
*/
public abstract boolean refreshAssetsIndex(String a) throws GameException;
public abstract boolean refreshAssetsIndex(String mcVersion) throws GameException;
public abstract boolean downloadMinecraftAssetsIndexAsync(AssetIndexDownloadInfo assetsId);
public abstract boolean downloadMinecraftAssetsIndexAsync(AssetIndexDownloadInfo assetId);
public abstract Task downloadMinecraftAssetsIndex(AssetIndexDownloadInfo assetsId);
public abstract Task downloadMinecraftAssetsIndex(AssetIndexDownloadInfo assetId);
public abstract File getAssetObject(String assetVersion, String name) throws IOException;
public abstract File getAssetObject(String assetId, AssetsObject assetsObject);
}

View File

@@ -40,10 +40,6 @@ public class AssetIndexDownloadInfo extends GameDownloadInfo {
return dt.getProvider().getIndexesDownloadURL() + id + ".json";
}
public String getId() {
return id;
}
public int getTotalSize() {
return totalSize;
}

View File

@@ -36,7 +36,7 @@ public class GameDownloadInfo implements Cloneable {
/**
* Ready for AssetIndexDownloadInfo, and GameDownloadInfo also need this.
*/
public String id = null;
protected String id;
/**
* Get the game download url.
@@ -68,6 +68,10 @@ public class GameDownloadInfo implements Cloneable {
return dt.getProvider().getVersionsDownloadURL() + id + "/" + id + ".jar";
}
public String getId() {
return id;
}
@Override
public Object clone() {
try {

View File

@@ -21,9 +21,12 @@ import com.google.gson.annotations.SerializedName;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import org.jackhuang.hellominecraft.api.HMCLAPI;
import org.jackhuang.hellominecraft.launcher.api.event.version.MinecraftLibraryPathEvent;
import org.jackhuang.hellominecraft.util.sys.OS;
import org.jackhuang.hellominecraft.util.sys.Platform;
import org.jackhuang.hellominecraft.util.StrUtils;
import org.jackhuang.hellominecraft.util.Wrapper;
/**
*
@@ -104,7 +107,9 @@ public class MinecraftLibrary extends IMinecraftLibrary {
LibraryDownloadInfo info = getDownloadInfo();
if (info == null)
return null;
return new File(gameDir, "libraries/" + info.path);
MinecraftLibraryPathEvent event = new MinecraftLibraryPathEvent(this, "libraries/" + info.path, new Wrapper<>(new File(gameDir, "libraries/" + info.path)));
HMCLAPI.EVENT_BUS.fireChannel(event);
return event.getFile().getValue();
}
@Override

View File

@@ -31,6 +31,7 @@ import org.jackhuang.hellominecraft.api.HMCLAPI;
import org.jackhuang.hellominecraft.launcher.api.event.config.AuthenticatorChangedEvent;
import org.jackhuang.hellominecraft.launcher.api.event.config.DownloadTypeChangedEvent;
import org.jackhuang.hellominecraft.launcher.api.event.config.ThemeChangedEvent;
import org.jackhuang.hellominecraft.launcher.core.MCUtils;
import org.jackhuang.hellominecraft.util.sys.JdkVersion;
import org.jackhuang.hellominecraft.util.sys.OS;
@@ -44,6 +45,8 @@ public final class Config implements Cloneable {
private String last;
@SerializedName("bgpath")
private String bgpath;
@SerializedName("commonpath")
private String commonpath;
@SerializedName("clientToken")
private final String clientToken;
@SerializedName("proxyHost")
@@ -152,6 +155,15 @@ public final class Config implements Cloneable {
Settings.save();
}
public String getCommonpath() {
return commonpath;
}
public void setCommonpath(String commonpath) {
this.commonpath = commonpath;
Settings.save();
}
public String getClientToken() {
return clientToken;
}
@@ -210,6 +222,7 @@ public final class Config implements Cloneable {
theme = 4;
decorated = OS.os() == OS.LINUX;
auth = new HashMap<>();
commonpath = MCUtils.getWorkingDirectory("hmcl").getAbsolutePath();
}
public DownloadType getDownloadSource() {

View File

@@ -87,7 +87,7 @@ public final class GameSettingsPanel extends RepaintPage implements DropTargetLi
public GameSettingsPanel() {
HMCLAPI.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(t -> {
if (Settings.getLastProfile().service() == t.getValue())
if (Settings.getLastProfile().service() == t.getValue() && t.getValue().version().getVersions().isEmpty())
if (!showedNoVersion && Settings.getLastProfile().service().checkingModpack) {
showedNoVersion = true;
SwingUtilities.invokeLater(() -> {

View File

@@ -19,7 +19,7 @@
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="lblProxy" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="lblProxyHost" min="-2" max="-2" attributes="0"/>
@@ -38,35 +38,9 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyPassword" min="-2" pref="80" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblDownloadSource" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblTheme" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblBackground" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblLang" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="cboLang" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<Component id="txtBackgroundPath" pref="664" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnSelBackgroundPath" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="cboDownloadSource" alignment="1" max="32767" attributes="0"/>
<Component id="cboTheme" alignment="1" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="btnCheckUpdate" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnMCBBS" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lblAbout" min="-2" max="-2" attributes="0"/>
<Component id="lblModpack" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblRestart" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="chkDecorated" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="chkEnableShadow" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
@@ -74,10 +48,42 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="chkEnableAnimation" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="chkDecorated" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblAbout" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="btnCheckUpdate" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnMCBBS" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lblModpack" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblRestart" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblDownloadSource" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblTheme" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblBackground" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblLang" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblCommonPath" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="txtCommonPath" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnSetCommonPath" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="cboLang" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<Component id="txtBackgroundPath" pref="585" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnSelBackgroundPath" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="cboDownloadSource" alignment="1" max="32767" attributes="0"/>
<Component id="cboTheme" alignment="1" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@@ -86,6 +92,12 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblCommonPath" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtCommonPath" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="btnSetCommonPath" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblBackground" alignment="3" min="-2" max="-2" attributes="0"/>
@@ -127,7 +139,7 @@
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="chkDecorated" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="6" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnCheckUpdate" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="btnMCBBS" alignment="3" max="32767" attributes="0"/>
@@ -138,7 +150,7 @@
<Component id="lblModpack" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblAbout" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@@ -367,5 +379,29 @@
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="chkEnableAnimationItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblCommonPath">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="launcher.common_location" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtCommonPath">
<Properties>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="launcher.commpath_tooltip" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnSetCommonPath">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/lang/I18N.properties" key="ui.button.explore" replaceFormat="C.i18n(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnSetCommonPathActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View File

@@ -64,6 +64,7 @@ public class LauncherSettingsPanel extends RepaintPage {
cboLang.setSelectedIndex(id);
txtBackgroundPath.setText(Settings.getInstance().getBgpath());
txtCommonPath.setText(Settings.getInstance().getCommonpath());
txtProxyHost.setText(Settings.getInstance().getProxyHost());
txtProxyPort.setText(Settings.getInstance().getProxyPort());
txtProxyUsername.setText(Settings.getInstance().getProxyUserName());
@@ -118,6 +119,9 @@ public class LauncherSettingsPanel extends RepaintPage {
btnMCBBS = new javax.swing.JButton();
chkEnableBlur = new javax.swing.JCheckBox();
chkEnableAnimation = new javax.swing.JCheckBox();
lblCommonPath = new javax.swing.JLabel();
txtCommonPath = new javax.swing.JTextField();
btnSetCommonPath = new javax.swing.JButton();
cboDownloadSource.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
@@ -252,6 +256,17 @@ public class LauncherSettingsPanel extends RepaintPage {
}
});
lblCommonPath.setText(C.i18n("launcher.common_location")); // NOI18N
txtCommonPath.setToolTipText(C.i18n("launcher.commpath_tooltip")); // NOI18N
btnSetCommonPath.setText(C.i18n("ui.button.explore")); // NOI18N
btnSetCommonPath.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnSetCommonPathActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@@ -259,7 +274,7 @@ public class LauncherSettingsPanel extends RepaintPage {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(lblProxy)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblProxyHost)
@@ -279,42 +294,52 @@ public class LauncherSettingsPanel extends RepaintPage {
.addComponent(txtProxyPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblDownloadSource)
.addComponent(lblTheme)
.addComponent(lblBackground)
.addComponent(lblLang))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(cboLang, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(txtBackgroundPath, javax.swing.GroupLayout.DEFAULT_SIZE, 664, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnSelBackgroundPath))
.addComponent(cboDownloadSource, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(cboTheme, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(btnCheckUpdate)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnMCBBS))
.addComponent(lblAbout, 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)
.addComponent(lblRestart)
.addComponent(chkDecorated)
.addGroup(layout.createSequentialGroup()
.addComponent(chkEnableShadow)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkEnableBlur)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkEnableAnimation))
.addComponent(chkDecorated))
.addGap(0, 0, Short.MAX_VALUE)))
.addComponent(lblAbout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup()
.addComponent(btnCheckUpdate)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnMCBBS))
.addComponent(lblModpack, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblRestart))
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblDownloadSource)
.addComponent(lblTheme)
.addComponent(lblBackground)
.addComponent(lblLang)
.addComponent(lblCommonPath))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(txtCommonPath)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnSetCommonPath))
.addComponent(cboLang, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(txtBackgroundPath, javax.swing.GroupLayout.DEFAULT_SIZE, 585, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnSelBackgroundPath))
.addComponent(cboDownloadSource, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(cboTheme, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblCommonPath)
.addComponent(txtCommonPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnSetCommonPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblBackground)
.addComponent(btnSelBackgroundPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
@@ -349,7 +374,7 @@ public class LauncherSettingsPanel extends RepaintPage {
.addComponent(chkEnableAnimation))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkDecorated)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 6, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnCheckUpdate, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnMCBBS, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
@@ -447,10 +472,29 @@ public class LauncherSettingsPanel extends RepaintPage {
Settings.getInstance().setEnableAnimation(chkEnableAnimation.isSelected());
}//GEN-LAST:event_chkEnableAnimationItemStateChanged
private void btnSetCommonPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSetCommonPathActionPerformed
JSystemFileChooser fc = new JSystemFileChooser();
fc.setFileSelectionMode(JSystemFileChooser.DIRECTORIES_ONLY);
fc.setDialogTitle(C.i18n("launcher.choose_commonpath"));
fc.setMultiSelectionEnabled(false);
fc.showOpenDialog(this);
if (fc.getSelectedFile() == null)
return;
try {
String path = fc.getSelectedFile().getCanonicalPath();
txtCommonPath.setText(path);
Settings.getInstance().setCommonpath(path);
} catch (IOException e) {
HMCLog.warn("Failed to set common path.", e);
MessageBox.show(C.i18n("ui.label.failed_set") + e.getMessage());
}
}//GEN-LAST:event_btnSetCommonPathActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCheckUpdate;
private javax.swing.JButton btnMCBBS;
private javax.swing.JButton btnSelBackgroundPath;
private javax.swing.JButton btnSetCommonPath;
private javax.swing.JComboBox cboDownloadSource;
private javax.swing.JComboBox cboLang;
private javax.swing.JComboBox cboTheme;
@@ -460,6 +504,7 @@ public class LauncherSettingsPanel extends RepaintPage {
private javax.swing.JCheckBox chkEnableShadow;
private javax.swing.JLabel lblAbout;
private javax.swing.JLabel lblBackground;
private javax.swing.JLabel lblCommonPath;
private javax.swing.JLabel lblDownloadSource;
private javax.swing.JLabel lblLang;
private javax.swing.JLabel lblModpack;
@@ -471,6 +516,7 @@ public class LauncherSettingsPanel extends RepaintPage {
private javax.swing.JLabel lblRestart;
private javax.swing.JLabel lblTheme;
private javax.swing.JTextField txtBackgroundPath;
private javax.swing.JTextField txtCommonPath;
private javax.swing.JTextField txtProxyHost;
private javax.swing.JTextField txtProxyPassword;
private javax.swing.JTextField txtProxyPort;

View File

@@ -0,0 +1,47 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.launcher.util;
import java.io.File;
import org.jackhuang.hellominecraft.launcher.core.asset.MinecraftAssetService;
import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService;
import org.jackhuang.hellominecraft.launcher.setting.Settings;
/**
*
* @author huang
*/
public class HMCLAssetService extends MinecraftAssetService {
public HMCLAssetService(IMinecraftService service) {
super(service);
}
private boolean useSelf(String assetId) {
return new File(service.baseDirectory(), "assets/indexes/" + assetId + ",json").exists();
}
@Override
public File getAssets(String assetId) {
if (useSelf(assetId))
return new File(service.baseDirectory(), "assets");
else
return new File(Settings.getInstance().getCommonpath(), "assets");
}
}

View File

@@ -18,8 +18,11 @@
package org.jackhuang.hellominecraft.launcher.util;
import java.io.File;
import org.jackhuang.hellominecraft.api.HMCLAPI;
import org.jackhuang.hellominecraft.launcher.api.event.version.MinecraftLibraryPathEvent;
import org.jackhuang.hellominecraft.launcher.core.version.GameDirType;
import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersionManager;
import org.jackhuang.hellominecraft.launcher.setting.Settings;
import org.jackhuang.hellominecraft.launcher.setting.VersionSetting;
/**
@@ -30,6 +33,11 @@ public class HMCLGameProvider extends MinecraftVersionManager {
public HMCLGameProvider(HMCLMinecraftService p) {
super(p);
HMCLAPI.EVENT_BUS.channel(MinecraftLibraryPathEvent.class).register(t -> {
if (!t.getFile().getValue().exists())
t.getFile().setValue(new File(Settings.getInstance().getCommonpath(), t.getLocation()));
});
}
@Override

View File

@@ -75,7 +75,7 @@ public class HMCLMinecraftService extends IMinecraftService {
HMCLAPI.EVENT_BUS.channel(LoadedOneVersionEvent.class).register(e -> loadVersionSetting(e.getValue()));
this.mms = new MinecraftModService(this);
this.mds = new MinecraftDownloadService(this);
this.mas = new MinecraftAssetService(this);
this.mas = new HMCLAssetService(this);
this.mis = new MinecraftInstallerService(this);
}

View File

@@ -0,0 +1,39 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hellominecraft.util;
/**
*
* @author huang
*/
public class Wrapper<T> {
T value;
public Wrapper(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}

View File

@@ -308,11 +308,14 @@ mainwindow.no_version=No version found. Switch to Game Downloads Tab?
launcher.about=<html>About Author<br/>Minecraft Forum ID: klkl6523<br/>Copyright (c) 2013 huangyuhui<br/>Opened source under GPL v3 license:http://github.com/huanghongxun/HMCL/<br/>This software used project Gson which is under Apache License 2.0, thanks contributors.</html>
launcher.download_source=Download Source
launcher.background_location=Background Location
launcher.common_location=Common Location
launcher.exit_failed=Failed to shutdown.
launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem?
launcher.versions_json_not_matched_cannot_auto_completion=The version %s lost version information file, delete it?
launcher.versions_json_not_formatted=The version information of %s is malformed! Redownload it?
launcher.choose_bgpath=Choose background path.
launcher.choose_commonpath=Choose common path.
launcher.commpath_tooltip=<html><body>This app will save all game libraries and assets here unless there are existant files in game folder.</body></html>
launcher.background_tooltip=<html><body>The laucher uses a default background.<br/>If you use custom background.png, link it and it will be used.<br />If there is "bg" subdirectory, this app will chooses one picture in "bgskin" randomly.<br />If you set the background setting, this app will use it.</body></html>
launcher.update_launcher=Check for update
launcher.enable_shadow=Enable Window Shadow

View File

@@ -308,11 +308,14 @@ mainwindow.no_version=No version found. Switch to Game Downloads Tab?
launcher.about=<html>About Author<br/>Minecraft Forum ID: klkl6523<br/>Copyright (c) 2013 huangyuhui<br/>Opened source under GPL v3 license:http://github.com/huanghongxun/HMCL/<br/>This software used project Gson which is under Apache License 2.0, thanks contributors.</html>
launcher.download_source=Download Source
launcher.background_location=Background Location
launcher.common_location=Common Location
launcher.exit_failed=Failed to shutdown.
launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem?
launcher.versions_json_not_matched_cannot_auto_completion=The version %s lost version information file, delete it?
launcher.versions_json_not_formatted=The version information of %s is malformed! Redownload it?
launcher.choose_bgpath=Choose background path.
launcher.choose_commonpath=Choose common path.
launcher.commpath_tooltip=<html><body>This app will save all game libraries and assets here unless there are existant files in game folder.</body></html>
launcher.background_tooltip=<html><body>The laucher uses a default background.<br/>If you use custom background.png, link it and it will be used.<br />If there is "bg" subdirectory, this app will chooses one picture in "bgskin" randomly.<br />If you set the background setting, this app will use it.</body></html>
launcher.update_launcher=Check for update
launcher.enable_shadow=Enable Window Shadow

View File

@@ -306,11 +306,14 @@ mainwindow.no_version=Không có phiên bản minecraft nào được tìm thấ
launcher.about=<html>Về tác giả<br/>Minecraft Forum ID: klkl6523<br/>Copyright (c) 2013 huangyuhui<br/>http://github.com/huanghongxun/HMCL/<br/>Phần mềm này dùng project Gson, cảm ơn người đóng góp.</html>
launcher.download_source=Download Source
launcher.background_location=Background Location
launcher.common_location=Common Location
launcher.exit_failed=Tắt launcher thất bại.
launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem?
launcher.versions_json_not_matched_cannot_auto_completion=The version %s lost version information file, delete it?
launcher.versions_json_not_formatted=The version information of %s is malformed! Redownload it?
launcher.choose_bgpath=Choose background path.
launcher.choose_commonpath=Choose common path.
launcher.commpath_tooltip=<html><body>This app will save all game libraries and assets here unless there are existant files in game folder.</body></html>
launcher.background_tooltip=<html><body>This app uses the default background at first.<br />If there is background.png in the directory, it will be used.<br />If there is "bg" subdirectory, this app will chooses one picture in "bgskin" randomly.<br />If you set the background setting, this app will use it.</body></html>
launcher.update_launcher=Check for update
launcher.enable_shadow=Enable Window Shadow

View File

@@ -306,11 +306,14 @@ mainwindow.no_version=Kh\u00f4ng c\u00f3 phi\u00ean b\u1ea3n minecraft n\u00e0o
launcher.about=<html>V\u1ec1 t\u00e1c gi\u1ea3<br/>Minecraft Forum ID: klkl6523<br/>Copyright (c) 2013 huangyuhui<br/>http://github.com/huanghongxun/HMCL/<br/>Ph\u1ea7n m\u1ec1m n\u00e0y d\u00f9ng project Gson, c\u1ea3m \u01a1n ng\u01b0\u1eddi \u0111\u00f3ng g\u00f3p.</html>
launcher.download_source=Download Source
launcher.background_location=Background Location
launcher.common_location=Common Location
launcher.exit_failed=T\u1eaft launcher th\u1ea5t b\u1ea1i.
launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem?
launcher.versions_json_not_matched_cannot_auto_completion=The version %s lost version information file, delete it?
launcher.versions_json_not_formatted=The version information of %s is malformed! Redownload it?
launcher.choose_bgpath=Choose background path.
launcher.choose_commonpath=Choose common path.
launcher.commpath_tooltip=<html><body>This app will save all game libraries and assets here unless there are existant files in game folder.</body></html>
launcher.background_tooltip=<html><body>This app uses the default background at first.<br />If there is background.png in the directory, it will be used.<br />If there is "bg" subdirectory, this app will chooses one picture in "bgskin" randomly.<br />If you set the background setting, this app will use it.</body></html>
launcher.update_launcher=Check for update
launcher.enable_shadow=Enable Window Shadow

View File

@@ -308,11 +308,14 @@ mainwindow.no_version=未找到任何版本,是否进入游戏下载?
launcher.about=<html>默认背景图感谢gamerteam提供。<br/>关于作者:<br/>百度IDhuanghongxun20<br/>mcbbshuanghongxun<br/>Minecraft Forum ID: klkl6523<br/>欢迎提交Bug哦<br/>Copyright (c) 2013-2017 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.background_location=背景地址
launcher.common_location=公共文件夹
launcher.exit_failed=强制退出失败可能是Forge 1.7.10及更高版本导致的,无法解决。
launcher.versions_json_not_matched=版本%s格式不规范该版本文件夹下有json:%s是否更名这个文件来规范格式
launcher.versions_json_not_matched_cannot_auto_completion=版本%s缺失必要的版本信息文件是否删除该版本
launcher.versions_json_not_formatted=版本%s信息文件格式错误是否重新下载
launcher.choose_bgpath=选择背景路径
launcher.choose_commonpath=选择公共路径
launcher.commpath_tooltip=<html><body>启动器将所有游戏资源及依赖库文件放于此集中管理,如果游戏文件夹内有现成的将不会使用公共库文件</body></html>
launcher.background_tooltip=<html><body>启动器默认使用自带的背景<br />如果当前目录有background.png则会使用该文件作为背景<br />如果当前目录有bg子目录则会随机使用里面的一张图作为背景<br />如果该背景地址被修改,则会使用背景地址里的一张图作为背景<br />背景地址允许有多个地址,使用半角分号";"(不包含双引号)分隔</body></html>
launcher.update_launcher=检查更新
launcher.enable_shadow=启用窗口阴影

View File

@@ -308,11 +308,14 @@ mainwindow.no_version=\u672a\u627e\u5230\u4efb\u4f55\u7248\u672c\uff0c\u662f\u54
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/>Minecraft Forum ID: klkl6523<br/>\u6b22\u8fce\u63d0\u4ea4Bug\u54e6<br/>Copyright (c) 2013-2017 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.background_location=\u80cc\u666f\u5730\u5740
launcher.common_location=\u516c\u5171\u6587\u4ef6\u5939
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.versions_json_not_matched=\u7248\u672c%s\u683c\u5f0f\u4e0d\u89c4\u8303\uff01\u8be5\u7248\u672c\u6587\u4ef6\u5939\u4e0b\u6709json:%s\uff0c\u662f\u5426\u66f4\u540d\u8fd9\u4e2a\u6587\u4ef6\u6765\u89c4\u8303\u683c\u5f0f\uff1f
launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f\u6587\u4ef6\uff0c\u662f\u5426\u5220\u9664\u8be5\u7248\u672c\uff1f
launcher.versions_json_not_formatted=\u7248\u672c%s\u4fe1\u606f\u6587\u4ef6\u683c\u5f0f\u9519\u8bef\uff0c\u662f\u5426\u91cd\u65b0\u4e0b\u8f7d\uff1f
launcher.choose_bgpath=\u9009\u62e9\u80cc\u666f\u8def\u5f84
launcher.choose_commonpath=\u9009\u62e9\u516c\u5171\u8def\u5f84
launcher.commpath_tooltip=<html><body>\u542f\u52a8\u5668\u5c06\u6240\u6709\u6e38\u620f\u8d44\u6e90\u53ca\u4f9d\u8d56\u5e93\u6587\u4ef6\u653e\u4e8e\u6b64\u96c6\u4e2d\u7ba1\u7406\uff0c\u5982\u679c\u6e38\u620f\u6587\u4ef6\u5939\u5185\u6709\u73b0\u6210\u7684\u5c06\u4e0d\u4f1a\u4f7f\u7528\u516c\u5171\u5e93\u6587\u4ef6</body></html>
launcher.background_tooltip=<html><body>\u542f\u52a8\u5668\u9ed8\u8ba4\u4f7f\u7528\u81ea\u5e26\u7684\u80cc\u666f<br />\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709background.png\uff0c\u5219\u4f1a\u4f7f\u7528\u8be5\u6587\u4ef6\u4f5c\u4e3a\u80cc\u666f<br />\u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709bg\u5b50\u76ee\u5f55\uff0c\u5219\u4f1a\u968f\u673a\u4f7f\u7528\u91cc\u9762\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f<br />\u5982\u679c\u8be5\u80cc\u666f\u5730\u5740\u88ab\u4fee\u6539\uff0c\u5219\u4f1a\u4f7f\u7528\u80cc\u666f\u5730\u5740\u91cc\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f<br />\u80cc\u666f\u5730\u5740\u5141\u8bb8\u6709\u591a\u4e2a\u5730\u5740\uff0c\u4f7f\u7528\u534a\u89d2\u5206\u53f7";"(\u4e0d\u5305\u542b\u53cc\u5f15\u53f7)\u5206\u9694</body></html>
launcher.update_launcher=\u68c0\u67e5\u66f4\u65b0
launcher.enable_shadow=\u542f\u7528\u7a97\u53e3\u9634\u5f71