|
|
|
@ -18,223 +18,236 @@
|
|
|
|
|
package net.raphimc.viaproxy.protocoltranslator.viaproxy;
|
|
|
|
|
|
|
|
|
|
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
|
|
|
|
import com.viaversion.viaversion.util.Config;
|
|
|
|
|
import joptsimple.OptionException;
|
|
|
|
|
import joptsimple.OptionParser;
|
|
|
|
|
import joptsimple.OptionSet;
|
|
|
|
|
import joptsimple.OptionSpec;
|
|
|
|
|
import net.raphimc.vialoader.util.JLoggerToSLF4J;
|
|
|
|
|
import net.lenni0451.optconfig.ConfigContext;
|
|
|
|
|
import net.lenni0451.optconfig.annotations.*;
|
|
|
|
|
import net.lenni0451.optconfig.index.ClassIndexer;
|
|
|
|
|
import net.lenni0451.optconfig.index.ConfigType;
|
|
|
|
|
import net.lenni0451.optconfig.index.types.ConfigOption;
|
|
|
|
|
import net.lenni0451.optconfig.index.types.SectionIndex;
|
|
|
|
|
import net.raphimc.viaproxy.ViaProxy;
|
|
|
|
|
import net.raphimc.viaproxy.cli.BetterHelpFormatter;
|
|
|
|
|
import net.raphimc.viaproxy.cli.HelpRequestedException;
|
|
|
|
|
import net.raphimc.viaproxy.cli.ProtocolVersionConverter;
|
|
|
|
|
import net.raphimc.viaproxy.plugins.events.PostOptionsParseEvent;
|
|
|
|
|
import net.raphimc.viaproxy.plugins.events.PreOptionsParseEvent;
|
|
|
|
|
import net.raphimc.viaproxy.protocoltranslator.ProtocolTranslator;
|
|
|
|
|
import net.raphimc.viaproxy.saves.impl.accounts.Account;
|
|
|
|
|
import net.raphimc.viaproxy.util.AddressUtil;
|
|
|
|
|
import net.raphimc.viaproxy.util.config.*;
|
|
|
|
|
import net.raphimc.viaproxy.util.logging.Logger;
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.net.SocketAddress;
|
|
|
|
|
import java.net.URI;
|
|
|
|
|
import java.net.URISyntaxException;
|
|
|
|
|
import java.net.URL;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Locale;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Stack;
|
|
|
|
|
|
|
|
|
|
public class ViaProxyConfig extends Config implements com.viaversion.viaversion.api.configuration.Config {
|
|
|
|
|
@OptConfig(header = "ViaProxy configuration file", version = 1)
|
|
|
|
|
public class ViaProxyConfig {
|
|
|
|
|
|
|
|
|
|
private static final java.util.logging.Logger LOGGER = new JLoggerToSLF4J(LoggerFactory.getLogger("ViaProxy"));
|
|
|
|
|
|
|
|
|
|
private final OptionParser optionParser;
|
|
|
|
|
private final OptionSpec<Void> optionHelp;
|
|
|
|
|
private final OptionSpec<String> optionBindAddress;
|
|
|
|
|
private final OptionSpec<String> optionTargetAddress;
|
|
|
|
|
private final OptionSpec<ProtocolVersion> optionTargetVersion;
|
|
|
|
|
private final OptionSpec<Boolean> optionProxyOnlineMode;
|
|
|
|
|
private final OptionSpec<Integer> optionConnectTimeout;
|
|
|
|
|
private final OptionSpec<AuthMethod> optionAuthMethod;
|
|
|
|
|
private final OptionSpec<Integer> optionMinecraftAccountIndex;
|
|
|
|
|
private final OptionSpec<Boolean> optionBetacraftAuth;
|
|
|
|
|
private final OptionSpec<String> optionBackendProxyUrl;
|
|
|
|
|
private final OptionSpec<Boolean> optionBackendHaProxy;
|
|
|
|
|
private final OptionSpec<Boolean> optionFrontendHaProxy;
|
|
|
|
|
private final OptionSpec<Boolean> optionChatSigning;
|
|
|
|
|
private final OptionSpec<Integer> optionCompressionThreshold;
|
|
|
|
|
private final OptionSpec<Boolean> optionAllowBetaPinging;
|
|
|
|
|
private final OptionSpec<Boolean> optionIgnoreProtocolTranslationErrors;
|
|
|
|
|
private final OptionSpec<Boolean> optionSuppressClientProtocolErrors;
|
|
|
|
|
private final OptionSpec<Boolean> optionAllowLegacyClientPassthrough;
|
|
|
|
|
private final OptionSpec<Boolean> optionBungeecordPlayerInfoPassthrough;
|
|
|
|
|
private final OptionSpec<String> optionCustomMotd;
|
|
|
|
|
private final OptionSpec<String> optionResourcePackUrl;
|
|
|
|
|
private final OptionSpec<WildcardDomainHandling> optionWildcardDomainHandling;
|
|
|
|
|
private final OptionSpec<Boolean> optionSimpleVoiceChatSupport;
|
|
|
|
|
private final OptionSpec<Boolean> optionFakeAcceptResourcePacks;
|
|
|
|
|
private ConfigContext<ViaProxyConfig> configContext;
|
|
|
|
|
|
|
|
|
|
@NotReloadable
|
|
|
|
|
@Option("bind-address")
|
|
|
|
|
@Description("The address ViaProxy should listen for connections.")
|
|
|
|
|
@TypeSerializer(SocketAddressTypeSerializer.class)
|
|
|
|
|
private SocketAddress bindAddress = AddressUtil.parse("0.0.0.0:25568", null);
|
|
|
|
|
|
|
|
|
|
@Option(value = "target-address", dependencies = "target-version")
|
|
|
|
|
@Description("The address of the server ViaProxy should connect to.")
|
|
|
|
|
@TypeSerializer(TargetAddressTypeSerializer.class)
|
|
|
|
|
private SocketAddress targetAddress = AddressUtil.parse("127.0.0.1:25565", null);
|
|
|
|
|
|
|
|
|
|
@Option("target-version")
|
|
|
|
|
@Description("The version ViaProxy should translate to. (See ViaProxy GUI for a list of versions)")
|
|
|
|
|
@TypeSerializer(ProtocolVersionTypeSerializer.class)
|
|
|
|
|
private ProtocolVersion targetVersion = ProtocolTranslator.AUTO_DETECT_PROTOCOL;
|
|
|
|
|
|
|
|
|
|
@Option("connect-timeout")
|
|
|
|
|
@Description("The connect timeout for backend server connections in milliseconds.")
|
|
|
|
|
private int connectTimeout = 8000;
|
|
|
|
|
|
|
|
|
|
@Option("proxy-online-mode")
|
|
|
|
|
@Description({
|
|
|
|
|
"Proxy Online Mode allows you to see skins on online mode servers and use the signed chat features.",
|
|
|
|
|
"Enabling Proxy Online Mode requires your client to have a valid minecraft account."
|
|
|
|
|
})
|
|
|
|
|
private boolean proxyOnlineMode = false;
|
|
|
|
|
|
|
|
|
|
@Option("auth-method")
|
|
|
|
|
@Description({
|
|
|
|
|
"The authentication method to use for joining the target server.",
|
|
|
|
|
"none: No authentication (Offline mode)",
|
|
|
|
|
"openauthmod: Requires the OpenAuthMod client mod (https://modrinth.com/mod/openauthmod)",
|
|
|
|
|
"account: Use an account for joining the target server. (Has to be configured in ViaProxy GUI)"
|
|
|
|
|
})
|
|
|
|
|
private AuthMethod authMethod = AuthMethod.NONE;
|
|
|
|
|
|
|
|
|
|
@Option(value = "minecraft-account-index", dependencies = "auth-method")
|
|
|
|
|
@Description("The GUI account list index (0 indexed) of the account if the auth method is set to account.")
|
|
|
|
|
@TypeSerializer(AccountTypeSerializer.class)
|
|
|
|
|
private Account account = null;
|
|
|
|
|
|
|
|
|
|
@Option("betacraft-auth")
|
|
|
|
|
@Description({
|
|
|
|
|
"Use BetaCraft authentication for classic servers.",
|
|
|
|
|
"Enabling BetaCraft Auth allows you to join classic servers which have online mode enabled."
|
|
|
|
|
})
|
|
|
|
|
private boolean betacraftAuth = false;
|
|
|
|
|
|
|
|
|
|
@Option("backend-proxy-url")
|
|
|
|
|
@Description({
|
|
|
|
|
"URL of a SOCKS(4/5)/HTTP(S) proxy which will be used for backend server connections. Leave empty to connect directly.",
|
|
|
|
|
"Supported formats:",
|
|
|
|
|
"- type://address:port",
|
|
|
|
|
"- type://username:password@address:port"
|
|
|
|
|
})
|
|
|
|
|
@TypeSerializer(ProxyUriTypeSerializer.class)
|
|
|
|
|
private URI backendProxyUrl = null;
|
|
|
|
|
|
|
|
|
|
@Option("backend-haproxy")
|
|
|
|
|
@Description("Send HAProxy protocol messages to the target server.")
|
|
|
|
|
private boolean backendHaProxy = false;
|
|
|
|
|
|
|
|
|
|
@Option("frontend-haproxy")
|
|
|
|
|
@Description("Read HAProxy protocol messages from client connections.")
|
|
|
|
|
private boolean frontendHaProxy = false;
|
|
|
|
|
|
|
|
|
|
@Option("chat-signing")
|
|
|
|
|
@Description("Enables sending signed chat messages on >= 1.19 servers.")
|
|
|
|
|
private boolean chatSigning = true;
|
|
|
|
|
|
|
|
|
|
@Option("compression-threshold")
|
|
|
|
|
@Description("The threshold for packet compression. Packets larger than this size will be compressed. (-1 to disable)")
|
|
|
|
|
private int compressionThreshold = 256;
|
|
|
|
|
|
|
|
|
|
@Option("allow-beta-pinging")
|
|
|
|
|
@Description("Enabling this will allow you to ping <= b1.7.3 servers. This may cause issues with servers that block too frequent connections.")
|
|
|
|
|
private boolean allowBetaPinging = false;
|
|
|
|
|
|
|
|
|
|
@Option("ignore-protocol-translation-errors")
|
|
|
|
|
@Description({
|
|
|
|
|
"Enabling this will prevent getting disconnected from the server when a packet translation error occurs and instead only print the error in the console.",
|
|
|
|
|
"This may cause issues depending on the type of packet which failed to translate."
|
|
|
|
|
})
|
|
|
|
|
private boolean ignoreProtocolTranslationErrors = false;
|
|
|
|
|
|
|
|
|
|
@Option("suppress-client-protocol-errors")
|
|
|
|
|
@Description({
|
|
|
|
|
"Enabling this will suppress client protocol errors to prevent lag when ViaProxy is getting spammed with invalid packets.",
|
|
|
|
|
"This may cause issues with debugging client connection issues because no error messages will be printed."
|
|
|
|
|
})
|
|
|
|
|
private boolean suppressClientProtocolErrors = false;
|
|
|
|
|
|
|
|
|
|
@Option("allow-legacy-client-passthrough")
|
|
|
|
|
@Description("Allow <= 1.6.4 clients to connect through ViaProxy to the target server. (No protocol translation or packet handling)")
|
|
|
|
|
private boolean allowLegacyClientPassthrough = false;
|
|
|
|
|
|
|
|
|
|
@Option("bungeecord-player-info-passthrough")
|
|
|
|
|
@Description({
|
|
|
|
|
"Allow additional information like player ip, player uuid to be passed through to the backend server.",
|
|
|
|
|
"This is typically used by proxies like BungeeCord and requires support from the backend server as well."
|
|
|
|
|
})
|
|
|
|
|
private boolean bungeecordPlayerInfoPassthrough = false;
|
|
|
|
|
|
|
|
|
|
@Option("custom-motd")
|
|
|
|
|
@Description("Custom MOTD to send when clients ping the proxy. Leave empty to use the target server's MOTD.")
|
|
|
|
|
private String customMotd = "";
|
|
|
|
|
|
|
|
|
|
@Option("resource-pack-url")
|
|
|
|
|
@Description({"URL of a resource pack which clients can optionally download when connecting to the server. Leave empty to disable.", "Example: http://example.com/resourcepack.zip"})
|
|
|
|
|
private String resourcePackUrl = "";
|
|
|
|
|
|
|
|
|
|
@Option("wildcard-domain-handling")
|
|
|
|
|
@Description({
|
|
|
|
|
"Allows clients to specify a target server and version using wildcard domains.",
|
|
|
|
|
"none: No wildcard domain handling.",
|
|
|
|
|
"public: Public wildcard domain handling. Intended for usage by external clients. (Example: address_port_version.viaproxy.127.0.0.1.nip.io)",
|
|
|
|
|
"internal: Internal wildcard domain handling. Intended for local usage by custom clients. (Example: original-handshake-address\\7address:port\\7version\\7classic-mppass)"
|
|
|
|
|
})
|
|
|
|
|
private WildcardDomainHandling wildcardDomainHandling = WildcardDomainHandling.NONE;
|
|
|
|
|
|
|
|
|
|
@Option("simple-voice-chat-support")
|
|
|
|
|
@Description("Enables handling and rewriting of Simple Voice Chat mod packets.")
|
|
|
|
|
private boolean simpleVoiceChatSupport = false;
|
|
|
|
|
|
|
|
|
|
@Option("fake-accept-resource-packs")
|
|
|
|
|
@Description({
|
|
|
|
|
"Accepts resource packs from the server without showing a prompt to the client.",
|
|
|
|
|
"This is required for servers that require a resource pack, but the client can't load it due to version differences."
|
|
|
|
|
})
|
|
|
|
|
private boolean fakeAcceptResourcePacks = false;
|
|
|
|
|
|
|
|
|
|
public ViaProxyConfig(final File configFile) {
|
|
|
|
|
super(configFile, LOGGER);
|
|
|
|
|
@SuppressWarnings("UnstableApiUsage")
|
|
|
|
|
public void loadFromArguments(final String[] args) throws Exception {
|
|
|
|
|
final OptionParser optionParser = new OptionParser();
|
|
|
|
|
final OptionSpec<Void> optionHelp = optionParser.accepts("help").forHelp();
|
|
|
|
|
|
|
|
|
|
this.optionParser = new OptionParser();
|
|
|
|
|
this.optionHelp = this.optionParser.accepts("help").forHelp();
|
|
|
|
|
this.optionBindAddress = this.optionParser.accepts("bind-address").withRequiredArg().ofType(String.class).defaultsTo(AddressUtil.toString(this.bindAddress));
|
|
|
|
|
this.optionTargetAddress = this.optionParser.accepts("target-address").withRequiredArg().ofType(String.class).defaultsTo(AddressUtil.toString(this.targetAddress));
|
|
|
|
|
this.optionTargetVersion = this.optionParser.accepts("target-version").withRequiredArg().withValuesConvertedBy(new ProtocolVersionConverter()).defaultsTo(this.targetVersion);
|
|
|
|
|
this.optionProxyOnlineMode = this.optionParser.accepts("proxy-online-mode").withRequiredArg().ofType(Boolean.class).defaultsTo(this.proxyOnlineMode);
|
|
|
|
|
this.optionConnectTimeout = this.optionParser.accepts("connect-timeout").withRequiredArg().ofType(Integer.class).defaultsTo(this.connectTimeout);
|
|
|
|
|
this.optionAuthMethod = this.optionParser.accepts("auth-method").withRequiredArg().ofType(AuthMethod.class).defaultsTo(this.authMethod);
|
|
|
|
|
this.optionMinecraftAccountIndex = this.optionParser.accepts("minecraft-account-index").withRequiredArg().ofType(Integer.class).defaultsTo(0);
|
|
|
|
|
this.optionBetacraftAuth = this.optionParser.accepts("betacraft-auth").withRequiredArg().ofType(Boolean.class).defaultsTo(this.betacraftAuth);
|
|
|
|
|
this.optionBackendProxyUrl = this.optionParser.accepts("backend-proxy-url").withRequiredArg().ofType(String.class).defaultsTo("");
|
|
|
|
|
this.optionBackendHaProxy = this.optionParser.accepts("backend-haproxy").withRequiredArg().ofType(Boolean.class).defaultsTo(this.backendHaProxy);
|
|
|
|
|
this.optionFrontendHaProxy = this.optionParser.accepts("frontend-haproxy").withRequiredArg().ofType(Boolean.class).defaultsTo(this.frontendHaProxy);
|
|
|
|
|
this.optionChatSigning = this.optionParser.accepts("chat-signing").withRequiredArg().ofType(Boolean.class).defaultsTo(this.chatSigning);
|
|
|
|
|
this.optionCompressionThreshold = this.optionParser.accepts("compression-threshold").withRequiredArg().ofType(Integer.class).defaultsTo(this.compressionThreshold);
|
|
|
|
|
this.optionAllowBetaPinging = this.optionParser.accepts("allow-beta-pinging").withRequiredArg().ofType(Boolean.class).defaultsTo(this.allowBetaPinging);
|
|
|
|
|
this.optionIgnoreProtocolTranslationErrors = this.optionParser.accepts("ignore-protocol-translation-errors").withRequiredArg().ofType(Boolean.class).defaultsTo(this.ignoreProtocolTranslationErrors);
|
|
|
|
|
this.optionSuppressClientProtocolErrors = this.optionParser.accepts("suppress-client-protocol-errors").withRequiredArg().ofType(Boolean.class).defaultsTo(this.suppressClientProtocolErrors);
|
|
|
|
|
this.optionAllowLegacyClientPassthrough = this.optionParser.accepts("allow-legacy-client-passthrough").withRequiredArg().ofType(Boolean.class).defaultsTo(this.allowLegacyClientPassthrough);
|
|
|
|
|
this.optionBungeecordPlayerInfoPassthrough = this.optionParser.accepts("bungeecord-player-info-passthrough").withRequiredArg().ofType(Boolean.class).defaultsTo(this.bungeecordPlayerInfoPassthrough);
|
|
|
|
|
this.optionCustomMotd = this.optionParser.accepts("custom-motd").withRequiredArg().ofType(String.class).defaultsTo(this.customMotd);
|
|
|
|
|
this.optionResourcePackUrl = this.optionParser.accepts("resource-pack-url").withRequiredArg().ofType(String.class).defaultsTo(this.resourcePackUrl);
|
|
|
|
|
this.optionWildcardDomainHandling = this.optionParser.accepts("wildcard-domain-handling").withRequiredArg().ofType(WildcardDomainHandling.class).defaultsTo(this.wildcardDomainHandling);
|
|
|
|
|
this.optionSimpleVoiceChatSupport = this.optionParser.accepts("simple-voice-chat-support").withRequiredArg().ofType(Boolean.class).defaultsTo(this.simpleVoiceChatSupport);
|
|
|
|
|
this.optionFakeAcceptResourcePacks = this.optionParser.accepts("fake-accept-resource-packs").withRequiredArg().ofType(Boolean.class).defaultsTo(this.fakeAcceptResourcePacks);
|
|
|
|
|
final Map<OptionSpec<Object>, ConfigOption> optionMap = new HashMap<>();
|
|
|
|
|
final Stack<SectionIndex> stack = new Stack<>();
|
|
|
|
|
stack.push(ClassIndexer.indexClass(ConfigType.INSTANCED, ViaProxyConfig.class));
|
|
|
|
|
while (!stack.isEmpty()) {
|
|
|
|
|
final SectionIndex index = stack.pop();
|
|
|
|
|
stack.addAll(index.getSubSections().values());
|
|
|
|
|
|
|
|
|
|
for (ConfigOption option : index.getOptions()) {
|
|
|
|
|
if (index.getSubSections().containsKey(option)) continue;
|
|
|
|
|
|
|
|
|
|
Object defaultValue = option.getField().get(this);
|
|
|
|
|
if (option.getTypeSerializer() != null) {
|
|
|
|
|
defaultValue = option.createTypeSerializer(null, ViaProxyConfig.class, this).serialize(defaultValue);
|
|
|
|
|
}
|
|
|
|
|
final OptionSpec<Object> cliOption = optionParser.accepts(option.getName()).withRequiredArg().ofType((Class<Object>) defaultValue.getClass()).defaultsTo(defaultValue);
|
|
|
|
|
optionMap.put(cliOption, option);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void reload() {
|
|
|
|
|
super.reload();
|
|
|
|
|
|
|
|
|
|
this.bindAddress = AddressUtil.parse(this.getString("bind-address", AddressUtil.toString(this.bindAddress)), null);
|
|
|
|
|
this.targetVersion = ProtocolVersion.getClosest(this.getString("target-version", this.targetVersion.getName()));
|
|
|
|
|
this.checkTargetVersion();
|
|
|
|
|
this.targetAddress = AddressUtil.parse(this.getString("target-address", AddressUtil.toString(this.targetAddress)), this.targetVersion);
|
|
|
|
|
this.connectTimeout = this.getInt("connect-timeout", this.connectTimeout);
|
|
|
|
|
this.proxyOnlineMode = this.getBoolean("proxy-online-mode", this.proxyOnlineMode);
|
|
|
|
|
this.authMethod = AuthMethod.byName(this.getString("auth-method", this.authMethod.name()));
|
|
|
|
|
final List<Account> accounts = ViaProxy.getSaveManager().accountsSave.getAccounts();
|
|
|
|
|
final int accountIndex = this.getInt("minecraft-account-index", 0);
|
|
|
|
|
if (this.authMethod == AuthMethod.ACCOUNT && accountIndex >= 0 && accountIndex < accounts.size()) {
|
|
|
|
|
this.account = accounts.get(accountIndex);
|
|
|
|
|
} else {
|
|
|
|
|
this.account = null;
|
|
|
|
|
}
|
|
|
|
|
this.betacraftAuth = this.getBoolean("betacraft-auth", this.betacraftAuth);
|
|
|
|
|
this.backendProxyUrl = this.parseProxyUrl(this.getString("backend-proxy-url", ""));
|
|
|
|
|
this.backendHaProxy = this.getBoolean("backend-haproxy", this.backendHaProxy);
|
|
|
|
|
this.frontendHaProxy = this.getBoolean("frontend-haproxy", this.frontendHaProxy);
|
|
|
|
|
this.chatSigning = this.getBoolean("chat-signing", this.chatSigning);
|
|
|
|
|
this.compressionThreshold = this.getInt("compression-threshold", this.compressionThreshold);
|
|
|
|
|
this.allowBetaPinging = this.getBoolean("allow-beta-pinging", this.allowBetaPinging);
|
|
|
|
|
this.ignoreProtocolTranslationErrors = this.getBoolean("ignore-protocol-translation-errors", this.ignoreProtocolTranslationErrors);
|
|
|
|
|
this.suppressClientProtocolErrors = this.getBoolean("suppress-client-protocol-errors", this.suppressClientProtocolErrors);
|
|
|
|
|
this.allowLegacyClientPassthrough = this.getBoolean("allow-legacy-client-passthrough", this.allowLegacyClientPassthrough);
|
|
|
|
|
this.bungeecordPlayerInfoPassthrough = this.getBoolean("bungeecord-player-info-passthrough", this.bungeecordPlayerInfoPassthrough);
|
|
|
|
|
this.customMotd = this.getString("custom-motd", this.customMotd);
|
|
|
|
|
this.resourcePackUrl = this.getString("resource-pack-url", this.resourcePackUrl);
|
|
|
|
|
this.wildcardDomainHandling = WildcardDomainHandling.byName(this.getString("wildcard-domain-handling", this.wildcardDomainHandling.name()));
|
|
|
|
|
this.simpleVoiceChatSupport = this.getBoolean("simple-voice-chat-support", this.simpleVoiceChatSupport);
|
|
|
|
|
this.fakeAcceptResourcePacks = this.getBoolean("fake-accept-resource-packs", this.fakeAcceptResourcePacks);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void loadFromArguments(final String[] args) throws IOException {
|
|
|
|
|
try {
|
|
|
|
|
ViaProxy.EVENT_MANAGER.call(new PreOptionsParseEvent(this.optionParser));
|
|
|
|
|
final OptionSet options = this.optionParser.parse(args);
|
|
|
|
|
if (options.has(this.optionHelp)) {
|
|
|
|
|
ViaProxy.EVENT_MANAGER.call(new PreOptionsParseEvent(optionParser));
|
|
|
|
|
final OptionSet options = optionParser.parse(args);
|
|
|
|
|
if (options.has(optionHelp)) {
|
|
|
|
|
throw new HelpRequestedException();
|
|
|
|
|
}
|
|
|
|
|
this.bindAddress = AddressUtil.parse(options.valueOf(this.optionBindAddress), null);
|
|
|
|
|
this.targetVersion = options.valueOf(this.optionTargetVersion);
|
|
|
|
|
this.checkTargetVersion();
|
|
|
|
|
this.targetAddress = AddressUtil.parse(options.valueOf(this.optionTargetAddress), this.targetVersion);
|
|
|
|
|
this.connectTimeout = options.valueOf(this.optionConnectTimeout);
|
|
|
|
|
this.proxyOnlineMode = options.valueOf(this.optionProxyOnlineMode);
|
|
|
|
|
this.authMethod = options.valueOf(this.optionAuthMethod);
|
|
|
|
|
final List<Account> accounts = ViaProxy.getSaveManager().accountsSave.getAccounts();
|
|
|
|
|
final int accountIndex = options.valueOf(this.optionMinecraftAccountIndex);
|
|
|
|
|
if (options.has(this.optionMinecraftAccountIndex) && accountIndex >= 0 && accountIndex < accounts.size()) {
|
|
|
|
|
|
|
|
|
|
if (options.has("minecraft-account-index")) {
|
|
|
|
|
this.authMethod = AuthMethod.ACCOUNT;
|
|
|
|
|
this.account = accounts.get(accountIndex);
|
|
|
|
|
} else {
|
|
|
|
|
this.account = null;
|
|
|
|
|
}
|
|
|
|
|
this.betacraftAuth = options.valueOf(this.optionBetacraftAuth);
|
|
|
|
|
this.backendProxyUrl = this.parseProxyUrl(options.valueOf(this.optionBackendProxyUrl));
|
|
|
|
|
this.backendHaProxy = options.valueOf(this.optionBackendHaProxy);
|
|
|
|
|
this.frontendHaProxy = options.valueOf(this.optionFrontendHaProxy);
|
|
|
|
|
this.chatSigning = options.valueOf(this.optionChatSigning);
|
|
|
|
|
this.compressionThreshold = options.valueOf(this.optionCompressionThreshold);
|
|
|
|
|
this.allowBetaPinging = options.valueOf(this.optionAllowBetaPinging);
|
|
|
|
|
this.ignoreProtocolTranslationErrors = options.valueOf(this.optionIgnoreProtocolTranslationErrors);
|
|
|
|
|
this.suppressClientProtocolErrors = options.valueOf(this.optionSuppressClientProtocolErrors);
|
|
|
|
|
this.allowLegacyClientPassthrough = options.valueOf(this.optionAllowLegacyClientPassthrough);
|
|
|
|
|
this.bungeecordPlayerInfoPassthrough = options.valueOf(this.optionBungeecordPlayerInfoPassthrough);
|
|
|
|
|
this.customMotd = options.valueOf(this.optionCustomMotd);
|
|
|
|
|
this.resourcePackUrl = options.valueOf(this.optionResourcePackUrl);
|
|
|
|
|
this.wildcardDomainHandling = options.valueOf(this.optionWildcardDomainHandling);
|
|
|
|
|
this.simpleVoiceChatSupport = options.valueOf(this.optionSimpleVoiceChatSupport);
|
|
|
|
|
this.fakeAcceptResourcePacks = options.valueOf(this.optionFakeAcceptResourcePacks);
|
|
|
|
|
for (Map.Entry<OptionSpec<Object>, ConfigOption> entry : optionMap.entrySet()) {
|
|
|
|
|
final ConfigOption option = entry.getValue();
|
|
|
|
|
if (options.has(entry.getKey())) {
|
|
|
|
|
Object value = options.valueOf(entry.getKey());
|
|
|
|
|
if (option.getTypeSerializer() != null) {
|
|
|
|
|
value = option.createTypeSerializer(null, ViaProxyConfig.class, this).deserialize((Class<Object>) option.getField().getType(), value);
|
|
|
|
|
}
|
|
|
|
|
if (option.getValidator() != null) {
|
|
|
|
|
value = option.getValidator().invoke(this, value);
|
|
|
|
|
}
|
|
|
|
|
option.getField().set(this, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ViaProxy.EVENT_MANAGER.call(new PostOptionsParseEvent(options));
|
|
|
|
|
return;
|
|
|
|
|
} catch (OptionException e) {
|
|
|
|
|
this.logger.severe("Error parsing CLI options: " + e.getMessage());
|
|
|
|
|
Logger.LOGGER.fatal("Error parsing CLI options: " + e.getMessage());
|
|
|
|
|
} catch (HelpRequestedException ignored) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.optionParser.formatHelpWith(new BetterHelpFormatter());
|
|
|
|
|
this.optionParser.printHelpOn(Logger.SYSOUT);
|
|
|
|
|
this.logger.info("For a more detailed description of the options, please refer to the viaproxy.yml file.");
|
|
|
|
|
optionParser.formatHelpWith(new BetterHelpFormatter());
|
|
|
|
|
optionParser.printHelpOn(Logger.SYSOUT);
|
|
|
|
|
Logger.LOGGER.info("For a more detailed description of the options, please refer to the viaproxy.yml file.");
|
|
|
|
|
System.exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public URL getDefaultConfigURL() {
|
|
|
|
|
return this.getClass().getClassLoader().getResource("assets/viaproxy/viaproxy.yml");
|
|
|
|
|
public void save() {
|
|
|
|
|
try {
|
|
|
|
|
this.configContext.save();
|
|
|
|
|
} catch (Throwable e) {
|
|
|
|
|
throw new RuntimeException("Failed to save config", e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void handleConfig(Map<String, Object> map) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<String> getUnsupportedOptions() {
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void set(String path, Object value) {
|
|
|
|
|
super.set(path, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SocketAddress getBindAddress() {
|
|
|
|
@ -243,7 +256,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setBindAddress(final SocketAddress bindAddress) {
|
|
|
|
|
this.bindAddress = bindAddress;
|
|
|
|
|
this.set("bind-address", AddressUtil.toString(bindAddress));
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SocketAddress getTargetAddress() {
|
|
|
|
@ -252,7 +265,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setTargetAddress(final SocketAddress targetAddress) {
|
|
|
|
|
this.targetAddress = targetAddress;
|
|
|
|
|
this.set("target-address", AddressUtil.toString(targetAddress));
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ProtocolVersion getTargetVersion() {
|
|
|
|
@ -261,7 +274,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setTargetVersion(final ProtocolVersion targetVersion) {
|
|
|
|
|
this.targetVersion = targetVersion;
|
|
|
|
|
this.set("target-version", targetVersion.getName());
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getConnectTimeout() {
|
|
|
|
@ -270,7 +283,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setConnectTimeout(final int connectTimeout) {
|
|
|
|
|
this.connectTimeout = connectTimeout;
|
|
|
|
|
this.set("connect-timeout", connectTimeout);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean isProxyOnlineMode() {
|
|
|
|
@ -279,7 +292,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setProxyOnlineMode(final boolean proxyOnlineMode) {
|
|
|
|
|
this.proxyOnlineMode = proxyOnlineMode;
|
|
|
|
|
this.set("proxy-online-mode", proxyOnlineMode);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public AuthMethod getAuthMethod() {
|
|
|
|
@ -288,7 +301,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setAuthMethod(final AuthMethod authMethod) {
|
|
|
|
|
this.authMethod = authMethod;
|
|
|
|
|
this.set("auth-method", authMethod.name().toLowerCase(Locale.ROOT));
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Account getAccount() {
|
|
|
|
@ -297,7 +310,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setAccount(final Account account) {
|
|
|
|
|
this.account = account;
|
|
|
|
|
this.set("minecraft-account-index", ViaProxy.getSaveManager().accountsSave.getAccounts().indexOf(account));
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean useBetacraftAuth() {
|
|
|
|
@ -306,7 +319,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setBetacraftAuth(final boolean betacraftAuth) {
|
|
|
|
|
this.betacraftAuth = betacraftAuth;
|
|
|
|
|
this.set("betacraft-auth", betacraftAuth);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public URI getBackendProxyUrl() {
|
|
|
|
@ -315,11 +328,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setBackendProxyUrl(final URI backendProxyUrl) {
|
|
|
|
|
this.backendProxyUrl = backendProxyUrl;
|
|
|
|
|
if (backendProxyUrl != null) {
|
|
|
|
|
this.set("backend-proxy-url", backendProxyUrl.toString());
|
|
|
|
|
} else {
|
|
|
|
|
this.set("backend-proxy-url", "");
|
|
|
|
|
}
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean useBackendHaProxy() {
|
|
|
|
@ -328,7 +337,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setBackendHaProxy(final boolean backendHaProxy) {
|
|
|
|
|
this.backendHaProxy = backendHaProxy;
|
|
|
|
|
this.set("backend-haproxy", backendHaProxy);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean useFrontendHaProxy() {
|
|
|
|
@ -337,7 +346,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setFrontendHaProxy(final boolean frontendHaProxy) {
|
|
|
|
|
this.frontendHaProxy = frontendHaProxy;
|
|
|
|
|
this.set("frontend-haproxy", frontendHaProxy);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean shouldSignChat() {
|
|
|
|
@ -346,7 +355,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setChatSigning(final boolean chatSigning) {
|
|
|
|
|
this.chatSigning = chatSigning;
|
|
|
|
|
this.set("chat-signing", chatSigning);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getCompressionThreshold() {
|
|
|
|
@ -355,7 +364,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setCompressionThreshold(final int compressionThreshold) {
|
|
|
|
|
this.compressionThreshold = compressionThreshold;
|
|
|
|
|
this.set("compression-threshold", compressionThreshold);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean shouldAllowBetaPinging() {
|
|
|
|
@ -364,7 +373,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setAllowBetaPinging(final boolean allowBetaPinging) {
|
|
|
|
|
this.allowBetaPinging = allowBetaPinging;
|
|
|
|
|
this.set("allow-beta-pinging", allowBetaPinging);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean shouldIgnoreProtocolTranslationErrors() {
|
|
|
|
@ -373,7 +382,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setIgnoreProtocolTranslationErrors(final boolean ignoreProtocolTranslationErrors) {
|
|
|
|
|
this.ignoreProtocolTranslationErrors = ignoreProtocolTranslationErrors;
|
|
|
|
|
this.set("ignore-protocol-translation-errors", ignoreProtocolTranslationErrors);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean shouldSuppressClientProtocolErrors() {
|
|
|
|
@ -382,7 +391,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setSuppressClientProtocolErrors(final boolean suppressClientProtocolErrors) {
|
|
|
|
|
this.suppressClientProtocolErrors = suppressClientProtocolErrors;
|
|
|
|
|
this.set("suppress-client-protocol-errors", suppressClientProtocolErrors);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean shouldAllowLegacyClientPassthrough() {
|
|
|
|
@ -391,7 +400,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setAllowLegacyClientPassthrough(final boolean allowLegacyClientPassthrough) {
|
|
|
|
|
this.allowLegacyClientPassthrough = allowLegacyClientPassthrough;
|
|
|
|
|
this.set("allow-legacy-client-passthrough", allowLegacyClientPassthrough);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean shouldPassthroughBungeecordPlayerInfo() {
|
|
|
|
@ -400,7 +409,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setPassthroughBungeecordPlayerInfo(final boolean bungeecordPlayerInfoPassthrough) {
|
|
|
|
|
this.bungeecordPlayerInfoPassthrough = bungeecordPlayerInfoPassthrough;
|
|
|
|
|
this.set("bungeecord-player-info-passthrough", bungeecordPlayerInfoPassthrough);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getCustomMotd() {
|
|
|
|
@ -409,7 +418,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setCustomMotd(final String customMotd) {
|
|
|
|
|
this.customMotd = customMotd;
|
|
|
|
|
this.set("custom-motd", customMotd);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getResourcePackUrl() {
|
|
|
|
@ -418,7 +427,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setResourcePackUrl(final String resourcePackUrl) {
|
|
|
|
|
this.resourcePackUrl = resourcePackUrl;
|
|
|
|
|
this.set("resource-pack-url", resourcePackUrl);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public WildcardDomainHandling getWildcardDomainHandling() {
|
|
|
|
@ -427,7 +436,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setWildcardDomainHandling(final WildcardDomainHandling wildcardDomainHandling) {
|
|
|
|
|
this.wildcardDomainHandling = wildcardDomainHandling;
|
|
|
|
|
this.set("wildcard-domain-handling", wildcardDomainHandling.name().toLowerCase(Locale.ROOT));
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean shouldSupportSimpleVoiceChat() {
|
|
|
|
@ -436,7 +445,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setSimpleVoiceChatSupport(final boolean simpleVoiceChatSupport) {
|
|
|
|
|
this.simpleVoiceChatSupport = simpleVoiceChatSupport;
|
|
|
|
|
this.set("simple-voice-chat-support", simpleVoiceChatSupport);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean shouldFakeAcceptResourcePacks() {
|
|
|
|
@ -445,31 +454,21 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
|
|
|
|
|
public void setFakeAcceptResourcePacks(final boolean fakeAcceptResourcePacks) {
|
|
|
|
|
this.fakeAcceptResourcePacks = fakeAcceptResourcePacks;
|
|
|
|
|
this.set("fake-accept-resource-packs", fakeAcceptResourcePacks);
|
|
|
|
|
this.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void checkTargetVersion() {
|
|
|
|
|
if (this.targetVersion == null) {
|
|
|
|
|
this.targetVersion = ProtocolTranslator.AUTO_DETECT_PROTOCOL;
|
|
|
|
|
this.logger.info("Invalid target version: " + this.getString("target-version", "") + ". Defaulting to auto detect.");
|
|
|
|
|
this.logger.info("=== Supported Protocol Versions ===");
|
|
|
|
|
@Validator("target-version")
|
|
|
|
|
private ProtocolVersion validateTargetVersion(final ProtocolVersion targetVersion) {
|
|
|
|
|
if (targetVersion == null) {
|
|
|
|
|
Logger.LOGGER.warn("Invalid target server version. Defaulting to auto detect.");
|
|
|
|
|
Logger.LOGGER.warn("=== Supported Protocol Versions ===");
|
|
|
|
|
for (ProtocolVersion version : ProtocolVersion.getProtocols()) {
|
|
|
|
|
this.logger.info(version.getName());
|
|
|
|
|
Logger.LOGGER.warn(version.getName());
|
|
|
|
|
}
|
|
|
|
|
this.logger.info("===================================");
|
|
|
|
|
Logger.LOGGER.warn("===================================");
|
|
|
|
|
return ProtocolTranslator.AUTO_DETECT_PROTOCOL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private URI parseProxyUrl(final String proxyUrl) {
|
|
|
|
|
if (!proxyUrl.isBlank()) {
|
|
|
|
|
try {
|
|
|
|
|
return new URI(proxyUrl);
|
|
|
|
|
} catch (URISyntaxException e) {
|
|
|
|
|
throw new IllegalArgumentException("Invalid proxy url: " + proxyUrl + ". Proxy url format: type://address:port or type://username:password@address:port");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
return targetVersion;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public enum AuthMethod {
|
|
|
|
@ -493,16 +492,6 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
this.guiTranslationKey = guiTranslationKey;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static AuthMethod byName(String name) {
|
|
|
|
|
for (AuthMethod mode : values()) {
|
|
|
|
|
if (mode.name().equalsIgnoreCase(name)) {
|
|
|
|
|
return mode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getGuiTranslationKey() {
|
|
|
|
|
return this.guiTranslationKey;
|
|
|
|
|
}
|
|
|
|
@ -522,17 +511,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
|
|
|
|
|
/**
|
|
|
|
|
* Iternal wildcard domain handling
|
|
|
|
|
*/
|
|
|
|
|
INTERNAL;
|
|
|
|
|
|
|
|
|
|
public static WildcardDomainHandling byName(String name) {
|
|
|
|
|
for (WildcardDomainHandling mode : values()) {
|
|
|
|
|
if (mode.name().equalsIgnoreCase(name)) {
|
|
|
|
|
return mode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NONE;
|
|
|
|
|
}
|
|
|
|
|
INTERNAL,
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|