1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-19 14:59:27 +00:00

Resolve "not in event loop" issue on Geyser-Velocity with use-direct-connection enabled (#5720)

This commit is contained in:
chris
2025-08-15 23:38:42 +03:00
committed by GitHub
parent 28dcffa21e
commit e2ae101419
4 changed files with 36 additions and 66 deletions

View File

@@ -8,6 +8,10 @@ dependencies {
annotationProcessor(libs.velocity.api)
api(projects.core)
compileOnly(libs.velocity.proxy)
compileOnly(libs.netty.transport.native.io.uring)
compileOnly(libs.netty.transport.native.kqueue)
compileOnlyApi(libs.velocity.api)
api(libs.cloud.velocity)
}

View File

@@ -26,6 +26,7 @@
package org.geysermc.geyser.platform.velocity;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.proxy.network.TransportType;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
@@ -33,18 +34,25 @@ import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.IoEventLoop;
import io.netty.channel.IoEventLoopGroup;
import io.netty.channel.IoHandler;
import io.netty.channel.IoHandlerFactory;
import io.netty.channel.MultiThreadIoEventLoopGroup;
import io.netty.channel.SingleThreadIoEventLoop;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.epoll.EpollIoHandler;
import io.netty.channel.kqueue.KQueueIoHandler;
import io.netty.channel.local.LocalAddress;
import io.netty.channel.local.LocalIoHandler;
import io.netty.channel.nio.NioIoHandler;
import io.netty.channel.uring.IoUringIoHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.ThreadAwareExecutor;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.network.netty.GeyserInjector;
import org.geysermc.geyser.network.netty.IoHandlerWrapper;
import org.geysermc.geyser.network.netty.LocalServerChannelWrapper;
import org.geysermc.geyser.network.netty.WatchedSingleThreadIoEventLoop;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -86,9 +94,18 @@ public class GeyserVelocityInjector extends GeyserInjector {
Field workerGroupField = connectionManagerClass.getDeclaredField("workerGroup");
workerGroupField.setAccessible(true);
EventLoopGroup workerGroup = (EventLoopGroup) workerGroupField.get(connectionManager);
IoEventLoopGroup workerGroup = (IoEventLoopGroup) workerGroupField.get(connectionManager);
EventLoopGroup wrapperGroup = new MultiThreadIoEventLoopGroup(LocalIoHandler.newFactory()) {
var factory = LocalIoHandler.newFactory();
var nativeFactory = getNativeHandlerFactory();
var wrapperFactory = new IoHandlerFactory() {
@Override
public IoHandler newHandler(ThreadAwareExecutor ioExecutor) {
return new IoHandlerWrapper(factory.newHandler(ioExecutor), nativeFactory.newHandler(ioExecutor));
}
};
EventLoopGroup wrapperGroup = new MultiThreadIoEventLoopGroup(factory) {
@Override
protected ThreadFactory newDefaultThreadFactory() {
return new DefaultThreadFactory("Geyser Backend Worker Group", Thread.MAX_PRIORITY);
@@ -96,7 +113,7 @@ public class GeyserVelocityInjector extends GeyserInjector {
@Override
protected IoEventLoop newChild(Executor executor, IoHandlerFactory ioHandlerFactory, Object... args) {
return new WatchedSingleThreadIoEventLoop(workerGroup, this, executor, ioHandlerFactory);
return new SingleThreadIoEventLoop(workerGroup, executor, wrapperFactory);
}
};
@@ -126,4 +143,13 @@ public class GeyserVelocityInjector extends GeyserInjector {
this.localChannel = channelFuture;
this.serverSocketAddress = channelFuture.channel().localAddress();
}
private static IoHandlerFactory getNativeHandlerFactory() {
return switch (TransportType.bestType()) {
case NIO -> NioIoHandler.newFactory();
case EPOLL -> EpollIoHandler.newFactory();
case KQUEUE -> KQueueIoHandler.newFactory();
case IO_URING -> IoUringIoHandler.newFactory();
};
}
}