Compare commits

...
Author SHA1 Message Date
huangyuhui bd38c9424f Fix using Java 8 methods 2018-08-15 03:18:09 +08:00
huangyuhui c47dea94e3 Change update source 2018-08-15 03:05:55 +08:00
huangyuhui 69c0382bd5 Removed -XstartOnFirstThread to fix freezed launched game. GH-257 2018-02-01 16:03:10 +08:00
huangyuhui 1d80cd9fa2 Merge 'arguments' in json 2017-11-16 00:02:32 +08:00
huangyuhui 3721842c8b Removed funtionalities of Log4jHandler 2017-11-04 22:30:38 +08:00
huangyuhui 47d8b59b93 Update Gradle 2017-11-04 10:22:37 +08:00
huangyuhui b5fbc69ee6 Default game arguments 2017-11-03 13:38:20 +08:00
huangyuhui 9d95d3ea66 JVM arguments in minecraft.json supported 2017-11-02 20:21:32 +08:00
huangyuhui 06b3ec8337 Launching 1.13 2017-11-02 19:34:21 +08:00
huangyuhui fabb6b50b4 Prevent launching in path that contains ! 2017-10-31 19:31:22 +08:00
huangyuhui ca627b8a2d Update Gradle 2017-10-18 19:27:35 +08:00
huanghongxun a0c619a747 Ignore RejectedExecutionException 2017-10-11 20:03:17 +08:00
huanghongxun 5386ae3736 Removed log4j support 2017-10-11 19:54:08 +08:00
huangyuhui 32fd125b97 Added proxy type selection. Closes #192 2017-08-27 13:34:12 +08:00
huangyuhui 7a86881926 Fixed downloading libraries that are forbidden in specific OS. Closes #163 2017-08-26 17:45:40 +08:00
huangyuhui b255fd4601 CDATA 2017-08-26 09:04:10 +08:00
huangyuhui 562dd8d916 Fixed #190 2017-08-26 08:35:27 +08:00
huangyuhui 97d820446a Fixed Read end dead. Closes #186 2017-08-24 10:03:19 +08:00
huangyuhui 826d382ad5 Changed log colors. Closes #187 2017-08-24 09:37:33 +08:00
huangyuhui 59d7ac3c82 ProcessThread.interrupt 2017-08-20 12:07:13 +08:00
huanghongxun 566aed4ed6 Merge pull request #185 from ron-gh/master
Fix "java.io.IOException: Read end dead"
2017-08-18 21:32:53 +08:00
ron 1b90e94615 Fix "java.io.IOException: Read end dead" when different Threads are writing to a single PipedOutputStream 2017-08-18 14:54:55 +02:00
huanghongxun 22ede84c3d Merge pull request #183 from jp8900308/master
Set a custom User-Agent, fixes optifine.net downloads
2017-08-15 23:43:05 +08:00
Jean-Paul Bergeron 0c4da069b7 Set a custom User-Agent, fixes optifine.net downloads 2017-08-15 07:23:03 -07:00
huangyuhui 90733c6a7e Merge branch 'master' of https://github.com/huanghongxun/HMCL 2017-08-13 19:57:08 +08:00
huangyuhui 44daf656b5 Fixed downloading text2speech 2017-08-13 19:56:02 +08:00
huangyuhui 90f416095e Fixed multi-character account: no player when log in the next time 2017-08-13 19:39:41 +08:00
huanghongxun 076d4d5dce Merge pull request #180 from jp8900308/master
partial rv 7fe3e28a, fixes Forge on 1.12
2017-08-12 09:39:23 +08:00
Jean-Paul Bergeron 3c77f249e5 partial rv 7fe3e28a, fixes Forge on 1.12 2017-08-09 12:24:39 -07:00
huangyuhui 11e5dc3782 Update Russian lang 2017-08-07 21:55:03 +08:00
63 changed files with 1428 additions and 762 deletions

No files matched your search

