mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-22 22:45:04 +01:00
Remove old network code & use manual ping
This commit is contained in:
parent
3f42d68f4e
commit
74798d8071
13 changed files with 215 additions and 139 deletions
|
@ -30,8 +30,6 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.steveice10.packetlib.tcp.TcpSession;
|
||||
import com.nukkitx.network.raknet.RakNetConstants;
|
||||
import com.nukkitx.network.util.EventLoops;
|
||||
import io.netty.channel.epoll.Epoll;
|
||||
import io.netty.channel.kqueue.KQueue;
|
||||
import io.netty.util.NettyRuntime;
|
||||
|
@ -284,34 +282,16 @@ public class GeyserImpl implements GeyserApi {
|
|||
CooldownUtils.setDefaultShowCooldown(config.getShowCooldown());
|
||||
DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether
|
||||
|
||||
// https://github.com/GeyserMC/Geyser/issues/957
|
||||
RakNetConstants.MAXIMUM_MTU_SIZE = (short) config.getMtu();
|
||||
logger.debug("Setting MTU to " + config.getMtu());
|
||||
|
||||
Integer bedrockThreadCount = Integer.getInteger("Geyser.BedrockNetworkThreads");
|
||||
if (bedrockThreadCount == null) {
|
||||
// Copy the code from Netty's default thread count fallback
|
||||
bedrockThreadCount = Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
|
||||
}
|
||||
|
||||
boolean enableProxyProtocol = config.getBedrock().isEnableProxyProtocol();
|
||||
if (config.isDebugMode()) {
|
||||
logger.debug("EventLoop type: " + EventLoops.getChannelType());
|
||||
if (EventLoops.getChannelType() == EventLoops.ChannelType.NIO) {
|
||||
if (System.getProperties().contains("disableNativeEventLoop")) {
|
||||
logger.debug("EventLoop type is NIO because native event loops are disabled.");
|
||||
} else {
|
||||
logger.debug("Reason for no Epoll: " + Epoll.unavailabilityCause().toString());
|
||||
logger.debug("Reason for no KQueue: " + KQueue.unavailabilityCause().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldStartListener) {
|
||||
try {
|
||||
this.geyserServer = new GeyserServer(this, bedrockThreadCount);
|
||||
this.geyserServer.bind(new InetSocketAddress(config.getBedrock().address(), config.getBedrock().port()))
|
||||
.awaitUninterruptibly();
|
||||
this.geyserServer.bind(new InetSocketAddress(config.getBedrock().address(), config.getBedrock().port()));
|
||||
|
||||
logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.getBedrock().address(),
|
||||
String.valueOf(config.getBedrock().port())));
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
package org.geysermc.geyser.level.block;
|
||||
|
||||
import com.nukkitx.network.util.Preconditions;
|
||||
import org.cloudburstmc.protocol.common.util.Preconditions;
|
||||
|
||||
public class BlockPositionIterator {
|
||||
private final int minX;
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
|
||||
package org.geysermc.geyser.level.chunk;
|
||||
|
||||
import com.nukkitx.network.VarInts;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import lombok.Getter;
|
||||
import org.cloudburstmc.protocol.common.util.VarInts;
|
||||
import org.geysermc.geyser.level.chunk.bitarray.BitArray;
|
||||
import org.geysermc.geyser.level.chunk.bitarray.BitArrayVersion;
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
package org.geysermc.geyser.level.chunk;
|
||||
|
||||
import com.nukkitx.network.util.Preconditions;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.cloudburstmc.protocol.common.util.Preconditions;
|
||||
|
||||
public class GeyserChunkSection {
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
package org.geysermc.geyser.level.chunk.bitarray;
|
||||
|
||||
import com.nukkitx.network.VarInts;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.cloudburstmc.protocol.common.util.VarInts;
|
||||
|
||||
public interface BitArray {
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
package org.geysermc.geyser.level.chunk.bitarray;
|
||||
|
||||
import com.nukkitx.network.util.Preconditions;
|
||||
import org.cloudburstmc.protocol.common.util.Preconditions;
|
||||
import org.geysermc.geyser.util.MathUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
package org.geysermc.geyser.level.chunk.bitarray;
|
||||
|
||||
import com.nukkitx.network.util.Preconditions;
|
||||
import org.cloudburstmc.protocol.common.util.Preconditions;
|
||||
import org.geysermc.geyser.util.MathUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
|
|
@ -35,21 +35,8 @@ import org.geysermc.geyser.GeyserImpl;
|
|||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class GeyserServerInitializer extends BedrockServerInitializer {
|
||||
private static final boolean PRINT_DEBUG_PINGS = Boolean.parseBoolean(System.getProperty("Geyser.PrintPingsInDebugMode", "true"));
|
||||
|
||||
/*
|
||||
The following constants are all used to ensure the ping does not reach a length where it is unparsable by the Bedrock client
|
||||
*/
|
||||
private static final int MINECRAFT_VERSION_BYTES_LENGTH = GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion().getBytes(StandardCharsets.UTF_8).length;
|
||||
private static final int BRAND_BYTES_LENGTH = GeyserImpl.NAME.getBytes(StandardCharsets.UTF_8).length;
|
||||
/**
|
||||
* The MOTD, sub-MOTD and Minecraft version ({@link #MINECRAFT_VERSION_BYTES_LENGTH}) combined cannot reach this length.
|
||||
*/
|
||||
private static final int MAGIC_RAKNET_LENGTH = 338;
|
||||
|
||||
private final GeyserImpl geyser;
|
||||
// There is a constructor that doesn't require inputting threads, but older Netty versions don't have it
|
||||
private final DefaultEventLoopGroup eventLoopGroup = new DefaultEventLoopGroup(0, new DefaultThreadFactory("Geyser player thread"));
|
||||
|
@ -81,89 +68,11 @@ public class GeyserServerInitializer extends BedrockServerInitializer {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BedrockPong onQuery(InetSocketAddress inetSocketAddress) {
|
||||
if (geyser.getConfig().isDebugMode() && PRINT_DEBUG_PINGS) {
|
||||
String ip = geyser.getConfig().isLogPlayerIpAddresses() ? inetSocketAddress.toString() : "<IP address withheld>";
|
||||
geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.network.pinged", ip));
|
||||
}
|
||||
|
||||
GeyserConfiguration config = geyser.getConfig();
|
||||
|
||||
GeyserPingInfo pingInfo = null;
|
||||
if (config.isPassthroughMotd() || config.isPassthroughPlayerCounts()) {
|
||||
IGeyserPingPassthrough pingPassthrough = geyser.getBootstrap().getGeyserPingPassthrough();
|
||||
pingInfo = pingPassthrough.getPingInformation(inetSocketAddress);
|
||||
}
|
||||
|
||||
BedrockPong pong = new BedrockPong();
|
||||
pong.setEdition("MCPE");
|
||||
pong.setGameType("Survival"); // Can only be Survival or Creative as of 1.16.210.59
|
||||
pong.setNintendoLimited(false);
|
||||
pong.setProtocolVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion());
|
||||
pong.setVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()); // Required to not be empty as of 1.16.210.59. Can only contain . and numbers.
|
||||
pong.setIpv4Port(config.getBedrock().port());
|
||||
|
||||
if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) {
|
||||
String[] motd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n");
|
||||
String mainMotd = motd[0]; // First line of the motd.
|
||||
String subMotd = (motd.length != 1) ? motd[1] : GeyserImpl.NAME; // Second line of the motd if present, otherwise default.
|
||||
|
||||
pong.setMotd(mainMotd.trim());
|
||||
pong.setSubMotd(subMotd.trim()); // Trimmed to shift it to the left, prevents the universe from collapsing on us just because we went 2 characters over the text box's limit.
|
||||
} else {
|
||||
pong.setMotd(config.getBedrock().primaryMotd());
|
||||
pong.setSubMotd(config.getBedrock().secondaryMotd());
|
||||
}
|
||||
|
||||
if (config.isPassthroughPlayerCounts() && pingInfo != null) {
|
||||
pong.setPlayerCount(pingInfo.getPlayers().getOnline());
|
||||
pong.setMaximumPlayerCount(pingInfo.getPlayers().getMax());
|
||||
} else {
|
||||
pong.setPlayerCount(geyser.getSessionManager().getSessions().size());
|
||||
pong.setMaximumPlayerCount(config.getMaxPlayers());
|
||||
}
|
||||
|
||||
// Fallbacks to prevent errors and allow Bedrock to see the server
|
||||
if (pong.getMotd() == null || pong.getMotd().isBlank()) {
|
||||
pong.setMotd(GeyserImpl.NAME);
|
||||
}
|
||||
if (pong.getSubMotd() == null || pong.getSubMotd().isBlank()) {
|
||||
// Sub-MOTD cannot be empty as of 1.16.210.59
|
||||
pong.setSubMotd(GeyserImpl.NAME);
|
||||
}
|
||||
|
||||
// The ping will not appear if the MOTD + sub-MOTD is of a certain length.
|
||||
// We don't know why, though
|
||||
byte[] motdArray = pong.getMotd().getBytes(StandardCharsets.UTF_8);
|
||||
int subMotdLength = pong.getSubMotd().getBytes(StandardCharsets.UTF_8).length;
|
||||
if (motdArray.length + subMotdLength > (MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH)) {
|
||||
// Shorten the sub-MOTD first since that only appears locally
|
||||
if (subMotdLength > BRAND_BYTES_LENGTH) {
|
||||
pong.setSubMotd(GeyserImpl.NAME);
|
||||
subMotdLength = BRAND_BYTES_LENGTH;
|
||||
}
|
||||
if (motdArray.length > (MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH - subMotdLength)) {
|
||||
// If the top MOTD is still too long, we chop it down
|
||||
byte[] newMotdArray = new byte[MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH - subMotdLength];
|
||||
System.arraycopy(motdArray, 0, newMotdArray, 0, newMotdArray.length);
|
||||
pong.setMotd(new String(newMotdArray, StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
//Bedrock will not even attempt a connection if the client thinks the server is full
|
||||
//so we have to fake it not being full
|
||||
if (pong.getPlayerCount() >= pong.getMaximumPlayerCount()) {
|
||||
pong.setMaximumPlayerCount(pong.getPlayerCount() + 1);
|
||||
}
|
||||
|
||||
return pong;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void initSession(@Nonnull BedrockServerSession bedrockServerSession) {
|
||||
System.out.println("init session");
|
||||
try {
|
||||
bedrockServerSession.setCodec(Bedrock_v554.CODEC); // Has the RequestNetworkSettingsPacket
|
||||
bedrockServerSession.setLogging(true);
|
||||
|
|
|
@ -25,36 +25,76 @@
|
|||
|
||||
package org.geysermc.geyser.network.netty;
|
||||
|
||||
import com.nukkitx.network.util.EventLoops;
|
||||
import com.github.steveice10.packetlib.helper.TransportHelper;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.epoll.Epoll;
|
||||
import io.netty.channel.epoll.EpollDatagramChannel;
|
||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||
import io.netty.channel.kqueue.KQueue;
|
||||
import io.netty.channel.kqueue.KQueueDatagramChannel;
|
||||
import io.netty.channel.kqueue.KQueueEventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.DatagramChannel;
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakChannelFactory;
|
||||
import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption;
|
||||
import org.cloudburstmc.netty.handler.codec.raknet.common.UnconnectedPingEncoder;
|
||||
import org.cloudburstmc.netty.handler.codec.raknet.common.UnconnectedPongDecoder;
|
||||
import org.cloudburstmc.netty.handler.codec.raknet.common.UnconnectedPongEncoder;
|
||||
import org.cloudburstmc.netty.handler.codec.raknet.server.RakServerOfflineHandler;
|
||||
import org.cloudburstmc.protocol.bedrock.BedrockPong;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.network.GeyserServerInitializer;
|
||||
import org.geysermc.geyser.ping.GeyserPingInfo;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Random;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class GeyserServer {
|
||||
private static final boolean PRINT_DEBUG_PINGS = Boolean.parseBoolean(System.getProperty("Geyser.PrintPingsInDebugMode", "true"));
|
||||
|
||||
/*
|
||||
The following constants are all used to ensure the ping does not reach a length where it is unparsable by the Bedrock client
|
||||
*/
|
||||
private static final int MINECRAFT_VERSION_BYTES_LENGTH = GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion().getBytes(StandardCharsets.UTF_8).length;
|
||||
private static final int BRAND_BYTES_LENGTH = GeyserImpl.NAME.getBytes(StandardCharsets.UTF_8).length;
|
||||
/**
|
||||
* The MOTD, sub-MOTD and Minecraft version ({@link #MINECRAFT_VERSION_BYTES_LENGTH}) combined cannot reach this length.
|
||||
*/
|
||||
private static final int MAGIC_RAKNET_LENGTH = 338;
|
||||
|
||||
private static final Transport TRANSPORT = compatibleTransport();
|
||||
|
||||
private final GeyserImpl geyser;
|
||||
private final EventLoopGroup group;
|
||||
private final ServerBootstrap bootstrap;
|
||||
|
||||
private ChannelFuture future;
|
||||
private Channel channel;
|
||||
|
||||
public GeyserServer(GeyserImpl geyser, int threadCount) {
|
||||
this.geyser = geyser;
|
||||
this.group = EventLoops.newEventLoopGroup(threadCount);
|
||||
this.group = TRANSPORT.eventLoopGroupFactory().apply(threadCount);
|
||||
|
||||
this.bootstrap = this.createBootstrap(group);
|
||||
this.bootstrap = this.createBootstrap(this.group);
|
||||
}
|
||||
|
||||
public ChannelFuture bind(InetSocketAddress address) {
|
||||
return this.future = this.bootstrap.bind(address);
|
||||
public void bind(InetSocketAddress address) {
|
||||
this.future = this.bootstrap.bind(address).syncUninterruptibly();
|
||||
this.channel = this.future.channel();
|
||||
|
||||
// Add our ping handler
|
||||
this.channel.pipeline().addAfter(RakServerOfflineHandler.NAME, RakPingHandler.NAME, new RakPingHandler(this));
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
|
@ -63,25 +103,122 @@ public final class GeyserServer {
|
|||
}
|
||||
|
||||
private ServerBootstrap createBootstrap(EventLoopGroup group) {
|
||||
// TODO
|
||||
boolean enableProxyProtocol = this.geyser.getConfig().getBedrock().isEnableProxyProtocol();
|
||||
if (this.geyser.getConfig().isDebugMode()) {
|
||||
this.geyser.getLogger().debug("EventLoop type: " + TRANSPORT.datagramChannel());
|
||||
if (TRANSPORT.datagramChannel() == NioDatagramChannel.class) {
|
||||
if (System.getProperties().contains("disableNativeEventLoop")) {
|
||||
this.geyser.getLogger().debug("EventLoop type is NIO because native event loops are disabled.");
|
||||
} else {
|
||||
this.geyser.getLogger().debug("Reason for no Epoll: " + Epoll.unavailabilityCause().toString());
|
||||
this.geyser.getLogger().debug("Reason for no KQueue: " + KQueue.unavailabilityCause().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ServerBootstrap()
|
||||
.channelFactory(RakChannelFactory.server(EventLoops.getChannelType().getDatagramChannel()))
|
||||
.option(RakChannelOption.RAK_ADVERTISEMENT, bedrockPong().toByteBuf())
|
||||
.channelFactory(RakChannelFactory.server(TRANSPORT.datagramChannel()))
|
||||
.group(group)
|
||||
.option(RakChannelOption.RAK_HANDLE_PING, true)
|
||||
.childHandler(new GeyserServerInitializer(this.geyser));
|
||||
}
|
||||
|
||||
// TODO: Temp
|
||||
private BedrockPong bedrockPong() {
|
||||
return new BedrockPong()
|
||||
public BedrockPong onQuery(InetSocketAddress inetSocketAddress) {
|
||||
if (geyser.getConfig().isDebugMode() && PRINT_DEBUG_PINGS) {
|
||||
String ip = geyser.getConfig().isLogPlayerIpAddresses() ? inetSocketAddress.toString() : "<IP address withheld>";
|
||||
geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.network.pinged", ip));
|
||||
}
|
||||
|
||||
GeyserConfiguration config = geyser.getConfig();
|
||||
|
||||
GeyserPingInfo pingInfo = null;
|
||||
if (config.isPassthroughMotd() || config.isPassthroughPlayerCounts()) {
|
||||
IGeyserPingPassthrough pingPassthrough = geyser.getBootstrap().getGeyserPingPassthrough();
|
||||
pingInfo = pingPassthrough.getPingInformation(inetSocketAddress);
|
||||
}
|
||||
|
||||
BedrockPong pong = new BedrockPong()
|
||||
.edition("MCPE")
|
||||
.gameType("Survival") // Can only be Survival or Creative as of 1.16.210.59
|
||||
.nintendoLimited(false)
|
||||
.protocolVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
|
||||
.version(GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()) // Required to not be empty as of 1.16.210.59. Can only contain . and numbers.
|
||||
.ipv4Port(this.geyser.getConfig().getBedrock().port())
|
||||
.motd(this.geyser.getConfig().getBedrock().primaryMotd())
|
||||
.subMotd(this.geyser.getConfig().getBedrock().secondaryMotd())
|
||||
.playerCount(geyser.getSessionManager().getSessions().size())
|
||||
.maximumPlayerCount(this.geyser.getConfig().getMaxPlayers());
|
||||
.ipv4Port(this.geyser.getConfig().getBedrock().port());
|
||||
|
||||
if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) {
|
||||
String[] motd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n");
|
||||
String mainMotd = motd[0]; // First line of the motd.
|
||||
String subMotd = (motd.length != 1) ? motd[1] : GeyserImpl.NAME; // Second line of the motd if present, otherwise default.
|
||||
|
||||
pong.motd(mainMotd.trim());
|
||||
pong.subMotd(subMotd.trim()); // Trimmed to shift it to the left, prevents the universe from collapsing on us just because we went 2 characters over the text box's limit.
|
||||
} else {
|
||||
pong.motd(config.getBedrock().primaryMotd());
|
||||
pong.subMotd(config.getBedrock().secondaryMotd());
|
||||
}
|
||||
|
||||
if (config.isPassthroughPlayerCounts() && pingInfo != null) {
|
||||
pong.playerCount(pingInfo.getPlayers().getOnline());
|
||||
pong.maximumPlayerCount(pingInfo.getPlayers().getMax());
|
||||
} else {
|
||||
pong.playerCount(geyser.getSessionManager().getSessions().size());
|
||||
pong.maximumPlayerCount(config.getMaxPlayers());
|
||||
}
|
||||
|
||||
// Fallbacks to prevent errors and allow Bedrock to see the server
|
||||
if (pong.motd() == null || pong.motd().isBlank()) {
|
||||
pong.motd(GeyserImpl.NAME);
|
||||
}
|
||||
if (pong.subMotd() == null || pong.subMotd().isBlank()) {
|
||||
// Sub-MOTD cannot be empty as of 1.16.210.59
|
||||
pong.subMotd(GeyserImpl.NAME);
|
||||
}
|
||||
|
||||
// The ping will not appear if the MOTD + sub-MOTD is of a certain length.
|
||||
// We don't know why, though
|
||||
byte[] motdArray = pong.motd().getBytes(StandardCharsets.UTF_8);
|
||||
int subMotdLength = pong.subMotd().getBytes(StandardCharsets.UTF_8).length;
|
||||
if (motdArray.length + subMotdLength > (MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH)) {
|
||||
// Shorten the sub-MOTD first since that only appears locally
|
||||
if (subMotdLength > BRAND_BYTES_LENGTH) {
|
||||
pong.subMotd(GeyserImpl.NAME);
|
||||
subMotdLength = BRAND_BYTES_LENGTH;
|
||||
}
|
||||
if (motdArray.length > (MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH - subMotdLength)) {
|
||||
// If the top MOTD is still too long, we chop it down
|
||||
byte[] newMotdArray = new byte[MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH - subMotdLength];
|
||||
System.arraycopy(motdArray, 0, newMotdArray, 0, newMotdArray.length);
|
||||
pong.motd(new String(newMotdArray, StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
//Bedrock will not even attempt a connection if the client thinks the server is full
|
||||
//so we have to fake it not being full
|
||||
if (pong.playerCount() >= pong.maximumPlayerCount()) {
|
||||
pong.maximumPlayerCount(pong.playerCount() + 1);
|
||||
}
|
||||
|
||||
return pong;
|
||||
}
|
||||
|
||||
private static Transport compatibleTransport() {
|
||||
TransportHelper.TransportMethod transportMethod = TransportHelper.determineTransportMethod();
|
||||
if (transportMethod == TransportHelper.TransportMethod.EPOLL) {
|
||||
return new Transport(EpollDatagramChannel.class, EpollEventLoopGroup::new);
|
||||
}
|
||||
|
||||
if (transportMethod == TransportHelper.TransportMethod.KQUEUE) {
|
||||
return new Transport(KQueueDatagramChannel.class, KQueueEventLoopGroup::new);
|
||||
}
|
||||
|
||||
// if (transportMethod == TransportHelper.TransportMethod.IO_URING) {
|
||||
// return new Transport(IOUringDatagramChannel.class, IOUringEventLoopGroup::new);
|
||||
// }
|
||||
|
||||
return new Transport(NioDatagramChannel.class, NioEventLoopGroup::new);
|
||||
}
|
||||
|
||||
private record Transport(Class<? extends DatagramChannel> datagramChannel, Function<Integer, EventLoopGroup> eventLoopGroupFactory) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.network.netty;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakPing;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakPong;
|
||||
import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption;
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
@RequiredArgsConstructor
|
||||
public class RakPingHandler extends SimpleChannelInboundHandler<RakPing> {
|
||||
public static final String NAME = "rak-ping-handler";
|
||||
|
||||
private final GeyserServer server;
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, RakPing msg) throws Exception {
|
||||
long guid = ctx.channel().config().getOption(RakChannelOption.RAK_GUID);
|
||||
|
||||
RakPong pong = msg.reply(guid, this.server.onQuery(msg.getSender()).toByteBuf());
|
||||
ctx.writeAndFlush(pong);
|
||||
}
|
||||
}
|
|
@ -60,14 +60,14 @@ public class BlockMappings {
|
|||
Set<BlockDefinition> jigsawStates;
|
||||
|
||||
public int getBedrockBlockId(int state) {
|
||||
if (state >= this.javaToBedrockBlocks.length) {
|
||||
if (state < 0 || state >= this.javaToBedrockBlocks.length) {
|
||||
return bedrockAir.getRuntimeId();
|
||||
}
|
||||
return this.javaToBedrockBlocks[state].getRuntimeId();
|
||||
}
|
||||
|
||||
public BlockDefinition getBedrockBlock(int state) {
|
||||
if (state >= this.javaToBedrockBlocks.length) {
|
||||
if (state < 0 || state >= this.javaToBedrockBlocks.length) {
|
||||
return bedrockAir;
|
||||
}
|
||||
return this.javaToBedrockBlocks[state];
|
||||
|
|
|
@ -35,10 +35,10 @@ import com.nimbusds.jose.Payload;
|
|||
import com.nimbusds.jose.shaded.json.JSONObject;
|
||||
import com.nimbusds.jose.shaded.json.JSONValue;
|
||||
import com.nimbusds.jwt.SignedJWT;
|
||||
import com.nukkitx.network.util.Preconditions;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.LoginPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.ServerToClientHandshakePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.util.EncryptionUtils;
|
||||
import org.cloudburstmc.protocol.common.util.Preconditions;
|
||||
import org.geysermc.cumulus.form.CustomForm;
|
||||
import org.geysermc.cumulus.form.ModalForm;
|
||||
import org.geysermc.cumulus.form.SimpleForm;
|
||||
|
|
|
@ -6,7 +6,7 @@ guava = "29.0-jre"
|
|||
gson = "2.3.1" # Provided by Spigot 1.8.8
|
||||
websocket = "1.5.1"
|
||||
protocol = "3.0.0.Beta2-SNAPSHOT"
|
||||
raknet = "1.6.28-20220125.214016-6"
|
||||
raknet = "0.0.1.Final-SNAPSHOT"
|
||||
mcauthlib = "d9d773e"
|
||||
mcprotocollib = "1.19.2-SNAPSHOT"
|
||||
packetlib = "3.0"
|
||||
|
@ -82,7 +82,7 @@ junit = { group = "junit", name = "junit", version.ref = "junit" }
|
|||
mcauthlib = { group = "com.github.GeyserMC", name = "MCAuthLib", version.ref = "mcauthlib" }
|
||||
mcprotocollib = { group = "com.github.steveice10", name = "mcprotocollib", version.ref = "mcprotocollib" }
|
||||
packetlib = { group = "com.github.steveice10", name = "packetlib", version.ref = "packetlib" }
|
||||
raknet = { group = "com.nukkitx.network", name = "raknet", version.ref = "raknet" }
|
||||
raknet = { group = "org.cloudburstmc.netty", name = "netty-transport-raknet", version.ref = "raknet" }
|
||||
sponge-api = { group = "org.spongepowered", name = "spongeapi", version.ref = "sponge" }
|
||||
terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" }
|
||||
velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }
|
||||
|
|
Loading…
Reference in a new issue