mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-01-03 17:52:15 +01:00
Implement session restructure mcpl PR
This commit is contained in:
parent
2019e53bad
commit
73633f7811
7 changed files with 58 additions and 137 deletions
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
package org.geysermc.geyser.platform.spigot;
|
package org.geysermc.geyser.platform.spigot;
|
||||||
|
|
||||||
|
import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
|
||||||
import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
|
import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
|
||||||
import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer;
|
import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer;
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
|
@ -176,9 +177,9 @@ public class GeyserSpigotInjector extends GeyserInjector {
|
||||||
*/
|
*/
|
||||||
private void workAroundWeirdBug(GeyserBootstrap bootstrap) {
|
private void workAroundWeirdBug(GeyserBootstrap bootstrap) {
|
||||||
MinecraftProtocol protocol = new MinecraftProtocol();
|
MinecraftProtocol protocol = new MinecraftProtocol();
|
||||||
LocalSession session = new LocalSession(bootstrap.getGeyserConfig().getRemote().address(),
|
LocalSession session = new LocalSession(this.serverSocketAddress, InetAddress.getLoopbackAddress().getHostAddress(), protocol, Runnable::run);
|
||||||
bootstrap.getGeyserConfig().getRemote().port(), this.serverSocketAddress,
|
session.setFlag(MinecraftConstants.CLIENT_HOST, bootstrap.getGeyserConfig().getRemote().address());
|
||||||
InetAddress.getLoopbackAddress().getHostAddress(), protocol, Runnable::run);
|
session.setFlag(MinecraftConstants.CLIENT_PORT, bootstrap.getGeyserConfig().getRemote().port());
|
||||||
session.connect();
|
session.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,6 @@ import org.geysermc.geyser.util.MinecraftAuthLogger;
|
||||||
import org.geysermc.geyser.util.NewsHandler;
|
import org.geysermc.geyser.util.NewsHandler;
|
||||||
import org.geysermc.geyser.util.VersionCheckUtils;
|
import org.geysermc.geyser.util.VersionCheckUtils;
|
||||||
import org.geysermc.geyser.util.WebUtils;
|
import org.geysermc.geyser.util.WebUtils;
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpSession;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
|
|
|
@ -28,18 +28,19 @@ package org.geysermc.geyser.network.netty;
|
||||||
import io.netty.channel.local.LocalChannel;
|
import io.netty.channel.local.LocalChannel;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client -> server storing the spoofed remote address.
|
* Client -> server storing the spoofed remote address.
|
||||||
*/
|
*/
|
||||||
public class LocalChannelWithRemoteAddress extends LocalChannel {
|
public class LocalChannelWithRemoteAddress extends LocalChannel {
|
||||||
private InetSocketAddress spoofedAddress;
|
private SocketAddress spoofedAddress;
|
||||||
|
|
||||||
public InetSocketAddress spoofedRemoteAddress() {
|
public SocketAddress spoofedRemoteAddress() {
|
||||||
return spoofedAddress;
|
return spoofedAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void spoofedRemoteAddress(InetSocketAddress socketAddress) {
|
public void spoofedRemoteAddress(SocketAddress socketAddress) {
|
||||||
this.spoofedAddress = socketAddress;
|
this.spoofedAddress = socketAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,150 +27,65 @@ package org.geysermc.geyser.network.netty;
|
||||||
|
|
||||||
import io.netty.bootstrap.Bootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.buffer.ByteBufAllocator;
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelFactory;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelOption;
|
import io.netty.channel.ChannelOption;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ReflectiveChannelFactory;
|
||||||
import io.netty.channel.DefaultEventLoopGroup;
|
|
||||||
import io.netty.channel.unix.PreferredDirectByteBufAllocator;
|
import io.netty.channel.unix.PreferredDirectByteBufAllocator;
|
||||||
import io.netty.handler.codec.haproxy.HAProxyCommand;
|
|
||||||
import io.netty.handler.codec.haproxy.HAProxyMessage;
|
|
||||||
import io.netty.handler.codec.haproxy.HAProxyMessageEncoder;
|
|
||||||
import io.netty.handler.codec.haproxy.HAProxyProtocolVersion;
|
|
||||||
import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol;
|
|
||||||
import io.netty.handler.timeout.ReadTimeoutHandler;
|
|
||||||
import io.netty.handler.timeout.WriteTimeoutHandler;
|
|
||||||
import io.netty.util.concurrent.DefaultThreadFactory;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.mcprotocollib.network.BuiltinFlags;
|
import org.geysermc.mcprotocollib.network.helper.NettyHelper;
|
||||||
import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper;
|
import org.geysermc.mcprotocollib.network.net.MinecraftChannelInitializer;
|
||||||
|
import org.geysermc.mcprotocollib.network.net.NetClientSession;
|
||||||
import org.geysermc.mcprotocollib.network.packet.PacketProtocol;
|
import org.geysermc.mcprotocollib.network.packet.PacketProtocol;
|
||||||
import org.geysermc.mcprotocollib.network.tcp.FlushHandler;
|
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpFlowControlHandler;
|
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpPacketCodec;
|
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpPacketCompression;
|
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpPacketEncryptor;
|
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpPacketSizer;
|
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpSession;
|
|
||||||
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
|
|
||||||
|
|
||||||
import java.net.Inet4Address;
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages a Minecraft Java session over our LocalChannel implementations.
|
* Manages a Minecraft Java session over our LocalChannel implementations.
|
||||||
*/
|
*/
|
||||||
public final class LocalSession extends TcpSession {
|
public final class LocalSession extends NetClientSession {
|
||||||
private static DefaultEventLoopGroup DEFAULT_EVENT_LOOP_GROUP;
|
|
||||||
private static PreferredDirectByteBufAllocator PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR = null;
|
private static PreferredDirectByteBufAllocator PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR = null;
|
||||||
|
|
||||||
private final SocketAddress targetAddress;
|
private final SocketAddress spoofedRemoteAddress;
|
||||||
private final String clientIp;
|
|
||||||
private final PacketCodecHelper codecHelper;
|
|
||||||
|
|
||||||
public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, Executor packetHandlerExecutor) {
|
public LocalSession(SocketAddress targetAddress, String clientIp, PacketProtocol protocol, Executor packetHandlerExecutor) {
|
||||||
super(host, port, protocol, packetHandlerExecutor);
|
super(targetAddress, null, protocol, null, packetHandlerExecutor);
|
||||||
this.targetAddress = targetAddress;
|
this.spoofedRemoteAddress = new InetSocketAddress(clientIp, 0);
|
||||||
this.clientIp = clientIp;
|
|
||||||
this.codecHelper = protocol.createHelper();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connect(boolean wait, boolean transferring) {
|
protected ChannelFactory<? extends Channel> getChannelFactory() {
|
||||||
if (this.disconnected) {
|
return new ReflectiveChannelFactory<>(LocalChannelWithRemoteAddress.class);
|
||||||
throw new IllegalStateException("Connection has already been disconnected.");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (DEFAULT_EVENT_LOOP_GROUP == null) {
|
|
||||||
DEFAULT_EVENT_LOOP_GROUP = new DefaultEventLoopGroup(new DefaultThreadFactory(this.getClass(), true));
|
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(
|
|
||||||
() -> DEFAULT_EVENT_LOOP_GROUP.shutdownGracefully(100, 500, TimeUnit.MILLISECONDS)));
|
|
||||||
}
|
|
||||||
|
|
||||||
final Bootstrap bootstrap = new Bootstrap();
|
|
||||||
bootstrap.channel(LocalChannelWithRemoteAddress.class);
|
|
||||||
bootstrap.handler(new ChannelInitializer<LocalChannelWithRemoteAddress>() {
|
|
||||||
@Override
|
|
||||||
public void initChannel(@NonNull LocalChannelWithRemoteAddress channel) {
|
|
||||||
channel.spoofedRemoteAddress(new InetSocketAddress(clientIp, 0));
|
|
||||||
PacketProtocol protocol = getPacketProtocol();
|
|
||||||
protocol.newClientSession(LocalSession.this, transferring);
|
|
||||||
|
|
||||||
ChannelPipeline pipeline = channel.pipeline();
|
|
||||||
|
|
||||||
addHAProxySupport(pipeline);
|
|
||||||
|
|
||||||
pipeline.addLast("read-timeout", new ReadTimeoutHandler(getFlag(BuiltinFlags.READ_TIMEOUT, 30)));
|
|
||||||
pipeline.addLast("write-timeout", new WriteTimeoutHandler(getFlag(BuiltinFlags.WRITE_TIMEOUT, 0)));
|
|
||||||
|
|
||||||
pipeline.addLast("encryption", new TcpPacketEncryptor());
|
|
||||||
pipeline.addLast("sizer", new TcpPacketSizer(protocol.getPacketHeader(), getCodecHelper()));
|
|
||||||
pipeline.addLast("compression", new TcpPacketCompression(getCodecHelper()));
|
|
||||||
|
|
||||||
pipeline.addLast("flow-control", new TcpFlowControlHandler());
|
|
||||||
pipeline.addLast("codec", new TcpPacketCodec(LocalSession.this, true));
|
|
||||||
pipeline.addLast("flush-handler", new FlushHandler());
|
|
||||||
pipeline.addLast("manager", LocalSession.this);
|
|
||||||
}
|
|
||||||
}).group(DEFAULT_EVENT_LOOP_GROUP).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getFlag(BuiltinFlags.CLIENT_CONNECT_TIMEOUT, 30) * 1000);
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setOptions(Bootstrap bootstrap) {
|
||||||
if (PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR != null) {
|
if (PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR != null) {
|
||||||
bootstrap.option(ChannelOption.ALLOCATOR, PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR);
|
bootstrap.option(ChannelOption.ALLOCATOR, PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrap.remoteAddress(targetAddress);
|
|
||||||
|
|
||||||
CompletableFuture<Void> handleFuture = new CompletableFuture<>();
|
|
||||||
bootstrap.connect().addListener((futureListener) -> {
|
|
||||||
if (!futureListener.isSuccess()) {
|
|
||||||
exceptionCaught(null, futureListener.cause());
|
|
||||||
}
|
|
||||||
|
|
||||||
handleFuture.complete(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (wait) {
|
|
||||||
handleFuture.join();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MinecraftCodecHelper getCodecHelper() {
|
protected ChannelHandler getChannelHandler() {
|
||||||
return (MinecraftCodecHelper) this.codecHelper;
|
return new MinecraftChannelInitializer<>(channel -> {
|
||||||
}
|
PacketProtocol protocol = getPacketProtocol();
|
||||||
|
protocol.newClientSession(LocalSession.this);
|
||||||
|
|
||||||
// TODO duplicate code
|
return LocalSession.this;
|
||||||
private void addHAProxySupport(ChannelPipeline pipeline) {
|
}, true) {
|
||||||
InetSocketAddress clientAddress = getFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS);
|
@Override
|
||||||
if (clientAddress != null) {
|
public void initChannel(@NonNull Channel channel) throws Exception {
|
||||||
pipeline.addFirst("proxy-protocol-packet-sender", new ChannelInboundHandlerAdapter() {
|
((LocalChannelWithRemoteAddress) channel).spoofedRemoteAddress(spoofedRemoteAddress);
|
||||||
@Override
|
|
||||||
public void channelActive(@NonNull ChannelHandlerContext ctx) throws Exception {
|
NettyHelper.initializeHAProxySupport(LocalSession.this, channel);
|
||||||
HAProxyProxiedProtocol proxiedProtocol = clientAddress.getAddress() instanceof Inet4Address ? HAProxyProxiedProtocol.TCP4 : HAProxyProxiedProtocol.TCP6;
|
|
||||||
InetSocketAddress remoteAddress;
|
super.initChannel(channel);
|
||||||
if (ctx.channel().remoteAddress() instanceof InetSocketAddress) {
|
}
|
||||||
remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress();
|
};
|
||||||
} else {
|
}
|
||||||
remoteAddress = new InetSocketAddress(host, port);
|
|
||||||
}
|
|
||||||
ctx.channel().writeAndFlush(new HAProxyMessage(
|
|
||||||
HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, proxiedProtocol,
|
|
||||||
clientAddress.getAddress().getHostAddress(), remoteAddress.getAddress().getHostAddress(),
|
|
||||||
clientAddress.getPort(), remoteAddress.getPort()
|
|
||||||
));
|
|
||||||
ctx.pipeline().remove(this);
|
|
||||||
ctx.pipeline().remove("proxy-protocol-encoder");
|
|
||||||
super.channelActive(ctx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
pipeline.addFirst("proxy-protocol-encoder", HAProxyMessageEncoder.INSTANCE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should only be called when direct ByteBufs should be preferred. At this moment, this should only be called on BungeeCord.
|
* Should only be called when direct ByteBufs should be preferred. At this moment, this should only be called on BungeeCord.
|
||||||
|
|
|
@ -28,14 +28,14 @@ package org.geysermc.geyser.session;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.geysermc.mcprotocollib.network.ClientSession;
|
||||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpSession;
|
|
||||||
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
|
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class DownstreamSession {
|
public class DownstreamSession {
|
||||||
private final TcpSession session;
|
private final ClientSession session;
|
||||||
|
|
||||||
public void sendPacket(@NonNull Packet packet) {
|
public void sendPacket(@NonNull Packet packet) {
|
||||||
this.session.send(packet);
|
this.session.send(packet);
|
||||||
|
|
|
@ -186,15 +186,17 @@ import org.geysermc.geyser.util.LoginEncryptionUtils;
|
||||||
import org.geysermc.geyser.util.MinecraftAuthLogger;
|
import org.geysermc.geyser.util.MinecraftAuthLogger;
|
||||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||||
import org.geysermc.mcprotocollib.network.BuiltinFlags;
|
import org.geysermc.mcprotocollib.network.BuiltinFlags;
|
||||||
|
import org.geysermc.mcprotocollib.network.ClientSession;
|
||||||
|
import org.geysermc.mcprotocollib.network.NetworkConstants;
|
||||||
import org.geysermc.mcprotocollib.network.Session;
|
import org.geysermc.mcprotocollib.network.Session;
|
||||||
import org.geysermc.mcprotocollib.network.event.session.ConnectedEvent;
|
import org.geysermc.mcprotocollib.network.event.session.ConnectedEvent;
|
||||||
import org.geysermc.mcprotocollib.network.event.session.DisconnectedEvent;
|
import org.geysermc.mcprotocollib.network.event.session.DisconnectedEvent;
|
||||||
import org.geysermc.mcprotocollib.network.event.session.PacketErrorEvent;
|
import org.geysermc.mcprotocollib.network.event.session.PacketErrorEvent;
|
||||||
import org.geysermc.mcprotocollib.network.event.session.PacketSendingEvent;
|
import org.geysermc.mcprotocollib.network.event.session.PacketSendingEvent;
|
||||||
import org.geysermc.mcprotocollib.network.event.session.SessionAdapter;
|
import org.geysermc.mcprotocollib.network.event.session.SessionAdapter;
|
||||||
|
import org.geysermc.mcprotocollib.network.net.NetClientSession;
|
||||||
|
import org.geysermc.mcprotocollib.network.net.NetSession;
|
||||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpClientSession;
|
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpSession;
|
|
||||||
import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
|
import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
|
||||||
import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
|
import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
|
import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
|
||||||
|
@ -949,15 +951,17 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||||
// Start ticking
|
// Start ticking
|
||||||
tickThread = tickEventLoop.scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS);
|
tickThread = tickEventLoop.scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
TcpSession downstream;
|
ClientSession downstream;
|
||||||
if (geyser.getBootstrap().getSocketAddress() != null) {
|
if (geyser.getBootstrap().getSocketAddress() != null) {
|
||||||
// We're going to connect through the JVM and not through TCP
|
// We're going to connect through the JVM and not through TCP
|
||||||
downstream = new LocalSession(this.remoteServer.address(), this.remoteServer.port(),
|
downstream = new LocalSession(geyser.getBootstrap().getSocketAddress(),
|
||||||
geyser.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(),
|
upstream.getAddress().getAddress().getHostAddress(),
|
||||||
this.protocol, tickEventLoop);
|
this.protocol, tickEventLoop);
|
||||||
|
downstream.setFlag(MinecraftConstants.CLIENT_HOST, this.remoteServer.address());
|
||||||
|
downstream.setFlag(MinecraftConstants.CLIENT_PORT, this.remoteServer.port());
|
||||||
this.downstream = new DownstreamSession(downstream);
|
this.downstream = new DownstreamSession(downstream);
|
||||||
} else {
|
} else {
|
||||||
downstream = new TcpClientSession(this.remoteServer.address(), this.remoteServer.port(), "0.0.0.0", 0, this.protocol, null, tickEventLoop);
|
downstream = new NetClientSession(new InetSocketAddress(this.remoteServer.address(), this.remoteServer.port()), null, this.protocol, null, tickEventLoop);
|
||||||
this.downstream = new DownstreamSession(downstream);
|
this.downstream = new DownstreamSession(downstream);
|
||||||
|
|
||||||
boolean resolveSrv = false;
|
boolean resolveSrv = false;
|
||||||
|
@ -1159,7 +1163,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||||
setDaylightCycle(true);
|
setDaylightCycle(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
downstream.connect(false, loginEvent.transferring());
|
downstream.setFlag(BuiltinFlags.CLIENT_TRANSFERRING, loginEvent.transferring());
|
||||||
|
downstream.connect(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect(String reason) {
|
public void disconnect(String reason) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ protocol-common = "3.0.0.Beta5-20241203.200249-19"
|
||||||
protocol-codec = "3.0.0.Beta5-20241203.200249-19"
|
protocol-codec = "3.0.0.Beta5-20241203.200249-19"
|
||||||
raknet = "1.0.0.CR3-20240416.144209-1"
|
raknet = "1.0.0.CR3-20240416.144209-1"
|
||||||
minecraftauth = "4.1.1"
|
minecraftauth = "4.1.1"
|
||||||
mcprotocollib = "1.21.2-20241127.160724-5"
|
mcprotocollib = "5c2249d"
|
||||||
adventure = "4.14.0"
|
adventure = "4.14.0"
|
||||||
adventure-platform = "4.3.0"
|
adventure-platform = "4.3.0"
|
||||||
junit = "5.9.2"
|
junit = "5.9.2"
|
||||||
|
@ -123,7 +123,7 @@ guava = { group = "com.google.guava", name = "guava", version.ref = "guava" }
|
||||||
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
|
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
|
||||||
junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" }
|
junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" }
|
||||||
minecraftauth = { group = "net.raphimc", name = "MinecraftAuth", version.ref = "minecraftauth" }
|
minecraftauth = { group = "net.raphimc", name = "MinecraftAuth", version.ref = "minecraftauth" }
|
||||||
mcprotocollib = { group = "org.geysermc.mcprotocollib", name = "protocol", version.ref = "mcprotocollib" }
|
mcprotocollib = { group = "com.github.AlexProgrammerDE", name = "MCProtocolLib", version.ref = "mcprotocollib" }
|
||||||
raknet = { group = "org.cloudburstmc.netty", name = "netty-transport-raknet", version.ref = "raknet" }
|
raknet = { group = "org.cloudburstmc.netty", name = "netty-transport-raknet", version.ref = "raknet" }
|
||||||
terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" }
|
terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" }
|
||||||
velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }
|
velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }
|
||||||
|
|
Loading…
Reference in a new issue