+5 -5
View File
@@ -24,9 +24,9 @@ import java.util.zip.ZipEntry
import java.util.zip.ZipFile
plugins {
id "edu.sc.seis.macAppBundle" version "2.1.6"
id "me.tatarka.retrolambda" version "3.5.0"
id 'edu.sc.seis.launch4j' version '2.3.0'
id "edu.sc.seis.macAppBundle" version "2.1.8"
id "me.tatarka.retrolambda" version "3.7.0"
id 'edu.sc.seis.launch4j' version '2.4.2'
//id "org.jetbrains.kotlin.jvm" version "1.1.2-2"
}
@@ -38,11 +38,11 @@ def buildnumber = System.getenv("TRAVIS_BUILD_NUMBER")
if (buildnumber == null)
buildnumber = System.getenv("BUILD_NUMBER")
if (buildnumber == null)
buildnumber = "33"
buildnumber = "60"
def versionroot = System.getenv("VERSION_ROOT")
if (versionroot == null)
versionroot = "2.7.8"
versionroot = "2.7.10"
String mavenGroupId = 'HMCL'
String mavenVersion = versionroot + '.' + buildnumber
+27 -27
View File
@@ -23,8 +23,10 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -46,7 +48,6 @@ import org.jackhuang.hmcl.ui.LogWindow;
import org.jackhuang.hmcl.ui.MainFrame;
import org.jackhuang.hmcl.util.CrashReporter;
import org.jackhuang.hmcl.util.DefaultPlugin;
import org.jackhuang.hmcl.util.MathUtils;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.lang.SupportedLocales;
@@ -100,6 +101,11 @@ public final class Main {
public static void main(String[] args) throws IOException {
{
if (new File("").getAbsolutePath().contains("!")) {
MessageBox.show("HMCL cannot run at such path that contains '!'");
return;
}
try {
File file = new File("hmcl.log").getAbsoluteFile();
if (!file.exists() && !file.createNewFile())
@@ -137,7 +143,7 @@ public final class Main {
}
};
HMCLApi.HMCL_VERSION = VersionNumber.check(LAUNCHER_VERSION);
HMCLApi.HMCL_VERSION = VersionNumber.asVersion(LAUNCHER_VERSION);
PluginManager.getPlugin(DefaultPlugin.class);
for (String s : args)
@@ -156,7 +162,7 @@ public final class Main {
}
PluginManager.loadPlugins();
IUpgrader.NOW_UPGRADER.parseArguments(HMCLApi.HMCL_VERSION, args);
IUpgrader.NOW_UPGRADER.parseArguments(HMCLApi.HMCL_VERSION, Arrays.asList(args));
System.setProperty("awt.useSystemAAFontSettings", "on");
System.setProperty("swing.aatext", "true");
@@ -199,10 +205,24 @@ public final class Main {
Settings.UPDATE_CHECKER.upgrade.register(IUpgrader.NOW_UPGRADER);
Settings.UPDATE_CHECKER.process(false).reg(t -> Main.invokeUpdate()).execute();
if (StrUtils.isNotBlank(Settings.getInstance().getProxyHost()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPort()) && MathUtils.canParseInt(Settings.getInstance().getProxyPort())) {
HMCLog.log("Initializing customized proxy");
System.setProperty("http.proxyHost", Settings.getInstance().getProxyHost());
System.setProperty("http.proxyPort", Settings.getInstance().getProxyPort());
if (Settings.getInstance().getProxyType() != Proxy.Type.DIRECT && StrUtils.isNotBlank(Settings.getInstance().getProxyHost())) {
switch (Settings.getInstance().getProxyType()) {
case DIRECT:
break;
case HTTP:
System.setProperty("http.proxyHost", Settings.getInstance().getProxyHost());
if (StrUtils.isNotBlank(Settings.getInstance().getProxyPort()))
System.setProperty("http.proxyPort", Settings.getInstance().getProxyPort());
HMCLog.log("Initialized HTTP proxy.");
break;
case SOCKS:
System.setProperty("socksProxyHost", Settings.getInstance().getProxyHost());
if (StrUtils.isNotBlank(Settings.getInstance().getProxyPort()))
System.setProperty("socksProxyPort", Settings.getInstance().getProxyPort());
HMCLog.log("Initialized Socks v4/v5 proxy.");
break;
}
if (StrUtils.isNotBlank(Settings.getInstance().getProxyUserName()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPassword()))
Authenticator.setDefault(new Authenticator() {
@Override
@@ -212,12 +232,6 @@ public final class Main {
});
}
try {
unpackDefaultLog4jConfiguration();
} catch(IOException e) {
HMCLog.err("Failed to unpack log4j.xml, log window will not work well.", e);
}
MainFrame.showMainFrame();
}
}
@@ -225,20 +239,6 @@ public final class Main {
public static void invokeUpdate() {
MainFrame.INSTANCE.invokeUpdate();
}
public static final File LOG4J_FILE = new File(MCUtils.getWorkingDirectory("hmcl"), "log4j.xml");
public static void unpackDefaultLog4jConfiguration() throws IOException {
LOG4J_FILE.getParentFile().mkdirs();
if (LOG4J_FILE.exists()) return;
LOG4J_FILE.createNewFile();
try (InputStream is = Main.class.getResourceAsStream("/org/jackhuang/hmcl/log4j.xml");
FileOutputStream fos = new FileOutputStream(LOG4J_FILE)) {
int b;
while ((b = is.read()) != -1)
fos.write(b);
}
}
public static ImageIcon getIcon(String path) {
try {
@@ -20,6 +20,7 @@ package org.jackhuang.hmcl.setting;
import org.jackhuang.hmcl.core.download.DownloadType;
import com.google.gson.annotations.SerializedName;
import java.awt.Font;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -60,6 +61,8 @@ public final class Config implements Cloneable {
private String proxyUserName;
@SerializedName("proxyPassword")
private String proxyPassword;
@SerializedName("proxyType")
private int proxyType;
@SerializedName("enableShadow")
private boolean enableShadow;
@SerializedName("enableBlur")
@@ -91,7 +94,7 @@ public final class Config implements Cloneable {
public Config() {
clientToken = UUID.randomUUID().toString();
logintype = downloadtype = 0;
proxyType = logintype = downloadtype = 0;
logLines = 100;
enableAnimation = enableBlur = true;
if (OS.os() == OS.WINDOWS)
@@ -269,6 +272,19 @@ public final class Config implements Cloneable {
Settings.save();
}
public Proxy.Type getProxyType() {
if (proxyType < 0 || proxyType >= 3) {
proxyType = 0;
Settings.save();
}
return Proxy.Type.values()[proxyType];
}
public void setProxyType(Proxy.Type proxyType) {
this.proxyType = proxyType.ordinal();
Settings.save();
}
public String getProxyUserName() {
return proxyUserName == null ? "" : proxyUserName;
}
@@ -112,8 +112,7 @@ public final class Profile implements IProfile {
}
public void makeVersionSettingGlobal(String id) {
HMCLMinecraftService s = (HMCLMinecraftService) service();
VersionSetting vs = s.getVersionSetting(id);
VersionSetting vs = service().getVersionSetting(id);
if (vs == null)
return;
vs.setUsesGlobal(true);
@@ -33,7 +33,7 @@ import org.jackhuang.hmcl.api.event.config.ProfileLoadingEvent;
import org.jackhuang.hmcl.laf.utils.AnimationController;
import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.UpdateChecker;
import org.jackhuang.hmcl.util.upgrade.UpdateChecker;
import org.jackhuang.hmcl.util.sys.IOUtils;
/**
@@ -95,35 +95,36 @@
<Component id="btnCheckUpdate" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnMCBBS" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="418" max="32767" attributes="0"/>
</Group>
<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"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyHost" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblProxyPort" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyPort" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblProxyUserName" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyUsername" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblProxyPassword" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyPassword" min="-2" pref="80" max="-2" attributes="0"/>
<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="lblCommonPath" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblLang" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblProxy" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="cboProxyType" pref="156" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblProxyHost" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyHost" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblProxyPort" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyPort" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblProxyUserName" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyUsername" min="-2" pref="80" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblProxyPassword" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtProxyPassword" min="-2" pref="80" max="-2" attributes="0"/>
</Group>
<Component id="cboLang" alignment="1" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="txtCommonPath" max="32767" attributes="0"/>
@@ -168,6 +169,7 @@
<Component id="lblProxyUserName" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtProxyPassword" alignment="3" min="-2" pref="26" max="-2" attributes="0"/>
<Component id="lblProxyPassword" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cboProxyType" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="69" max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
@@ -315,6 +317,23 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="cboProxyType">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="3">
<StringItem index="0" value="Direct"/>
<StringItem index="1" value="HTTP"/>
<StringItem index="2" value="Socks"/>
</StringArray>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cboProxyTypeItemStateChanged"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="pnlUI">
@@ -348,7 +367,7 @@
<Component id="chkEnableAnimation" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="15" max="32767" attributes="0"/>
<EmptySpace min="0" pref="163" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
@@ -500,7 +519,7 @@
<Component class="javax.swing.JComboBox" name="cboFontFamily">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<SerializedValue value="-84,-19,0,5,115,114,0,32,106,97,118,97,120,46,115,119,105,110,103,46,68,101,102,97,117,108,116,67,111,109,98,111,66,111,120,77,111,100,101,108,92,-10,105,-80,-61,-104,-56,48,2,0,2,76,0,7,111,98,106,101,99,116,115,116,0,18,76,106,97,118,97,47,117,116,105,108,47,86,101,99,116,111,114,59,76,0,14,115,101,108,101,99,116,101,100,79,98,106,101,99,116,116,0,18,76,106,97,118,97,47,108,97,110,103,47,79,98,106,101,99,116,59,120,114,0,29,106,97,118,97,120,46,115,119,105,110,103,46,65,98,115,116,114,97,99,116,76,105,115,116,77,111,100,101,108,87,-79,61,-30,108,45,-87,-39,2,0,1,76,0,12,108,105,115,116,101,110,101,114,76,105,115,116,116,0,37,76,106,97,118,97,120,47,115,119,105,110,103,47,101,118,101,110,116,47,69,118,101,110,116,76,105,115,116,101,110,101,114,76,105,115,116,59,120,112,115,114,0,35,106,97,118,97,120,46,115,119,105,110,103,46,101,118,101,110,116,46,69,118,101,110,116,76,105,115,116,101,110,101,114,76,105,115,116,-79,54,-58,125,-124,-22,-42,68,3,0,0,120,112,116,0,34,106,97,118,97,120,46,115,119,105,110,103,46,101,118,101,110,116,46,76,105,115,116,68,97,116,97,76,105,115,116,101,110,101,114,115,114,0,21,106,97,118,97,120,46,115,119,105,110,103,46,74,67,111,109,98,111,66,111,120,115,-25,-16,-68,-83,109,105,-54,3,0,14,90,0,17,102,105,114,105,110,103,65,99,116,105,111,110,69,118,101,110,116,90,0,10,105,115,69,100,105,116,97,98,108,101,90,0,23,108,105,103,104,116,87,101,105,103,104,116,80,111,112,117,112,69,110,97,98,108,101,100,73,0,15,109,97,120,105,109,117,109,82,111,119,67,111,117,110,116,90,0,13,115,101,108,101,99,116,105,110,103,73,116,101,109,76,0,6,97,99,116,105,111,110,116,0,20,76,106,97,118,97,120,47,115,119,105,110,103,47,65,99,116,105,111,110,59,76,0,13,97,99,116,105,111,110,67,111,109,109,97,110,100,116,0,18,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,76,0,28,97,99,116,105,111,110,80,114,111,112,101,114,116,121,67,104,97,110,103,101,76,105,115,116,101,110,101,114,116,0,35,76,106,97,118,97,47,98,101,97,110,115,47,80,114,111,112,101,114,116,121,67,104,97,110,103,101,76,105,115,116,101,110,101,114,59,76,0,9,100,97,116,97,77,111,100,101,108,116,0,27,76,106,97,118,97,120,47,115,119,105,110,103,47,67,111,109,98,111,66,111,120,77,111,100,101,108,59,76,0,6,101,100,105,116,111,114,116,0,28,76,106,97,118,97,120,47,115,119,105,110,103,47,67,111,109,98,111,66,111,120,69,100,105,116,111,114,59,76,0,19,107,101,121,83,101,108,101,99,116,105,111,110,77,97,110,97,103,101,114,116,0,43,76,106,97,118,97,120,47,115,119,105,110,103,47,74,67,111,109,98,111,66,111,120,36,75,101,121,83,101,108,101,99,116,105,111,110,77,97,110,97,103,101,114,59,76,0,21,112,114,111,116,111,116,121,112,101,68,105,115,112,108,97,121,86,97,108,117,101,113,0,126,0,2,76,0,8,114,101,110,100,101,114,101,114,116,0,30,76,106,97,118,97,120,47,115,119,105,110,103,47,76,105,115,116,67,101,108,108,82,101,110,100,101,114,101,114,59,76,0,20,115,101,108,101,99,116,101,100,73,116,101,109,82,101,109,105,110,100,101,114,113,0,126,0,2,120,114,0,22,106,97,118,97,120,46,115,119,105,110,103,46,74,67,111,109,112,111,110,101,110,116,51,-17,99,38,30,108,-90,-113,3,0,16,70,0,10,97,108,105,103,110,109,101,110,116,88,70,0,10,97,108,105,103,110,109,101,110,116,89,90,0,11,97,117,116,111,115,99,114,111,108,108,115,73,0,5,102,108,97,103,115,90,0,15,105,115,65,108,105,103,110,109,101,110,116,88,83,101,116,90,0,15,105,115,65,108,105,103,110,109,101,110,116,89,83,101,116,90,0,26,118,101,114,105,102,121,73,110,112,117,116,87,104,101,110,70,111,99,117,115,84,97,114,103,101,116,76,0,9,97,99,116,105,111,110,77,97,112,116,0,23,76,106,97,118,97,120,47,115,119,105,110,103,47,65,99,116,105,111,110,77,97,112,59,76,0,16,97,110,99,101,115,116,111,114,73,110,112,117,116,77,97,112,116,0,22,76,106,97,118,97,120,47,115,119,105,110,103,47,73,110,112,117,116,77,97,112,59,76,0,6,98,111,114,100,101,114,116,0,27,76,106,97,118,97,120,47,115,119,105,110,103,47,98,111,114,100,101,114,47,66,111,114,100,101,114,59,76,0,13,102,111,99,117,115,73,110,112,117,116,77,97,112,113,0,126,0,19,76,0,13,105,110,112,117,116,86,101,114,105,102,105,101,114,116,0,27,76,106,97,118,97,120,47,115,119,105,110,103,47,73,110,112,117,116,86,101,114,105,102,105,101,114,59,76,0,12,108,105,115,116,101,110,101,114,76,105,115,116,113,0,126,0,4,76,0,9,112,111,112,117,112,77,101,110,117,116,0,24,76,106,97,118,97,120,47,115,119,105,110,103,47,74,80,111,112,117,112,77,101,110,117,59,76,0,21,118,101,116,111,97,98,108,101,67,104,97,110,103,101,83,117,112,112,111,114,116,116,0,34,76,106,97,118,97,47,98,101,97,110,115,47,86,101,116,111,97,98,108,101,67,104,97,110,103,101,83,117,112,112,111,114,116,59,76,0,14,119,105,110,100,111,119,73,110,112,117,116,77,97,112,116,0,31,76,106,97,118,97,120,47,115,119,105,110,103,47,67,111,109,112,111,110,101,110,116,73,110,112,117,116,77,97,112,59,120,114,0,18,106,97,118,97,46,97,119,116,46,67,111,110,116,97,105,110,101,114,64,7,-128,115,-3,20,12,39,3,0,8,73,0,30,99,111,110,116,97,105,110,101,114,83,101,114,105,97,108,105,122,101,100,68,97,116Line truncated
<SerializedValue value="-84,-19,0,5,115,114,0,32,106,97,118,97,120,46,115,119,105,110,103,46,68,101,102,97,117,108,116,67,111,109,98,111,66,111,120,77,111,100,101,108,92,-10,105,-80,-61,-104,-56,48,2,0,2,76,0,7,111,98,106,101,99,116,115,116,0,18,76,106,97,118,97,47,117,116,105,108,47,86,101,99,116,111,114,59,76,0,14,115,101,108,101,99,116,101,100,79,98,106,101,99,116,116,0,18,76,106,97,118,97,47,108,97,110,103,47,79,98,106,101,99,116,59,120,114,0,29,106,97,118,97,120,46,115,119,105,110,103,46,65,98,115,116,114,97,99,116,76,105,115,116,77,111,100,101,108,87,-79,61,-30,108,45,-87,-39,2,0,1,76,0,12,108,105,115,116,101,110,101,114,76,105,115,116,116,0,37,76,106,97,118,97,120,47,115,119,105,110,103,47,101,118,101,110,116,47,69,118,101,110,116,76,105,115,116,101,110,101,114,76,105,115,116,59,120,112,115,114,0,35,106,97,118,97,120,46,115,119,105,110,103,46,101,118,101,110,116,46,69,118,101,110,116,76,105,115,116,101,110,101,114,76,105,115,116,-79,54,-58,125,-124,-22,-42,68,3,0,0,120,112,116,0,34,106,97,118,97,120,46,115,119,105,110,103,46,101,118,101,110,116,46,76,105,115,116,68,97,116,97,76,105,115,116,101,110,101,114,115,114,0,21,106,97,118,97,120,46,115,119,105,110,103,46,74,67,111,109,98,111,66,111,120,115,-25,-16,-68,-83,109,105,-54,3,0,14,90,0,17,102,105,114,105,110,103,65,99,116,105,111,110,69,118,101,110,116,90,0,10,105,115,69,100,105,116,97,98,108,101,90,0,23,108,105,103,104,116,87,101,105,103,104,116,80,111,112,117,112,69,110,97,98,108,101,100,73,0,15,109,97,120,105,109,117,109,82,111,119,67,111,117,110,116,90,0,13,115,101,108,101,99,116,105,110,103,73,116,101,109,76,0,6,97,99,116,105,111,110,116,0,20,76,106,97,118,97,120,47,115,119,105,110,103,47,65,99,116,105,111,110,59,76,0,13,97,99,116,105,111,110,67,111,109,109,97,110,100,116,0,18,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,76,0,28,97,99,116,105,111,110,80,114,111,112,101,114,116,121,67,104,97,110,103,101,76,105,115,116,101,110,101,114,116,0,35,76,106,97,118,97,47,98,101,97,110,115,47,80,114,111,112,101,114,116,121,67,104,97,110,103,101,76,105,115,116,101,110,101,114,59,76,0,9,100,97,116,97,77,111,100,101,108,116,0,27,76,106,97,118,97,120,47,115,119,105,110,103,47,67,111,109,98,111,66,111,120,77,111,100,101,108,59,76,0,6,101,100,105,116,111,114,116,0,28,76,106,97,118,97,120,47,115,119,105,110,103,47,67,111,109,98,111,66,111,120,69,100,105,116,111,114,59,76,0,19,107,101,121,83,101,108,101,99,116,105,111,110,77,97,110,97,103,101,114,116,0,43,76,106,97,118,97,120,47,115,119,105,110,103,47,74,67,111,109,98,111,66,111,120,36,75,101,121,83,101,108,101,99,116,105,111,110,77,97,110,97,103,101,114,59,76,0,21,112,114,111,116,111,116,121,112,101,68,105,115,112,108,97,121,86,97,108,117,101,113,0,126,0,2,76,0,8,114,101,110,100,101,114,101,114,116,0,30,76,106,97,118,97,120,47,115,119,105,110,103,47,76,105,115,116,67,101,108,108,82,101,110,100,101,114,101,114,59,76,0,20,115,101,108,101,99,116,101,100,73,116,101,109,82,101,109,105,110,100,101,114,113,0,126,0,2,120,114,0,22,106,97,118,97,120,46,115,119,105,110,103,46,74,67,111,109,112,111,110,101,110,116,51,-17,99,38,30,108,-90,-113,3,0,16,70,0,10,97,108,105,103,110,109,101,110,116,88,70,0,10,97,108,105,103,110,109,101,110,116,89,90,0,11,97,117,116,111,115,99,114,111,108,108,115,73,0,5,102,108,97,103,115,90,0,15,105,115,65,108,105,103,110,109,101,110,116,88,83,101,116,90,0,15,105,115,65,108,105,103,110,109,101,110,116,89,83,101,116,90,0,26,118,101,114,105,102,121,73,110,112,117,116,87,104,101,110,70,111,99,117,115,84,97,114,103,101,116,76,0,9,97,99,116,105,111,110,77,97,112,116,0,23,76,106,97,118,97,120,47,115,119,105,110,103,47,65,99,116,105,111,110,77,97,112,59,76,0,16,97,110,99,101,115,116,111,114,73,110,112,117,116,77,97,112,116,0,22,76,106,97,118,97,120,47,115,119,105,110,103,47,73,110,112,117,116,77,97,112,59,76,0,6,98,111,114,100,101,114,116,0,27,76,106,97,118,97,120,47,115,119,105,110,103,47,98,111,114,100,101,114,47,66,111,114,100,101,114,59,76,0,13,102,111,99,117,115,73,110,112,117,116,77,97,112,113,0,126,0,19,76,0,13,105,110,112,117,116,86,101,114,105,102,105,101,114,116,0,27,76,106,97,118,97,120,47,115,119,105,110,103,47,73,110,112,117,116,86,101,114,105,102,105,101,114,59,76,0,12,108,105,115,116,101,110,101,114,76,105,115,116,113,0,126,0,4,76,0,9,112,111,112,117,112,77,101,110,117,116,0,24,76,106,97,118,97,120,47,115,119,105,110,103,47,74,80,111,112,117,112,77,101,110,117,59,76,0,21,118,101,116,111,97,98,108,101,67,104,97,110,103,101,83,117,112,112,111,114,116,116,0,34,76,106,97,118,97,47,98,101,97,110,115,47,86,101,116,111,97,98,108,101,67,104,97,110,103,101,83,117,112,112,111,114,116,59,76,0,14,119,105,110,100,111,119,73,110,112,117,116,77,97,112,116,0,31,76,106,97,118,97,120,47,115,119,105,110,103,47,67,111,109,112,111,110,101,110,116,73,110,112,117,116,77,97,112,59,120,114,0,18,106,97,118,97,46,97,119,116,46,67,111,110,116,97,105,110,101,114,64,7,-128,115,-3,20,12,39,3,0,8,73,0,30,99,111,110,116,97,105,110,101,114,83,101,114,105,97,108,105,122,101,100,68,97,116Line truncated
</Property>
</Properties>
<Events>
@@ -549,7 +568,7 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="lblAbout" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="104" max="32767" attributes="0"/>
<EmptySpace pref="252" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@@ -18,6 +18,7 @@
package org.jackhuang.hmcl.ui;
import java.io.IOException;
import java.net.Proxy;
import javax.swing.DefaultComboBoxModel;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.jackhuang.hmcl.util.C;
@@ -78,6 +79,7 @@ public class LauncherSettingsPanel extends RepaintPage {
spinnerFontSize.setValue(Settings.getInstance().getFontSize());
cboFontFamily.setSelectedItem(Settings.getInstance().getFontFamily());
cboDownloadSource.setSelectedIndex(Settings.getInstance().getDownloadType());
cboProxyType.setSelectedIndex(Settings.getInstance().getProxyType().ordinal());
cboTheme.setSelectedItem(Settings.getInstance().getTheme());
chkEnableShadow.setSelected(Settings.getInstance().isEnableShadow());
chkEnableBlur.setSelected(Settings.getInstance().isEnableBlur());
@@ -122,6 +124,7 @@ public class LauncherSettingsPanel extends RepaintPage {
btnMCBBS = new javax.swing.JButton();
cboLang = new javax.swing.JComboBox();
lblLang = new javax.swing.JLabel();
cboProxyType = new javax.swing.JComboBox<>();
pnlUI = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation());
lblTheme = new javax.swing.JLabel();
cboTheme = new javax.swing.JComboBox();
@@ -231,6 +234,13 @@ public class LauncherSettingsPanel extends RepaintPage {
lblLang.setText(C.i18n("launcher.lang")); // NOI18N
cboProxyType.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Direct", "HTTP", "Socks" }));
cboProxyType.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
cboProxyTypeItemStateChanged(evt);
}
});
javax.swing.GroupLayout pnlGeneralLayout = new javax.swing.GroupLayout(pnlGeneral);
pnlGeneral.setLayout(pnlGeneralLayout);
pnlGeneralLayout.setHorizontalGroup(
@@ -242,32 +252,33 @@ public class LauncherSettingsPanel extends RepaintPage {
.addComponent(btnCheckUpdate)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnMCBBS)
.addGap(0, 418, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlGeneralLayout.createSequentialGroup()
.addComponent(lblProxy)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblProxyHost)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyHost, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblProxyPort)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyPort, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblProxyUserName)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyUsername, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblProxyPassword)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(pnlGeneralLayout.createSequentialGroup()
.addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblDownloadSource)
.addComponent(lblCommonPath)
.addComponent(lblLang))
.addComponent(lblLang)
.addComponent(lblProxy))
.addGap(28, 28, 28)
.addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnlGeneralLayout.createSequentialGroup()
.addComponent(cboProxyType, 0, 156, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblProxyHost)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyHost, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblProxyPort)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyPort, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblProxyUserName)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyUsername, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblProxyPassword)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtProxyPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(cboLang, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(pnlGeneralLayout.createSequentialGroup()
.addComponent(txtCommonPath)
@@ -302,7 +313,8 @@ public class LauncherSettingsPanel extends RepaintPage {
.addComponent(txtProxyUsername, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblProxyUserName)
.addComponent(txtProxyPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblProxyPassword))
.addComponent(lblProxyPassword)
.addComponent(cboProxyType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 69, Short.MAX_VALUE)
.addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnCheckUpdate, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
@@ -397,7 +409,7 @@ public class LauncherSettingsPanel extends RepaintPage {
.addComponent(chkEnableBlur)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkEnableAnimation)))
.addGap(0, 15, Short.MAX_VALUE))
.addGap(0, 163, Short.MAX_VALUE))
.addGroup(pnlUILayout.createSequentialGroup()
.addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblBackground)
@@ -460,7 +472,7 @@ public class LauncherSettingsPanel extends RepaintPage {
.addGroup(pnlAboutLayout.createSequentialGroup()
.addContainerGap()
.addComponent(lblAbout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(104, Short.MAX_VALUE))
.addContainerGap(252, Short.MAX_VALUE))
);
pnlAboutLayout.setVerticalGroup(
pnlAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -612,6 +624,10 @@ public class LauncherSettingsPanel extends RepaintPage {
lblExample.setFont(Settings.getInstance().getConsoleFont());
}//GEN-LAST:event_spinnerFontSizeStateChanged
private void cboProxyTypeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboProxyTypeItemStateChanged
Settings.getInstance().setProxyType(Proxy.Type.values()[cboProxyType.getSelectedIndex()]);
}//GEN-LAST:event_cboProxyTypeItemStateChanged
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCheckUpdate;
private javax.swing.JButton btnMCBBS;
@@ -620,6 +636,7 @@ public class LauncherSettingsPanel extends RepaintPage {
private javax.swing.JComboBox cboDownloadSource;
private javax.swing.JComboBox cboFontFamily;
private javax.swing.JComboBox cboLang;
private javax.swing.JComboBox<String> cboProxyType;
private javax.swing.JComboBox cboTheme;
private javax.swing.JCheckBox chkDecorated;
private javax.swing.JCheckBox chkEnableAnimation;
@@ -52,8 +52,9 @@ import org.xml.sax.XMLReader;
* @author huangyuhui
*/
public class LaunchingUIDaemon {
XMLReader reader;
Log4jHandler logHandler;
public LaunchingUIDaemon() {
HMCLApi.EVENT_BUS.channel(LaunchingStateChangedEvent.class).register(LAUNCHING_STATE_CHANGED);
@@ -76,12 +77,12 @@ public class LaunchingUIDaemon {
PipedOutputStream os = new PipedOutputStream();
monitor.setTag(obj);
try {
Log4jHandler handler = new Log4jHandler(monitor, os);
handler.addForbiddenToken(obj.getLoginResult().getAccessToken(), "<access token>");
handler.addForbiddenToken(obj.getLoginResult().getSession(), "<session>");
handler.addForbiddenToken(obj.getLoginResult().getUserId(), "<uuid>");
handler.addForbiddenToken("Setting user: " + obj.getLoginResult().getUserName(), "<player>");
handler.start();
logHandler = new Log4jHandler(monitor, os, false);
logHandler.addForbiddenToken(obj.getLoginResult().getAccessToken(), "<access token>");
logHandler.addForbiddenToken(obj.getLoginResult().getSession(), "<session>");
logHandler.addForbiddenToken(obj.getLoginResult().getUserId(), "<uuid>");
logHandler.addForbiddenToken("Setting user: " + obj.getLoginResult().getUserName(), "<player>");
logHandler.start();
} catch(Exception e) {
HMCLog.err("", e);
}
@@ -128,7 +129,7 @@ public class LaunchingUIDaemon {
noExitThisTime = true;
});
}
static LauncherVisibility unpackProcessMonitor(Object obj) {
GameLauncher launcher = ((GameLauncher) ((ProcessMonitor) obj).getTag());
HMCLGameLauncher.GameLauncherTag tag = (HMCLGameLauncher.GameLauncherTag) launcher.getTag();
@@ -161,9 +162,9 @@ public class LaunchingUIDaemon {
((HMCLGameLauncher.GameLauncherTag) value.getTag()).state = 2;
}, MainFrame.INSTANCE::failed, Settings.getInstance().getAuthenticator().getPassword());
}
class PrintlnProcessor implements Consumer<PrintlnEvent> {
GameLauncher launcher;
PipedOutputStream os;
@@ -174,25 +175,24 @@ public class LaunchingUIDaemon {
@Override
public void accept(PrintlnEvent t) {
if (!t.isError())
try {
os.write((t.getLine() + C.LINE_SEPARATOR).replace("log4j:Event", "log4j_Event").replace("log4j:Message", "log4j_Message").getBytes());
os.flush();
} catch(IOException e) {
HMCLog.err("", e);
}
String log = t.getLine();
if (!t.isError() && logHandler != null) {
logHandler.newLogLine(log + C.LINE_SEPARATOR);
}
else System.err.println(t.getLine());
HMCLGameLauncher.GameLauncherTag tag = (HMCLGameLauncher.GameLauncherTag) launcher.getTag();
LauncherVisibility l = tag.launcherVisibility;
if (t.getLine().contains("LWJGL Version: ") && l != LauncherVisibility.KEEP)
if (l != LauncherVisibility.HIDE_AND_REOPEN)
MainFrame.INSTANCE.dispose();
else { // If current state is 'hide and reopen', closes the main window and reset the state to normal.
MainFrame.INSTANCE.setVisible(false);
HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(launcher, LaunchingState.Done));
}
SwingUtilities.invokeLater(() -> {
if (l != LauncherVisibility.HIDE_AND_REOPEN)
MainFrame.INSTANCE.dispose();
else { // If current state is 'hide and reopen', closes the main window and reset the state to normal.
MainFrame.INSTANCE.setVisible(false);
HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(launcher, LaunchingState.Done));
}
});
}
}
private static final Consumer<LaunchingStateChangedEvent> LAUNCHING_STATE_CHANGED = t -> {
@@ -231,13 +231,10 @@ public class LaunchingUIDaemon {
private void checkExit(LauncherVisibility v) {
if (v == LauncherVisibility.HIDE_AND_REOPEN) {
HMCLog.log("Launcher will not exit now.");
MainFrame.INSTANCE.setVisible(true);
} else if (v != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible() && !noExitThisTime) {
HMCLog.log("Launcher will exit now.");
System.exit(0);
} else {
HMCLog.log("Launcher will not exit now.");
noExitThisTime = false;
}
}
@@ -253,5 +250,5 @@ public class LaunchingUIDaemon {
}
MainFrame.INSTANCE.closeMessage();
};
}
@@ -252,7 +252,7 @@ public class LogWindow extends javax.swing.JFrame {
}//GEN-LAST:event_btnClearActionPerformed
private void btnCopyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCopyActionPerformed
Utils.setClipborad(this.txtLog.getText());
Utils.setClipboard(this.txtLog.getText());
}//GEN-LAST:event_btnCopyActionPerformed
private void btnContactActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnContactActionPerformed
@@ -69,7 +69,6 @@ import org.jackhuang.hmcl.api.auth.IAuthenticator;
import org.jackhuang.hmcl.api.ui.Theme;
import org.jackhuang.hmcl.api.ui.TopTabPage;
/**
*
* @author huangyuhui
@@ -256,7 +255,7 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
realPanel.setBounds(1, 0, 800, 511);
add(realPanel);
reloadColor(Settings.getInstance().getTheme());
}
@@ -396,11 +395,10 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
public void reloadColor(Theme t) {
if (isShowedMessage)
return;
for (Map.Entry<String, String> entry : t.settings.entrySet()) {
for (Map.Entry<String, String> entry : t.settings.entrySet())
if (entry.getValue().startsWith("#"))
UIManager.put(entry.getKey(), GraphicsUtils.getWebColor(entry.getValue()));
}
initBorderColor();
if (border != null)
border.setColor(borderColor);
@@ -423,14 +421,14 @@ public final class MainFrame extends DraggableFrame implements IRepaint {
@Override
public void paint(Graphics g) {
if (!enableShadow)
int off = enableShadow ? 16 : 0;
int width = this.getWidth();
int height = this.getHeight();
int contentWidth = width - off - off;
int contentHeight = height - off - off;
if (!enableShadow || contentWidth <= 0 || contentHeight <= 0)
paintImpl(g);
else {
int off = enableShadow ? 16 : 0;
int width = this.getWidth();
int height = this.getHeight();
int contentWidth = width - off - off;
int contentHeight = height - off - off;
BufferedImage contentImage = new BufferedImage(contentWidth,
contentHeight, Transparency.OPAQUE);
Graphics2D contentG2d = contentImage.createGraphics();
@@ -39,7 +39,7 @@ public class HMCLGameProvider extends MinecraftVersionManager<HMCLMinecraftServi
public File getLibraryFile(MinecraftVersion version, IMinecraftLibrary lib) {
VersionSetting vs = service.getProfile().getVersionSetting(version.id);
File self = super.getLibraryFile(version, lib);
if (self.exists() || (vs != null && service.getProfile().isNoCommon()))
if (self == null || self.exists() || (vs != null && service.getProfile().isNoCommon()))
return self;
else
return lib.getFilePath(new File(Settings.getInstance().getCommonpath()));
@@ -18,6 +18,7 @@
package org.jackhuang.hmcl.util;
import java.util.List;
import java.util.Map;
import org.jackhuang.hmcl.Main;
import org.jackhuang.hmcl.api.auth.UserProfileProvider;
import org.jackhuang.hmcl.api.game.LaunchOptions;
@@ -36,16 +37,10 @@ public class HMCLMinecraftLoader extends MinecraftLoader {
}
@Override
protected void appendJVMArgs(List<String> list) {
super.appendJVMArgs(list);
list.add("-Dminecraft.launcher.version=" + Main.LAUNCHER_VERSION);
list.add("-Dminecraft.launcher.brand=" + Main.LAUNCHER_NAME);
boolean flag = false;
for (String s : list) if (s.contains("-Dlog4j.configurationFile=")) flag = true;
if (!flag) {
list.add("-Dlog4j.configurationFile=" + Main.LOG4J_FILE.getAbsolutePath());
}
protected Map<String, String> getConfigurations() {
Map<String, String> map = super.getConfigurations();
map.put("${launcher_version}", Main.LAUNCHER_VERSION);
map.put("${launcher_name}", Main.LAUNCHER_NAME);
return map;
}
}
@@ -17,14 +17,13 @@
*/
package org.jackhuang.hmcl.util;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.process.JavaProcessStoppedEvent;
import org.jackhuang.hmcl.api.func.Consumer;
@@ -32,11 +31,8 @@ import org.jackhuang.hmcl.ui.LogWindow;
import org.jackhuang.hmcl.util.log.Level;
import org.jackhuang.hmcl.util.sys.ProcessMonitor;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
/**
*
@@ -44,50 +40,48 @@ import org.xml.sax.helpers.XMLReaderFactory;
*/
public class Log4jHandler extends Thread implements Consumer<JavaProcessStoppedEvent> {
XMLReader reader;
ProcessMonitor monitor;
PipedInputStream inputStream;
PipedOutputStream outputStream;
List<Pair<String, String>> forbiddenTokens = new LinkedList<>();
AtomicBoolean interrupted = new AtomicBoolean(false);
boolean enabled = true;
public Log4jHandler(ProcessMonitor monitor, PipedOutputStream outputStream) throws ParserConfigurationException, IOException, SAXException {
reader = XMLReaderFactory.createXMLReader();
inputStream = new PipedInputStream(outputStream);
this.outputStream = outputStream;
public Log4jHandler(ProcessMonitor monitor, PipedOutputStream outputStream, boolean enabled) {
this.monitor = monitor;
this.enabled = enabled;
HMCLApi.EVENT_BUS.channel(JavaProcessStoppedEvent.class).register((Consumer<JavaProcessStoppedEvent>) this);
}
public void addForbiddenToken(String token, String replacement) {
forbiddenTokens.add(new Pair<>(token, replacement));
}
@Override
public void run() {
try {
outputStream.write("<output>".getBytes());
outputStream.flush();
reader.setContentHandler(new Log4jHandlerImpl());
reader.parse(new InputSource(inputStream));
} catch (SAXException | IOException e) {
}
}
@Override
public void accept(JavaProcessStoppedEvent t) {
if (t.getSource() == monitor) {
try {
outputStream.write("</output>".getBytes());
outputStream.close();
} catch (IOException ignore) { // won't happen
throw new Error(ignore);
}
}
}
/**
* Always use this instance method to write to the log,
* to make sure only this Thread writes to the PipedOutputStream.
*
* It will also flush the buffer, directly after write.
*
* This prevents java.io.IOException: Read end dead
* See also https://techtavern.wordpress.com/2008/07/16/whats-this-ioexception-write-end-dead/
*
* @param content The content to be written to the log
*/
public Future newLogLine(String content) {
printlnImpl(content, Level.guessLevel(content));
return null;
}
class Log4jHandlerImpl extends DefaultHandler {
private final SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
String date = "", thread = "", logger = "";
@@ -104,7 +98,7 @@ public class Log4jHandler extends Thread implements Consumer<JavaProcessStoppedE
date = df.format(d);
try {
l = Level.valueOf(attributes.getValue("level"));
} catch(IllegalArgumentException e) {
} catch (IllegalArgumentException e) {
l = Level.INFO;
}
thread = attributes.getValue("thread");
@@ -133,7 +127,8 @@ public class Log4jHandler extends Thread implements Consumer<JavaProcessStoppedE
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String line = new String(ch, start, length);
if (line.trim().isEmpty()) return;
if (line.trim().isEmpty())
return;
if (readingMessage)
message.append(line).append(C.LINE_SEPARATOR);
else
@@ -141,10 +136,14 @@ public class Log4jHandler extends Thread implements Consumer<JavaProcessStoppedE
}
public void println(String message, Level l) {
for (Pair<String, String> entry : forbiddenTokens)
message = message.replace(entry.key, entry.value);
if (LogWindow.outputStream != null)
LogWindow.outputStream.log(message, l);
printlnImpl(message, l);
}
}
private void printlnImpl(String message, Level l) {
for (Pair<String, String> entry : forbiddenTokens)
message = message.replace(entry.key, entry.value);
if (LogWindow.outputStream != null)
LogWindow.outputStream.log(message, l);
}
}
@@ -17,20 +17,19 @@
*/
package org.jackhuang.hmcl.util.upgrade;
import com.google.gson.JsonSyntaxException;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
@@ -45,14 +44,13 @@ import org.jackhuang.hmcl.core.MCUtils;
import org.jackhuang.hmcl.util.task.Task;
import org.jackhuang.hmcl.util.task.TaskWindow;
import org.jackhuang.hmcl.util.net.FileDownloadTask;
import org.jackhuang.hmcl.util.ArrayUtils;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.util.UpdateChecker;
import org.jackhuang.hmcl.util.Utils;
import org.jackhuang.hmcl.api.VersionNumber;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.sys.IOUtils;
import org.jackhuang.hmcl.util.sys.Java;
import org.jackhuang.hmcl.util.sys.OS;
/**
@@ -61,45 +59,49 @@ import org.jackhuang.hmcl.util.sys.OS;
*/
public class AppDataUpgrader extends IUpgrader {
private boolean launchNewerVersion(String[] args, File jar) throws IOException, PrivilegedActionException {
private void launchNewerVersion(List<String> args, File jar) throws IOException, ReflectiveOperationException {
try (JarFile jarFile = new JarFile(jar)) {
String mainClass = jarFile.getManifest().getMainAttributes().getValue("Main-Class");
if (mainClass != null) {
ArrayList<String> al = new ArrayList<>(Arrays.asList(args));
al.add("--noupdate");
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
new URLClassLoader(new URL[] { jar.toURI().toURL() },
URLClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass)
.getMethod("main", String[].class).invoke(null, new Object[] { al.toArray(new String[0]) });
return null;
});
return true;
if (mainClass == null)
throw new ClassNotFoundException("Main-Class not found in manifest");
ArrayList<String> al = new ArrayList<>(args);
al.add("--noupdate");
ClassLoader pre = Thread.currentThread().getContextClassLoader();
try {
ClassLoader now = new URLClassLoader(new URL[] { jar.toURI().toURL() }, ClassLoader.getSystemClassLoader().getParent());
Thread.currentThread().setContextClassLoader(now);
now.loadClass(mainClass).getMethod("main", String[].class).invoke(null, new Object[] { al.toArray(new String[0]) });
} finally {
Thread.currentThread().setContextClassLoader(pre);
}
}
return false;
}
@Override
public void parseArguments(VersionNumber nowVersion, String[] args) {
public void parseArguments(VersionNumber nowVersion, List<String> args) {
File f = AppDataUpgraderPackGzTask.HMCL_VER_FILE;
if (!ArrayUtils.contains(args, "--noupdate"))
if (!args.contains("--noupdate"))
try {
if (f.exists()) {
Map<String, String> m = C.GSON.fromJson(FileUtils.read(f), Map.class);
Map<String, String> m = C.GSON.fromJson(FileUtils.read(f), new TypeToken<Map<String, String>>() {
}.getType());
String s = m.get("ver");
if (s != null && VersionNumber.check(s).compareTo(nowVersion) > 0) {
if (s != null && VersionNumber.asVersion(s).compareTo(nowVersion) > 0) {
String j = m.get("loc");
if (j != null) {
File jar = new File(j);
if (jar.exists() && launchNewerVersion(args, jar))
if (jar.exists()) {
launchNewerVersion(args, jar);
System.exit(0);
}
}
}
}
} catch (JsonSyntaxException ex) {
} catch (JsonParseException ex) {
f.delete();
} catch (IOException | PrivilegedActionException t) {
HMCLog.err("Failed to execute newer version application", t);
} catch (IOException | ReflectiveOperationException t) {
HMCLog.err("Unable to execute newer version application", t);
AppDataUpgraderPackGzTask.HMCL_VER_FILE.delete(); // delete version json, let HMCL re-download the newer version.
}
}
@@ -107,53 +109,71 @@ public class AppDataUpgrader extends IUpgrader {
public void accept(SimpleEvent<VersionNumber> event) {
final VersionNumber version = event.getValue();
((UpdateChecker) event.getSource()).requestDownloadLink().reg(map -> {
if (MessageBox.show(C.i18n("update.newest_version") + version.firstVer + "." + version.secondVer + "." + version.thirdVer + "\n"
boolean flag = false;
for (Java java : Java.JAVA)
if (java.getName().startsWith("1.8") || java.getName().startsWith("9") || java.getName().startsWith("10")) {
flag = true;
break;
}
if (!flag) {
MessageBox.show("请安装 Java 8");
try {
java.awt.Desktop.getDesktop().browse(new URI("https://java.com"));
} catch (URISyntaxException | IOException e) {
Utils.setClipboard("https://java.com");
MessageBox.show(C.i18n("update.no_browser"));
}
}
if (MessageBox.show(C.i18n("update.newest_version") + version.toString() + "\n"
+ C.i18n("update.should_open_link"),
MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION)
if (map != null && map.containsKey("jar") && !StrUtils.isBlank(map.get("jar")))
try {
String hash = null;
if (map.containsKey("jarsha1"))
hash = map.get("jarsha1");
if (TaskWindow.factory().append(new AppDataUpgraderJarTask(map.get("jar"), version.version, hash)).execute()) {
new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderJarTask.getSelf(version.version).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start();
System.exit(0);
}
} catch (IOException ex) {
Main.LOGGER.log(Level.SEVERE, "Failed to create upgrader", ex);
}
else if (map != null && map.containsKey("pack") && !StrUtils.isBlank(map.get("pack")))
if (map != null && map.containsKey("pack") && !StrUtils.isBlank(map.get("pack")))
try {
String hash = null;
if (map.containsKey("packsha1"))
hash = map.get("packsha1");
if (TaskWindow.factory().append(new AppDataUpgraderPackGzTask(map.get("pack"), version.version, hash)).execute()) {
new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.version).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start();
if (TaskWindow.factory().append(new AppDataUpgraderPackGzTask(map.get("pack"), version.toString(), hash)).execute()) {
new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.toString()).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start();
System.exit(0);
}
} catch (IOException ex) {
HMCLog.err("Failed to create upgrader", ex);
}
else if (map != null && map.containsKey("jar") && !StrUtils.isBlank(map.get("jar")))
try {
String hash = null;
if (map.containsKey("jarsha1"))
hash = map.get("jarsha1");
if (TaskWindow.factory().append(new AppDataUpgraderJarTask(map.get("jar"), version.toString(), hash)).execute()) {
new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderJarTask.getSelf(version.toString()).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start();
System.exit(0);
}
} catch (IOException ex) {
Main.LOGGER.log(Level.SEVERE, "Failed to create upgrader", ex);
}
else {
String url = C.URL_PUBLISH;
if (map != null)
if (map.containsKey(OS.os().checked_name))
url = map.get(OS.os().checked_name);
else if (map.containsKey(OS.UNKOWN.checked_name))
url = map.get(OS.UNKOWN.checked_name);
if (map.containsKey(OS.os().checkedName))
url = map.get(OS.os().checkedName);
else if (map.containsKey(OS.UNKNOWN.checkedName))
url = map.get(OS.UNKNOWN.checkedName);
if (url == null)
url = C.URL_PUBLISH;
try {
java.awt.Desktop.getDesktop().browse(new URI(url));
} catch (URISyntaxException | IOException e) {
HMCLog.err("Failed to browse uri: " + url, e);
Utils.setClipborad(url);
Utils.setClipboard(url);
MessageBox.show(C.i18n("update.no_browser"));
}
}
}).execute();
}
;
public static class AppDataUpgraderPackGzTask extends Task {
public static final File BASE_FOLDER = MCUtils.getWorkingDirectory("hmcl");
@@ -175,7 +195,7 @@ public class AppDataUpgrader extends IUpgrader {
@Override
public Collection<Task> getDependTasks() {
return Arrays.asList(new FileDownloadTask(downloadLink, tempFile, expectedHash));
return Collections.singleton(new FileDownloadTask(downloadLink, tempFile, expectedHash));
}
@Override
@@ -194,8 +214,9 @@ public class AppDataUpgrader extends IUpgrader {
if (!f.createNewFile())
throw new IOException("Failed to create new file: " + f);
try (JarOutputStream jos = new JarOutputStream(FileUtils.openOutputStream(f))) {
Pack200.newUnpacker().unpack(new GZIPInputStream(FileUtils.openInputStream(tempFile)), jos);
try (GZIPInputStream in = new GZIPInputStream(FileUtils.openInputStream(tempFile));
JarOutputStream jos = new JarOutputStream(FileUtils.openOutputStream(f))) {
Pack200.newUnpacker().unpack(in, jos);
}
json.put("ver", newestVersion);
json.put("loc", f.getAbsolutePath());
@@ -231,7 +252,7 @@ public class AppDataUpgrader extends IUpgrader {
@Override
public Collection<Task> getDependTasks() {
return Arrays.asList(new FileDownloadTask(downloadLink, tempFile, expectedHash));
return Collections.singleton(new FileDownloadTask(downloadLink, tempFile, expectedHash));
}
@Override
@@ -17,6 +17,7 @@
*/
package org.jackhuang.hmcl.util.upgrade;
import java.util.List;
import org.jackhuang.hmcl.api.event.SimpleEvent;
import org.jackhuang.hmcl.api.VersionNumber;
import org.jackhuang.hmcl.api.func.Consumer;
@@ -35,7 +36,7 @@ public abstract class IUpgrader implements Consumer<SimpleEvent<VersionNumber>>
* @param nowVersion now launcher version
* @param args Application CommandLine Arguments
*/
public abstract void parseArguments(VersionNumber nowVersion, String[] args);
public abstract void parseArguments(VersionNumber nowVersion, List<String> args);
/**
* Just download the new app.
@@ -1,65 +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.hmcl.util.upgrade;
import java.io.File;
import java.io.IOException;
import org.jackhuang.hmcl.api.event.SimpleEvent;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.task.TaskWindow;
import org.jackhuang.hmcl.util.net.FileDownloadTask;
import org.jackhuang.hmcl.util.ArrayUtils;
import org.jackhuang.hmcl.api.VersionNumber;
import org.jackhuang.hmcl.util.sys.FileUtils;
import org.jackhuang.hmcl.util.sys.IOUtils;
/**
*
* @author huangyuhui
*/
public class NewFileUpgrader extends IUpgrader {
@Override
public void parseArguments(VersionNumber nowVersion, String[] args) {
int i = ArrayUtils.indexOf(args, "--removeOldLauncher");
if (i != -1 && i < args.length - 1) {
File f = new File(args[i + 1]);
if (f.exists())
f.deleteOnExit();
}
}
@Override
public void accept(SimpleEvent<VersionNumber> event) {
String str = requestDownloadLink();
File newf = new File(FileUtils.getName(str));
if (TaskWindow.factory().append(new FileDownloadTask(str, newf)).execute()) {
try {
new ProcessBuilder(new String[] { newf.getCanonicalPath(), "--removeOldLauncher", IOUtils.getRealPath() }).directory(new File("").getAbsoluteFile()).start();
} catch (IOException ex) {
HMCLog.err("Failed to start new app", ex);
}
System.exit(0);
}
}
private String requestDownloadLink() {
return null;
}
}
@@ -15,7 +15,7 @@
* 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.hmcl.util;
package org.jackhuang.hmcl.util.upgrade;
import org.jackhuang.hmcl.util.ui.MessageBox;
import org.jackhuang.hmcl.api.VersionNumber;
@@ -25,9 +25,13 @@ import com.google.gson.JsonSyntaxException;
import java.io.IOException;
import org.jackhuang.hmcl.api.HMCLog;
import java.util.Map;
import org.jackhuang.hmcl.Main;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.SimpleEvent;
import org.jackhuang.hmcl.api.event.OutOfDateEvent;
import org.jackhuang.hmcl.util.AbstractSwingWorker;
import org.jackhuang.hmcl.util.C;
import org.jackhuang.hmcl.util.IUpdateChecker;
/**
*
@@ -58,15 +62,15 @@ public final class UpdateChecker implements IUpdateChecker {
@Override
protected void work() throws Exception {
if (value == null) {
versionString = NetUtils.get("http://huangyuhui.duapp.com/info.php?type=" + type);
value = VersionNumber.check(versionString);
versionString = NetUtils.get("http://hmcl.huangyuhui.net/api/update?version=" + Main.LAUNCHER_VERSION);
value = VersionNumber.asVersion(versionString);
}
if (value == null) {
HMCLog.warn("Failed to check update...");
if (showMessage)
MessageBox.show(C.i18n("update.failed"));
} else if (VersionNumber.isOlder(base, value))
} else if (base.compareTo(value) < 0)
outOfDate = true;
if (outOfDate)
publish(value);
@@ -86,7 +90,7 @@ public final class UpdateChecker implements IUpdateChecker {
protected void work() throws Exception {
if (download_link == null)
try {
download_link = C.GSON.<Map<String, String>>fromJson(NetUtils.get("http://huangyuhui.duapp.com/update_link.php?type=" + type), Map.class);
download_link = C.GSON.<Map<String, String>>fromJson(NetUtils.get("http://hmcl.huangyuhui.net/api/update_link?version=" + Main.LAUNCHER_VERSION), Map.class);
} catch (JsonSyntaxException | IOException e) {
HMCLog.warn("Failed to get update link.", e);
}
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="SysOut" target="SYSTEM_OUT">
<LegacyXMLLayout />
<XMLLayout />
</Console>
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
<Policies>
<TimeBasedTriggeringPolicy />
<OnStartupTriggeringPolicy />
</Policies>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Root level="info">
<filters>
<MarkerFilter marker="NETWORK_PACKETS" onMatch="DENY" onMismatch="NEUTRAL" />
</filters>
<AppenderRef ref="SysOut"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
@@ -0,0 +1,59 @@
/*
* 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.hmcl.api;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* If a version string contains '-', a {@link ComposedVersionNumber}
* will be generated.
*
* Formats like 1.7.10-OptiFine, 1.12.2-Forge
*
* @author huangyuhui
*/
public final class ComposedVersionNumber extends VersionNumber {
List<VersionNumber> composed;
public static boolean isComposedVersionNumber(String version) {
return version.contains("-");
}
ComposedVersionNumber(String version) {
String slice[] = version.split("-");
composed = new LinkedList<>();
for (String str : slice) composed.add(VersionNumber.asVersion(str));
}
@Override
public int hashCode() {
return Objects.hash(composed);
}
@Override
public String toString() {
List<String> seq = new LinkedList<>();
for (VersionNumber str : composed)
seq.add(str.toString());
return String.join("-", seq);
}
}
@@ -0,0 +1,72 @@
/*
* 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.hmcl.api;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
/**
* If a version string formats x.x.x.x, a {@code IntVersionNumber}
* will be generated.
*
* @author huangyuhui
*/
public final class IntVersionNumber extends VersionNumber {
final List<Integer> version;
public static boolean isIntVersionNumber(String version) {
if (version.contains("..")) return false;
if (version.trim().isEmpty()) return false;
for (char ch : version.toCharArray())
if (ch != '.' && (ch < '0' || ch > '9'))
return false;
return true;
}
IntVersionNumber(String version) {
if (!isIntVersionNumber(version))
throw new IllegalArgumentException("The version " + version + " is malformed, only dots and digits are allowed.");
String[] slice = version.split("\\.");
List<Integer> versions = new LinkedList<>();
for (String str : slice) versions.add(Integer.parseInt(str));
while (!versions.isEmpty() && versions.get(versions.size() - 1) == 0)
versions.remove(versions.size() - 1);
this.version = versions;
}
public int get(int index) {
return version.get(index);
}
@Override
public int hashCode() {
return Objects.hash(version);
}
@Override
public String toString() {
List<String> seq = new LinkedList<>();
for (int str : version)
seq.add(Integer.toString(str));
return String.join(".", seq);
}
}
@@ -0,0 +1,51 @@
/*
* 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.hmcl.api;
import java.util.Objects;
/**
* If a version string contains alphabets, a {@code StringVersionNumber}
* will be constructed.
*
* @author huangyuhui
*/
public final class StringVersionNumber extends VersionNumber {
private final String version;
StringVersionNumber(String version) {
Objects.requireNonNull(version);
this.version = version;
}
public String getVersion() {
return version;
}
@Override
public int hashCode() {
return version.hashCode();
}
@Override
public String toString() {
return version;
}
}
@@ -17,100 +17,78 @@
*/
package org.jackhuang.hmcl.api;
import java.util.*;
/**
* The formatted version number represents a version string.
*
* @author huangyuhui
*/
public final class VersionNumber implements Comparable<VersionNumber> {
public abstract class VersionNumber implements Comparable<VersionNumber> {
public final byte firstVer, secondVer, thirdVer;
public final String version;
public VersionNumber(byte a, byte b, byte c) {
this(a, b, c, null);
}
public VersionNumber(byte a, byte b, byte c, String version) {
firstVer = a;
secondVer = b;
thirdVer = c;
this.version = version;
public static VersionNumber asVersion(String version) {
Objects.requireNonNull(version);
if (ComposedVersionNumber.isComposedVersionNumber(version))
return new ComposedVersionNumber(version);
else if (IntVersionNumber.isIntVersionNumber(version))
return new IntVersionNumber(version);
else
return new StringVersionNumber(version);
}
@Override
public String toString() {
return "" + firstVer + '.' + secondVer + '.' + thirdVer;
}
public static VersionNumber check(String data) {
while (!data.isEmpty() && ((data.charAt(0) < '0' || data.charAt(0) > '9') && data.charAt(0) != '.'))
data = data.substring(1);
if (data.isEmpty())
return null;
VersionNumber ur;
String[] ver = data.split("\\.");
if (ver.length >= 3) {
byte v1, v2, v3;
try {
v1 = Byte.parseByte(ver[0]);
v2 = Byte.parseByte(ver[1]);
v3 = Byte.parseByte(ver[2]);
ur = new VersionNumber(v1, v2, v3, data);
return ur;
} catch (Exception e) {
HMCLog.warn("Failed to parse the version", e);
}
}
return null;
}
public static boolean isOlder(VersionNumber a, VersionNumber b) {
if (a.firstVer < b.firstVer)
return true;
else if (a.firstVer == b.firstVer)
if (a.secondVer < b.secondVer)
return true;
else if (a.secondVer == b.secondVer)
if (a.thirdVer < b.thirdVer)
return true;
return false;
}
@Override
public int hashCode() {
int hash = 3;
hash = 83 * hash + this.firstVer;
hash = 83 * hash + this.secondVer;
hash = 83 * hash + this.thirdVer;
return hash;
public int compareTo(VersionNumber o) {
return COMPARATOR.compare(this, o);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final VersionNumber other = (VersionNumber) obj;
if (this.firstVer != other.firstVer)
return false;
if (this.secondVer != other.secondVer)
return false;
if (this.thirdVer != other.thirdVer)
return false;
return true;
}
@Override
public int compareTo(VersionNumber o) {
if (isOlder(this, o))
return -1;
else if (isOlder(o, this))
return 1;
else
return 0;
if (obj == null) return false;
else return toString().equals(obj.toString());
}
}
private static <T extends Comparable<T>> int compareTo(List<T> a, List<T> b) {
int i;
for (i = 0; i < a.size() && i < b.size(); ++i) {
int res = a.get(i).compareTo(b.get(i));
if (res != 0)
return res;
}
if (i < a.size()) return 1;
else if (i < b.size()) return -1;
else return 0;
}
public static final Comparator<VersionNumber> COMPARATOR = new Comparator<VersionNumber>() {
@Override
public int compare(VersionNumber a, VersionNumber b) {
if (a == null || b == null)
return 0;
else {
if (a instanceof ComposedVersionNumber) {
if (b instanceof ComposedVersionNumber)
return compareTo(((ComposedVersionNumber) a).composed, ((ComposedVersionNumber) b).composed);
else
return compare(((ComposedVersionNumber) a).composed.get(0), b);
} else if (a instanceof IntVersionNumber) {
if (b instanceof ComposedVersionNumber)
return -compare(b, a);
else if (b instanceof IntVersionNumber)
return compareTo(((IntVersionNumber) a).version, ((IntVersionNumber) b).version);
else if (b instanceof StringVersionNumber)
return a.toString().compareTo(b.toString());
} else if (a instanceof StringVersionNumber) {
if (b instanceof ComposedVersionNumber)
return -compare(b, a);
else if (b instanceof StringVersionNumber)
return a.toString().compareTo(b.toString());
else if (b instanceof IntVersionNumber)
return a.toString().compareTo(b.toString());
}
throw new IllegalArgumentException("Unrecognized VersionNumber " + a + " and " + b);
}
}
};
}
@@ -95,9 +95,9 @@ public class AssetsMojangLoader extends IAssetsHandler {
@Override
public boolean isVersionAllowed(String formattedVersion) {
VersionNumber ur = VersionNumber.check(formattedVersion);
VersionNumber ur = VersionNumber.asVersion(formattedVersion);
if (ur == null)
return false;
return VersionNumber.check("1.6.0").compareTo(ur) <= 0;
return VersionNumber.asVersion("1.6.0").compareTo(ur) <= 0;
}
}
@@ -75,6 +75,7 @@ public final class YggdrasilAuthenticator extends AbstractAuthenticator {
if (sel == -1)
throw new AuthenticationException("No selection");
selectedProfile = profiles[sel];
ua.setSelectedProfile(profiles[sel]);
username = names[sel];
} else
username = MessageBox.showInputDialog(C.i18n("login.no_charactor"));
@@ -81,7 +81,7 @@ public class GameProfile {
if (!(json instanceof JsonObject))
throw new JsonParseException("The json element is not a JsonObject.");
JsonObject object = (JsonObject) json;
UUID id = object.has("id") ? (UUID) context.deserialize(object.get("id"), UUID.class) : null;
UUID id = object.has("id") ? context.deserialize(object.get("id"), UUID.class) : null;
String name = object.has("name") ? object.getAsJsonPrimitive("name").getAsString() : null;
return new GameProfile(id, name);
}
@@ -71,8 +71,7 @@ public class PropertyMap extends HashMap<String, Property> {
for (Map.Entry<String, JsonElement> entry : object.entrySet())
if (entry.getValue() instanceof JsonArray)
for (JsonElement element : (JsonArray) entry.getValue())
result.put(entry.getKey(),
new Property((String) entry.getKey(), element.getAsString()));
result.put(entry.getKey(), new Property(entry.getKey(), element.getAsString()));
} else if ((json instanceof JsonArray))
for (JsonElement element : (JsonArray) json)
if ((element instanceof JsonObject)) {
@@ -36,7 +36,7 @@ public enum UserType {
}
public static UserType byName(String name) {
return (UserType) BY_NAME.get(name.toLowerCase());
return BY_NAME.get(name.toLowerCase());
}
public static UserType byLegacy(boolean isLegacy) {
@@ -27,6 +27,7 @@ import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import org.jackhuang.hmcl.util.ArrayUtils;
import org.jackhuang.hmcl.util.C;
@@ -87,6 +88,13 @@ public class YggdrasilAuthentication {
public GameProfile getSelectedProfile() {
return this.selectedProfile;
}
public void setSelectedProfile(GameProfile profile) {
if (profiles != null)
for (GameProfile p : profiles)
if (Objects.equals(profile, p))
selectedProfile = profile;
}
public String getUserId() {
return this.userid;
@@ -133,7 +141,7 @@ public class YggdrasilAuthentication {
if (StrUtils.isNotBlank(getAuthenticatedToken())) {
if (StrUtils.isBlank(getUserId()))
if (StrUtils.isBlank(username))
if (StrUtils.isNotBlank(username))
userid = username;
else
throw new AuthenticationException(C.i18n("login.invalid_uuid_and_username"));
@@ -57,7 +57,7 @@ public class MinecraftDownloadService extends IMinecraftDownloadService {
for (IMinecraftLibrary l : v.getLibraries())
if (l != null && l.allow()) {
File ff = service.version().getLibraryFile(mv, l);
if (!ff.exists() && l.getDownloadURL(service.getDownloadType().name()) != null) {
if (ff != null && !ff.exists() && l.getDownloadURL(service.getDownloadType().name()) != null) {
String libURL = l.getDownloadURL(service.getDownloadType().name());
if (libURL != null)
downloadLibraries.add(new DownloadLibraryJob(l, libURL, ff));
@@ -66,7 +66,7 @@ public class LiteLoaderInstaller extends Task implements PreviousResultRegistrar
mv.libraries = new ArrayList<>(Arrays.asList(version.libraries));
MinecraftLibrary ml = new MinecraftLibrary("com.mumfrey:liteloader:" + version.selfVersion);
ml.url = "http://dl.liteloader.com/versions";
ml.url = "http://dl.liteloader.com/versions/";
mv.libraries.add(0, ml);
// We use options from the old vanilla version.
@@ -86,12 +86,9 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
appendJVMArgs(res);
if (jv == null || !jv.isEarlyAccess()) {
if (OS.os() == OS.WINDOWS)
res.add("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump");
if (jv != null && jv.getParsedVersion() >= JdkVersion.JAVA_17)
res.add("-XX:+UseG1GC");
else
res.add("-Xincgc");
res.add("-XX:-UseAdaptiveSizePolicy");
res.add("-XX:-OmitStackTraceInFastThrow");
@@ -131,7 +128,6 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
res.add(a);
}
res.add("-Djava.library.path=" + service.version().getDecompressNativesToLocation(version).getAbsolutePath());
res.add("-Dfml.ignoreInvalidMinecraftCertificates=true");
res.add("-Dfml.ignorePatchDiscrepancies=true");
@@ -150,13 +146,6 @@ public abstract class AbstractMinecraftLoader implements IMinecraftLoader {
HMCLog.log("On making launcher args.");
if (StrUtils.isNotBlank(options.getHeight()) && StrUtils.isNotBlank(options.getWidth())) {
res.add("--height");
res.add(options.getHeight());
res.add("--width");
res.add(options.getWidth());
}
String serverIp = options.getServerIp();
if (StrUtils.isNotBlank(serverIp)) {
String[] args = serverIp.split(":");
@@ -19,7 +19,6 @@ package org.jackhuang.hmcl.core.launch;
import org.jackhuang.hmcl.api.game.LaunchOptions;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import org.jackhuang.hmcl.core.download.DownloadLibraryJob;
import org.jackhuang.hmcl.api.auth.LoginInfo;
@@ -43,13 +42,8 @@ public class DefaultGameLauncher extends GameLauncher {
public boolean downloadLibraries(List<DownloadLibraryJob> jobs) {
final TaskWindow.TaskWindowFactory dw = TaskWindow.factory();
ParallelTask parallelTask = new ParallelTask();
HashSet<String> names = new HashSet<>();
for (DownloadLibraryJob s : jobs) {
if (names.contains(s.lib.getName()))
continue;
names.add(s.lib.getName());
for (DownloadLibraryJob s : jobs)
parallelTask.addTask(new LibraryDownloadTask(s, service.getDownloadType()));
}
dw.append(parallelTask);
boolean flag = true;
if (jobs.size() > 0)
@@ -21,8 +21,11 @@ import org.jackhuang.hmcl.api.game.LaunchOptions;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.sys.OS;
@@ -30,7 +33,8 @@ import org.jackhuang.hmcl.core.GameException;
import org.jackhuang.hmcl.api.auth.UserProfileProvider;
import org.jackhuang.hmcl.core.version.MinecraftLibrary;
import org.jackhuang.hmcl.core.service.IMinecraftService;
import org.jackhuang.hmcl.core.version.LoggingInfo;
import org.jackhuang.hmcl.core.version.Argument;
import org.jackhuang.hmcl.core.version.Arguments;
/**
*
@@ -40,10 +44,28 @@ public class MinecraftLoader extends AbstractMinecraftLoader {
public MinecraftLoader(LaunchOptions p, IMinecraftService provider, UserProfileProvider lr) throws GameException {
super(p, provider, p.getLaunchVersion(), lr);
if (version.arguments == null)
version.arguments = new Arguments();
if (version.arguments.game == null)
version.arguments.game = getDefaultGameArguments();
if (version.arguments.jvm == null)
version.arguments.jvm = getDefaultJVMArguments();
}
protected List<Argument> getDefaultJVMArguments() {
return Arguments.DEFAULT_JVM_ARGUMENTS;
}
protected List<Argument> getDefaultGameArguments() {
return Arguments.DEFAULT_GAME_ARGUMENTS;
}
@Override
protected void makeSelf(List<String> res) throws GameException {
String game_assets = assetProvider.provide(version, !options.isNotCheckGame());
Map<String, String> configuration = getConfigurations();
StringBuilder library = new StringBuilder("");
ArrayList<MinecraftLibrary> opt = new ArrayList<>();
for (MinecraftLibrary l : version.libraries)
@@ -67,37 +89,44 @@ public class MinecraftLoader extends AbstractMinecraftLoader {
if (!f.exists())
throw new GameException("Minecraft jar does not exist");
library.append(f.getAbsolutePath()).append(File.pathSeparator);
res.add("-cp");
res.add(library.toString().substring(0, library.length() - File.pathSeparator.length()));
String classpath = library.toString().substring(0, library.length() - File.pathSeparator.length());
configuration.put("${classpath}", classpath);
configuration.put("${natives_directory}", service.version().getDecompressNativesToLocation(version).getAbsolutePath());
configuration.put("${game_assets}", game_assets);
res.addAll(Arguments.parseArguments(version.arguments.jvm, configuration));
res.add(version.mainClass);
if (version.minecraftArguments == null)
throw new GameException(new NullPointerException("Minecraft Arguments can not be null."));
String[] splitted = StrUtils.tokenize(version.minecraftArguments);
Map<String, Boolean> features = getFeatures();
String game_assets = assetProvider.provide(version, !options.isNotCheckGame());
res.addAll(Arguments.parseArguments(version.arguments.game, configuration, features));
res.addAll(Arguments.parseStringArguments(Arrays.asList(StrUtils.tokenize(version.minecraftArguments)), configuration));
}
protected Map<String, Boolean> getFeatures() {
Map<String, Boolean> features = new HashMap<>();
features.put("has_custom_resolution", StrUtils.isNotBlank(options.getHeight()) && StrUtils.isNotBlank(options.getWidth()));
return features;
}
for (String t : splitted) {
t = t.replace("${auth_player_name}", lr.getUserName());
t = t.replace("${auth_session}", lr.getSession());
t = t.replace("${auth_uuid}", lr.getUserId());
t = t.replace("${version_name}", options.getVersionName());
t = t.replace("${profile_name}", options.getName());
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(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());
t = t.replace("${user_properties}", lr.getUserProperties());
res.add(t);
}
if (res.indexOf("--gameDir") != -1 && res.indexOf("--workDir") != -1) {
res.add("--workDir");
res.add(gameDir.getAbsolutePath());
}
protected Map<String, String> getConfigurations() {
HashMap<String, String> map = new HashMap();
map.put("${auth_player_name}", lr.getUserName());
map.put("${auth_session}", lr.getSession());
map.put("${auth_uuid}", lr.getUserId());
map.put("${version_name}", options.getVersionName());
map.put("${profile_name}", options.getName());
map.put("${version_type}", options.getType());
map.put("${game_directory}", service.version().getRunDirectory(version.id).getAbsolutePath());
map.put("${assets_root}", service.asset().getAssets(version.getAssetsIndex().getId()).getAbsolutePath());
map.put("${auth_access_token}", lr.getAccessToken());
map.put("${user_type}", lr.getUserType());
map.put("${assets_index_name}", version.getAssetsIndex().getId());
map.put("${user_properties}", lr.getUserProperties());
map.put("${resolution_width}", options.getWidth());
map.put("${resolution_height}", options.getHeight());
map.put("${natives_directory}", service.version().getDecompressNativesToLocation(version).getAbsolutePath());
return map;
}
@Override
@@ -112,15 +141,17 @@ public class MinecraftLoader extends AbstractMinecraftLoader {
} catch (IOException e) {
HMCLog.err("Failed to append jvm arguments when searching for asset objects.", e);
}
list.add("-Dminecraft.client.jar=" + version.getJar(service.baseDirectory()).getAbsolutePath());
/*
if (version.logging != null && version.logging.containsKey("client")) {
LoggingInfo logging = version.logging.get("client");
File file = service.asset().getLoggingObject(version.getAssetsIndex().getId(), logging);
if (file.exists())
list.add(logging.argument.replace("${path}", file.getAbsolutePath()));
}
*/
}
private final IAssetProvider DEFAULT_ASSET_PROVIDER = (t, allow) -> {
@@ -82,7 +82,7 @@ public class MinecraftModService extends IMinecraftModService {
HMCLog.warn("Failed to make directories: " + modsFolder);
File newf = new File(modsFolder, f.getName());
FileUtils.copyFile(f, newf);
ModInfo i = ModInfo.readModInfo(f);
ModInfo i = ModInfo.readModInfo(newf);
modCache.get(id).add(i);
return true;
} catch (IOException ex) {
@@ -41,7 +41,11 @@ public abstract class AbstractMinecraftLibrary implements IMinecraftLibrary {
@Override
public String getDownloadURL(String downloadSource) {
return getDownloadInfo().getUrl(DownloadType.valueOf(downloadSource));
LibraryDownloadInfo info = getDownloadInfo();
if (info == null)
return null;
else
return info.getUrl(DownloadType.valueOf(downloadSource));
}
@Override
@@ -0,0 +1,69 @@
/*
* 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.hmcl.core.version;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
/**
*
* @author huang
*/
public interface Argument extends Cloneable {
/**
* Parse this argument in form: ${key name} or simply a string.
*
* @param keys the parse map
* @param features the map that contains some features such as 'is_demo_user', 'has_custom_resolution'
* @return parsed argument element, empty if this argument is ignored and will not be added.
*/
List<String> toString(Map<String, String> keys, Map<String, Boolean> features);
public Object clone();
public static class ArgumentSerializer implements JsonDeserializer<Argument>, JsonSerializer<Argument> {
@Override
public Argument deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonPrimitive())
return new StringArgument(json.getAsString());
else
return context.deserialize(json, RuledArgument.class);
}
@Override
public JsonElement serialize(Argument src, Type typeOfSrc, JsonSerializationContext context) {
if (src instanceof StringArgument)
return new JsonPrimitive(((StringArgument) src).argument);
else if (src instanceof RuledArgument)
return context.serialize(src, RuledArgument.class);
else
throw new AssertionError("Unrecognized argument type: " + src);
}
}
}
@@ -0,0 +1,89 @@
/*
* 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.hmcl.core.version;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.jackhuang.hmcl.util.ArrayUtils;
import org.jackhuang.hmcl.util.CollectionUtils;
/**
*
* @author huang
*/
public class Arguments {
@SerializedName("game")
public List<Argument> game;
@SerializedName("jvm")
public List<Argument> jvm;
public static Arguments clone(Arguments original) {
if (original == null)
return null;
Arguments ret = new Arguments();
ret.game = CollectionUtils.deepCopy(original.game, value -> (Argument) value.clone());
ret.jvm = CollectionUtils.deepCopy(original.jvm, value -> (Argument) value.clone());
return ret;
}
public static Arguments merge(Arguments a, Arguments b) {
if (a == null) return b;
else if (b == null) return a;
Arguments ret = new Arguments();
ret.game = ArrayUtils.merge(a.game, b.game);
ret.jvm = ArrayUtils.merge(a.jvm, b.jvm);
if (ret.game == null && ret.jvm == null) return null;
return ret;
}
public static List<String> parseStringArguments(List<String> arguments, Map<String, String> keys) {
return CollectionUtils.map(arguments, str -> keys.getOrDefault(str, str));
}
public static List<String> parseArguments(List<Argument> arguments, Map<String, String> keys) {
return parseArguments(arguments, keys, Collections.EMPTY_MAP);
}
public static List<String> parseArguments(List<Argument> arguments, Map<String, String> keys, Map<String, Boolean> features) {
return CollectionUtils.flatMap(arguments, arg -> arg.toString(keys, features));
}
public static final List<Argument> DEFAULT_JVM_ARGUMENTS;
public static final List<Argument> DEFAULT_GAME_ARGUMENTS;
static {
List<Argument> jvm = new LinkedList<>();
jvm.add(new RuledArgument(Collections.singletonList(new Rules("allow", new OSRestriction("windows"))), Collections.singletonList("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump")));
jvm.add(new RuledArgument(Collections.singletonList(new Rules("allow", new OSRestriction("windows", "^10\\."))), Arrays.asList("-Dos.name=Windows 10", "-Dos.version=10.0")));
jvm.add(new StringArgument("-Djava.library.path=${natives_directory}"));
jvm.add(new StringArgument("-Dminecraft.launcher.brand=${launcher_name}"));
jvm.add(new StringArgument("-Dminecraft.launcher.version=${launcher_version}"));
jvm.add(new StringArgument("-cp"));
jvm.add(new StringArgument("${classpath}"));
DEFAULT_JVM_ARGUMENTS = Collections.unmodifiableList(jvm);
List<Argument> game = new LinkedList<>();
game.add(new RuledArgument(Collections.singletonList(new Rules("allow", Collections.singletonMap("has_custom_resolution", true))), Arrays.asList("--width", "${resolution_width}", "--height", "${resolution_height}")));
DEFAULT_GAME_ARGUMENTS = Collections.unmodifiableList(game);
}
}
@@ -54,16 +54,7 @@ public class MinecraftLibrary extends AbstractMinecraftLibrary {
*/
@Override
public boolean allow() {
if (rules != null) {
boolean flag = false;
for (Rules r : rules)
if ("disallow".equals(r.action()))
return false;
else if ("allow".equals(r.action()))
flag = true;
return flag;
} else
return true;
return Rules.allow(rules);
}
private String formatArch(String nati) {
@@ -123,6 +114,8 @@ public class MinecraftLibrary extends AbstractMinecraftLibrary {
if (natives != null) {
if (downloads.classifiers == null)
downloads.classifiers = new HashMap<>();
if (StrUtils.isBlank(getNative()))
return null;
if (!downloads.classifiers.containsKey(getNative()))
downloads.classifiers.put(getNative(), info = new LibraryDownloadInfo());
else info = downloads.classifiers.get(getNative());
@@ -34,6 +34,7 @@ import org.jackhuang.hmcl.core.GameException;
import org.jackhuang.hmcl.core.service.IMinecraftProvider;
import org.jackhuang.hmcl.core.asset.AssetsIndex;
import org.jackhuang.hmcl.util.ArrayUtils;
import org.jackhuang.hmcl.util.CollectionUtils;
/**
*
@@ -43,6 +44,8 @@ public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion>
@SerializedName("minecraftArguments")
public String minecraftArguments;
@SerializedName("arguments")
public Arguments arguments;
@SerializedName("mainClass")
public String mainClass;
@SerializedName("time")
@@ -79,8 +82,9 @@ public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion>
public MinecraftVersion() {
}
public MinecraftVersion(String minecraftArguments, String mainClass, String time, String id, String type, String processArguments, String releaseTime, String assets, String jar, String inheritsFrom, String runDir, int minimumLauncherVersion, List<MinecraftLibrary> libraries, boolean hidden, Map<String, GameDownloadInfo> downloads, AssetIndexDownloadInfo assetIndexDownloadInfo, Map<String, LoggingInfo> logging) {
public MinecraftVersion(Arguments arguments, String minecraftArguments, String mainClass, String time, String id, String type, String processArguments, String releaseTime, String assets, String jar, String inheritsFrom, String runDir, int minimumLauncherVersion, List<MinecraftLibrary> libraries, boolean hidden, Map<String, GameDownloadInfo> downloads, AssetIndexDownloadInfo assetIndexDownloadInfo, Map<String, LoggingInfo> logging) {
this();
this.arguments = Arguments.clone(arguments);
this.minecraftArguments = minecraftArguments;
this.mainClass = mainClass;
this.time = time;
@@ -98,28 +102,9 @@ public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion>
this.assetIndex = null;
else
this.assetIndex = (AssetIndexDownloadInfo) assetIndexDownloadInfo.clone();
if (libraries == null)
this.libraries = new ArrayList<>();
else {
this.libraries = new ArrayList<>(libraries.size());
for (MinecraftLibrary library : libraries)
if (library != null)
this.libraries.add((MinecraftLibrary) library.clone());
}
if (downloads == null)
this.downloads = null;
else {
this.downloads = new HashMap<>(downloads.size());
for (Map.Entry<String, GameDownloadInfo> entry : downloads.entrySet())
this.downloads.put(entry.getKey(), (GameDownloadInfo) entry.getValue().clone());
}
if (logging == null)
this.logging = null;
else {
this.logging = new HashMap<>(logging.size());
for (Map.Entry<String, LoggingInfo> entry : logging.entrySet())
this.logging.put(entry.getKey(), (LoggingInfo) entry.getValue().clone());
}
this.libraries = CollectionUtils.deepCopy(libraries, value -> (MinecraftLibrary) value.clone());
this.downloads = CollectionUtils.deepCopy(downloads, value -> (GameDownloadInfo) value.clone());
this.logging = CollectionUtils.deepCopy(logging, value -> (LoggingInfo) value.clone());
}
@Override
@@ -151,16 +136,17 @@ public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion>
}
parent = parent.resolve(provider, resolvedSoFar);
MinecraftVersion result = new MinecraftVersion(
this.minecraftArguments != null ? this.minecraftArguments : parent.minecraftArguments,
this.mainClass != null ? this.mainClass : parent.mainClass,
this.time, this.id, this.type, parent.processArguments, this.releaseTime,
this.assets != null ? this.assets : parent.assets,
this.jar != null ? this.jar : parent.jar,
null, this.runDir, parent.minimumLauncherVersion,
this.libraries != null ? ArrayUtils.merge(this.libraries, parent.libraries) : parent.libraries, this.hidden,
this.downloads != null ? this.downloads : parent.downloads,
this.assetIndex != null ? this.assetIndex : parent.assetIndex,
this.logging != null ? this.logging : parent.logging);
Arguments.merge(parent.arguments, this.arguments),
this.minecraftArguments != null ? this.minecraftArguments : parent.minecraftArguments,
this.mainClass != null ? this.mainClass : parent.mainClass,
this.time, this.id, this.type, parent.processArguments, this.releaseTime,
this.assets != null ? this.assets : parent.assets,
this.jar != null ? this.jar : parent.jar,
null, this.runDir, parent.minimumLauncherVersion,
this.libraries != null ? ArrayUtils.merge(this.libraries, parent.libraries) : parent.libraries, this.hidden,
this.downloads != null ? this.downloads : parent.downloads,
this.assetIndex != null ? this.assetIndex : parent.assetIndex,
this.logging != null ? this.logging : parent.logging);
return result;
}
@@ -203,7 +189,7 @@ public class MinecraftVersion implements Cloneable, Comparable<MinecraftVersion>
return false;
return Objects.equals(this.id, ((MinecraftVersion) obj).id);
}
public AssetIndexDownloadInfo getAssetsIndex() {
if (assetIndex == null)
assetIndex = new AssetIndexDownloadInfo(assets == null ? AssetsIndex.DEFAULT_ASSET_NAME : assets);
@@ -247,11 +247,13 @@ public class MinecraftVersionManager<T extends IMinecraftService> extends IMinec
throw new GameException("Wrong format: minecraft.json");
ArrayList<File> unzippings = new ArrayList<>();
ArrayList<Extract> extractRules = new ArrayList<>();
for (IMinecraftLibrary l : v.libraries)
if (l.isNative() && v.isAllowedToUnpackNatives()) {
unzippings.add(getLibraryFile(v, l));
for (IMinecraftLibrary l : v.libraries) {
final File f = getLibraryFile(v, l);
if (l.isNative() && v.isAllowedToUnpackNatives() && l.allow() && f != null) {
unzippings.add(f);
extractRules.add(l.getDecompressExtractRules());
}
}
return new DecompressLibraryJob(unzippings.toArray(new File[unzippings.size()]), extractRules.toArray(new Extract[extractRules.size()]), getDecompressNativesToLocation(v));
}
@@ -18,19 +18,40 @@
package org.jackhuang.hmcl.core.version;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hmcl.util.StrUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jackhuang.hmcl.util.sys.OS;
/**
*
* @author huangyuhui
*/
public class OSRestriction {
public class OSRestriction implements Cloneable {
@SerializedName("version")
private String version;
@SerializedName("name")
public String name;
@SerializedName("arch")
public String arch;
public OSRestriction() {
this(null);
}
public OSRestriction(String name) {
this(name, null);
}
public OSRestriction(String name, String version) {
this(name, version, null);
}
public OSRestriction(String name, String version, String arch) {
this.name = name;
this.version = version;
this.arch = arch;
}
public String getVersion() {
return version;
@@ -49,6 +70,33 @@ public class OSRestriction {
}
public boolean isCurrentOS() {
return StrUtils.isBlank(getName()) || OS.os().name().equalsIgnoreCase(getName());
if (name != null && !OS.os().name().equalsIgnoreCase(name))
return false;
if (version != null) {
try {
Pattern pattern = Pattern.compile(version);
Matcher matcher = pattern.matcher(System.getProperty("os.version"));
if (!matcher.matches())
return false;
} catch (Throwable t) {}
}
if (arch != null) {
try {
Pattern pattern = Pattern.compile(arch);
Matcher matcher = pattern.matcher(System.getProperty("os.arch"));
if (!matcher.matches())
return false;
} catch (Throwable t) {}
}
return true;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException ex) {
throw new AssertionError(ex);
}
}
}
@@ -0,0 +1,93 @@
/*
* 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.hmcl.core.version;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.jackhuang.hmcl.util.CollectionUtils;
/**
*
* @author huang
*/
public class RuledArgument implements Argument {
public List<Rules> rules;
public List<String> value;
public RuledArgument() {
}
public RuledArgument(List<Rules> rules, List<String> args) {
this.rules = rules;
this.value = args;
}
@Override
public Object clone() {
try {
RuledArgument ret = (RuledArgument) super.clone();
ret.rules = CollectionUtils.deepCopy(rules, value -> (Rules) value.clone());
ret.value = CollectionUtils.copy(value);
return ret;
} catch (CloneNotSupportedException ex) {
throw new AssertionError(ex);
}
}
@Override
public List<String> toString(Map<String, String> keys, Map<String, Boolean> features) {
if (!Rules.allow(rules, features))
return Collections.EMPTY_LIST;
else
return CollectionUtils.map(value, a -> new StringArgument(a).toString(keys, features).get(0));
}
public static class RuledArgumentSerializer implements JsonSerializer<RuledArgument>, JsonDeserializer<RuledArgument> {
@Override
public JsonElement serialize(RuledArgument src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject obj = new JsonObject();
obj.add("rules", context.serialize(src.rules));
obj.add("value", context.serialize(src.value));
return obj;
}
@Override
public RuledArgument deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject obj = json.getAsJsonObject();
RuledArgument a = new RuledArgument();
a.rules = context.deserialize(obj.get("rules"), new TypeToken<List<Rules>>(){}.getType());
if (obj.get("value").isJsonPrimitive())
a.value = Collections.singletonList(obj.get("value").getAsString());
else
a.value = context.<List<String>>deserialize(obj.get("value"), new TypeToken<List<String>>(){}.getType());
return a;
}
}
}
@@ -18,23 +18,77 @@
package org.jackhuang.hmcl.core.version;
import com.google.gson.annotations.SerializedName;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import org.jackhuang.hmcl.util.CollectionUtils;
/**
*
* @author huangyuhui
*/
public class Rules {
public class Rules implements Cloneable {
@SerializedName("action")
private String action;
@SerializedName("os")
private OSRestriction os;
@SerializedName("features")
private Map<String, Boolean> features;
public Rules() {
}
public Rules(String action, OSRestriction os) {
this.action = action;
this.os = os;
}
public Rules(String action, Map<String, Boolean> features) {
this.action = action;
this.features = features;
}
public String action() {
return os == null || os.isCurrentOS() ? action : null;
@Override
public Object clone() {
try {
Rules rules = (Rules) super.clone();
rules.os = (OSRestriction) os.clone();
rules.features = CollectionUtils.copy(features);
return rules;
} catch (CloneNotSupportedException ex) {
throw new AssertionError(ex);
}
}
public String action(Map<String, Boolean> features) {
if (os != null && !os.isCurrentOS()) return null;
if (this.features != null) {
for (Map.Entry<String, Boolean> entry : this.features.entrySet())
if (!features.containsKey(entry.getKey()))
return null;
else
if (!features.get(entry.getKey()).equals(entry.getValue()))
return null;
}
return action;
}
public static boolean allow(Collection<Rules> c) {
return allow(c, Collections.EMPTY_MAP);
}
public static boolean allow(Collection<Rules> c, Map<String, Boolean> features) {
if (c != null) {
boolean flag = false;
for (Rules r : c)
if ("disallow".equals(r.action(features)))
return false;
else if ("allow".equals(r.action(features)))
flag = true;
return flag;
} else
return true;
}
}
@@ -0,0 +1,59 @@
/*
* 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.hmcl.core.version;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* @author huang
*/
public class StringArgument implements Argument {
public String argument;
public StringArgument(String argument) {
this.argument = argument;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException ex) {
throw new AssertionError(ex);
}
}
@Override
public List<String> toString(Map<String, String> keys, Map<String, Boolean> features) {
String res = argument;
Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");
Matcher m = pattern.matcher(argument);
while (m.find()) {
String entry = m.group();
res = res.replace(entry, keys.getOrDefault(entry, entry));
}
return Collections.singletonList(res);
}
}
@@ -73,6 +73,9 @@ public final class ArrayUtils {
}
public static <T> ArrayList<T> merge(List<T> a, List<T> b) {
if (a == null && b == null) return null;
else if (a == null) return new ArrayList<>(b);
else if (b == null) return new ArrayList<>(a);
ArrayList<T> al = new ArrayList<>(a.size() + b.size());
al.addAll(a);
al.addAll(b);
@@ -86,7 +89,7 @@ public final class ArrayUtils {
return l;
}
public static <T> int matchArray(byte[] a, byte[] b) {
public static int matchArray(byte[] a, byte[] b) {
for (int i = 0; i < a.length - b.length; i++) {
int j = 1;
for (int k = 0; k < b.length; k++) {
@@ -20,6 +20,8 @@ package org.jackhuang.hmcl.util;
import org.jackhuang.hmcl.util.lang.SupportedLocales;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.jackhuang.hmcl.core.version.Argument;
import org.jackhuang.hmcl.core.version.RuledArgument;
/**
*
@@ -27,7 +29,10 @@ import com.google.gson.GsonBuilder;
*/
public final class C {
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(RuledArgument.class, new RuledArgument.RuledArgumentSerializer())
.registerTypeAdapter(Argument.class, new Argument.ArgumentSerializer())
.setPrettyPrinting().create();
//http://repo1.maven.org/maven2
public static final String URL_PUBLISH = "http://www.mcbbs.net/thread-142335-1-1.html";
@@ -35,7 +40,7 @@ public final class C {
public static final String URL_FORGE_LIST = "http://files.minecraftforge.net/maven/net/minecraftforge/forge/json";
public static final String URL_LITELOADER_LIST = "http://dl.liteloader.com/versions/versions.json";
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
private C() {
@@ -20,7 +20,11 @@ package org.jackhuang.hmcl.util;
import org.jackhuang.hmcl.api.func.Predicate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.jackhuang.hmcl.api.func.Function;
/**
*
@@ -31,7 +35,7 @@ public final class CollectionUtils {
private CollectionUtils() {
}
public static <T> ArrayList<T> filter(Collection<T> coll, Predicate<T> p) {
public static <T> List<T> filter(Collection<T> coll, Predicate<T> p) {
ArrayList<T> newColl = new ArrayList<>();
for (T t : coll)
if (p.apply(t))
@@ -39,6 +43,20 @@ public final class CollectionUtils {
return newColl;
}
public static <U, V> List<V> map(Collection<U> coll, Function<U, V> p) {
ArrayList<V> newColl = new ArrayList<>(coll.size());
for (U t : coll)
newColl.add(p.apply(t));
return newColl;
}
public static <U, V> List<V> flatMap(Collection<U> coll, Function<U, Collection<V>> p) {
ArrayList<V> newColl = new ArrayList<>(coll.size());
for (U t : coll)
newColl.addAll(p.apply(t));
return newColl;
}
public static <T> boolean removeIf(Collection<T> coll, Predicate<T> p) {
boolean removed = false;
final Iterator<T> each = coll.iterator();
@@ -49,4 +67,40 @@ public final class CollectionUtils {
}
return removed;
}
public static <T extends Cloneable> ArrayList<T> deepCopy(List<T> original, Function<T, T> clone) {
if (original == null)
return null;
ArrayList<T> ret = new ArrayList<>(original.size());
for (T x : original)
ret.add(clone.apply(x));
return ret;
}
public static <T> ArrayList<T> copy(List<T> original) {
if (original == null)
return null;
ArrayList<T> ret = new ArrayList<>(original.size());
for (T x : original)
ret.add(x);
return ret;
}
public static <K, V extends Cloneable> Map<K, V> deepCopy(Map<K, V> original, Function<V, V> clone) {
if (original == null)
return null;
HashMap<K, V> ret = new HashMap<>(original.size());
for (HashMap.Entry<K, V> x : original.entrySet())
ret.put(x.getKey(), clone.apply(x.getValue()));
return ret;
}
public static <K, V> Map<K, V> copy(Map<K, V> original) {
if (original == null)
return null;
HashMap<K, V> ret = new HashMap<>(original.size());
for (HashMap.Entry<K, V> x : original.entrySet())
ret.put(x.getKey(), x.getValue());
return ret;
}
}
@@ -25,7 +25,6 @@ import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
import org.jackhuang.hmcl.api.func.Function;
import org.jackhuang.hmcl.api.func.Predicate;
/**
*
@@ -87,10 +86,10 @@ public final class StrUtils {
return false;
}
public static boolean containsOne(List<String> base, List<String> match, Predicate<String> pred) {
public static boolean containsOne(Collection<String> base, String... match) {
for (String a : base)
for (String b : match)
if (pred.apply(a) && a.toLowerCase().contains(b.toLowerCase()))
if (a.toLowerCase().contains(b.toLowerCase()))
return true;
return false;
}
@@ -154,8 +153,11 @@ public final class StrUtils {
return sb.toString();
}
public static String[] tokenize(String paramString1) {
return tokenize(paramString1, " \t\n\r\f");
public static String[] tokenize(String str) {
if (str == null)
return new String[0];
else
return tokenize(str, " \t\n\r\f");
}
public static String[] tokenize(String str, String delim) {
@@ -38,7 +38,7 @@ public final class Utils {
return ((URLClassLoader) Utils.class.getClassLoader()).getURLs();
}
public static void setClipborad(String text) {
public static void setClipboard(String text) {
try {
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(text), null);
} catch(HeadlessException ignored) {
@@ -20,6 +20,7 @@ package org.jackhuang.hmcl.util.log;
import java.awt.Color;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jackhuang.hmcl.util.ui.GraphicsUtils;
/**
*
@@ -27,12 +28,12 @@ import java.util.regex.Pattern;
*/
public enum Level {
FATAL(1, Color.red),
ERROR(2, Color.red),
WARN(3, Color.orange),
FATAL(1, GraphicsUtils.getWebColor("#C0392B")),
ERROR(2, GraphicsUtils.getWebColor("#D35400")),
WARN(3, GraphicsUtils.getWebColor("#F39C12")),
INFO(4, Color.black),
DEBUG(5, Color.blue),
TRACE(6, Color.blue),
DEBUG(5, GraphicsUtils.getWebColor("#2980B9")),
TRACE(6, GraphicsUtils.getWebColor("#16A085")),
ALL(2147483647, Color.black);
public final int level;
@@ -40,6 +40,7 @@ public final class NetUtils {
public static HttpURLConnection createConnection(URL url, Proxy proxy) throws IOException {
HttpURLConnection con = (HttpURLConnection) url.openConnection(proxy);
con.setRequestProperty("User-Agent", "Hello Minecraft!");
con.setDoInput(true);
con.setUseCaches(false);
con.setConnectTimeout(15000);
@@ -48,7 +49,9 @@ public final class NetUtils {
}
public static String get(String url, String encoding) throws IOException {
return IOUtils.toString(new URL(url).openConnection().getInputStream());
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
con.setRequestProperty("User-Agent", "Hello Minecraft!");
return IOUtils.toString(con.getInputStream());
}
public static String get(String url) throws IOException {
@@ -0,0 +1,79 @@
/*
* 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.hmcl.util.sys;
import java.util.Collection;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.IProcess;
import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent;
import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent;
import org.jackhuang.hmcl.api.event.process.JavaProcessStoppedEvent;
import org.jackhuang.hmcl.util.CollectionUtils;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.util.log.Level;
/**
*
* @author huang
*/
public class ExitWaiter extends Thread {
private final ProcessMonitor monitor;
private final IProcess process;
private final Runnable callback;
/**
* Constructor
* @param monitor
* @param callback nullable, will be called when process exited.
*/
public ExitWaiter(ProcessMonitor monitor, Runnable callback) {
this.monitor = monitor;
this.process = monitor.getProcess();
this.callback = callback;
setName("exit-waitor");
}
@Override
public void run() {
try {
int exitCode = process.getRawProcess().waitFor();
monitor.errorThread.join();
monitor.inputThread.join();
Collection<String> errorLines = CollectionUtils.filter(process.getStdOutLines(), str -> Level.isError(Level.guessLevel(str)));
// LaunchWrapper will terminate the application with exit code 0, though this is error state.
if (exitCode != 0 || StrUtils.containsOne(errorLines, "Unable to launch"))
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessExitedAbnormallyEvent(monitor, process));
else if (exitCode != 0 && StrUtils.containsOne(errorLines,
"Could not create the Java Virtual Machine.",
"Error occurred during initialization of VM",
"A fatal exception has occurred. Program will exit.",
"Unable to launch"))
HMCLApi.EVENT_BUS.fireChannel(new JVMLaunchFailedEvent(monitor, process));
else
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStoppedEvent(this, process));
if (callback != null)
callback.run();
} catch (InterruptedException ex) {
}
}
}
@@ -121,6 +121,8 @@ public class Java {
try {
queryJava(ans, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\");
queryJava(ans, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\");
queryJava(ans, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\JRE\\");
queryJava(ans, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\JDK\\");
} catch (IOException | InterruptedException ex) {
HMCLog.err("Faield to query java", ex);
}
@@ -31,14 +31,14 @@ public enum OS {
LINUX('/', "linux"),
WINDOWS('\\', "windows"),
OSX('/', "osx"),
UNKOWN('/', "universal");
UNKNOWN('/', "universal");
public final char fileSeparator;
public final String checked_name;
public final String checkedName;
private OS(char fileSeparator, String n) {
this.fileSeparator = fileSeparator;
checked_name = n;
checkedName = n;
}
public static OS os() {
@@ -55,7 +55,7 @@ public enum OS {
return OS.LINUX;
if (str.contains("unix"))
return OS.LINUX;
return OS.UNKOWN;
return OS.UNKNOWN;
}
/**
@@ -17,19 +17,11 @@
*/
package org.jackhuang.hmcl.util.sys;
import java.util.Arrays;
import java.util.HashSet;
import java.util.concurrent.CountDownLatch;
import org.jackhuang.hmcl.api.HMCLApi;
import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent;
import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent;
import org.jackhuang.hmcl.api.event.process.JavaProcessStartingEvent;
import org.jackhuang.hmcl.api.event.process.JavaProcessStoppedEvent;
import org.jackhuang.hmcl.util.StrUtils;
import org.jackhuang.hmcl.api.HMCLog;
import org.jackhuang.hmcl.util.log.Level;
import org.jackhuang.hmcl.api.IProcess;
import org.jackhuang.hmcl.api.event.SimpleEvent;
import org.jackhuang.hmcl.api.func.Consumer;
/**
@@ -43,6 +35,7 @@ public class ProcessMonitor {
private final CountDownLatch latch = new CountDownLatch(2);
ProcessThread inputThread;
ProcessThread errorThread;
ExitWaiter waitorThread;
WaitForThread waitForThread;
private final IProcess p;
@@ -50,9 +43,7 @@ public class ProcessMonitor {
this.p = p;
inputThread = new ProcessThread(this, false);
errorThread = new ProcessThread(this, true);
inputThread.stopEvent.register(this::threadStopped);
inputThread.stopEvent.register(event -> processThreadStopped((ProcessThread) event.getSource()));
errorThread.stopEvent.register(this::threadStopped);
waitorThread = new ExitWaiter(this, this::processThreadStopped);
}
public IProcess getProcess() {
@@ -75,51 +66,14 @@ public class ProcessMonitor {
}
public void start() {
hasFired = false;
MONITORS.add(this);
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStartingEvent(this, p));
inputThread.start();
errorThread.start();
}
private void threadStopped(SimpleEvent<IProcess> event) {
latch.countDown();
ProcessThread t = (ProcessThread) event.getSource();
int exitCode = Integer.MAX_VALUE;
try {
exitCode = p.getExitCode();
} catch(IllegalThreadStateException e) {
HMCLog.err("Failed to ");
}
if (p.getExitCode() != 0 || StrUtils.containsOne(t.getLines(),
Arrays.asList("Unable to launch"), // LaunchWrapper will terminate the application returning exit code 0, but this is an error state.
x -> Level.isError(Level.guessLevel(x))))
synchronized (this) {
if (!hasFired) {
hasFired = true;
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessExitedAbnormallyEvent(ProcessMonitor.this, p));
}
}
if (p.getExitCode() != 0 && StrUtils.containsOne(t.getLines(),
Arrays.asList("Could not create the Java Virtual Machine.",
"Error occurred during initialization of VM",
"A fatal exception has occurred. Program will exit.",
"Unable to launch"),
x -> Level.isError(Level.guessLevel(x))))
synchronized (this) {
if (!hasFired) {
hasFired = true;
HMCLApi.EVENT_BUS.fireChannel(new JVMLaunchFailedEvent(ProcessMonitor.this, p));
}
}
}
boolean hasFired = false;
private void processThreadStopped(ProcessThread t1) {
private void processThreadStopped() {
MONITORS.remove(this);
errorThread.interrupt();
HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStoppedEvent(this, p));
}
public static void stopAll() {
@@ -127,6 +81,7 @@ public class ProcessMonitor {
monitor.getProcess().getRawProcess().destroy();
monitor.inputThread.interrupt();
monitor.errorThread.interrupt();
monitor.waitorThread.interrupt();
}
}
@@ -71,11 +71,20 @@ public class ProcessThread extends Thread {
br = new BufferedReader(new InputStreamReader(in, Charsets.toCharset()));
String line;
while (p.isRunning())
while ((line = br.readLine()) != null)
while (p.isRunning()) {
if (isInterrupted())
return;
while ((line = br.readLine()) != null) {
if (isInterrupted())
return;
println(line);
while ((line = br.readLine()) != null)
}
}
while ((line = br.readLine()) != null) {
if (isInterrupted())
return;
println(line);
}
} catch (IOException e) {
HMCLog.err("An error occured when reading process stdout/stderr.", e);
} finally {
@@ -79,10 +79,9 @@ public class ZipEngine implements Closeable {
File[] files;
if (source.isDirectory())
files = source.listFiles();
else {
files = new File[1];
files[0] = source;
}
else
files = new File[] { source };
if (files == null)
return;
String pathName;//存相对路径(相对于待压缩的根目录)
@@ -19,15 +19,15 @@ launch.failed=Не удалось запустить.
launch.failed_creating_process=Не удалось создать процесс, возможно, ваш путь java - указан не верно, пожалуйста, измените свой путь java.
launch.failed_sh_permission=Не удалось добавить разрешение на запуск скрипта.
launch.failed_packing_jar=Не удалось упаковать в jar.
launch.unsupported_launcher_version=Извините, Launcher не может запустить minecraft, но повторяет попытку запуска.
launch.too_big_memory_alloc_64bit=Вы выделили слишком много памяти, потому что 32-разрядная Среда выполнения java, то игра скорее всего приведет к крашу. Максимальный объем памяти 1024МБ. Лаунчер будет пытаться запустить его.
launch.unsupported_launcher_version=Извините, Launcher не может запустить minecraft, но он повторяет попытку запуска.
launch.too_big_memory_alloc_64bit=Вы выделили слишком много памяти для 32-разрядной ОС java игра скорее всего приведет к крашу. Максимальный объем памяти 1024МБ. Лаунчер будет пытаться запустить его.
launch.too_big_memory_alloc_free_space_too_low=Вы выделили слишком много памяти, потому что размер физической памяти составляет %dMB, ваша игра скорее всего приведет к крашу. Лаунчер будет пытаться запустить его.
launch.cannot_create_jvm=Мы видим, что он не может создать java виртуальная машина. В Java агреманы могут возникнуть проблемы. Вы можете включить режим No args в настройках.
launch.cannot_create_jvm=Мы видим, что он не может создать java виртуальная машина. В Java аргументах могут возникнуть проблемы. Вы можете включить режим No args в настройках.
launch.circular_dependency_versions=Нашли круговой версии зависимостей, пожалуйста, проверьте, если ваш клиент был изменен.
launch.not_finished_downloading_libraries=Не закончив загрузку библиотек, продолжить запуск игры?
launch.not_finished_decompressing_natives=Не закончил распаковки собственных библиотек, продолжить запуск игры?
launch.wrong_javadir=Неправильные каталоги java, будут сброшены по умолчанию каталогов java.
launch.exited_abnormally=Игра завершилась аварийно, пожалуйста, посетите журнал, или попросить кого-то о помощи.
launch.not_finished_decompressing_natives=Не закончил распаковку библиотек, продолжить запуск игры?
launch.wrong_javadir=Неправильные каталоги java, он будет сброшен по умолчанию каталог java.
launch.exited_abnormally=Игра завершилась крашем, пожалуйста, посетите журнал, или попросить кого-то о помощи.
launch.state.logging_in=Вход
launch.state.generating_launching_codes=Генерирования стартового кода
@@ -36,7 +36,7 @@ launch.state.decompressing_natives=Туземцев распаковки
launch.state.waiting_launching=Ждем запуска игры
install.no_version=Версия не найдена.
install.no_version_if_intall=Нужная версия не найдена, вы хотите, чтобы автоматически установить версию?
install.no_version_if_intall=Нужная версия не найдена, вы хотите, чтобы автоматически установилась версия?
install.not_refreshed=Список установки не обновляется.
install.download_list=Скачать список
@@ -86,7 +86,7 @@ login.type=Логин
login.username=Ник
login.account=Почта
login.invalid_token=Пожалуйста, выйдите и повторно введите пароль для входа в систему.
login.no_valid_character=Не допустимый характер, пожалуйста, посетите skinme.cc и создать своего собственного персонажа.
login.no_valid_character=Не допустимый характер, пожалуйста, посетите skinme.cc и создайте своего собственного персонажа.
proxy.username=Аккаунт
proxy.password=Пароль
@@ -96,7 +96,7 @@ proxy.port=Порт
login.failed.connect_authentication_server=Не удается подключиться к серверу авторизации. Проверьте вашу сеть.
login.profile.not_logged_in=Вы не вошли в систему, Вы не можете изменить профиль!
login.profile.selected=Не могу изменить профиль, выйти и пойти повторить.
login.profile.selected=Не могу изменить профиль, выйдите и повторите.
login.methods.yggdrasil=Email и пароль
login.methods.offline=Введите ваш ник
@@ -114,9 +114,9 @@ ui.login.password=Пароль
ui.more=Больше
crash.advice.UnsupportedClassVersionError=Может быть, ваша версия java старая, попробуйте обновить java.
crash.advice.ConcurrentModificationException=Может быть, ваш java новее, чем 1.8.0_11, вы можете понизить до версии java 7.
crash.advice.ConcurrentModificationException=Может быть, ваш java новее, чем 1.8.0_11, вы можете понизить до версии Java 7.
crash.advice.ClassNotFoundException=Minecraft или моды, являются неполными. Повторите, если есть какие-то библиотеки, которые не скачали или обновить игру и модов! Или вы можете попробовать настройки игры -> Управление (версии) -> библиотека удалить файлы, чтобы решить проблему.
crash.advice.NoSuchFieldError=Майнкрафт или моды, являются неполными. Повторите, если есть какие-то библиотеки, которые не скачали или обновить игру и модов!
crash.advice.NoSuchFieldError=Minecraft или моды, являются неполными. Повторите, если есть какие-то библиотеки, которые не скачали или обновить игру и моды!
crash.advice.LWJGLException=Может быть, ваш видео драйвер не работает, пожалуйста, обновите ваш видео драйвер.
crash.advice.SecurityException=Может быть, вы изменили minecraft.jar но не удалили META-INF.
crash.advice.OutOfMemoryError=Максимум памяти для JVM слишком мал, пожалуйста, измените его.
@@ -127,21 +127,21 @@ crash.advice.no_lwjgl=Может быть драйвера вызвали про
crash.advice.no=Никакие советы.
crash.user_fault=Вашей операционной системы или среды java не может быть установлен неправильно, в результате сбой этой программы, пожалуйста, проверьте вашу среду java или компьютер!
crash.headless=Если ваша ОС Linux можно использовать Oracle версии jdk вместо openjdk, то или добавить "-Djava.awt.headless=false" аргумент jvm, или проверить, если ваш x-сервер работает нормально.
crash.user_fault=Вашей операционной системы или среды Java не может быть установлен неправильно, в результате сбой этой программы, пожалуйста, проверьте вашу среду Java или компьютер!
crash.headless=Если ваша ОС Linux может использовать Oracle версии JDK вместо OpenJDK, то или добавить "-Djava.awt.headless=false" аргумент JVM, или проверить, если ваш сервер работает нормально.
crash.NoClassDefFound=Пожалуйста, проверьте "Launcher" программное обеспечение в комплекте.
crash.error=Minecraft крашнулся.
crash.main_class_not_found=Главный Класс не найден, может быть ваш МК был нарушен.
crash.class_path_wrong=Может запустить скрипт неправильный.
ui.label.newProfileWindow.new_profile_name=Новое Имя Профиля:
ui.label.newProfileWindow.copy_from=Скопировать Из:
ui.newProfileWindow.title=Новый Конфиг
ui.label.newProfileWindow.new_profile_name=Новое Имя профиля:
ui.label.newProfileWindow.copy_from=Скопировать из:
ui.newProfileWindow.title=Новый конфиг
ui.button.ok=OK
ui.button.refresh=Обновить
ui.button.run=Играть
ui.button.run=Войти в игру
ui.button.settings=Настройки
ui.button.about=About
ui.button.others=Другие
@@ -160,8 +160,8 @@ ui.button.test=Тест
ui.button.preview=Показать
button.cancel=Отменить
button.ok=OK
button.yes=да
button.no=Неа
button.yes=Да
button.no=Нет
ui.label.version=Версия
ui.label.password=Пароль
@@ -176,8 +176,8 @@ ui.message.update_java=Пожалуйста, обновите ваш Java.
ui.message.open_jdk=Мы уже выяснили, что вы начали это приложение, используя OpenJDK, который станет причиной стольких бед для рисования интерфейса. Мы предлагаем Вам вместо того, чтобы с помощью Oracle версии JDK.
ui.label.settings=Настройки
ui.label.crashing=<html>Hello Minecraft! Launcher крашнулся!</html>
ui.label.crashing_out_dated=<html>Hello Minecraft! Launcher крашнулся! Ваш лаунчер устарел. Обновить его</html>
ui.label.crashing=<html>Launcher крашнулся!</html>
ui.label.crashing_out_dated=<html>Launcher крашнулся! Ваш лаунчер устарел. Обновить его</html>
ui.label.failed_set=Не удалось установить:
download=Скачать
@@ -190,16 +190,16 @@ download.successfully=Успешно скачал
download.source=Скачать Исходник
message.error=Ошибка
message.cannot_open_explorer=Cannot open explorer:
message.cannot_open_explorer=Не можете открыть проводник:
message.cancelled=Отменен
message.info=Информация
message.loading=Загрузка...
folder.game=Game Dir
folder.mod=Мод
folder.coremod=Core Mod
folder.game=Директория
folder.mod=Моды
folder.coremod=Ядро
folder.config=Конфигурации
folder.resourcepacks=Ресурс паки
folder.resourcepacks=Ресурс пак
folder.screenshots=Скриншоты
folder.saves=Сохранить
@@ -208,25 +208,25 @@ settings.tabs.installers=Установщик
settings.tabs.assets_downloads=Дополнения
settings=Настройки
settings.explore=Выбрать
settings.explore=Обзор...
settings.manage=Управлять
settings.cannot_remove_default_config=Не удается удалить configution по умолчанию.
settings.max_memory=Max Memory/MB
settings.java_dir=Java Dir
settings.game_directory=Директории Игры
settings.dimension=Игра Окно Измерения
settings.fullscreen=Полноэкранный
settings.cannot_remove_default_config=Не удается удалить конфигурацию по умолчанию.
settings.max_memory=Выделение памяти
settings.java_dir=Путь к Java
settings.game_directory=Директория
settings.dimension=Разрешение
settings.fullscreen=Полноэкранный режим
settings.update_version=Обновление версии в формате json.
settings.run_directory=Запуск Каталога(Изоляция Версия)
settings.physical_memory=Размер Физической Памяти
settings.choose_javapath=Выбрать Каталог Java.
settings.default=Default
settings.run_directory=Выбор каталога
settings.physical_memory=Размер физической памяти
settings.choose_javapath=Выбрать каталог Java.
settings.default=По умолчанию
settings.custom=Выбрать
settings.choose_gamedir=Выбрать Директорию Игры
settings.choose_gamedir=Выбрать директорию игры
settings.failed_load=Не смог файл загрузить настройки. Удалить его?
settings.test_game=Тестовая игра
settings.type.none=Нет версии игры, пожалуйста, откройте на разделе скачать игры.
settings.type.none=Нет версии игры, пожалуйста, откройте раздел скачать игру.
settings.type.global=<html><a href="">Нажмите здесь, чтобы перейти в специализированных версий. Сейчас это глобальная настройка.</a></html>
settings.type.special=<html><a href="">Нажмите здесь, чтобы перейти в глобальные настройки. Не это версии специализированных условиях.</a></html>
@@ -249,7 +249,7 @@ modpack.wizard.step.1.title=Набор основных вариантов modpa
modpack.wizard.step.initialization.include_launcher=Включить лаунчер
modpack.wizard.step.initialization.exported_version=Экспортируемые версии игры
modpack.wizard.step.initialization.save=Выберите папку для экспорта игровых файлов для
modpack.wizard.step.initialization.warning=<html>Прежде чем сделать суд, вы должны убедиться, что ваша игра сможет успешно запуска,<br/>и что ваш minecraft-это релиз, а не снимок.<br/>а что нельзя добавить модов, которые не позволили раздавать modpack.</html>
modpack.wizard.step.initialization.warning=<html>Прежде чем сделать modpack, вы должны убедиться, что ваша игра сможет успешно запустить,<br/>и что ваш minecraft-это релиз, а не снимок.<br/>а что нельзя добавить модов, которые не позволили раздавать modpack.</html>
modpack.wizard.step.2=Выбор файлов
modpack.wizard.step.2.title=Выберите файлы, которые Вы не хотите положить в modpack.
modpack.wizard.step.3=Описание
@@ -281,18 +281,18 @@ mods.choose_mod=Выбрать ваши моды
mods.failed=Не удалось добавить моды
mods.add=Добавить
mods.remove=Удалить
mods.default_information=<html><font color=#c0392b>Пожалуйста, убедитесь, что у вас есть установленный Forge или LiteLoader перед установкой модов!<br>Вы можете оставить свой mod файлов из проводника/Finder и удаление модов с помощью кнопки удалить.<br>Отключить мод, оставив флажок снят; выбрать товар, чтобы получить информацию.</font></html>
mods.default_information=<html><font color=#c0392b>Пожалуйста, убедитесь, что у вас есть установленный Forge или LiteLoader перед установкой модов!<br>Вы можете оставить свой mod файл из проводника/Finder и удаление модов с помощью кнопки удалить.<br>Отключить мод, оставив флажок снят; выбрать товар, чтобы получить информацию.</font></html>
advancedsettings=Расширенный
advancedsettings.launcher_visible=Лаунчер Видимость
advancedsettings.debug_mode=Режим Отладки
advancedsettings.launcher_visible=При запуске Minecraft
advancedsettings.debug_mode=Режим отладки
advancedsettings.java_permanent_generation_space=PermGen Space/MB
advancedsettings.jvm_args=Java VM Arguments
advancedsettings.Minecraft_arguments=Майнкрафт Аргументы
advancedsettings.jvm_args=Java VM Аргументы
advancedsettings.Minecraft_arguments=Minecraft Аргументы
advancedsettings.launcher_visibility.close=Закрыть лаунчер, если игра запущена.
advancedsettings.launcher_visibility.hide=Скрывать запуска, когда игра запущена.
advancedsettings.launcher_visibility.keep=Держите пусковую видны.
advancedsettings.launcher_visibility.hide_reopen=Скрывать запуска и повторного открытия, когда игра закрывается.
advancedsettings.launcher_visibility.hide=Скрывать лаунчер, когда игра запущена.
advancedsettings.launcher_visibility.keep=Оставить лаунчер видимым.
advancedsettings.launcher_visibility.hide_reopen=Скрывать лаунчер и повторно открывать, когда выйдите из игры.
advancedsettings.game_dir.default=По умолчанию (.minecraft/)
advancedsettings.game_dir.independent=Независимые (.minecraft/версии/<номер версии>/, за исключением активов,библиотеки)
advancedsettings.no_jvm_args=No Default JVM Args
@@ -301,15 +301,15 @@ advancedsettings.java_args_default=Default java args: -XX:+UseConcMarkSweepGC -X
advancedsettings.wrapper_launcher=Лаунчер-оболочку(как и optirun...)
advancedsettings.precall_command=Команда Precalling(будут выполняться до запуска игры)
advancedsettings.server_ip=Сервера
advancedsettings.cancel_wrapper_launcher=Отмена Запуска Оболочки
advancedsettings.cancel_wrapper_launcher=Отмена запуска оболочки
advancedsettings.dont_check_game_completeness=Не проверить полноту игры
mainwindow.show_log=Показать Логи
mainwindow.make_launch_script=Сделать Запуск Скрипта.
mainwindow.make_launch_script=Сделать запуск скрипта.
mainwindow.make_launch_script_failed=Не удалось сделать скрипт.
mainwindow.enter_script_name=Введите имя скрипта.
mainwindow.make_launch_succeed=Закончил создание скрипта.
mainwindow.no_version=Версии не найдены. Переключить на вкладку загрузки игры?
mainwindow.no_version=Версии Minecraft не найдены. Переключить на вкладку загрузки версии для игры в Minecraft?
launcher.about=<html>Об Авторе<br/>Майнкрафт форум 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=Скачать Исходники
@@ -321,22 +321,22 @@ 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.commpath_tooltip=<html><body>Это приложение будет сохранять все игровые библиотеки здесь, если там нет файлов в папке с игрой.</body></html>
launcher.background_tooltip=<html><body>Лаучер использует по умолчанию фон.<br/>Если вы используете пользовательский фон.PNG, ссылку и оно будет использоваться.<br />Если есть "БГ" подкаталог, это приложение выбирает одну картинку в "bgskin" случайно.<br />Если вы установите параметр фон, это приложение будет использовать его.</body></html>
launcher.update_launcher=Проверить обновления
launcher.enable_shadow=Включить Window Shadow
launcher.enable_animation=Включить Animation
launcher.enable_blur=Включить Blur
launcher.enable_shadow=Включить тень окна
launcher.enable_animation=Включить анимацию
launcher.enable_blur=Включить размытие
launcher.theme=Тема
launcher.proxy=Прокси
launcher.decorated=Включить границы окна(для того, чтобы исправить эту проблему, что пользовательский интерфейс становятся все серые в ОС Linux)
launcher.modpack=<html><a href="http://blog.163.com/huanghongxun2008@126/blog/static/7738046920160323812771/">Документация для modpacks.</a></html>
launcher.decorated=Включить границы окна(для того, чтобы исправить проблему, если в пользовательском интерфейсе становится все серое в ОС Linux)
launcher.modpack=<html><a href="http://blog.163.com/huanghongxun2008@126/blog/static/7738046920160323812771/">Документация по modpacks.</a></html>
launcher.lang=Язык (Language)
launcher.restart=Варианты будут в операции, только если перезапустить это приложение.
launcher.log_font=Шрифт Лога
launcher.log_font=Шрифт лога
launcher.tab.general=Общие
launcher.tab.ui=Интерфейс
launcher.tab.about=Автор
launcher.tab.about=Версия
launcher.title.game=Игры
launcher.title.main=Главная
@@ -352,22 +352,22 @@ versions.manage.rename.message=Пожалуйста, введите новый
versions.manage.remove=Удалить версию
versions.manage.remove.confirm=Не забудьте удалить версию
versions.manage.redownload_json=Повторная загрузка конфигурации в Minecraft(minecraft.json)
versions.manage.redownload_assets_index=Индекс Перекачайте Активов
versions.mamage.remove_libraries=Библиотека удалять файлы
versions.manage.redownload_assets_index=Перекачать библиотеки
versions.mamage.remove_libraries=Библиотека удалить файлы
advice.os64butjdk32=Ваша ОС 64-битных но ваш java является 32-разрядной. В 64-разрядной версии java рекомендуется.
advice.java8=Java 8 представляет предположил, что может сделать игру работать более плавно. И много модов и Майнкрафт 1.12 и новые версии требуется java 8.
advice.os64butjdk32=Ваша ОС 64-битная, но ваш java является 32-разрядной. Вам рекомендуется 64-разрядная версия java.
advice.java8=Java 8 представляет предположил, что может сделать игру работать более производительной. Многие моды и Minecraft 1.12 и новые версии требуют java 8.
assets.download_all=Скачать Файлы
assets.not_refreshed=Список активов не обновляется, пожалуйста, обновите его один раз.
assets.not_refreshed=Список библиотек не обновляется, пожалуйста, обновите его один раз.
assets.failed=Не удалось получить список, попробуйте еще раз.
assets.list.1_7_3_after=1.7.3 и выше
assets.list.1_6=1.6(BMCLAPI)
assets.unkown_type_select_one=Неизвестная версия игры: %s, пожалуйста, выберите тип актива.
assets.type=Тип Актива
assets.download=Скачать Активы
assets.no_assets=Активов не завершена, завершить их?
assets.failed_download=Не удалось загрузить активы, может вызвать никаких звуков и языковые файлы.
assets.unkown_type_select_one=Неизвестная версия игры: %s, пожалуйста, выберите тип библиотеки.
assets.type=Тип библиолтек
assets.download=Скачать библиотеки
assets.no_assets=Библиотеки не завершены, завершить их?
assets.failed_download=Не удалось загрузить библиотеки из-за этого может не быть никаких звуков и языковых файлов.
gamedownload.not_refreshed=Список игр не обновляется, пожалуйста, обновите его один раз.
@@ -377,25 +377,25 @@ taskwindow.total_progress=Общий прогресс
taskwindow.cancel=Отменить
taskwindow.no_more_instance=Может быть, вы открыли больше чем одно окно задач, не открыть его снова!
taskwindow.file_name=Задача
taskwindow.download_progress=Проценты.
taskwindow.download_progress=%.
setupwindow.include_minecraft=Импорт игры
setupwindow.find_in_configurations=Завершения импорта. Вы можете найти его в панели выбора конфигурации.
setupwindow.give_a_name=Дать название новой игры.
setupwindow.give_a_name=Дайте название новой игры.
setupwindow.new=Новое
setupwindow.no_empty_name=Название версии не может быть пустым.
setupwindow.clean=Чистые файлы игры
update.no_browser=Не можете открыть любым браузером. Ссылка была скопирована в буфер обмена. Вставьте его в адресную строку браузера обновить.
update.no_browser=Не может открыть любым браузером. Ссылка была скопирована в буфер обмена. Вставьте его в адресную строку браузера обновить.
update.should_open_link=Вы готовы обновить лаунчер?
update.newest_version=Самая новая версия:
update.failed=Не удалось проверить наличие обновлений.
update.found=(Нашел Обновление!)
logwindow.terminate_game=Завершить Игру
logwindow.terminate_game=Завершить игру
logwindow.title=Лог
logwindow.contact=Свяжитесь С Нами
logwindow.show_lines=Показать Строки
logwindow.contact=Свяжитесь с нами
logwindow.show_lines=Показать строки
logwindow.search=Поиск
selector.choose=Выбрать
@@ -420,21 +420,21 @@ color.orange=Оранжевый
color.dark_blue=Темно-Синий
color.purple=Фиолетовый
wizard.next_>=Next >
wizard.next_>=Следующий >
wizard.next_mnemonic=N
wizard.<_prev=< Prev
wizard.<_prev=< Предыдущий
wizard.prev_mnemonic=P
wizard.finish=Finish
wizard.finish=Завершить
wizard.finish_mnemonic=F
wizard.cancel=Cancel
wizard.cancel=Отменить
wizard.cancel_mnemonic=C
wizard.help=Help
wizard.help=Помощь
wizard.help_mnemonic=H
wizard.close=Close
wizard.close=Закрыть
wizard.close_mnemonic=C
wizard.summary=Summary
wizard.failed=Failed
wizard.steps=Steps
lang=Russian
lang.default=Belong to OS language.
lang=Русский
lang.default=Выбран язык операционной системы.
@@ -19,15 +19,15 @@ launch.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u04
launch.failed_creating_process=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u0430\u0448 \u043f\u0443\u0442\u044c java - \u0443\u043a\u0430\u0437\u0430\u043d \u043d\u0435 \u0432\u0435\u0440\u043d\u043e, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u043f\u0443\u0442\u044c java.
launch.failed_sh_permission=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u043a\u0440\u0438\u043f\u0442\u0430.
launch.failed_packing_jar=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u0432 jar.
launch.unsupported_launcher_version=\u0418\u0437\u0432\u0438\u043d\u0438\u0442\u0435, Launcher \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c minecraft, \u043d\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430.
launch.too_big_memory_alloc_64bit=\u0412\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u043b\u0438 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u043f\u0430\u043c\u044f\u0442\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e 32-\u0440\u0430\u0437\u0440\u044f\u0434\u043d\u0430\u044f \u0421\u0440\u0435\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f java, \u0442\u043e \u0438\u0433\u0440\u0430 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043a\u0440\u0430\u0448\u0443. \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u0438 1024\u041c\u0411. \u041b\u0430\u0443\u043d\u0447\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e.
launch.unsupported_launcher_version=\u0418\u0437\u0432\u0438\u043d\u0438\u0442\u0435, Launcher \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c minecraft, \u043d\u043e \u043e\u043d \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430.
launch.too_big_memory_alloc_64bit=\u0412\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u043b\u0438 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u043f\u0430\u043c\u044f\u0442\u0438 \u0434\u043b\u044f 32-\u0440\u0430\u0437\u0440\u044f\u0434\u043d\u043e\u0439 \u041e\u0421 java \u0438\u0433\u0440\u0430 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043a\u0440\u0430\u0448\u0443. \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u0438 1024\u041c\u0411. \u041b\u0430\u0443\u043d\u0447\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e.
launch.too_big_memory_alloc_free_space_too_low=\u0412\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u043b\u0438 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u043f\u0430\u043c\u044f\u0442\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 %dMB, \u0432\u0430\u0448\u0430 \u0438\u0433\u0440\u0430 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043a\u0440\u0430\u0448\u0443. \u041b\u0430\u0443\u043d\u0447\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e.
launch.cannot_create_jvm=\u041c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043e\u043d \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c java \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u0430\u0448\u0438\u043d\u0430. \u0412 Java \u0430\u0433\u0440\u0435\u043c\u0430\u043d\u044b \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c No args \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445.
launch.cannot_create_jvm=\u041c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043e\u043d \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c java \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u0430\u0448\u0438\u043d\u0430. \u0412 Java \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u0445 \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c No args \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445.
launch.circular_dependency_versions=\u041d\u0430\u0448\u043b\u0438 \u043a\u0440\u0443\u0433\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0435\u0441\u043b\u0438 \u0432\u0430\u0448 \u043a\u043b\u0438\u0435\u043d\u0442 \u0431\u044b\u043b \u0438\u0437\u043c\u0435\u043d\u0435\u043d.
launch.not_finished_downloading_libraries=\u041d\u0435 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u0432 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a \u0438\u0433\u0440\u044b?
launch.not_finished_decompressing_natives=\u041d\u0435 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a \u0438\u0433\u0440\u044b?
launch.wrong_javadir=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0438 java, \u0431\u0443\u0434\u0443\u0442 \u0441\u0431\u0440\u043e\u0448\u0435\u043d\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u0432 java.
launch.exited_abnormally=\u0418\u0433\u0440\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430\u0441\u044c \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u043e, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u0436\u0443\u0440\u043d\u0430\u043b, \u0438\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043a\u043e\u0433\u043e-\u0442\u043e \u043e \u043f\u043e\u043c\u043e\u0449\u0438.
launch.not_finished_decompressing_natives=\u041d\u0435 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a \u0438\u0433\u0440\u044b?
launch.wrong_javadir=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0438 java, \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u0431\u0440\u043e\u0448\u0435\u043d \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043a\u0430\u0442\u0430\u043b\u043e\u0433 java.
launch.exited_abnormally=\u0418\u0433\u0440\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430\u0441\u044c \u043a\u0440\u0430\u0448\u0435\u043c, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u0436\u0443\u0440\u043d\u0430\u043b, \u0438\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043a\u043e\u0433\u043e-\u0442\u043e \u043e \u043f\u043e\u043c\u043e\u0449\u0438.
launch.state.logging_in=\u0412\u0445\u043e\u0434
launch.state.generating_launching_codes=\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u0434\u0430
@@ -36,7 +36,7 @@ launch.state.decompressing_natives=\u0422\u0443\u0437\u0435\u043c\u0446\u0435\u0
launch.state.waiting_launching=\u0416\u0434\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0433\u0440\u044b
install.no_version=\u0412\u0435\u0440\u0441\u0438\u044f \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430.
install.no_version_if_intall=\u041d\u0443\u0436\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430, \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e?
install.no_version_if_intall=\u041d\u0443\u0436\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430, \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0430\u0441\u044c \u0432\u0435\u0440\u0441\u0438\u044f?
install.not_refreshed=\u0421\u043f\u0438\u0441\u043e\u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f.
install.download_list=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a
@@ -86,7 +86,7 @@ login.type=\u041b\u043e\u0433\u0438\u043d
login.username=\u041d\u0438\u043a
login.account=\u041f\u043e\u0447\u0442\u0430
login.invalid_token=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u044b\u0439\u0434\u0438\u0442\u0435 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443.
login.no_valid_character=\u041d\u0435 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 skinme.cc \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u0435\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430.
login.no_valid_character=\u041d\u0435 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 skinme.cc \u0438 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0441\u0432\u043e\u0435\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430.
proxy.username=\u0410\u043a\u043a\u0430\u0443\u043d\u0442
proxy.password=\u041f\u0430\u0440\u043e\u043b\u044c
@@ -96,7 +96,7 @@ proxy.port=\u041f\u043e\u0440\u0442
login.failed.connect_authentication_server=\u041d\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0432\u0430\u0448\u0443 \u0441\u0435\u0442\u044c.
login.profile.not_logged_in=\u0412\u044b \u043d\u0435 \u0432\u043e\u0448\u043b\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443, \u0412\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c!
login.profile.selected=\u041d\u0435 \u043c\u043e\u0433\u0443 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c, \u0432\u044b\u0439\u0442\u0438 \u0438 \u043f\u043e\u0439\u0442\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c.
login.profile.selected=\u041d\u0435 \u043c\u043e\u0433\u0443 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c, \u0432\u044b\u0439\u0434\u0438\u0442\u0435 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435.
login.methods.yggdrasil=Email \u0438 \u043f\u0430\u0440\u043e\u043b\u044c
login.methods.offline=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0432\u0430\u0448 \u043d\u0438\u043a
@@ -114,9 +114,9 @@ ui.login.password=\u041f\u0430\u0440\u043e\u043b\u044c
ui.more=\u0411\u043e\u043b\u044c\u0448\u0435
crash.advice.UnsupportedClassVersionError=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u0430\u0448\u0430 \u0432\u0435\u0440\u0441\u0438\u044f java \u0441\u0442\u0430\u0440\u0430\u044f, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c java.
crash.advice.ConcurrentModificationException=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u0430\u0448 java \u043d\u043e\u0432\u0435\u0435, \u0447\u0435\u043c 1.8.0_11, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043d\u0438\u0437\u0438\u0442\u044c \u0434\u043e \u0432\u0435\u0440\u0441\u0438\u0438 java 7.
crash.advice.ConcurrentModificationException=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u0430\u0448 java \u043d\u043e\u0432\u0435\u0435, \u0447\u0435\u043c 1.8.0_11, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043d\u0438\u0437\u0438\u0442\u044c \u0434\u043e \u0432\u0435\u0440\u0441\u0438\u0438 Java 7.
crash.advice.ClassNotFoundException=Minecraft \u0438\u043b\u0438 \u043c\u043e\u0434\u044b, \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u043b\u043d\u044b\u043c\u0438. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u043a\u0430\u0447\u0430\u043b\u0438 \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0433\u0440\u0443 \u0438 \u043c\u043e\u0434\u043e\u0432! \u0418\u043b\u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u0433\u0440\u044b -> \u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 (\u0432\u0435\u0440\u0441\u0438\u0438) -> \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443.
crash.advice.NoSuchFieldError=\u041c\u0430\u0439\u043d\u043a\u0440\u0430\u0444\u0442 \u0438\u043b\u0438 \u043c\u043e\u0434\u044b, \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u043b\u043d\u044b\u043c\u0438. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u043a\u0430\u0447\u0430\u043b\u0438 \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0433\u0440\u0443 \u0438 \u043c\u043e\u0434\u043e\u0432!
crash.advice.NoSuchFieldError=Minecraft \u0438\u043b\u0438 \u043c\u043e\u0434\u044b, \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u043b\u043d\u044b\u043c\u0438. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u043a\u0430\u0447\u0430\u043b\u0438 \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0433\u0440\u0443 \u0438 \u043c\u043e\u0434\u044b!
crash.advice.LWJGLException=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u0430\u0448 \u0432\u0438\u0434\u0435\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0432\u0430\u0448 \u0432\u0438\u0434\u0435\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440.
crash.advice.SecurityException=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u044b \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438 minecraft.jar \u043d\u043e \u043d\u0435 \u0443\u0434\u0430\u043b\u0438\u043b\u0438 META-INF.
crash.advice.OutOfMemoryError=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043f\u0430\u043c\u044f\u0442\u0438 \u0434\u043b\u044f JVM \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u0430\u043b, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u0435\u0433\u043e.
@@ -127,21 +127,21 @@ crash.advice.no_lwjgl=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u
crash.advice.no=\u041d\u0438\u043a\u0430\u043a\u0438\u0435 \u0441\u043e\u0432\u0435\u0442\u044b.
crash.user_fault=\u0412\u0430\u0448\u0435\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438\u043b\u0438 \u0441\u0440\u0435\u0434\u044b java \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0441\u0431\u043e\u0439 \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0432\u0430\u0448\u0443 \u0441\u0440\u0435\u0434\u0443 java \u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440!
crash.headless=\u0415\u0441\u043b\u0438 \u0432\u0430\u0448\u0430 \u041e\u0421 Linux \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Oracle \u0432\u0435\u0440\u0441\u0438\u0438 jdk \u0432\u043c\u0435\u0441\u0442\u043e openjdk, \u0442\u043e \u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c "-Djava.awt.headless=false" \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 jvm, \u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u0430\u0448 x-\u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.
crash.user_fault=\u0412\u0430\u0448\u0435\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438\u043b\u0438 \u0441\u0440\u0435\u0434\u044b Java \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0441\u0431\u043e\u0439 \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0432\u0430\u0448\u0443 \u0441\u0440\u0435\u0434\u0443 Java \u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440!
crash.headless=\u0415\u0441\u043b\u0438 \u0432\u0430\u0448\u0430 \u041e\u0421 Linux \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Oracle \u0432\u0435\u0440\u0441\u0438\u0438 JDK \u0432\u043c\u0435\u0441\u0442\u043e OpenJDK, \u0442\u043e \u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c "-Djava.awt.headless=false" \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 JVM, \u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.
crash.NoClassDefFound=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 "Launcher" \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0442\u0435.
crash.error=Minecraft \u043a\u0440\u0430\u0448\u043d\u0443\u043b\u0441\u044f.
crash.main_class_not_found=\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u041a\u043b\u0430\u0441\u0441 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u0430\u0448 \u041c\u041a \u0431\u044b\u043b \u043d\u0430\u0440\u0443\u0448\u0435\u043d.
crash.class_path_wrong=\u041c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439.
ui.label.newProfileWindow.new_profile_name=\u041d\u043e\u0432\u043e\u0435 \u0418\u043c\u044f \u041f\u0440\u043e\u0444\u0438\u043b\u044f:
ui.label.newProfileWindow.copy_from=\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0418\u0437:
ui.newProfileWindow.title=\u041d\u043e\u0432\u044b\u0439 \u041a\u043e\u043d\u0444\u0438\u0433
ui.label.newProfileWindow.new_profile_name=\u041d\u043e\u0432\u043e\u0435 \u0418\u043c\u044f \u043f\u0440\u043e\u0444\u0438\u043b\u044f:
ui.label.newProfileWindow.copy_from=\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437:
ui.newProfileWindow.title=\u041d\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0444\u0438\u0433
ui.button.ok=OK
ui.button.refresh=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c
ui.button.run=\u0418\u0433\u0440\u0430\u0442\u044c
ui.button.run=\u0412\u043e\u0439\u0442\u0438 \u0432 \u0438\u0433\u0440\u0443
ui.button.settings=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
ui.button.about=About
ui.button.others=\u0414\u0440\u0443\u0433\u0438\u0435
@@ -160,8 +160,8 @@ ui.button.test=\u0422\u0435\u0441\u0442
ui.button.preview=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c
button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
button.ok=OK
button.yes=\u0434\u0430
button.no=\u041d\u0435\u0430
button.yes=\u0414\u0430
button.no=\u041d\u0435\u0442
ui.label.version=\u0412\u0435\u0440\u0441\u0438\u044f
ui.label.password=\u041f\u0430\u0440\u043e\u043b\u044c
@@ -176,8 +176,8 @@ ui.message.update_java=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0
ui.message.open_jdk=\u041c\u044b \u0443\u0436\u0435 \u0432\u044b\u044f\u0441\u043d\u0438\u043b\u0438, \u0447\u0442\u043e \u0432\u044b \u043d\u0430\u0447\u0430\u043b\u0438 \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f OpenJDK, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0442\u0430\u043d\u0435\u0442 \u043f\u0440\u0438\u0447\u0438\u043d\u043e\u0439 \u0441\u0442\u043e\u043b\u044c\u043a\u0438\u0445 \u0431\u0435\u0434 \u0434\u043b\u044f \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u041c\u044b \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c \u0412\u0430\u043c \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Oracle \u0432\u0435\u0440\u0441\u0438\u0438 JDK.
ui.label.settings=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
ui.label.crashing=<html>Hello Minecraft! Launcher \u043a\u0440\u0430\u0448\u043d\u0443\u043b\u0441\u044f!</html>
ui.label.crashing_out_dated=<html>Hello Minecraft! Launcher \u043a\u0440\u0430\u0448\u043d\u0443\u043b\u0441\u044f! \u0412\u0430\u0448 \u043b\u0430\u0443\u043d\u0447\u0435\u0440 \u0443\u0441\u0442\u0430\u0440\u0435\u043b. \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0435\u0433\u043e</html>
ui.label.crashing=<html>Launcher \u043a\u0440\u0430\u0448\u043d\u0443\u043b\u0441\u044f!</html>
ui.label.crashing_out_dated=<html>Launcher \u043a\u0440\u0430\u0448\u043d\u0443\u043b\u0441\u044f! \u0412\u0430\u0448 \u043b\u0430\u0443\u043d\u0447\u0435\u0440 \u0443\u0441\u0442\u0430\u0440\u0435\u043b. \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0435\u0433\u043e</html>
ui.label.failed_set=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c:
download=\u0421\u043a\u0430\u0447\u0430\u0442\u044c
@@ -190,16 +190,16 @@ download.successfully=\u0423\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043a\u0
download.source=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a
message.error=\u041e\u0448\u0438\u0431\u043a\u0430
message.cannot_open_explorer=Cannot open explorer:
message.cannot_open_explorer=\u041d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043f\u0440\u043e\u0432\u043e\u0434\u043d\u0438\u043a:
message.cancelled=\u041e\u0442\u043c\u0435\u043d\u0435\u043d
message.info=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f
message.loading=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430...
folder.game=Game Dir
folder.mod=\u041c\u043e\u0434
folder.coremod=Core Mod
folder.game=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f
folder.mod=\u041c\u043e\u0434\u044b
folder.coremod=\u042f\u0434\u0440\u043e
folder.config=\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438
folder.resourcepacks=\u0420\u0435\u0441\u0443\u0440\u0441 \u043f\u0430\u043a\u0438
folder.resourcepacks=\u0420\u0435\u0441\u0443\u0440\u0441 \u043f\u0430\u043a
folder.screenshots=\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b
folder.saves=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
@@ -208,25 +208,25 @@ settings.tabs.installers=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0449\u0438\
settings.tabs.assets_downloads=\u0414\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f
settings=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
settings.explore=\u0412\u044b\u0431\u0440\u0430\u0442\u044c
settings.explore=\u041e\u0431\u0437\u043e\u0440...
settings.manage=\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c
settings.cannot_remove_default_config=\u041d\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u0443\u0434\u0430\u043b\u0438\u0442\u044c configution \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.
settings.max_memory=Max Memory/MB
settings.java_dir=Java Dir
settings.game_directory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0418\u0433\u0440\u044b
settings.dimension=\u0418\u0433\u0440\u0430 \u041e\u043a\u043d\u043e \u0418\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f
settings.fullscreen=\u041f\u043e\u043b\u043d\u043e\u044d\u043a\u0440\u0430\u043d\u043d\u044b\u0439
settings.cannot_remove_default_config=\u041d\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.
settings.max_memory=\u0412\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438
settings.java_dir=\u041f\u0443\u0442\u044c \u043a Java
settings.game_directory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f
settings.dimension=\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435
settings.fullscreen=\u041f\u043e\u043b\u043d\u043e\u044d\u043a\u0440\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c
settings.update_version=\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 json.
settings.run_directory=\u0417\u0430\u043f\u0443\u0441\u043a \u041a\u0430\u0442\u0430\u043b\u043e\u0433\u0430(\u0418\u0437\u043e\u043b\u044f\u0446\u0438\u044f \u0412\u0435\u0440\u0441\u0438\u044f)
settings.physical_memory=\u0420\u0430\u0437\u043c\u0435\u0440 \u0424\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u041f\u0430\u043c\u044f\u0442\u0438
settings.choose_javapath=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u041a\u0430\u0442\u0430\u043b\u043e\u0433 Java.
settings.default=Default
settings.run_directory=\u0412\u044b\u0431\u043e\u0440 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430
settings.physical_memory=\u0420\u0430\u0437\u043c\u0435\u0440 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438
settings.choose_javapath=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043a\u0430\u0442\u0430\u043b\u043e\u0433 Java.
settings.default=\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e
settings.custom=\u0412\u044b\u0431\u0440\u0430\u0442\u044c
settings.choose_gamedir=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0418\u0433\u0440\u044b
settings.choose_gamedir=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0438\u0433\u0440\u044b
settings.failed_load=\u041d\u0435 \u0441\u043c\u043e\u0433 \u0444\u0430\u0439\u043b \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0435\u0433\u043e?
settings.test_game=\u0422\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u0438\u0433\u0440\u0430
settings.type.none=\u041d\u0435\u0442 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u0433\u0440\u044b, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043d\u0430 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0438\u0433\u0440\u044b.
settings.type.none=\u041d\u0435\u0442 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u0433\u0440\u044b, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u0440\u0430\u0437\u0434\u0435\u043b \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0438\u0433\u0440\u0443.
settings.type.global=<html><a href="">\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u0439. \u0421\u0435\u0439\u0447\u0430\u0441 \u044d\u0442\u043e \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430.</a></html>
settings.type.special=<html><a href="">\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u041d\u0435 \u044d\u0442\u043e \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445.</a></html>
@@ -249,7 +249,7 @@ modpack.wizard.step.1.title=\u041d\u0430\u0431\u043e\u0440 \u043e\u0441\u043d\u0
modpack.wizard.step.initialization.include_launcher=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043b\u0430\u0443\u043d\u0447\u0435\u0440
modpack.wizard.step.initialization.exported_version=\u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u0433\u0440\u044b
modpack.wizard.step.initialization.save=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u043b\u044f
modpack.wizard.step.initialization.warning=<html>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0443\u0434, \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0430\u0448\u0430 \u0438\u0433\u0440\u0430 \u0441\u043c\u043e\u0436\u0435\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430,<br/>\u0438 \u0447\u0442\u043e \u0432\u0430\u0448 minecraft-\u044d\u0442\u043e \u0440\u0435\u043b\u0438\u0437, \u0430 \u043d\u0435 \u0441\u043d\u0438\u043c\u043e\u043a.<br/>\u0430 \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u043e\u0434\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u0438 \u0440\u0430\u0437\u0434\u0430\u0432\u0430\u0442\u044c modpack.</html>
modpack.wizard.step.initialization.warning=<html>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c modpack, \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0430\u0448\u0430 \u0438\u0433\u0440\u0430 \u0441\u043c\u043e\u0436\u0435\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c,<br/>\u0438 \u0447\u0442\u043e \u0432\u0430\u0448 minecraft-\u044d\u0442\u043e \u0440\u0435\u043b\u0438\u0437, \u0430 \u043d\u0435 \u0441\u043d\u0438\u043c\u043e\u043a.<br/>\u0430 \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u043e\u0434\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u0438 \u0440\u0430\u0437\u0434\u0430\u0432\u0430\u0442\u044c modpack.</html>
modpack.wizard.step.2=\u0412\u044b\u0431\u043e\u0440 \u0444\u0430\u0439\u043b\u043e\u0432
modpack.wizard.step.2.title=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u0430\u0439\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0412\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0432 modpack.
modpack.wizard.step.3=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435
@@ -281,18 +281,18 @@ mods.choose_mod=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0430\u0448\u0
mods.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u043e\u0434\u044b
mods.add=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c
mods.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
mods.default_information=<html><font color=#c0392b>\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 Forge \u0438\u043b\u0438 LiteLoader \u043f\u0435\u0440\u0435\u0434 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 \u043c\u043e\u0434\u043e\u0432!<br>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0439 mod \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u0437 \u043f\u0440\u043e\u0432\u043e\u0434\u043d\u0438\u043a\u0430/Finder \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043d\u043e\u043f\u043a\u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c.<br>\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043c\u043e\u0434, \u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0444\u043b\u0430\u0436\u043e\u043a \u0441\u043d\u044f\u0442; \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0442\u043e\u0432\u0430\u0440, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e.</font></html>
mods.default_information=<html><font color=#c0392b>\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 Forge \u0438\u043b\u0438 LiteLoader \u043f\u0435\u0440\u0435\u0434 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 \u043c\u043e\u0434\u043e\u0432!<br>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0439 mod \u0444\u0430\u0439\u043b \u0438\u0437 \u043f\u0440\u043e\u0432\u043e\u0434\u043d\u0438\u043a\u0430/Finder \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043d\u043e\u043f\u043a\u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c.<br>\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043c\u043e\u0434, \u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0444\u043b\u0430\u0436\u043e\u043a \u0441\u043d\u044f\u0442; \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0442\u043e\u0432\u0430\u0440, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e.</font></html>
advancedsettings=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0439
advancedsettings.launcher_visible=\u041b\u0430\u0443\u043d\u0447\u0435\u0440 \u0412\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u044c
advancedsettings.debug_mode=\u0420\u0435\u0436\u0438\u043c \u041e\u0442\u043b\u0430\u0434\u043a\u0438
advancedsettings.launcher_visible=\u041f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 Minecraft
advancedsettings.debug_mode=\u0420\u0435\u0436\u0438\u043c \u043e\u0442\u043b\u0430\u0434\u043a\u0438
advancedsettings.java_permanent_generation_space=PermGen Space/MB
advancedsettings.jvm_args=Java VM Arguments
advancedsettings.Minecraft_arguments=\u041c\u0430\u0439\u043d\u043a\u0440\u0430\u0444\u0442 \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b
advancedsettings.jvm_args=Java VM \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b
advancedsettings.Minecraft_arguments=Minecraft \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b
advancedsettings.launcher_visibility.close=\u0417\u0430\u043a\u0440\u044b\u0442\u044c \u043b\u0430\u0443\u043d\u0447\u0435\u0440, \u0435\u0441\u043b\u0438 \u0438\u0433\u0440\u0430 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430.
advancedsettings.launcher_visibility.hide=\u0421\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u043a\u043e\u0433\u0434\u0430 \u0438\u0433\u0440\u0430 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430.
advancedsettings.launcher_visibility.keep=\u0414\u0435\u0440\u0436\u0438\u0442\u0435 \u043f\u0443\u0441\u043a\u043e\u0432\u0443\u044e \u0432\u0438\u0434\u043d\u044b.
advancedsettings.launcher_visibility.hide_reopen=\u0421\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u0438\u0433\u0440\u0430 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f.
advancedsettings.launcher_visibility.hide=\u0421\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043b\u0430\u0443\u043d\u0447\u0435\u0440, \u043a\u043e\u0433\u0434\u0430 \u0438\u0433\u0440\u0430 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430.
advancedsettings.launcher_visibility.keep=\u041e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043b\u0430\u0443\u043d\u0447\u0435\u0440 \u0432\u0438\u0434\u0438\u043c\u044b\u043c.
advancedsettings.launcher_visibility.hide_reopen=\u0421\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043b\u0430\u0443\u043d\u0447\u0435\u0440 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u0432\u044b\u0439\u0434\u0438\u0442\u0435 \u0438\u0437 \u0438\u0433\u0440\u044b.
advancedsettings.game_dir.default=\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e (.minecraft/)
advancedsettings.game_dir.independent=\u041d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 (.minecraft/\u0432\u0435\u0440\u0441\u0438\u0438/<\u043d\u043e\u043c\u0435\u0440 \u0432\u0435\u0440\u0441\u0438\u0438>/, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0430\u043a\u0442\u0438\u0432\u043e\u0432,\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438)
advancedsettings.no_jvm_args=No Default JVM Args
@@ -301,15 +301,15 @@ advancedsettings.java_args_default=Default java args: -XX:+UseConcMarkSweepGC -X
advancedsettings.wrapper_launcher=\u041b\u0430\u0443\u043d\u0447\u0435\u0440-\u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443(\u043a\u0430\u043a \u0438 optirun...)
advancedsettings.precall_command=\u041a\u043e\u043c\u0430\u043d\u0434\u0430 Precalling(\u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0434\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0433\u0440\u044b)
advancedsettings.server_ip=\u0421\u0435\u0440\u0432\u0435\u0440\u0430
advancedsettings.cancel_wrapper_launcher=\u041e\u0442\u043c\u0435\u043d\u0430 \u0417\u0430\u043f\u0443\u0441\u043a\u0430 \u041e\u0431\u043e\u043b\u043e\u0447\u043a\u0438
advancedsettings.cancel_wrapper_launcher=\u041e\u0442\u043c\u0435\u043d\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0438
advancedsettings.dont_check_game_completeness=\u041d\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0442\u0443 \u0438\u0433\u0440\u044b
mainwindow.show_log=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u041b\u043e\u0433\u0438
mainwindow.make_launch_script=\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u0417\u0430\u043f\u0443\u0441\u043a \u0421\u043a\u0440\u0438\u043f\u0442\u0430.
mainwindow.make_launch_script=\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u043a\u0440\u0438\u043f\u0442\u0430.
mainwindow.make_launch_script_failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442.
mainwindow.enter_script_name=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u0430.
mainwindow.make_launch_succeed=\u0417\u0430\u043a\u043e\u043d\u0447\u0438\u043b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430.
mainwindow.no_version=\u0412\u0435\u0440\u0441\u0438\u0438 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u044b. \u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u0433\u0440\u044b?
mainwindow.no_version=\u0412\u0435\u0440\u0441\u0438\u0438 Minecraft \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u044b. \u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u043b\u044f \u0438\u0433\u0440\u044b \u0432 Minecraft?
launcher.about=<html>\u041e\u0431 \u0410\u0432\u0442\u043e\u0440\u0435<br/>\u041c\u0430\u0439\u043d\u043a\u0440\u0430\u0444\u0442 \u0444\u043e\u0440\u0443\u043c 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=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438
@@ -321,22 +321,22 @@ launcher.versions_json_not_matched_cannot_auto_completion=\u0412\u0435\u0440\u04
launcher.versions_json_not_formatted=\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0432\u0435\u0440\u0441\u0438\u0438 %s \u0443\u0440\u043e\u0434\u043b\u0438\u0432! \u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430?
launcher.choose_bgpath=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u043e\u043d\u043e\u0432\u044b\u0439 \u043f\u0443\u0442\u0438.
launcher.choose_commonpath=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u043f\u0443\u0442\u044c.
launcher.commpath_tooltip=<html><body>\u042d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0438\u0433\u0440\u043e\u0432\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0430\u043a\u0442\u0438\u0432\u044b \u0437\u0434\u0435\u0441\u044c, \u0435\u0441\u043b\u0438 \u0442\u0430\u043c \u043d\u0435\u0442 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u043f\u0430\u043f\u043a\u0443 \u0441 \u0438\u0433\u0440\u043e\u0439.</body></html>
launcher.commpath_tooltip=<html><body>\u042d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0432\u0441\u0435 \u0438\u0433\u0440\u043e\u0432\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0437\u0434\u0435\u0441\u044c, \u0435\u0441\u043b\u0438 \u0442\u0430\u043c \u043d\u0435\u0442 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u043f\u0430\u043f\u043a\u0435 \u0441 \u0438\u0433\u0440\u043e\u0439.</body></html>
launcher.background_tooltip=<html><body>\u041b\u0430\u0443\u0447\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0444\u043e\u043d.<br/>\u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0444\u043e\u043d.PNG, \u0441\u0441\u044b\u043b\u043a\u0443 \u0438 \u043e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<br />\u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c "\u0411\u0413" \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433, \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0434\u043d\u0443 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443 \u0432 "bgskin" \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e.<br />\u0415\u0441\u043b\u0438 \u0432\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0444\u043e\u043d, \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e.</body></html>
launcher.update_launcher=\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f
launcher.enable_shadow=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c Window Shadow
launcher.enable_animation=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c Animation
launcher.enable_blur=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c Blur
launcher.enable_shadow=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0442\u0435\u043d\u044c \u043e\u043a\u043d\u0430
launcher.enable_animation=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e
launcher.enable_blur=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u044b\u0442\u0438\u0435
launcher.theme=\u0422\u0435\u043c\u0430
launcher.proxy=\u041f\u0440\u043e\u043a\u0441\u0438
launcher.decorated=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043e\u043a\u043d\u0430(\u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0432\u0441\u0435 \u0441\u0435\u0440\u044b\u0435 \u0432 \u041e\u0421 Linux)
launcher.modpack=<html><a href="http://blog.163.com/huanghongxun2008@126/blog/static/7738046920160323812771/">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0434\u043b\u044f modpacks.</a></html>
launcher.decorated=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043e\u043a\u043d\u0430(\u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u0435\u0441\u043b\u0438 \u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0432\u0441\u0435 \u0441\u0435\u0440\u043e\u0435 \u0432 \u041e\u0421 Linux)
launcher.modpack=<html><a href="http://blog.163.com/huanghongxun2008@126/blog/static/7738046920160323812771/">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e modpacks.</a></html>
launcher.lang=\u042f\u0437\u044b\u043a (Language)
launcher.restart=\u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0432 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438, \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.
launcher.log_font=\u0428\u0440\u0438\u0444\u0442 \u041b\u043e\u0433\u0430
launcher.log_font=\u0428\u0440\u0438\u0444\u0442 \u043b\u043e\u0433\u0430
launcher.tab.general=\u041e\u0431\u0449\u0438\u0435
launcher.tab.ui=\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441
launcher.tab.about=\u0410\u0432\u0442\u043e\u0440
launcher.tab.about=\u0412\u0435\u0440\u0441\u0438\u044f
launcher.title.game=\u0418\u0433\u0440\u044b
launcher.title.main=\u0413\u043b\u0430\u0432\u043d\u0430\u044f
@@ -352,22 +352,22 @@ versions.manage.rename.message=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\
versions.manage.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e
versions.manage.remove.confirm=\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e
versions.manage.redownload_json=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0432 Minecraft(minecraft.json)
versions.manage.redownload_assets_index=\u0418\u043d\u0434\u0435\u043a\u0441 \u041f\u0435\u0440\u0435\u043a\u0430\u0447\u0430\u0439\u0442\u0435 \u0410\u043a\u0442\u0438\u0432\u043e\u0432
versions.mamage.remove_libraries=\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0444\u0430\u0439\u043b\u044b
versions.manage.redownload_assets_index=\u041f\u0435\u0440\u0435\u043a\u0430\u0447\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438
versions.mamage.remove_libraries=\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b
advice.os64butjdk32=\u0412\u0430\u0448\u0430 \u041e\u0421 64-\u0431\u0438\u0442\u043d\u044b\u0445 \u043d\u043e \u0432\u0430\u0448 java \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f 32-\u0440\u0430\u0437\u0440\u044f\u0434\u043d\u043e\u0439. \u0412 64-\u0440\u0430\u0437\u0440\u044f\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 java \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f.
advice.java8=Java 8 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043b, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0433\u0440\u0443 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043b\u0430\u0432\u043d\u043e. \u0418 \u043c\u043d\u043e\u0433\u043e \u043c\u043e\u0434\u043e\u0432 \u0438 \u041c\u0430\u0439\u043d\u043a\u0440\u0430\u0444\u0442 1.12 \u0438 \u043d\u043e\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f java 8.
advice.os64butjdk32=\u0412\u0430\u0448\u0430 \u041e\u0421 64-\u0431\u0438\u0442\u043d\u0430\u044f, \u043d\u043e \u0432\u0430\u0448 java \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f 32-\u0440\u0430\u0437\u0440\u044f\u0434\u043d\u043e\u0439. \u0412\u0430\u043c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f 64-\u0440\u0430\u0437\u0440\u044f\u0434\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f java.
advice.java8=Java 8 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043b, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0433\u0440\u0443 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439. \u041c\u043d\u043e\u0433\u0438\u0435 \u043c\u043e\u0434\u044b \u0438 Minecraft 1.12 \u0438 \u043d\u043e\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 java 8.
assets.download_all=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0424\u0430\u0439\u043b\u044b
assets.not_refreshed=\u0421\u043f\u0438\u0441\u043e\u043a \u0430\u043a\u0442\u0438\u0432\u043e\u0432 \u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0435\u0433\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437.
assets.not_refreshed=\u0421\u043f\u0438\u0441\u043e\u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0435\u0433\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437.
assets.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0435 \u0440\u0430\u0437.
assets.list.1_7_3_after=1.7.3 \u0438 \u0432\u044b\u0448\u0435
assets.list.1_6=1.6(BMCLAPI)
assets.unkown_type_select_one=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0438\u0433\u0440\u044b: %s, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0438\u043f \u0430\u043a\u0442\u0438\u0432\u0430.
assets.type=\u0422\u0438\u043f \u0410\u043a\u0442\u0438\u0432\u0430
assets.download=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0410\u043a\u0442\u0438\u0432\u044b
assets.no_assets=\u0410\u043a\u0442\u0438\u0432\u043e\u0432 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430, \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0438\u0445?
assets.failed_download=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u044b, \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0437\u0432\u0443\u043a\u043e\u0432 \u0438 \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b.
assets.unkown_type_select_one=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0438\u0433\u0440\u044b: %s, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0438\u043f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.
assets.type=\u0422\u0438\u043f \u0431\u0438\u0431\u043b\u0438\u043e\u043b\u0442\u0435\u043a
assets.download=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438
assets.no_assets=\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u044b, \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0438\u0445?
assets.failed_download=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0431\u044b\u0442\u044c \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0437\u0432\u0443\u043a\u043e\u0432 \u0438 \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432.
gamedownload.not_refreshed=\u0421\u043f\u0438\u0441\u043e\u043a \u0438\u0433\u0440 \u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0435\u0433\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437.
@@ -377,25 +377,25 @@ taskwindow.total_progress=\u041e\u0431\u0449\u0438\u0439 \u043f\u0440\u043e\u043
taskwindow.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
taskwindow.no_more_instance=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u044b \u043e\u0442\u043a\u0440\u044b\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u0447\u0435\u043c \u043e\u0434\u043d\u043e \u043e\u043a\u043d\u043e \u0437\u0430\u0434\u0430\u0447, \u043d\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0435\u0433\u043e \u0441\u043d\u043e\u0432\u0430!
taskwindow.file_name=\u0417\u0430\u0434\u0430\u0447\u0430
taskwindow.download_progress=\u041f\u0440\u043e\u0446\u0435\u043d\u0442\u044b.
taskwindow.download_progress=%.
setupwindow.include_minecraft=\u0418\u043c\u043f\u043e\u0440\u0442 \u0438\u0433\u0440\u044b
setupwindow.find_in_configurations=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u0435\u0433\u043e \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438.
setupwindow.give_a_name=\u0414\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u0438\u0433\u0440\u044b.
setupwindow.give_a_name=\u0414\u0430\u0439\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u0438\u0433\u0440\u044b.
setupwindow.new=\u041d\u043e\u0432\u043e\u0435
setupwindow.no_empty_name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c.
setupwindow.clean=\u0427\u0438\u0441\u0442\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0438\u0433\u0440\u044b
update.no_browser=\u041d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043b\u044e\u0431\u044b\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c. \u0421\u0441\u044b\u043b\u043a\u0430 \u0431\u044b\u043b\u0430 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430. \u0412\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0435\u0433\u043e \u0432 \u0430\u0434\u0440\u0435\u0441\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c.
update.no_browser=\u041d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043b\u044e\u0431\u044b\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c. \u0421\u0441\u044b\u043b\u043a\u0430 \u0431\u044b\u043b\u0430 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430. \u0412\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0435\u0433\u043e \u0432 \u0430\u0434\u0440\u0435\u0441\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c.
update.should_open_link=\u0412\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043b\u0430\u0443\u043d\u0447\u0435\u0440?
update.newest_version=\u0421\u0430\u043c\u0430\u044f \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f:
update.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439.
update.found=(\u041d\u0430\u0448\u0435\u043b \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435!)
logwindow.terminate_game=\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0418\u0433\u0440\u0443
logwindow.terminate_game=\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0438\u0433\u0440\u0443
logwindow.title=\u041b\u043e\u0433
logwindow.contact=\u0421\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0421 \u041d\u0430\u043c\u0438
logwindow.show_lines=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0421\u0442\u0440\u043e\u043a\u0438
logwindow.contact=\u0421\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u043d\u0430\u043c\u0438
logwindow.show_lines=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438
logwindow.search=\u041f\u043e\u0438\u0441\u043a
selector.choose=\u0412\u044b\u0431\u0440\u0430\u0442\u044c
@@ -420,22 +420,21 @@ color.orange=\u041e\u0440\u0430\u043d\u0436\u0435\u0432\u044b\u0439
color.dark_blue=\u0422\u0435\u043c\u043d\u043e-\u0421\u0438\u043d\u0438\u0439
color.purple=\u0424\u0438\u043e\u043b\u0435\u0442\u043e\u0432\u044b\u0439
wizard.next_>=Next >
wizard.next_>=\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 >
wizard.next_mnemonic=N
wizard.<_prev=< Prev
wizard.<_prev=< \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439
wizard.prev_mnemonic=P
wizard.finish=Finish
wizard.finish=\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c
wizard.finish_mnemonic=F
wizard.cancel=Cancel
wizard.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
wizard.cancel_mnemonic=C
wizard.help=Help
wizard.help=\u041f\u043e\u043c\u043e\u0449\u044c
wizard.help_mnemonic=H
wizard.close=Close
wizard.close=\u0417\u0430\u043a\u0440\u044b\u0442\u044c
wizard.close_mnemonic=C
wizard.summary=Summary
wizard.failed=Failed
wizard.steps=Steps
lang=Russian
lang.default=Belong to OS language.
lang=\u0420\u0443\u0441\u0441\u043a\u0438\u0439
lang.default=\u0412\u044b\u0431\u0440\u0430\u043d \u044f\u0437\u044b\u043a \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b.
@@ -390,7 +390,7 @@ update.no_browser=无法打开浏览器,网址已经复制到剪贴板了,
update.should_open_link=是否更新?
update.newest_version=最新版本为:
update.failed=检查更新失败
update.found=(发现更新!)
update.found=(点击此处更新)
logwindow.terminate_game=结束游戏进程
logwindow.title=日志
@@ -390,7 +390,7 @@ update.no_browser=\u65e0\u6cd5\u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u7f51\u5740\u
update.should_open_link=\u662f\u5426\u66f4\u65b0\uff1f
update.newest_version=\u6700\u65b0\u7248\u672c\u4e3a\uff1a
update.failed=\u68c0\u67e5\u66f4\u65b0\u5931\u8d25
update.found=(\u53d1\u73b0\u66f4\u65b0!)
update.found=(\u70b9\u51fb\u6b64\u5904\u66f4\u65b0)
logwindow.terminate_game=\u7ed3\u675f\u6e38\u620f\u8fdb\u7a0b
logwindow.title=\u65e5\u5fd7
+1 -1
View File
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https://services.gradle.org/distributions/gradle-3.3-bin.zip
distributionUrl=https://services.gradle.org/distributions/gradle-4.3-bin.zip
+1 -1
View File
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
rootProject.name = 'Hello Minecraft!'
rootProject.name = 'Hello_Minecraft'
// Find the directories containing a "build.gradle" file in the root directory
// of the project. That is, every directory containing a "build.gradle" will