From 0f56376dbcce96a2afd1c48030d81ad736fa1e9b Mon Sep 17 00:00:00 2001 From: BlueDemonTR <83763146+BlueDemonTR@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:06:11 +0300 Subject: [PATCH 1/3] enable so_resureport Co-Authored-By: Ashtral <69469869+ashtr4l@users.noreply.github.com> --- .../java/dev/ryanhcode/sable/mixin/udp/ConnectionMixin.java | 2 ++ .../sable/mixin/udp/ServerConnectionListenerMixin.java | 3 +++ 2 files changed, 5 insertions(+) diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ConnectionMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ConnectionMixin.java index 80a8722b..ef0fb4c6 100644 --- a/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ConnectionMixin.java +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ConnectionMixin.java @@ -9,6 +9,7 @@ import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.epoll.Epoll; +import io.netty.channel.epoll.EpollChannelOption; import io.netty.channel.epoll.EpollDatagramChannel; import io.netty.channel.local.LocalChannel; import io.netty.channel.socket.nio.NioDatagramChannel; @@ -83,6 +84,7 @@ protected void initChannel(final Channel channel) { } }) .channel(channelClass) + .option(EpollChannelOption.SO_REUSEPORT, true) .connect(inetSocketAddress.getAddress(), inetSocketAddress.getPort()); channelFuture.syncUninterruptibly(); diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ServerConnectionListenerMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ServerConnectionListenerMixin.java index f3df9e77..77d358e1 100644 --- a/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ServerConnectionListenerMixin.java +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ServerConnectionListenerMixin.java @@ -9,6 +9,7 @@ import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.epoll.Epoll; +import io.netty.channel.epoll.EpollChannelOption; import io.netty.channel.epoll.EpollDatagramChannel; import io.netty.channel.local.LocalAddress; import io.netty.channel.local.LocalServerChannel; @@ -67,6 +68,7 @@ public class ServerConnectionListenerMixin implements ServerConnectionListenerEx this.channels.add(new Bootstrap() .channel(channelClass) .option(ChannelOption.SO_BROADCAST, true) + .option(EpollChannelOption.SO_REUSEPORT, true) .handler(new ChannelInitializer<>() { @Override protected void initChannel(final Channel channel) { @@ -93,6 +95,7 @@ protected void initChannel(final Channel channel) { this.channels.add(new Bootstrap() .channel(LocalServerChannel.class) .option(ChannelOption.SO_BROADCAST, true) + .option(EpollChannelOption.SO_REUSEPORT, true) .handler(new ChannelInitializer<>() { @Override protected void initChannel(final Channel channel) { From e6f2b647e70e3fdcd577848004749a921cb9de3a Mon Sep 17 00:00:00 2001 From: BlueDemonTR <83763146+BlueDemonTR@users.noreply.github.com> Date: Wed, 22 Apr 2026 20:59:49 +0300 Subject: [PATCH 2/3] add udp port control from config --- .../java/dev/ryanhcode/sable/SableConfig.java | 5 +++++ .../sable/mixin/udp/ConnectionMixin.java | 5 ++--- .../mixin/udp/ServerConnectionListenerMixin.java | 4 +--- .../tcp/ClientboundSableUDPActivationPacket.java | 6 +++++- .../udp/SableUDPClientboundKeepAlivePacket.java | 5 ++++- .../sable/network/udp/SableUDPServer.java | 15 +++++++++++++++ 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/dev/ryanhcode/sable/SableConfig.java b/common/src/main/java/dev/ryanhcode/sable/SableConfig.java index 27f47dbd..4c3ff887 100644 --- a/common/src/main/java/dev/ryanhcode/sable/SableConfig.java +++ b/common/src/main/java/dev/ryanhcode/sable/SableConfig.java @@ -17,6 +17,8 @@ public final class SableConfig { public static final ModConfigSpec.IntValue SUB_LEVEL_PUNCH_COOLDOWN_TICKS; public static final ModConfigSpec.BooleanValue DISABLE_UDP_PIPELINE; public static final ModConfigSpec.BooleanValue ATTEMPT_UDP_NETWORKING; + public static final ModConfigSpec.IntValue UDP_LISTEN_PORT; + static { final ModConfigSpec.Builder builder = new ModConfigSpec.Builder(); @@ -56,6 +58,9 @@ public final class SableConfig { ATTEMPT_UDP_NETWORKING = builder .comment("If Sable should attempt to authenticate with clients and send them sub-level data over UDP") .define("attempt_udp_networking", true); + UDP_LISTEN_PORT = builder + .comment("The port Sable will use when sending data over UDP (-1 = The Minecraft Server Instance Port)") + .defineInRange("udp_listen_port", -1, -1, 65535); SPEC = builder.build(); } diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ConnectionMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ConnectionMixin.java index ef0fb4c6..5d25ea16 100644 --- a/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ConnectionMixin.java +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ConnectionMixin.java @@ -5,11 +5,11 @@ import dev.ryanhcode.sable.SableClient; import dev.ryanhcode.sable.mixinterface.udp.ConnectionExtension; import dev.ryanhcode.sable.network.udp.SableUDPPacket; +import dev.ryanhcode.sable.network.udp.SableUDPServer; import dev.ryanhcode.sable.network.udp.handler.SableUDPChannelHandlerClient; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.epoll.Epoll; -import io.netty.channel.epoll.EpollChannelOption; import io.netty.channel.epoll.EpollDatagramChannel; import io.netty.channel.local.LocalChannel; import io.netty.channel.socket.nio.NioDatagramChannel; @@ -84,8 +84,7 @@ protected void initChannel(final Channel channel) { } }) .channel(channelClass) - .option(EpollChannelOption.SO_REUSEPORT, true) - .connect(inetSocketAddress.getAddress(), inetSocketAddress.getPort()); + .connect(inetSocketAddress.getAddress(), SableUDPServer.getUDPPort(inetSocketAddress.getPort())); channelFuture.syncUninterruptibly(); } diff --git a/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ServerConnectionListenerMixin.java b/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ServerConnectionListenerMixin.java index 77d358e1..ab4e3733 100644 --- a/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ServerConnectionListenerMixin.java +++ b/common/src/main/java/dev/ryanhcode/sable/mixin/udp/ServerConnectionListenerMixin.java @@ -68,7 +68,6 @@ public class ServerConnectionListenerMixin implements ServerConnectionListenerEx this.channels.add(new Bootstrap() .channel(channelClass) .option(ChannelOption.SO_BROADCAST, true) - .option(EpollChannelOption.SO_REUSEPORT, true) .handler(new ChannelInitializer<>() { @Override protected void initChannel(final Channel channel) { @@ -77,7 +76,7 @@ protected void initChannel(final Channel channel) { } }) .group(eventLoopGroup) - .localAddress(inetAddress, port) + .localAddress(inetAddress, SableUDPServer.getUDPPort(port)) .bind() .syncUninterruptibly()); } @@ -95,7 +94,6 @@ protected void initChannel(final Channel channel) { this.channels.add(new Bootstrap() .channel(LocalServerChannel.class) .option(ChannelOption.SO_BROADCAST, true) - .option(EpollChannelOption.SO_REUSEPORT, true) .handler(new ChannelInitializer<>() { @Override protected void initChannel(final Channel channel) { diff --git a/common/src/main/java/dev/ryanhcode/sable/network/packets/tcp/ClientboundSableUDPActivationPacket.java b/common/src/main/java/dev/ryanhcode/sable/network/packets/tcp/ClientboundSableUDPActivationPacket.java index 14c05ac1..fc764f4b 100644 --- a/common/src/main/java/dev/ryanhcode/sable/network/packets/tcp/ClientboundSableUDPActivationPacket.java +++ b/common/src/main/java/dev/ryanhcode/sable/network/packets/tcp/ClientboundSableUDPActivationPacket.java @@ -5,6 +5,7 @@ import dev.ryanhcode.sable.network.packets.udp.SableUDPAuthenticationPacket; import dev.ryanhcode.sable.network.tcp.SableTCPPacket; import dev.ryanhcode.sable.network.udp.AddressedSableUDPPacket; +import dev.ryanhcode.sable.network.udp.SableUDPServer; import foundry.veil.api.network.handler.PacketContext; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -44,7 +45,10 @@ public void handle(final PacketContext context) { final Channel channel = connectionExtension.sable$getUDPChannel(); final InetSocketAddress baseAddress = ((InetSocketAddress) connection.getRemoteAddress()); - final InetSocketAddress remoteAddress = new InetSocketAddress(baseAddress.getAddress(), baseAddress.getPort()); + final InetSocketAddress remoteAddress = new InetSocketAddress( + baseAddress.getAddress(), + SableUDPServer.getUDPPort(baseAddress.getPort()) + ); Sable.LOGGER.info("Received authentication request, sending response over UDP to {}", remoteAddress); diff --git a/common/src/main/java/dev/ryanhcode/sable/network/packets/udp/SableUDPClientboundKeepAlivePacket.java b/common/src/main/java/dev/ryanhcode/sable/network/packets/udp/SableUDPClientboundKeepAlivePacket.java index c4990411..b1492671 100644 --- a/common/src/main/java/dev/ryanhcode/sable/network/packets/udp/SableUDPClientboundKeepAlivePacket.java +++ b/common/src/main/java/dev/ryanhcode/sable/network/packets/udp/SableUDPClientboundKeepAlivePacket.java @@ -4,6 +4,7 @@ import dev.ryanhcode.sable.network.udp.AddressedSableUDPPacket; import dev.ryanhcode.sable.network.udp.SableUDPPacket; import dev.ryanhcode.sable.network.udp.SableUDPPacketType; +import dev.ryanhcode.sable.network.udp.SableUDPServer; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; @@ -30,7 +31,9 @@ public void handleClient(final Level level) { final Channel channel = connectionExtension.sable$getUDPChannel(); final InetSocketAddress baseAddress = ((InetSocketAddress) connection.getRemoteAddress()); - final InetSocketAddress remoteAddress = new InetSocketAddress(baseAddress.getAddress(), baseAddress.getPort()); + final InetSocketAddress remoteAddress = new InetSocketAddress( + baseAddress.getAddress(), + SableUDPServer.getUDPPort(baseAddress.getPort())); channel.eventLoop().execute(() -> { final SableUDPServerboundAlivePacket packet = new SableUDPServerboundAlivePacket(); diff --git a/common/src/main/java/dev/ryanhcode/sable/network/udp/SableUDPServer.java b/common/src/main/java/dev/ryanhcode/sable/network/udp/SableUDPServer.java index d17dce80..933243f0 100644 --- a/common/src/main/java/dev/ryanhcode/sable/network/udp/SableUDPServer.java +++ b/common/src/main/java/dev/ryanhcode/sable/network/udp/SableUDPServer.java @@ -17,6 +17,7 @@ import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; +import net.neoforged.neoforge.common.ModConfigSpec; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -52,6 +53,20 @@ public static SableUDPServer getServer(final MinecraftServer server) { return (((ServerConnectionListenerExtension) server.getConnection())).sable$getServer(); } + /** + * Returns the port that will be used by the UDP server + * + * @param _default the socket that will be used in the case where the port in config is set to -1 + * @return the port that will be used by the UDP server + */ + public static Integer getUDPPort(final int _default) { + final int fromConfig = SableConfig.UDP_LISTEN_PORT.getAsInt(); + + if(fromConfig == -1) return _default; + + return fromConfig; + } + /*@Override public void flushUDP() { if (this.udpChannel.eventLoop().inEventLoop()) From c92809d368629d33ec5df8c572c937e75d615739 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 3 May 2026 20:44:09 +0000 Subject: [PATCH 3/3] Automated build rust natives --- .../sable_rapier_binaries.zip.l4z | Bin 8900100 -> 8900099 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/common/src/main/resources/natives/sable_rapier/sable_rapier_binaries.zip.l4z b/common/src/main/resources/natives/sable_rapier/sable_rapier_binaries.zip.l4z index 022e3039ab0aa0e01e870701f005a7c60d69209d..416b42dcf77a031adf47a5d48573725b352194b6 100644 GIT binary patch delta 540 zcmW;I%X5oy6o>I&$=cAa5`|DX#qt+D9X7)KYM<@d}phbK?9L6OG9EX-)kCXamPFqZ-> zSg|pW`Pgx=fI=2hL@|pf!O3D=EMY0jSWYQ!Je1*O1uI#_YJ99=E$b-9&w47@z(y+B z#Addzl`6JTO$`CIvx8cK?4*ue)U%sC>}4POIY5YmG|)&Bhd4|#VUEzkQI2t(6P)A} zr#Zt}&T*a#T;viFT8VO*HrnZU8>_Kur5}H`MBEs)UTK&%P3ktS zQ*?=L(Ic*kUePD6iR&UEZWuN#`Q7D~D=v#EsHu*^Dci)4A~i8yq?*I^;aB&5wKX{^ zzvjAMWL$>3H2K$+AB=xds=rM429kz1kQ(-BlfU15%6)E44Vil+r!krm{oyO0ak5zi6@Y}dv{tpdB B&2Rt! delta 509 zcmXBQOK?kZ7{=lMk<-%V91)R_rf8}SMNyZ!G_$we5sccI${isIXKWMp_IAIql|K# z7?{k*#RA+c#KR)I_*l#m{8SL2lBFzTIaLIyW(76W5@IE*sADy2SW7+YSkDF;*vKX} zvxP>svW@NRpouU$*+nxg?534Hw6T|c?B@UnIYc`hbaI#@L^w(pQI2t(6P%=*9!}BA zY0hw#KF)ET3tZ$9{lvJ;6|OSyKHg;L6TPW-*=8d?;&4^WSW`w^4BAu1wa!0U(K7Yx z;)WO!H^s2HC2os5;;y(S?%SrG_!qZ-!OxivD-=%Hp>Q%+r+@#@{VMyZKRNFB;h(W0v7~q)9*Pn1NQ{ax@mM?& zDS;TbBeAsB8kA&vxi;ibe|<$W^Tw?*Pu>5!pZ9$9TqIrIh8$ Wr)^i>$~kBMFj=sIvrE1dtonaMUB5X1