Skip to content

Commit

Permalink
Merge branch 'feature/threaded-udp-server'
Browse files Browse the repository at this point in the history
  • Loading branch information
ishland committed Jan 13, 2025
2 parents 8ff8f27 + 0c0773f commit 41243b9
Show file tree
Hide file tree
Showing 16 changed files with 170 additions and 51 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: validate gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: setup jdk ${{ matrix.java }}
Expand Down
6 changes: 2 additions & 4 deletions .github/workflows/checkMappings.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
name: check mappings
on:
push:
branches:
- 'master'
on: [pull_request, push]

jobs:
checkMappings:
Expand All @@ -20,6 +17,7 @@ jobs:
uses: actions/checkout@v2
with:
fetch-depth: 0
submodules: true
- name: validate gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: setup jdk ${{ matrix.java }}
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "netty-raknet"]
path = netty-raknet
url = https://github.com/RelativityMC/netty-raknet.git
6 changes: 3 additions & 3 deletions common/build.gradle
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
dependencies {
api("com.github.RelativityMC.netty-raknet:netty-raknet-common:${project.netty_raknet_version}") {
api("com.github.RelativityMC.netty-raknet:netty-raknet-common") {
transitive = false
}
api("com.github.RelativityMC.netty-raknet:netty-raknet-client:${project.netty_raknet_version}")
api("com.github.RelativityMC.netty-raknet:netty-raknet-server:${project.netty_raknet_version}")
api("com.github.RelativityMC.netty-raknet:netty-raknet-client")
api("com.github.RelativityMC.netty-raknet:netty-raknet-server")
api("org.apache.commons:commons-math3:3.6.1")

//noinspection GradlePackageUpdate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import com.google.common.base.Suppliers;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.netty.channel.DefaultEventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.FastThreadLocalThread;
Expand All @@ -39,7 +40,18 @@ public class RaknetifyEventLoops {
0,
new ThreadFactoryBuilder()
.setThreadFactory(FastThreadLocalThread::new)
.setNameFormat("Raknetify NIO #%d")
.setNameFormat("Netty Server NIO Raknetify #%d")
.setDaemon(true)
.build()
)
);

public static final Supplier<NioEventLoopGroup> NIO_CLIENT_EVENT_LOOP_GROUP =
Suppliers.memoize(() -> new NioEventLoopGroup(
0,
new ThreadFactoryBuilder()
.setThreadFactory(FastThreadLocalThread::new)
.setNameFormat("Netty Client NIO Raknetify #%d")
.setDaemon(true)
.build()
)
Expand All @@ -50,7 +62,40 @@ public class RaknetifyEventLoops {
0,
new ThreadFactoryBuilder()
.setThreadFactory(FastThreadLocalThread::new)
.setNameFormat("Raknetify Epoll #%d")
.setNameFormat("Netty Server Epoll Raknetify #%d")
.setDaemon(true)
.build()
)
);

public static final Supplier<EpollEventLoopGroup> EPOLL_CLIENT_EVENT_LOOP_GROUP =
Suppliers.memoize(() -> new EpollEventLoopGroup(
0,
new ThreadFactoryBuilder()
.setThreadFactory(FastThreadLocalThread::new)
.setNameFormat("Netty Client Epoll Raknetify #%d")
.setDaemon(true)
.build()
)
);

public static final Supplier<DefaultEventLoopGroup> DEFAULT_EVENT_LOOP_GROUP =
Suppliers.memoize(() -> new DefaultEventLoopGroup(
0,
new ThreadFactoryBuilder()
.setThreadFactory(FastThreadLocalThread::new)
.setNameFormat("Netty Server App Raknetify #%d")
.setDaemon(true)
.build()
)
);

public static final Supplier<DefaultEventLoopGroup> DEFAULT_CLIENT_EVENT_LOOP_GROUP =
Suppliers.memoize(() -> new DefaultEventLoopGroup(
0,
new ThreadFactoryBuilder()
.setThreadFactory(FastThreadLocalThread::new)
.setNameFormat("Netty Client App Raknetify #%d")
.setDaemon(true)
.build()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ private ClientConnection connectRaknet(InetSocketAddress address, boolean useEpo
return this.isRaknet ? RakNetClientConnectionUtil.connect(address, useEpoll, this.raknetLargeMTU, original, false) : original.call(address, useEpoll);
}

@Redirect(method = "run()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;"), require = 0)
private ChannelFuture connectRaknet(InetSocketAddress address, boolean useEpoll, ClientConnection connection) {
return this.isRaknet ? RakNetClientConnectionUtil.connect(address, useEpoll, this.raknetLargeMTU, connection) : ClientConnection.connect(address, useEpoll, connection);
@WrapOperation(method = "run()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;"), require = 0)
private ChannelFuture connectRaknet(InetSocketAddress address, boolean useEpoll, ClientConnection connection, Operation<ChannelFuture> original) {
return this.isRaknet ? RakNetClientConnectionUtil.connect(address, useEpoll, this.raknetLargeMTU, connection) : original.call(address, useEpoll, connection);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@
public abstract class MixinMultiplayerServerListPinger {

@Dynamic
@Redirect(method = {"add", "method_3003"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ServerAddress;parse(Ljava/lang/String;)Lnet/minecraft/client/network/ServerAddress;"))
private ServerAddress modifyRaknetAddress(String address) {
@WrapOperation(method = {"add", "method_3003"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ServerAddress;parse(Ljava/lang/String;)Lnet/minecraft/client/network/ServerAddress;"))
private ServerAddress modifyRaknetAddress(String address, Operation<ServerAddress> original) {
final PrefixUtil.Info info = PrefixUtil.getInfo(address);
return ServerAddress.parse(info.stripped());
return original.call(info.stripped());
}

@Dynamic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package com.ishland.raknetify.fabric.mixin.client;

import com.ishland.raknetify.fabric.mixin.access.IClientConnection;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import io.netty.channel.Channel;
import net.minecraft.client.network.MultiplayerServerListPinger;
import net.minecraft.client.network.ServerAddress;
Expand Down Expand Up @@ -63,15 +64,17 @@ private void setPingImmediately(CallbackInfo ci) {
}

@Dynamic
@Redirect(method = {"method_10839(Lnet/minecraft/class_2561;)V", "onDisconnected"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/MultiplayerServerListPinger;ping(Ljava/net/InetSocketAddress;Lnet/minecraft/client/network/ServerAddress;Lnet/minecraft/client/network/ServerInfo;)V"), require = 0)
private void noPingRaknet(MultiplayerServerListPinger instance, InetSocketAddress socketAddress, ServerAddress address, ServerInfo serverInfo) {
// no-op
@WrapWithCondition(method = {"method_10839(Lnet/minecraft/class_2561;)V", "onDisconnected"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/MultiplayerServerListPinger;ping(Ljava/net/InetSocketAddress;Lnet/minecraft/client/network/ServerAddress;Lnet/minecraft/client/network/ServerInfo;)V"), require = 0)
private boolean noPingRaknet(MultiplayerServerListPinger instance, InetSocketAddress socketAddress, ServerAddress address, ServerInfo serverInfo) {
final Channel channel = ((IClientConnection) field_3774).getChannel();
return !(channel.config() instanceof RakNet.Config);
}

@Dynamic
@Redirect(method = "method_10839(Lnet/minecraft/class_2561;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/MultiplayerServerListPinger;method_3001(Ljava/net/InetSocketAddress;Lnet/minecraft/client/network/ServerInfo;)V"), require = 0)
private void noPingRaknet(MultiplayerServerListPinger instance, InetSocketAddress address, ServerInfo info) {
// no-op
@WrapWithCondition(method = "method_10839(Lnet/minecraft/class_2561;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/MultiplayerServerListPinger;method_3001(Ljava/net/InetSocketAddress;Lnet/minecraft/client/network/ServerInfo;)V"), require = 0)
private boolean noPingRaknet(MultiplayerServerListPinger instance, InetSocketAddress address, ServerInfo info) {
final Channel channel = ((IClientConnection) field_3774).getChannel();
return !(channel.config() instanceof RakNet.Config);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,38 +28,42 @@
import com.ishland.raknetify.common.connection.RakNetConnectionUtil;
import com.ishland.raknetify.common.connection.RaknetifyEventLoops;
import com.ishland.raknetify.common.util.ThreadLocalUtil;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import io.netty.bootstrap.AbstractBootstrap;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.FixedRecvByteBufAllocator;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollDatagramChannel;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioDatagramChannel;
import net.minecraft.network.ClientConnection;
import net.minecraft.util.Lazy;
import network.ycc.raknet.RakNet;
import network.ycc.raknet.client.channel.RakNetClientThreadedChannel;
import org.spongepowered.asm.mixin.Dynamic;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

import java.net.InetSocketAddress;
import java.util.function.Supplier;

@Mixin(ClientConnection.class)
public class MixinCCConnect {

@Dynamic("method_10753 for compat")
@Redirect(method = {"connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;", "method_10753(Ljava/net/InetSocketAddress;Z)Lnet/minecraft/network/ClientConnection;", "method_10753"}, at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;channel(Ljava/lang/Class;)Lio/netty/bootstrap/AbstractBootstrap;", remap = false), require = 1)
private static AbstractBootstrap<Bootstrap, Channel> redirectChannel(Bootstrap instance, Class<? extends SocketChannel> aClass, InetSocketAddress address, boolean useEpoll) {
@WrapOperation(method = {"connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;", "method_10753(Ljava/net/InetSocketAddress;Z)Lnet/minecraft/network/ClientConnection;", "method_10753"}, at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;group(Lio/netty/channel/EventLoopGroup;)Lio/netty/bootstrap/AbstractBootstrap;", remap = false), require = 1)
private static AbstractBootstrap<Bootstrap, Channel> redirectGroup(Bootstrap instance, EventLoopGroup eventLoopGroup, Operation<AbstractBootstrap<Bootstrap, Channel>> original, InetSocketAddress address, boolean useEpoll) {
return ThreadLocalUtil.isInitializingRaknet()
? original.call(instance, RaknetifyEventLoops.DEFAULT_CLIENT_EVENT_LOOP_GROUP.get())
: original.call(instance, eventLoopGroup);
}

@Dynamic("method_10753 for compat")
@WrapOperation(method = {"connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;", "method_10753(Ljava/net/InetSocketAddress;Z)Lnet/minecraft/network/ClientConnection;", "method_10753"}, at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;channel(Ljava/lang/Class;)Lio/netty/bootstrap/AbstractBootstrap;", remap = false), require = 1)
private static AbstractBootstrap<Bootstrap, Channel> redirectChannel(Bootstrap instance, Class<? extends SocketChannel> aClass, Operation<AbstractBootstrap<Bootstrap, Channel>> original, InetSocketAddress address, boolean useEpoll) {
boolean actuallyUseEpoll = Epoll.isAvailable() && useEpoll;
return ThreadLocalUtil.isInitializingRaknet()
? instance.channelFactory(() -> {
Expand All @@ -74,10 +78,10 @@ private static AbstractBootstrap<Bootstrap, Channel> redirectChannel(Bootstrap i
return channel1;
});
RakNet.config(channel).setMTU(initializingRaknetLargeMTU ? Constants.LARGE_MTU : Constants.DEFAULT_MTU);
channel.setProvidedEventLoop(actuallyUseEpoll ? RaknetifyEventLoops.EPOLL_EVENT_LOOP_GROUP.get().next() : RaknetifyEventLoops.NIO_EVENT_LOOP_GROUP.get().next());
channel.setProvidedParentEventLoop(actuallyUseEpoll ? RaknetifyEventLoops.EPOLL_CLIENT_EVENT_LOOP_GROUP.get().next() : RaknetifyEventLoops.NIO_CLIENT_EVENT_LOOP_GROUP.get().next());
return channel;
})
: instance.channel(aClass);
: original.call(instance, aClass);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* This file is a part of the Raknetify project, licensed under MIT.
*
* Copyright (c) 2022-2023 ishland
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.ishland.raknetify.fabric.mixin.common;

import com.ishland.raknetify.common.Constants;
import com.ishland.raknetify.common.util.PrefixUtil;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import net.minecraft.client.network.ServerAddress;
import org.spongepowered.asm.mixin.Mixin;

@Mixin(ServerAddress.class)
public class MixinServerAddress {

@WrapMethod(method = "parse")
private static ServerAddress wrapParsing(String address, Operation<ServerAddress> original) {
PrefixUtil.Info info = PrefixUtil.getInfo(address);
if (info.useRakNet()) {
ServerAddress addr = original.call(info.stripped());
return new ServerAddress(
(info.largeMTU() ? Constants.RAKNET_LARGE_MTU_PREFIX : Constants.RAKNET_PREFIX) + addr.getAddress(),
addr.getPort()
);
} else {
return original.call(address);
}
}

}
Loading

0 comments on commit 41243b9

Please sign in to comment.