From 9dd0702ccb79f59064fae4359a52fa79b303e1ce Mon Sep 17 00:00:00 2001 From: luajscss <70727706+luajscss@users.noreply.github.com> Date: Sun, 9 Nov 2025 22:00:30 +0300 Subject: [PATCH 1/3] Update to 1.21.1 --- .gitignore | 3 + build.gradle | 2 +- gradle.properties | 8 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../java/ru/fiw/proxyserver/TestPing.java | 106 ++++++++++-------- 5 files changed, 71 insertions(+), 50 deletions(-) diff --git a/.gitignore b/.gitignore index 09cd281..9502dfd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# project files +Minecraft_fabric_1.21.1_source + # gradle .gradle/ diff --git a/build.gradle b/build.gradle index 7b6f882..efdc3d2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.6-SNAPSHOT' + id 'fabric-loom' version '1.7-SNAPSHOT' id 'maven-publish' } diff --git a/gradle.properties b/gradle.properties index a5458c3..2417fae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,13 +2,13 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use -minecraft_version=1.20.4 -yarn_mappings=1.20.4+build.3 -loader_version=0.15.10 +minecraft_version=1.21.1 +yarn_mappings=1.21.1+build.3 +loader_version=0.17.3 # Mod Properties mod_version=1.3 maven_group=ru.fiw.proxyserver archives_base_name=ProxyServer # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api -fabric_version=0.97.0+1.20.4 \ No newline at end of file +fabric_version=0.102.1+1.21.1 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23..a441313 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/ru/fiw/proxyserver/TestPing.java b/src/main/java/ru/fiw/proxyserver/TestPing.java index b1c2938..cdd61a1 100644 --- a/src/main/java/ru/fiw/proxyserver/TestPing.java +++ b/src/main/java/ru/fiw/proxyserver/TestPing.java @@ -7,12 +7,11 @@ import io.netty.handler.proxy.Socks4ProxyHandler; import io.netty.handler.proxy.Socks5ProxyHandler; import io.netty.handler.timeout.ReadTimeoutHandler; -import net.minecraft.SharedConstants; import net.minecraft.network.ClientConnection; +import net.minecraft.network.DisconnectionInfo; import net.minecraft.network.NetworkSide; import net.minecraft.network.listener.ClientQueryPacketListener; import net.minecraft.network.packet.c2s.handshake.ConnectionIntent; -import net.minecraft.network.packet.c2s.handshake.HandshakeC2SPacket; import net.minecraft.network.packet.c2s.query.QueryPingC2SPacket; import net.minecraft.network.packet.c2s.query.QueryRequestC2SPacket; import net.minecraft.network.packet.s2c.query.PingResultS2CPacket; @@ -42,9 +41,8 @@ public void run(String ip, int port, Proxy proxy) { private void ping(String ip, int port) { state = Text.translatable("ui.proxyserver.ping.pinging", ip).getString(); - ClientConnection clientConnection; try { - clientConnection = createTestClientConnection(InetAddress.getByName(ip), port); + pingDestination = createTestClientConnection(ip, port); } catch (UnknownHostException e) { state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantConnect").getString(); return; @@ -52,9 +50,23 @@ private void ping(String ip, int port) { state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantPing", ip).getString(); return; } - pingDestination = clientConnection; - clientConnection.setPacketListener(new ClientQueryPacketListener() { + ClientConnection clientConnection = pingDestination; + + ClientQueryPacketListener listener = new ClientQueryPacketListener() { private boolean successful; + private boolean sentQuery; + + @Override + public void onResponse(QueryResponseS2CPacket packet) { + if (this.sentQuery) { + clientConnection.disconnect(Text.translatable("multiplayer.status.unrequested")); + return; + } + + this.sentQuery = true; + pingSentAt = Util.getMeasuringTimeMs(); + clientConnection.send(new QueryPingC2SPacket(pingSentAt)); + } @Override public void onPingResult(PingResultS2CPacket packet) { @@ -65,59 +77,65 @@ public void onPingResult(PingResultS2CPacket packet) { clientConnection.disconnect(Text.translatable("multiplayer.status.finished")); } - public void onResponse(QueryResponseS2CPacket packet) { - pingSentAt = Util.getMeasuringTimeMs(); - clientConnection.send(new QueryPingC2SPacket(pingSentAt)); - } - - public void onDisconnected(Text reason) { + @Override + public void onDisconnected(DisconnectionInfo info) { pingDestination = null; if (!this.successful) { - state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantPingReason", ip, reason.getString()).getString(); + state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantPingReason", ip, info.reason().getString()).getString(); } } @Override public boolean isConnectionOpen() { - return true; + return clientConnection.isOpen(); } - - public ClientConnection getConnection() { - return clientConnection; - } - }); + }; try { - clientConnection.send(new HandshakeC2SPacket(SharedConstants.getGameVersion().getProtocolVersion(), ip, port, ConnectionIntent.STATUS)); - clientConnection.send(new QueryRequestC2SPacket()); + clientConnection.connect(ip, port, listener); + clientConnection.send(QueryRequestC2SPacket.INSTANCE); } catch (Throwable throwable) { + pingDestination = null; state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantPing", ip).getString(); + clientConnection.disconnect(Text.translatable("multiplayer.status.cancelled")); } } - private ClientConnection createTestClientConnection(InetAddress address, int port) { - final ClientConnection clientConnection = new ClientConnection(NetworkSide.CLIENTBOUND); - - (new Bootstrap()).group(ClientConnection.CLIENT_IO_GROUP.get()).handler(new ChannelInitializer<>() { - protected void initChannel(Channel channel) { - ClientConnection.setHandlers(channel); - - try { - channel.config().setOption(ChannelOption.TCP_NODELAY, true); - } catch (ChannelException channelexception) { - } - - ChannelPipeline channelpipeline = channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)); - ClientConnection.addHandlers(channelpipeline, NetworkSide.CLIENTBOUND, null); - - if (proxy.type == Proxy.ProxyType.SOCKS5) { - channel.pipeline().addFirst(new Socks5ProxyHandler(new InetSocketAddress(proxy.getIp(), proxy.getPort()), proxy.username.isEmpty() ? null : proxy.username, proxy.password.isEmpty() ? null : proxy.password)); - } else { - channel.pipeline().addFirst(new Socks4ProxyHandler(new InetSocketAddress(proxy.getIp(), proxy.getPort()), proxy.username.isEmpty() ? null : proxy.username)); - } - } - }).channel(NioSocketChannel.class).connect(address, port).syncUninterruptibly(); - return clientConnection; + private ClientConnection createTestClientConnection(String host, int port) throws UnknownHostException { + InetSocketAddress address = new InetSocketAddress(InetAddress.getByName(host), port); + ClientConnection connection = new ClientConnection(NetworkSide.CLIENTBOUND); + + new Bootstrap() + .group((EventLoopGroup) ClientConnection.CLIENT_IO_GROUP.get()) + .handler(new ChannelInitializer<>() { + @Override + protected void initChannel(Channel channel) { + try { + channel.config().setOption(ChannelOption.TCP_NODELAY, true); + } catch (ChannelException ignored) { + } + + ChannelPipeline pipeline = channel.pipeline(); + + if (proxy.type == Proxy.ProxyType.SOCKS5) { + pipeline.addFirst(new Socks5ProxyHandler(new InetSocketAddress(proxy.getIp(), proxy.getPort()), + proxy.username.isEmpty() ? null : proxy.username, + proxy.password.isEmpty() ? null : proxy.password)); + } else { + pipeline.addFirst(new Socks4ProxyHandler(new InetSocketAddress(proxy.getIp(), proxy.getPort()), + proxy.username.isEmpty() ? null : proxy.username)); + } + + pipeline.addLast("timeout", new ReadTimeoutHandler(30)); + ClientConnection.addHandlers(pipeline, NetworkSide.CLIENTBOUND, false, null); + connection.addFlowControlHandler(pipeline); + } + }) + .channel(NioSocketChannel.class) + .connect(address) + .syncUninterruptibly(); + + return connection; } public void pingPendingNetworks() { From f83027aff3ee77ffdb3bb11bb7ec59a6d4916e6b Mon Sep 17 00:00:00 2001 From: luajscss <70727706+luajscss@users.noreply.github.com> Date: Wed, 3 Jun 2026 01:30:02 +0300 Subject: [PATCH 2/3] Update to 1.21.11 - Toolchain: Gradle 9.4, Loom 1.16.3, yarn 1.21.11+build.6, loader 0.18.4, fabric-api 0.141.3 - Fix Screen.keyPressed(KeyInput) and CheckboxWidget.onPress(AbstractInput) for the 1.21.6+ input refactor - Replace removed ClientConnection.CLIENT_IO_GROUP with NetworkingBackend in TestPing - Proxy source resolver: load proxy from file / system property / launch args --- .gitignore | 1 + build.gradle | 36 +++- gradle.properties | 10 +- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 9 +- .../java/ru/fiw/proxyserver/GuiProxy.java | 8 +- .../java/ru/fiw/proxyserver/ProxyServer.java | 8 + .../fiw/proxyserver/ProxySourceResolver.java | 189 ++++++++++++++++++ .../java/ru/fiw/proxyserver/TestPing.java | 3 +- src/main/resources/proxyserver.mixins.json | 2 +- 10 files changed, 244 insertions(+), 24 deletions(-) create mode 100644 src/main/java/ru/fiw/proxyserver/ProxySourceResolver.java diff --git a/.gitignore b/.gitignore index 9502dfd..200673f 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ bin/ # fabric run/ +run-alt/ diff --git a/build.gradle b/build.gradle index efdc3d2..123373e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,11 @@ plugins { - id 'fabric-loom' version '1.7-SNAPSHOT' + id 'fabric-loom' version '1.16.3' id 'maven-publish' } -sourceCompatibility = JavaVersion.VERSION_17 -targetCompatibility = JavaVersion.VERSION_17 - -archivesBaseName = project.archives_base_name +base { + archivesName = project.archives_base_name +} version = project.mod_version group = project.maven_group @@ -21,11 +20,27 @@ dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - // Fabric API. This is technically optional, but you probably want it anyw + // Fabric API. This is technically optional, but you probably want it anyway. modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" } + +loom { + runs { + client { + vmArgs "-Xms2G", "-Xmx2G", "-XX:MaxDirectMemorySize=2048m" + programArgs "--width", "800", "--height", "600" + } + + clientAlt { + inherit client + name "Client Alt" + runDir "run-alt" + } + } +} + processResources { - inputs.property "version", project.version + inputs.property "version", project.version filesMatching("fabric.mod.json") { expand "version": project.version @@ -33,7 +48,7 @@ processResources { } tasks.withType(JavaCompile).configureEach { - it.options.release = 17 + it.options.release = 21 } java { @@ -41,11 +56,14 @@ java { // if it is present. // If you remove this line, sources will not be generated. withSourcesJar() + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } } jar { from("LICENSE") { - rename { "${it}_${project.archivesBaseName}"} + rename { "${it}_${project.archives_base_name}"} } } diff --git a/gradle.properties b/gradle.properties index 2417fae..0061d3c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,13 +2,15 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use -minecraft_version=1.21.1 -yarn_mappings=1.21.1+build.3 -loader_version=0.17.3 +minecraft_version=1.21.11 +yarn_mappings=1.21.11+build.6 +loader_version=0.18.4 # Mod Properties mod_version=1.3 maven_group=ru.fiw.proxyserver archives_base_name=ProxyServer # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api -fabric_version=0.102.1+1.21.1 \ No newline at end of file +fabric_version=0.141.3+1.21.11 + +org.gradle.java.home=C:/Program Files/Java/jdk-21 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a441313..dbc3ce4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index 5b60df3..e8ad084 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,10 +1,9 @@ pluginManagement { repositories { - jcenter() - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } + maven { url "https://maven.fabricmc.net/" } + mavenCentral() gradlePluginPortal() } } + +rootProject.name = "proxy-server" diff --git a/src/main/java/ru/fiw/proxyserver/GuiProxy.java b/src/main/java/ru/fiw/proxyserver/GuiProxy.java index 37e3387..1cf5ecc 100644 --- a/src/main/java/ru/fiw/proxyserver/GuiProxy.java +++ b/src/main/java/ru/fiw/proxyserver/GuiProxy.java @@ -2,6 +2,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.input.KeyInput; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; @@ -10,6 +11,7 @@ import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.text.Text; import net.minecraft.util.Formatting; + import org.apache.commons.lang3.StringUtils; public class GuiProxy extends Screen { @@ -70,8 +72,8 @@ private void centerButtons(int amount, int buttonLength, int gap) { } @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - super.keyPressed(keyCode, scanCode, modifiers); + public boolean keyPressed(KeyInput input) { + super.keyPressed(input); msg = ""; testPing.state = ""; return true; @@ -82,7 +84,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float partialTic super.render(context, mouseX, mouseY, partialTicks); if (enabledCheck.isChecked() && !isValidIpPort(ipPort.getText())) { - enabledCheck.onPress(); + enabledCheck.onPress(new KeyInput(0, 0, 0)); } context.drawTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.options.proxyType").getString(), this.width / 2 - 150, positionY[1] + 5, 10526880); diff --git a/src/main/java/ru/fiw/proxyserver/ProxyServer.java b/src/main/java/ru/fiw/proxyserver/ProxyServer.java index 2e76e94..3e75ecb 100644 --- a/src/main/java/ru/fiw/proxyserver/ProxyServer.java +++ b/src/main/java/ru/fiw/proxyserver/ProxyServer.java @@ -16,5 +16,13 @@ public static String getLastUsedProxyIp() { @Override public void onInitialize() { Config.loadConfig(); + ProxySourceResolver.applyRuntimeOverrides(); + + if (proxy.ipPort.isEmpty()) { + ProxySourceResolver.loadDefaultFile().ifPresent(loadedProxy -> { + proxy = loadedProxy; + lastUsedProxy = loadedProxy; + }); + } } } diff --git a/src/main/java/ru/fiw/proxyserver/ProxySourceResolver.java b/src/main/java/ru/fiw/proxyserver/ProxySourceResolver.java new file mode 100644 index 0000000..d081d0a --- /dev/null +++ b/src/main/java/ru/fiw/proxyserver/ProxySourceResolver.java @@ -0,0 +1,189 @@ +package ru.fiw.proxyserver; + +import net.fabricmc.loader.api.FabricLoader; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Locale; +import java.util.Optional; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public final class ProxySourceResolver { + public static final String DEFAULT_PROXY_LIST_FILE = "config/proxy-list.txt"; + + private static final String PROPERTY_PROXY = "proxyserver.proxy"; + private static final String PROPERTY_PROXY_FILE = "proxyserver.proxyFile"; + private static final String ARG_PROXY = "--proxy="; + private static final String ARG_PROXY_FILE = "--proxy-file="; + + private ProxySourceResolver() { + } + + public static void applyRuntimeOverrides() { + if (applyFromString(System.getProperty(PROPERTY_PROXY), "system property " + PROPERTY_PROXY)) { + return; + } + + if (applyFromFileReference(System.getProperty(PROPERTY_PROXY_FILE), "system property " + PROPERTY_PROXY_FILE)) { + return; + } + + String[] launchArguments = FabricLoader.getInstance().getLaunchArguments(true); + for (String argument : launchArguments) { + if (argument.startsWith(ARG_PROXY)) { + if (applyFromString(argument.substring(ARG_PROXY.length()), "command line argument --proxy")) { + return; + } + } else if (argument.startsWith(ARG_PROXY_FILE)) { + if (applyFromFileReference(argument.substring(ARG_PROXY_FILE.length()), "command line argument --proxy-file")) { + return; + } + } + } + } + + public static Optional loadDefaultFile() { + return loadFirstValidFromFile(getDefaultProxyListPath()); + } + + public static Path getDefaultProxyListPath() { + return FabricLoader.getInstance().getGameDir().resolve(DEFAULT_PROXY_LIST_FILE); + } + + public static Optional parseProxy(String raw) { + if (raw == null) { + return Optional.empty(); + } + + String trimmed = raw.trim(); + if (trimmed.isEmpty() || trimmed.startsWith("#")) { + return Optional.empty(); + } + + Proxy.ProxyType type = Proxy.ProxyType.SOCKS5; + String working = trimmed; + int schemeIdx = trimmed.indexOf("://"); + if (schemeIdx > 0) { + String scheme = trimmed.substring(0, schemeIdx).toLowerCase(Locale.ROOT); + if ("socks4".equals(scheme)) { + type = Proxy.ProxyType.SOCKS4; + } else if ("socks5".equals(scheme)) { + type = Proxy.ProxyType.SOCKS5; + } else { + System.out.println("[ProxyServer] Unsupported proxy scheme: " + scheme); + return Optional.empty(); + } + working = trimmed.substring(schemeIdx + 3); + } + + String[] parts = working.split(":", 4); + if (parts.length < 2) { + System.out.println("[ProxyServer] Unable to parse proxy string (expected ip:port[:username[:password]]): " + raw); + return Optional.empty(); + } + + String ip = parts[0].trim(); + String portPart = parts[1].trim(); + if (ip.isEmpty()) { + System.out.println("[ProxyServer] Missing proxy host in: " + raw); + return Optional.empty(); + } + + int port; + try { + port = Integer.parseInt(portPart); + } catch (NumberFormatException e) { + System.out.println("[ProxyServer] Invalid proxy port in: " + raw); + return Optional.empty(); + } + + if (port <= 0 || port > 65535) { + System.out.println("[ProxyServer] Proxy port out of range in: " + raw); + return Optional.empty(); + } + + String username = parts.length >= 3 ? parts[2] : ""; + String password = parts.length == 4 ? parts[3] : ""; + + Proxy proxy = new Proxy(); + proxy.type = type; + proxy.ipPort = ip + ":" + port; + proxy.username = username; + proxy.password = password; + + return Optional.of(proxy); + } + + public static Optional loadFirstValidFromFile(Path path) { + if (!Files.exists(path)) { + System.out.println("[ProxyServer] Proxy file not found: " + path); + return Optional.empty(); + } + + try (Stream lines = Files.lines(path)) { + List proxies = lines + .map(String::trim) + .filter(line -> !line.isEmpty() && !line.startsWith("#")) + .map(ProxySourceResolver::parseProxy) + .flatMap(Optional::stream) + .collect(Collectors.toList()); + + if (proxies.isEmpty()) { + return Optional.empty(); + } + + Proxy randomProxy = proxies.get(ThreadLocalRandom.current().nextInt(proxies.size())); + return Optional.of(randomProxy); + } catch (IOException e) { + System.out.println("[ProxyServer] Failed to read proxy file " + path + ": " + e.getMessage()); + return Optional.empty(); + } + } + + private static boolean applyFromString(String raw, String source) { + Optional proxyOpt = parseProxy(raw); + if (proxyOpt.isEmpty()) { + return false; + } + + applyProxy(proxyOpt.get(), source); + return true; + } + + private static boolean applyFromFileReference(String reference, String source) { + if (reference == null || reference.isBlank()) { + return false; + } + + Path path = resolvePath(reference.trim()); + Optional proxyOpt = loadFirstValidFromFile(path); + if (proxyOpt.isPresent()) { + applyProxy(proxyOpt.get(), source + " -> " + path); + return true; + } + + System.out.println("[ProxyServer] No valid proxy entries found in: " + path); + return false; + } + + private static Path resolvePath(String value) { + Path path = Path.of(value); + if (path.isAbsolute()) { + return path; + } + return FabricLoader.getInstance().getGameDir().resolve(path).normalize(); + } + + private static void applyProxy(Proxy proxy, String source) { + ProxyServer.proxy = proxy; + ProxyServer.proxyEnabled = true; + ProxyServer.lastUsedProxy = proxy; + Config.setDefaultProxy(proxy); + Config.saveConfig(); + System.out.println("[ProxyServer] Loaded proxy from " + source + ": " + proxy.ipPort); + } +} diff --git a/src/main/java/ru/fiw/proxyserver/TestPing.java b/src/main/java/ru/fiw/proxyserver/TestPing.java index cdd61a1..a3eaca3 100644 --- a/src/main/java/ru/fiw/proxyserver/TestPing.java +++ b/src/main/java/ru/fiw/proxyserver/TestPing.java @@ -8,6 +8,7 @@ import io.netty.handler.proxy.Socks5ProxyHandler; import io.netty.handler.timeout.ReadTimeoutHandler; import net.minecraft.network.ClientConnection; +import net.minecraft.network.NetworkingBackend; import net.minecraft.network.DisconnectionInfo; import net.minecraft.network.NetworkSide; import net.minecraft.network.listener.ClientQueryPacketListener; @@ -106,7 +107,7 @@ private ClientConnection createTestClientConnection(String host, int port) throw ClientConnection connection = new ClientConnection(NetworkSide.CLIENTBOUND); new Bootstrap() - .group((EventLoopGroup) ClientConnection.CLIENT_IO_GROUP.get()) + .group(NetworkingBackend.remote(false).getEventLoopGroup()) .handler(new ChannelInitializer<>() { @Override protected void initChannel(Channel channel) { diff --git a/src/main/resources/proxyserver.mixins.json b/src/main/resources/proxyserver.mixins.json index 73c323d..1517164 100644 --- a/src/main/resources/proxyserver.mixins.json +++ b/src/main/resources/proxyserver.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "ru.fiw.proxyserver.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ ], "client": [ From e2e7c1e526a18fe99b651f6cf855996b70061d7d Mon Sep 17 00:00:00 2001 From: luajscss <70727706+luajscss@users.noreply.github.com> Date: Wed, 3 Jun 2026 02:15:37 +0300 Subject: [PATCH 3/3] Fix invisible GUI text on 1.21.11 (ARGB alpha) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drawTextWithShadow treats color as ARGB since 1.21.6 — a zero alpha byte renders text fully transparent. Add 0xFF alpha to all proxy GUI label/status colors. Also log TestPing exceptions instead of swallowing them silently. --- src/main/java/ru/fiw/proxyserver/GuiProxy.java | 14 +++++++------- src/main/java/ru/fiw/proxyserver/TestPing.java | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/ru/fiw/proxyserver/GuiProxy.java b/src/main/java/ru/fiw/proxyserver/GuiProxy.java index 1cf5ecc..0c29555 100644 --- a/src/main/java/ru/fiw/proxyserver/GuiProxy.java +++ b/src/main/java/ru/fiw/proxyserver/GuiProxy.java @@ -87,22 +87,22 @@ public void render(DrawContext context, int mouseX, int mouseY, float partialTic enabledCheck.onPress(new KeyInput(0, 0, 0)); } - context.drawTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.options.proxyType").getString(), this.width / 2 - 150, positionY[1] + 5, 10526880); - context.drawCenteredTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.options.auth").getString(), this.width / 2, positionY[3] + 8, Formatting.WHITE.getColorValue()); - context.drawTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.options.ipPort").getString(), this.width / 2 - 150, positionY[2] + 5, 10526880); + context.drawTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.options.proxyType").getString(), this.width / 2 - 150, positionY[1] + 5, 0xFFA0A0A0); + context.drawCenteredTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.options.auth").getString(), this.width / 2, positionY[3] + 8, 0xFFFFFFFF); + context.drawTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.options.ipPort").getString(), this.width / 2 - 150, positionY[2] + 5, 0xFFA0A0A0); this.ipPort.render(context, mouseX, mouseY, partialTicks); if (isSocks4) { - context.drawTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.auth.id").getString(), this.width / 2 - 150, positionY[4] + 5, 10526880); + context.drawTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.auth.id").getString(), this.width / 2 - 150, positionY[4] + 5, 0xFFA0A0A0); this.username.render(context, mouseX, mouseY, partialTicks); } else { - context.drawTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.auth.password").getString(), this.width / 2 - 150, positionY[5] + 5, 10526880); - context.drawTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.auth.username").getString(), this.width / 2 - 150, positionY[4] + 5, 10526880); + context.drawTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.auth.password").getString(), this.width / 2 - 150, positionY[5] + 5, 0xFFA0A0A0); + context.drawTextWithShadow(this.textRenderer, Text.translatable("ui.proxyserver.auth.username").getString(), this.width / 2 - 150, positionY[4] + 5, 0xFFA0A0A0); this.username.render(context, mouseX, mouseY, partialTicks); this.password.render(context, mouseX, mouseY, partialTicks); } - context.drawCenteredTextWithShadow(this.textRenderer, !msg.isEmpty() ? msg : testPing.state, this.width / 2, positionY[6] + 5, 10526880); + context.drawCenteredTextWithShadow(this.textRenderer, !msg.isEmpty() ? msg : testPing.state, this.width / 2, positionY[6] + 5, 0xFFA0A0A0); } @Override diff --git a/src/main/java/ru/fiw/proxyserver/TestPing.java b/src/main/java/ru/fiw/proxyserver/TestPing.java index a3eaca3..31d16ab 100644 --- a/src/main/java/ru/fiw/proxyserver/TestPing.java +++ b/src/main/java/ru/fiw/proxyserver/TestPing.java @@ -48,6 +48,7 @@ private void ping(String ip, int port) { state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantConnect").getString(); return; } catch (Exception e) { + e.printStackTrace(); state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantPing", ip).getString(); return; } @@ -96,6 +97,7 @@ public boolean isConnectionOpen() { clientConnection.connect(ip, port, listener); clientConnection.send(QueryRequestC2SPacket.INSTANCE); } catch (Throwable throwable) { + throwable.printStackTrace(); pingDestination = null; state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantPing", ip).getString(); clientConnection.disconnect(Text.translatable("multiplayer.status.cancelled"));