优化游戏代理参数设置 (#5273)

This commit is contained in:
Glavo
2026-01-21 20:40:28 +08:00
committed by GitHub
parent 0a0476b6d3
commit 8aecbe89f9
4 changed files with 145 additions and 94 deletions

View File

@@ -21,7 +21,6 @@ import org.jackhuang.hmcl.java.JavaRuntime;
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
import java.net.Proxy;
import java.nio.file.Path;
import java.util.*;
@@ -49,11 +48,7 @@ public class LaunchOptions implements Serializable {
private boolean fullscreen;
private QuickPlayOption quickPlayOption;
private String wrapper;
private Proxy.Type proxyType;
private String proxyHost;
private int proxyPort;
private String proxyUser;
private String proxyPass;
private ProxyOption proxyOption;
private boolean noGeneratedJVMArgs;
private boolean noGeneratedOptimizingJVMArgs;
private String preLaunchCommand;
@@ -195,30 +190,8 @@ public class LaunchOptions implements Serializable {
return wrapper;
}
public Proxy.Type getProxyType() {
return proxyType;
}
public String getProxyHost() {
return proxyHost;
}
public int getProxyPort() {
return proxyPort;
}
/**
* The user name of the proxy, optional.
*/
public String getProxyUser() {
return proxyUser;
}
/**
* The password of the proxy, optional
*/
public String getProxyPass() {
return proxyPass;
public ProxyOption getProxyOption() {
return proxyOption;
}
/**
@@ -422,28 +395,8 @@ public class LaunchOptions implements Serializable {
return this;
}
public Builder setProxyType(Proxy.Type proxyType) {
options.proxyType = proxyType;
return this;
}
public Builder setProxyHost(String proxyHost) {
options.proxyHost = proxyHost;
return this;
}
public Builder setProxyPort(int proxyPort) {
options.proxyPort = proxyPort;
return this;
}
public Builder setProxyUser(String proxyUser) {
options.proxyUser = proxyUser;
return this;
}
public Builder setProxyPass(String proxyPass) {
options.proxyPass = proxyPass;
public Builder setProxyOption(ProxyOption proxyOption) {
options.proxyOption = proxyOption;
return this;
}

View File

@@ -0,0 +1,63 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2026 huangyuhui <huanghongxun2008@126.com> and contributors
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.game;
import org.jackhuang.hmcl.util.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/// @author Glavo
public sealed interface ProxyOption {
final class Direct implements ProxyOption {
public static final Direct INSTANCE = new Direct();
private Direct() {
}
}
final class Default implements ProxyOption {
public static final Default INSTANCE = new Default();
private Default() {
}
}
record Http(@NotNull String host, int port, @Nullable String username,
@Nullable String password) implements ProxyOption {
public Http {
if (StringUtils.isBlank(host)) {
throw new IllegalArgumentException("Host cannot be blank");
}
if (port < 0 || port > 0xFFFF) {
throw new IllegalArgumentException("Illegal port: " + port);
}
}
}
record Socks(@NotNull String host, int port, @Nullable String username,
@Nullable String password) implements ProxyOption {
public Socks {
if (StringUtils.isBlank(host)) {
throw new IllegalArgumentException("Host cannot be blank");
}
if (port < 0 || port > 0xFFFF) {
throw new IllegalArgumentException("Illegal port: " + port);
}
}
}
}

View File

@@ -30,7 +30,6 @@ import org.jackhuang.hmcl.util.platform.*;
import org.jackhuang.hmcl.util.versioning.GameVersionNumber;
import java.io.*;
import java.net.Proxy;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
@@ -170,22 +169,36 @@ public class DefaultLauncher extends Launcher {
if (OperatingSystem.CURRENT_OS != OperatingSystem.WINDOWS)
res.addDefault("-Duser.home=", options.getGameDir().toAbsolutePath().getParent().toString());
Proxy.Type proxyType = options.getProxyType();
if (proxyType == null) {
res.addDefault("-Djava.net.useSystemProxies=", "true");
} else {
String proxyHost = options.getProxyHost();
int proxyPort = options.getProxyPort();
boolean addProxyOptions = res.noneMatch(arg ->
arg.startsWith("-Djava.net.useSystemProxies=")
|| arg.startsWith("-Dhttp.proxy")
|| arg.startsWith("-Dhttps.proxy")
|| arg.startsWith("-DsocksProxy")
|| arg.startsWith("-Djava.net.socks.")
);
if (StringUtils.isNotBlank(proxyHost) && proxyPort >= 0 && proxyPort <= 0xFFFF) {
if (proxyType == Proxy.Type.HTTP) {
res.addDefault("-Dhttp.proxyHost=", proxyHost);
res.addDefault("-Dhttp.proxyPort=", String.valueOf(proxyPort));
res.addDefault("-Dhttps.proxyHost=", proxyHost);
res.addDefault("-Dhttps.proxyPort=", String.valueOf(proxyPort));
} else if (proxyType == Proxy.Type.SOCKS) {
res.addDefault("-DsocksProxyHost=", proxyHost);
res.addDefault("-DsocksProxyPort=", String.valueOf(proxyPort));
if (addProxyOptions) {
if (options.getProxyOption() == null || options.getProxyOption() == ProxyOption.Default.INSTANCE) {
res.add("-Djava.net.useSystemProxies=", "true");
} else if (options.getProxyOption() instanceof ProxyOption.Http httpProxy) {
res.add("-Dhttp.proxyHost=" + httpProxy.host());
res.add("-Dhttp.proxyPort=" + httpProxy.port());
res.add("-Dhttps.proxyHost=" + httpProxy.host());
res.add("-Dhttps.proxyPort=" + httpProxy.port());
if (StringUtils.isNotBlank(httpProxy.username())) {
res.add("-Dhttp.proxyUser=" + httpProxy.username());
res.add("-Dhttp.proxyPassword=" + Objects.requireNonNullElse(httpProxy.password(), ""));
res.add("-Dhttps.proxyUser=" + httpProxy.username());
res.add("-Dhttps.proxyPassword=" + Objects.requireNonNullElse(httpProxy.password(), ""));
}
} else if (options.getProxyOption() instanceof ProxyOption.Socks socksProxy) {
res.add("-DsocksProxyHost=" + socksProxy.host());
res.add("-DsocksProxyPort=" + socksProxy.port());
if (StringUtils.isNotBlank(socksProxy.username())) {
res.add("-Djava.net.socks.username=" + socksProxy.username());
res.add("-Djava.net.socks.password=" + Objects.requireNonNullElse(socksProxy.password(), ""));
}
}
}
@@ -334,21 +347,17 @@ public class DefaultLauncher extends Launcher {
if (options.isFullscreen())
res.add("--fullscreen");
if (options.getProxyType() == Proxy.Type.SOCKS) {
String proxyHost = options.getProxyHost();
int proxyPort = options.getProxyPort();
if (StringUtils.isNotBlank(proxyHost) && proxyPort >= 0 && proxyPort <= 0xFFFF) {
res.add("--proxyHost");
res.add(proxyHost);
res.add("--proxyPort");
res.add(String.valueOf(proxyPort));
if (StringUtils.isNotBlank(options.getProxyUser()) && StringUtils.isNotBlank(options.getProxyPass())) {
res.add("--proxyUser");
res.add(options.getProxyUser());
res.add("--proxyPass");
res.add(options.getProxyPass());
}
// https://github.com/HMCL-dev/HMCL/issues/774
if (options.getProxyOption() instanceof ProxyOption.Socks socksProxy) {
res.add("--proxyHost");
res.add(socksProxy.host());
res.add("--proxyPort");
res.add(String.valueOf(socksProxy.port()));
if (StringUtils.isNotBlank(socksProxy.username())) {
res.add("--proxyUser");
res.add(socksProxy.username());
res.add("--proxyPass");
res.add(Objects.requireNonNullElse(socksProxy.password(), ""));
}
}