Merge pull request #388 from VelocityPowered/2/network

2/network
This commit is contained in:
Andrew Steinborn
2020-12-02 00:39:45 -06:00
committed by GitHub
146 changed files with 2971 additions and 2775 deletions

View File

@@ -32,6 +32,7 @@ dependencies {
api "net.kyori:adventure-text-serializer-gson:${adventureVersion}"
api "net.kyori:adventure-text-serializer-legacy:${adventureVersion}"
api "net.kyori:adventure-text-serializer-plain:${adventureVersion}"
api("net.kyori:coffee:1.0.0-SNAPSHOT")
api "org.slf4j:slf4j-api:${slf4jVersion}"
api 'com.google.inject:guice:4.2.3'
@@ -75,13 +76,13 @@ javadoc {
options.encoding = 'UTF-8'
options.charSet = 'UTF-8'
options.source = '8'
options.links(
'https://www.slf4j.org/apidocs/',
'https://guava.dev/releases/30.0-jre/api/docs/',
'https://google.github.io/guice/api-docs/4.2/javadoc/',
'https://docs.oracle.com/javase/8/docs/api/',
'https://jd.adventure.kyori.net/api/4.0.0/'
)
// options.links(
// 'https://www.slf4j.org/apidocs/',
// 'https://guava.dev/releases/30.0-jre/api/docs/',
// 'https://google.github.io/guice/api-docs/4.2/javadoc/',
// 'https://docs.oracle.com/javase/8/docs/api/',
// 'https://jd.adventure.kyori.net/api/4.0.0/'
// )
// Disable the crazy super-strict doclint tool in Java 8
options.addStringOption('Xdoclint:none', '-quiet')

View File

@@ -6,11 +6,12 @@ import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import net.kyori.coffee.Ordered;
/**
* Represents each Minecraft protocol version.
*/
public enum ProtocolVersion {
public enum ProtocolVersion implements Ordered<ProtocolVersion> {
UNKNOWN(-1, "Unknown"),
LEGACY(-2, "Legacy"),
MINECRAFT_1_7_2(4, "1.7.2"),

View File

@@ -3,7 +3,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:5.0.0'
classpath 'com.github.jengelman.gradle.plugins:shadow:5.2.0'
}
}

View File

@@ -27,6 +27,10 @@
<property name="eachLine" value="true"/>
</module>
<module name="SuppressionFilter">
<property name="file" value="${configDirectory}/suppressions.xml"/>
</module>
<module name="TreeWalker">
<module name="OuterTypeFilename"/>
<!-- <module name="IllegalTokenText">
@@ -42,7 +46,7 @@
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="LineLength">
<property name="max" value="100"/>
<property name="max" value="150"/>
<property name="ignorePattern"
value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suppressions PUBLIC "-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN" "http://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<!-- no javadoc warning for implementation -->
<suppress files="src[\\/]main[\\/]java[\\/]com[\\/]velocitypowered[\\/]proxy[\\/].*" checks="JavadocMethod"/>
</suppressions>

View File

@@ -1,8 +1,11 @@
checkstyle {
def configDirectory = new File(project.rootDir, ["config", "checkstyle"].join(File.separator))
toolVersion '8.14'
configFile new File(project.rootDir, ['config', 'checkstyle', 'checkstyle.xml'].join(File.separator))
configFile new File(configDirectory, "checkstyle.xml")
configProperties = [configDirectory: configDirectory.getAbsolutePath()]
// The build should immediately fail if we have errors.
maxErrors = 0
maxWarnings = 0
}
}

View File

@@ -27,11 +27,11 @@ import com.velocitypowered.proxy.config.VelocityConfiguration;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.console.VelocityConsole;
import com.velocitypowered.proxy.network.ConnectionManager;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.serialization.FaviconSerializer;
import com.velocitypowered.proxy.network.serialization.GameProfileSerializer;
import com.velocitypowered.proxy.plugin.VelocityEventManager;
import com.velocitypowered.proxy.plugin.VelocityPluginManager;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.util.FaviconSerializer;
import com.velocitypowered.proxy.protocol.util.GameProfileSerializer;
import com.velocitypowered.proxy.scheduler.VelocityScheduler;
import com.velocitypowered.proxy.server.ServerMap;
import com.velocitypowered.proxy.util.AddressUtil;
@@ -645,7 +645,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
}
public static Gson getPingGsonInstance(ProtocolVersion version) {
return version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0 ? POST_1_16_PING_SERIALIZER
return version.gte(ProtocolVersion.MINECRAFT_1_16) ? POST_1_16_PING_SERIALIZER
: PRE_1_16_PING_SERIALIZER;
}
}

View File

@@ -19,15 +19,15 @@ import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler;
import com.velocitypowered.proxy.connection.client.LoginSessionHandler;
import com.velocitypowered.proxy.connection.client.StatusSessionHandler;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.netty.MinecraftCipherDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftCipherEncoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftCompressDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftCompressEncoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder;
import com.velocitypowered.proxy.protocol.packet.SetCompressionPacket;
import com.velocitypowered.proxy.network.StateRegistry;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundSetCompressionPacket;
import com.velocitypowered.proxy.network.pipeline.MinecraftCipherDecoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftCipherEncoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftCompressDecoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftCompressEncoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftDecoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftEncoder;
import com.velocitypowered.proxy.util.except.QuietDecoderException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
@@ -224,8 +224,8 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
*/
public void closeWith(Object msg) {
if (channel.isActive()) {
boolean is17 = this.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) < 0
&& this.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_7_2) >= 0;
boolean is17 = this.getProtocolVersion().lt(ProtocolVersion.MINECRAFT_1_8)
&& this.getProtocolVersion().gte(ProtocolVersion.MINECRAFT_1_7_2);
if (is17 && this.getState() != StateRegistry.STATUS) {
channel.eventLoop().execute(() -> {
// 1.7.x versions have a race condition with switching protocol states, so just explicitly
@@ -369,7 +369,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/**
* Sets the compression threshold on the connection. You are responsible for sending
* {@link SetCompressionPacket} beforehand.
* {@link ClientboundSetCompressionPacket} beforehand.
* @param threshold the compression threshold to use
*/
public void setCompressionThreshold(int threshold) {

View File

@@ -1,192 +1,39 @@
package com.velocitypowered.proxy.connection;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.packet.AvailableCommandsPacket;
import com.velocitypowered.proxy.protocol.packet.BossBarPacket;
import com.velocitypowered.proxy.protocol.packet.ChatPacket;
import com.velocitypowered.proxy.protocol.packet.ClientSettingsPacket;
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
import com.velocitypowered.proxy.protocol.packet.EncryptionRequestPacket;
import com.velocitypowered.proxy.protocol.packet.EncryptionResponsePacket;
import com.velocitypowered.proxy.protocol.packet.HandshakePacket;
import com.velocitypowered.proxy.protocol.packet.HeaderAndFooterPacket;
import com.velocitypowered.proxy.protocol.packet.JoinGamePacket;
import com.velocitypowered.proxy.protocol.packet.KeepAlivePacket;
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessagePacket;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponsePacket;
import com.velocitypowered.proxy.protocol.packet.PlayerListItemPacket;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.protocol.packet.ResourcePackRequestPacket;
import com.velocitypowered.proxy.protocol.packet.ResourcePackResponsePacket;
import com.velocitypowered.proxy.protocol.packet.RespawnPacket;
import com.velocitypowered.proxy.protocol.packet.ServerLoginPacket;
import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccessPacket;
import com.velocitypowered.proxy.protocol.packet.SetCompressionPacket;
import com.velocitypowered.proxy.protocol.packet.StatusPingPacket;
import com.velocitypowered.proxy.protocol.packet.StatusRequestPacket;
import com.velocitypowered.proxy.protocol.packet.StatusResponsePacket;
import com.velocitypowered.proxy.protocol.packet.TabCompleteRequestPacket;
import com.velocitypowered.proxy.protocol.packet.TabCompleteResponsePacket;
import com.velocitypowered.proxy.protocol.packet.TitlePacket;
import com.velocitypowered.proxy.protocol.packet.legacy.LegacyHandshakePacket;
import com.velocitypowered.proxy.protocol.packet.legacy.LegacyPingPacket;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import io.netty.buffer.ByteBuf;
public interface MinecraftSessionHandler {
public interface MinecraftSessionHandler extends PacketHandler {
default boolean beforeHandle() {
return false;
}
default void handleGeneric(Packet packet) {
}
default void handleUnknown(ByteBuf buf) {
}
default void connected() {
}
default void disconnected() {
}
default void activated() {
}
default void deactivated() {
}
default void exception(Throwable throwable) {
}
default void writabilityChanged() {
}
default void readCompleted() {
}
default boolean handle(AvailableCommandsPacket commands) {
return false;
}
default boolean handle(BossBarPacket packet) {
return false;
}
default boolean handle(ChatPacket packet) {
return false;
}
default boolean handle(ClientSettingsPacket packet) {
return false;
}
default boolean handle(DisconnectPacket packet) {
return false;
}
default boolean handle(EncryptionRequestPacket packet) {
return false;
}
default boolean handle(EncryptionResponsePacket packet) {
return false;
}
default boolean handle(HandshakePacket packet) {
return false;
}
default boolean handle(HeaderAndFooterPacket packet) {
return false;
}
default boolean handle(JoinGamePacket packet) {
return false;
}
default boolean handle(KeepAlivePacket packet) {
return false;
}
default boolean handle(LegacyHandshakePacket packet) {
return false;
}
default boolean handle(LegacyPingPacket packet) {
return false;
}
default boolean handle(LoginPluginMessagePacket packet) {
return false;
}
default boolean handle(LoginPluginResponsePacket packet) {
return false;
}
default boolean handle(PluginMessagePacket packet) {
return false;
}
default boolean handle(RespawnPacket packet) {
return false;
}
default boolean handle(ServerLoginPacket packet) {
return false;
}
default boolean handle(ServerLoginSuccessPacket packet) {
return false;
}
default boolean handle(SetCompressionPacket packet) {
return false;
}
default boolean handle(StatusPingPacket packet) {
return false;
}
default boolean handle(StatusRequestPacket packet) {
return false;
}
default boolean handle(StatusResponsePacket packet) {
return false;
}
default boolean handle(TabCompleteRequestPacket packet) {
return false;
}
default boolean handle(TabCompleteResponsePacket packet) {
return false;
}
default boolean handle(TitlePacket packet) {
return false;
}
default boolean handle(PlayerListItemPacket packet) {
return false;
}
default boolean handle(ResourcePackRequestPacket packet) {
return false;
}
default boolean handle(ResourcePackResponsePacket packet) {
return false;
}
}

View File

@@ -2,7 +2,7 @@ package com.velocitypowered.proxy.connection.backend;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeHandshakeBackendPhase;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
/**
* Provides connection phase specific actions.
@@ -21,7 +21,7 @@ public interface BackendConnectionPhase {
*/
default boolean handle(VelocityServerConnection server,
ConnectedPlayer player,
PluginMessagePacket message) {
AbstractPluginMessagePacket<?> message) {
return false;
}

View File

@@ -2,7 +2,7 @@ package com.velocitypowered.proxy.connection.backend;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeHandshakeBackendPhase;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
/**
* Contains Vanilla {@link BackendConnectionPhase}s.
@@ -29,7 +29,7 @@ public final class BackendConnectionPhases {
@Override
public boolean handle(VelocityServerConnection serverConn,
ConnectedPlayer player,
PluginMessagePacket message) {
AbstractPluginMessagePacket<?> message) {
// The connection may be legacy forge. If so, the Forge handler will deal with this
// for us. Otherwise, we have nothing to do.
return LegacyForgeHandshakeBackendPhase.NOT_STARTED.handle(serverConn, player, message);

View File

@@ -16,15 +16,16 @@ import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler;
import com.velocitypowered.proxy.connection.util.ConnectionMessages;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.packet.AvailableCommandsPacket;
import com.velocitypowered.proxy.protocol.packet.BossBarPacket;
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
import com.velocitypowered.proxy.protocol.packet.KeepAlivePacket;
import com.velocitypowered.proxy.protocol.packet.PlayerListItemPacket;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.protocol.packet.TabCompleteResponsePacket;
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
import com.velocitypowered.proxy.network.PluginMessageUtil;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundAvailableCommandsPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundBossBarPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundKeepAlivePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPlayerListItemPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTabCompleteResponsePacket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
@@ -64,7 +65,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
serverConn.getServer().addPlayer(serverConn.getPlayer());
MinecraftConnection serverMc = serverConn.ensureConnected();
serverMc.write(PluginMessageUtil.constructChannelsPacket(serverMc.getProtocolVersion(),
ImmutableList.of(getBungeeCordChannel(serverMc.getProtocolVersion()))
ImmutableList.of(getBungeeCordChannel(serverMc.getProtocolVersion())), ClientboundPluginMessagePacket.FACTORY
));
}
@@ -79,30 +80,30 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(KeepAlivePacket packet) {
public boolean handle(ClientboundKeepAlivePacket packet) {
serverConn.setLastPingId(packet.getRandomId());
return false; // forwards on
}
@Override
public boolean handle(DisconnectPacket packet) {
public boolean handle(ClientboundDisconnectPacket packet) {
serverConn.disconnect();
serverConn.getPlayer().handleConnectionException(serverConn.getServer(), packet, true);
return true;
}
@Override
public boolean handle(BossBarPacket packet) {
if (packet.getAction() == BossBarPacket.ADD) {
public boolean handle(ClientboundBossBarPacket packet) {
if (packet.getAction() == ClientboundBossBarPacket.ADD) {
playerSessionHandler.getServerBossBars().add(packet.getUuid());
} else if (packet.getAction() == BossBarPacket.REMOVE) {
} else if (packet.getAction() == ClientboundBossBarPacket.REMOVE) {
playerSessionHandler.getServerBossBars().remove(packet.getUuid());
}
return false; // forward
}
@Override
public boolean handle(PluginMessagePacket packet) {
public boolean handle(ClientboundPluginMessagePacket packet) {
if (bungeecordMessageResponder.process(packet)) {
return true;
}
@@ -123,8 +124,8 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
}
if (PluginMessageUtil.isMcBrand(packet)) {
PluginMessagePacket rewritten = PluginMessageUtil.rewriteMinecraftBrand(packet,
server.getVersion(), playerConnection.getProtocolVersion());
AbstractPluginMessagePacket<?> rewritten = PluginMessageUtil.rewriteMinecraftBrand(packet,
server.getVersion(), playerConnection.getProtocolVersion(), ClientboundPluginMessagePacket.FACTORY);
playerConnection.write(rewritten);
return true;
}
@@ -145,7 +146,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
server.getEventManager().fire(event)
.thenAcceptAsync(pme -> {
if (pme.getResult().isAllowed() && !playerConnection.isClosed()) {
PluginMessagePacket copied = new PluginMessagePacket(packet.getChannel(),
ClientboundPluginMessagePacket copied = new ClientboundPluginMessagePacket(packet.getChannel(),
Unpooled.wrappedBuffer(copy));
playerConnection.write(copied);
}
@@ -158,19 +159,19 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(TabCompleteResponsePacket packet) {
public boolean handle(ClientboundTabCompleteResponsePacket packet) {
playerSessionHandler.handleTabCompleteResponse(packet);
return true;
}
@Override
public boolean handle(PlayerListItemPacket packet) {
public boolean handle(ClientboundPlayerListItemPacket packet) {
serverConn.getPlayer().getTabList().processBackendPacket(packet);
return false; //Forward packet to player
}
@Override
public boolean handle(AvailableCommandsPacket commands) {
public boolean handle(ClientboundAvailableCommandsPacket commands) {
RootCommandNode<CommandSource> rootNode = commands.getRootNode();
if (server.getConfiguration().isAnnounceProxyCommands()) {
// Inject commands from the proxy.
@@ -244,8 +245,8 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
@Override
public void handleGeneric(Packet packet) {
if (packet instanceof PluginMessagePacket) {
((PluginMessagePacket) packet).retain();
if (packet instanceof AbstractPluginMessagePacket<?>) {
((AbstractPluginMessagePacket<?>) packet).retain();
}
playerConnection.delayedWrite(packet);
}
@@ -277,7 +278,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
if (!serverConn.isGracefulDisconnect() && !exceptionTriggered) {
if (server.getConfiguration().isFailoverOnUnexpectedServerDisconnect()) {
serverConn.getPlayer().handleConnectionException(serverConn.getServer(),
DisconnectPacket.create(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR,
ClientboundDisconnectPacket.create(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR,
ProtocolVersion.MINECRAFT_1_16), true);
} else {
serverConn.getPlayer().disconnect(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR);

View File

@@ -9,9 +9,10 @@ import com.velocitypowered.api.util.UuidUtils;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.protocol.util.ByteBufDataInput;
import com.velocitypowered.proxy.protocol.util.ByteBufDataOutput;
import com.velocitypowered.proxy.network.buffer.ByteBufDataInput;
import com.velocitypowered.proxy.network.buffer.ByteBufDataOutput;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundPluginMessagePacket;
import com.velocitypowered.proxy.server.VelocityRegisteredServer;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.netty.buffer.ByteBuf;
@@ -45,7 +46,7 @@ public class BungeeCordMessageResponder {
this.player = player;
}
public static boolean isBungeeCordMessage(PluginMessagePacket message) {
public static boolean isBungeeCordMessage(AbstractPluginMessagePacket<?> message) {
return MODERN_CHANNEL.getId().equals(message.getChannel()) || LEGACY_CHANNEL.getId()
.equals(message.getChannel());
}
@@ -303,7 +304,7 @@ public class BungeeCordMessageResponder {
}
static String getBungeeCordChannel(ProtocolVersion version) {
return version.compareTo(ProtocolVersion.MINECRAFT_1_13) >= 0 ? MODERN_CHANNEL.getId()
return version.gte(ProtocolVersion.MINECRAFT_1_13) ? MODERN_CHANNEL.getId()
: LEGACY_CHANNEL.getId();
}
@@ -312,7 +313,7 @@ public class BungeeCordMessageResponder {
MinecraftConnection serverConnection = player.ensureAndGetCurrentServer().ensureConnected();
String chan = getBungeeCordChannel(serverConnection.getProtocolVersion());
PluginMessagePacket msg = null;
ServerboundPluginMessagePacket msg = null;
boolean released = false;
try {
@@ -322,7 +323,7 @@ public class BungeeCordMessageResponder {
}
MinecraftConnection serverConn = vsc.ensureConnected();
msg = new PluginMessagePacket(chan, buf);
msg = new ServerboundPluginMessagePacket(chan, buf);
serverConn.write(msg);
released = true;
} finally {
@@ -332,7 +333,7 @@ public class BungeeCordMessageResponder {
}
}
boolean process(PluginMessagePacket message) {
boolean process(AbstractPluginMessagePacket<?> message) {
if (!proxy.getConfiguration().isBungeePluginChannelEnabled()) {
return false;
}

View File

@@ -9,14 +9,14 @@ import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.VelocityConstants;
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults;
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
import com.velocitypowered.proxy.protocol.packet.EncryptionRequestPacket;
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessagePacket;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponsePacket;
import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccessPacket;
import com.velocitypowered.proxy.protocol.packet.SetCompressionPacket;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.StateRegistry;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundEncryptionRequestPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundLoginPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundServerLoginSuccessPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundSetCompressionPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundLoginPluginResponsePacket;
import com.velocitypowered.proxy.util.except.QuietRuntimeException;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@@ -49,12 +49,12 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(EncryptionRequestPacket packet) {
public boolean handle(ClientboundEncryptionRequestPacket packet) {
throw new IllegalStateException("Backend server is online-mode!");
}
@Override
public boolean handle(LoginPluginMessagePacket packet) {
public boolean handle(ClientboundLoginPluginMessagePacket packet) {
MinecraftConnection mc = serverConn.ensureConnected();
VelocityConfiguration configuration = server.getConfiguration();
if (configuration.getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN && packet
@@ -62,32 +62,33 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
ByteBuf forwardingData = createForwardingData(configuration.getForwardingSecret(),
cleanRemoteAddress(serverConn.getPlayer().getRemoteAddress()),
serverConn.getPlayer().getGameProfile());
LoginPluginResponsePacket response = new LoginPluginResponsePacket(packet.getId(), true,
forwardingData);
ServerboundLoginPluginResponsePacket response = new ServerboundLoginPluginResponsePacket(
packet.getId(), true, forwardingData);
mc.write(response);
informationForwarded = true;
} else {
// Don't understand
mc.write(new LoginPluginResponsePacket(packet.getId(), false, Unpooled.EMPTY_BUFFER));
mc.write(new ServerboundLoginPluginResponsePacket(packet.getId(), false,
Unpooled.EMPTY_BUFFER));
}
return true;
}
@Override
public boolean handle(DisconnectPacket packet) {
public boolean handle(ClientboundDisconnectPacket packet) {
resultFuture.complete(ConnectionRequestResults.forDisconnect(packet, serverConn.getServer()));
serverConn.disconnect();
return true;
}
@Override
public boolean handle(SetCompressionPacket packet) {
public boolean handle(ClientboundSetCompressionPacket packet) {
serverConn.ensureConnected().setCompressionThreshold(packet.getThreshold());
return true;
}
@Override
public boolean handle(ServerLoginSuccessPacket packet) {
public boolean handle(ClientboundServerLoginSuccessPacket packet) {
if (server.getConfiguration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN
&& !informationForwarded) {
resultFuture.complete(ConnectionRequestResults.forDisconnect(MODERN_IP_FORWARDING_FAILURE,

View File

@@ -14,11 +14,11 @@ import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.connection.util.ConnectionMessages;
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults;
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl;
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
import com.velocitypowered.proxy.protocol.packet.JoinGamePacket;
import com.velocitypowered.proxy.protocol.packet.KeepAlivePacket;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
import com.velocitypowered.proxy.network.PluginMessageUtil;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundJoinGamePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundKeepAlivePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPluginMessagePacket;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import org.apache.logging.log4j.LogManager;
@@ -60,13 +60,13 @@ public class TransitionSessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(KeepAlivePacket packet) {
public boolean handle(ClientboundKeepAlivePacket packet) {
serverConn.ensureConnected().write(packet);
return true;
}
@Override
public boolean handle(JoinGamePacket packet) {
public boolean handle(ClientboundJoinGamePacket packet) {
MinecraftConnection smc = serverConn.ensureConnected();
VelocityServerConnection existingConnection = serverConn.getPlayer().getConnectedServer();
@@ -132,7 +132,7 @@ public class TransitionSessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(DisconnectPacket packet) {
public boolean handle(ClientboundDisconnectPacket packet) {
final MinecraftConnection connection = serverConn.ensureConnected();
serverConn.disconnect();
@@ -150,7 +150,7 @@ public class TransitionSessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(PluginMessagePacket packet) {
public boolean handle(ClientboundPluginMessagePacket packet) {
if (!serverConn.getPlayer().canForwardPluginMessage(serverConn.ensureConnected()
.getProtocolVersion(), packet)) {
return true;

View File

@@ -20,11 +20,11 @@ import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.connection.registry.DimensionRegistry;
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.HandshakePacket;
import com.velocitypowered.proxy.protocol.packet.JoinGamePacket;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.protocol.packet.ServerLoginPacket;
import com.velocitypowered.proxy.network.StateRegistry;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundJoinGamePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundHandshakePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundServerLoginPacket;
import com.velocitypowered.proxy.server.VelocityRegisteredServer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@@ -143,7 +143,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
// Initiate the handshake.
ProtocolVersion protocolVersion = proxyPlayer.getConnection().getProtocolVersion();
HandshakePacket handshake = new HandshakePacket();
ServerboundHandshakePacket handshake = new ServerboundHandshakePacket();
handshake.setNextStatus(StateRegistry.LOGIN_ID);
handshake.setProtocolVersion(protocolVersion);
if (forwardingMode == PlayerInfoForwarding.LEGACY) {
@@ -165,7 +165,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
mc.setProtocolVersion(protocolVersion);
mc.setState(StateRegistry.LOGIN);
mc.delayedWrite(new ServerLoginPacket(proxyPlayer.getUsername()));
mc.delayedWrite(new ServerboundServerLoginPacket(proxyPlayer.getUsername()));
mc.flush();
}
@@ -234,7 +234,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
MinecraftConnection mc = ensureConnected();
PluginMessagePacket message = new PluginMessagePacket(identifier.getId(), data);
ServerboundPluginMessagePacket message = new ServerboundPluginMessagePacket(identifier.getId(), data);
mc.write(message);
return true;
}
@@ -308,7 +308,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
}
/**
* Gets whether the {@link JoinGamePacket}
* Gets whether the {@link ClientboundJoinGamePacket}
* packet has been sent by this server.
*
* @return Whether the join has been completed.

View File

@@ -2,7 +2,7 @@ package com.velocitypowered.proxy.connection.client;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeHandshakeClientPhase;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
/**
* Provides connection phase specific actions.
@@ -22,7 +22,7 @@ public interface ClientConnectionPhase {
* @return true if handled, false otherwise.
*/
default boolean handle(ConnectedPlayer player,
PluginMessagePacket message,
AbstractPluginMessagePacket<?> message,
VelocityServerConnection server) {
return false;
}

View File

@@ -3,7 +3,7 @@ package com.velocitypowered.proxy.connection.client;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_13;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_16;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8;
import static com.velocitypowered.proxy.protocol.util.PluginMessageUtil.constructChannelsPacket;
import static com.velocitypowered.proxy.network.PluginMessageUtil.constructChannelsPacket;
import com.velocitypowered.api.event.command.CommandExecuteEvent.CommandResult;
import com.velocitypowered.api.event.connection.PluginMessageEvent;
@@ -19,21 +19,23 @@ import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.backend.BackendConnectionPhases;
import com.velocitypowered.proxy.connection.backend.BungeeCordMessageResponder;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.BossBarPacket;
import com.velocitypowered.proxy.protocol.packet.ChatPacket;
import com.velocitypowered.proxy.protocol.packet.ClientSettingsPacket;
import com.velocitypowered.proxy.protocol.packet.JoinGamePacket;
import com.velocitypowered.proxy.protocol.packet.KeepAlivePacket;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.protocol.packet.ResourcePackResponsePacket;
import com.velocitypowered.proxy.protocol.packet.RespawnPacket;
import com.velocitypowered.proxy.protocol.packet.TabCompleteRequestPacket;
import com.velocitypowered.proxy.protocol.packet.TabCompleteResponsePacket;
import com.velocitypowered.proxy.protocol.packet.TabCompleteResponsePacket.Offer;
import com.velocitypowered.proxy.protocol.packet.TitlePacket;
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
import com.velocitypowered.proxy.network.PluginMessageUtil;
import com.velocitypowered.proxy.network.StateRegistry;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundBossBarPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundJoinGamePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundRespawnPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTabCompleteResponsePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTabCompleteResponsePacket.Offer;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTitlePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundChatPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundClientSettingsPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundKeepAlivePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundResourcePackResponsePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundTabCompleteRequestPacket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
@@ -64,9 +66,9 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
private final ConnectedPlayer player;
private boolean spawned = false;
private final List<UUID> serverBossBars = new ArrayList<>();
private final Queue<PluginMessagePacket> loginPluginMessages = new ArrayDeque<>();
private final Queue<ServerboundPluginMessagePacket> loginPluginMessages = new ArrayDeque<>();
private final VelocityServer server;
private @Nullable TabCompleteRequestPacket outstandingTabComplete;
private @Nullable ServerboundTabCompleteRequestPacket outstandingTabComplete;
/**
* Constructs a client play session handler.
@@ -83,7 +85,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
Collection<String> channels = server.getChannelRegistrar().getChannelsForProtocol(player
.getProtocolVersion());
if (!channels.isEmpty()) {
PluginMessagePacket register = constructChannelsPacket(player.getProtocolVersion(), channels);
AbstractPluginMessagePacket<?> register = constructChannelsPacket(player.getProtocolVersion(),
channels, ClientboundPluginMessagePacket.FACTORY);
player.getConnection().write(register);
player.getKnownChannels().addAll(channels);
}
@@ -91,13 +94,13 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
@Override
public void deactivated() {
for (PluginMessagePacket message : loginPluginMessages) {
for (ServerboundPluginMessagePacket message : loginPluginMessages) {
ReferenceCountUtil.release(message);
}
}
@Override
public boolean handle(KeepAlivePacket packet) {
public boolean handle(ServerboundKeepAlivePacket packet) {
VelocityServerConnection serverConnection = player.getConnectedServer();
if (serverConnection != null && packet.getRandomId() == serverConnection.getLastPingId()) {
MinecraftConnection smc = serverConnection.getConnection();
@@ -111,13 +114,13 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(ClientSettingsPacket packet) {
public boolean handle(ServerboundClientSettingsPacket packet) {
player.setPlayerSettings(packet);
return false; // will forward onto the server
}
@Override
public boolean handle(ChatPacket packet) {
public boolean handle(ServerboundChatPacket packet) {
VelocityServerConnection serverConnection = player.getConnectedServer();
if (serverConnection == null) {
return true;
@@ -154,7 +157,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
if (chatResult.isAllowed()) {
Optional<String> eventMsg = pme.getResult().getMessage();
if (eventMsg.isPresent()) {
smc.write(ChatPacket.createServerbound(eventMsg.get()));
smc.write(new ServerboundChatPacket(eventMsg.get()));
} else {
smc.write(packet);
}
@@ -169,7 +172,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(TabCompleteRequestPacket packet) {
public boolean handle(ServerboundTabCompleteRequestPacket packet) {
boolean isCommand = !packet.isAssumeCommand() && packet.getCommand().startsWith("/");
if (isCommand) {
@@ -180,7 +183,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(PluginMessagePacket packet) {
public boolean handle(ServerboundPluginMessagePacket packet) {
VelocityServerConnection serverConn = player.getConnectedServer();
MinecraftConnection backendConn = serverConn != null ? serverConn.getConnection() : null;
if (serverConn != null && backendConn != null) {
@@ -195,7 +198,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
backendConn.write(packet.retain());
} else if (PluginMessageUtil.isMcBrand(packet)) {
backendConn.write(PluginMessageUtil
.rewriteMinecraftBrand(packet, server.getVersion(), player.getProtocolVersion()));
.rewriteMinecraftBrand(packet, server.getVersion(), player.getProtocolVersion(), ServerboundPluginMessagePacket.FACTORY));
} else if (BungeeCordMessageResponder.isBungeeCordMessage(packet)) {
return true;
} else {
@@ -228,7 +231,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
PluginMessageEvent event = new PluginMessageEvent(player, serverConn, id, copy);
server.getEventManager().fire(event).thenAcceptAsync(pme -> {
if (pme.getResult().isAllowed()) {
PluginMessagePacket message = new PluginMessagePacket(packet.getChannel(),
ServerboundPluginMessagePacket message = new ServerboundPluginMessagePacket(packet.getChannel(),
Unpooled.wrappedBuffer(copy));
backendConn.write(message);
}
@@ -248,7 +251,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(ResourcePackResponsePacket packet) {
public boolean handle(ServerboundResourcePackResponsePacket packet) {
server.getEventManager().fireAndForget(new PlayerResourcePackStatusEvent(player,
packet.getStatus()));
return false;
@@ -264,8 +267,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
MinecraftConnection smc = serverConnection.getConnection();
if (smc != null && serverConnection.getPhase().consideredComplete()) {
if (packet instanceof PluginMessagePacket) {
((PluginMessagePacket) packet).retain();
if (packet instanceof AbstractPluginMessagePacket<?>) {
((AbstractPluginMessagePacket<?>) packet).retain();
}
smc.write(packet);
}
@@ -319,7 +322,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
* @param joinGame the join game packet
* @param destination the new server we are connecting to
*/
public void handleBackendJoinGame(JoinGamePacket joinGame, VelocityServerConnection destination) {
public void handleBackendJoinGame(ClientboundJoinGamePacket joinGame,
VelocityServerConnection destination) {
final MinecraftConnection serverMc = destination.ensureConnected();
if (!spawned) {
@@ -344,9 +348,9 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
// Remove previous boss bars. These don't get cleared when sending JoinGame, thus the need to
// track them.
for (UUID serverBossBar : serverBossBars) {
BossBarPacket deletePacket = new BossBarPacket();
ClientboundBossBarPacket deletePacket = new ClientboundBossBarPacket();
deletePacket.setUuid(serverBossBar);
deletePacket.setAction(BossBarPacket.REMOVE);
deletePacket.setAction(ClientboundBossBarPacket.REMOVE);
player.getConnection().delayedWrite(deletePacket);
}
serverBossBars.clear();
@@ -354,19 +358,19 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
// Tell the server about this client's plugin message channels.
ProtocolVersion serverVersion = serverMc.getProtocolVersion();
if (!player.getKnownChannels().isEmpty()) {
serverMc.delayedWrite(constructChannelsPacket(serverVersion, player.getKnownChannels()));
serverMc.delayedWrite(constructChannelsPacket(serverVersion, player.getKnownChannels(), ServerboundPluginMessagePacket.FACTORY));
}
// If we had plugin messages queued during login/FML handshake, send them now.
PluginMessagePacket pm;
ServerboundPluginMessagePacket pm;
while ((pm = loginPluginMessages.poll()) != null) {
serverMc.delayedWrite(pm);
}
// Clear any title from the previous server.
if (player.getProtocolVersion().compareTo(MINECRAFT_1_8) >= 0) {
if (player.getProtocolVersion().gte(MINECRAFT_1_8)) {
player.getConnection()
.delayedWrite(TitlePacket.resetForProtocolVersion(player.getProtocolVersion()));
.delayedWrite(ClientboundTitlePacket.reset(player.getProtocolVersion()));
}
// Flush everything
@@ -375,7 +379,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
destination.completeJoin();
}
private void doFastClientServerSwitch(JoinGamePacket joinGame) {
private void doFastClientServerSwitch(ClientboundJoinGamePacket joinGame) {
// In order to handle switching to another server, you will need to send two packets:
//
// - The join game packet from the backend server, with a different dimension
@@ -385,7 +389,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
// to perform entity ID rewrites, eliminating potential issues from rewriting packets and
// improving compatibility with mods.
int sentOldDim = joinGame.getDimension();
if (player.getProtocolVersion().compareTo(MINECRAFT_1_16) < 0) {
if (player.getProtocolVersion().lt(MINECRAFT_1_16)) {
// Before Minecraft 1.16, we could not switch to the same dimension without sending an
// additional respawn. On older versions of Minecraft this forces the client to perform
// garbage collection which adds additional latency.
@@ -394,13 +398,13 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
player.getConnection().delayedWrite(joinGame);
player.getConnection().delayedWrite(
new RespawnPacket(sentOldDim, joinGame.getPartialHashedSeed(),
new ClientboundRespawnPacket(sentOldDim, joinGame.getPartialHashedSeed(),
joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType(),
false, joinGame.getDimensionInfo(), joinGame.getPreviousGamemode(),
joinGame.getCurrentDimensionData()));
}
private void doSafeClientServerSwitch(JoinGamePacket joinGame) {
private void doSafeClientServerSwitch(ClientboundJoinGamePacket joinGame) {
// Some clients do not behave well with the "fast" respawn sequence. In this case we will use
// a "safe" respawn sequence that involves sending three packets to the client. They have the
// same effect but tend to work better with buggier clients (Forge 1.8 in particular).
@@ -411,14 +415,14 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
// Send a respawn packet in a different dimension.
int tempDim = joinGame.getDimension() == 0 ? -1 : 0;
player.getConnection().delayedWrite(
new RespawnPacket(tempDim, joinGame.getPartialHashedSeed(), joinGame.getDifficulty(),
joinGame.getGamemode(), joinGame.getLevelType(),
new ClientboundRespawnPacket(tempDim, joinGame.getPartialHashedSeed(),
joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType(),
false, joinGame.getDimensionInfo(), joinGame.getPreviousGamemode(),
joinGame.getCurrentDimensionData()));
// Now send a respawn packet in the correct dimension.
player.getConnection().delayedWrite(
new RespawnPacket(joinGame.getDimension(), joinGame.getPartialHashedSeed(),
new ClientboundRespawnPacket(joinGame.getDimension(), joinGame.getPartialHashedSeed(),
joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType(),
false, joinGame.getDimensionInfo(), joinGame.getPreviousGamemode(),
joinGame.getCurrentDimensionData()));
@@ -428,7 +432,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
return serverBossBars;
}
private boolean handleCommandTabComplete(TabCompleteRequestPacket packet) {
private boolean handleCommandTabComplete(ServerboundTabCompleteRequestPacket packet) {
// In 1.13+, we need to do additional work for the richer suggestions available.
String command = packet.getCommand().substring(1);
int commandEndPosition = command.indexOf(' ');
@@ -438,7 +442,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
String commandLabel = command.substring(0, commandEndPosition);
if (!server.getCommandManager().hasCommand(commandLabel)) {
if (player.getProtocolVersion().compareTo(MINECRAFT_1_13) < 0) {
if (player.getProtocolVersion().lt(MINECRAFT_1_13)) {
// Outstanding tab completes are recorded for use with 1.12 clients and below to provide
// additional tab completion support.
outstandingTabComplete = packet;
@@ -458,7 +462,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
}
int startPos = packet.getCommand().lastIndexOf(' ') + 1;
if (startPos > 0) {
TabCompleteResponsePacket resp = new TabCompleteResponsePacket();
ClientboundTabCompleteResponsePacket resp = new ClientboundTabCompleteResponsePacket();
resp.setTransactionId(packet.getTransactionId());
resp.setStart(startPos);
resp.setLength(packet.getCommand().length() - startPos);
@@ -474,8 +478,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
return true; // Sorry, handler; we're just gonna have to lie to you here.
}
private boolean handleRegularTabComplete(TabCompleteRequestPacket packet) {
if (player.getProtocolVersion().compareTo(MINECRAFT_1_13) < 0) {
private boolean handleRegularTabComplete(ServerboundTabCompleteRequestPacket packet) {
if (player.getProtocolVersion().lt(MINECRAFT_1_13)) {
// Outstanding tab completes are recorded for use with 1.12 clients and below to provide
// additional tab completion support.
outstandingTabComplete = packet;
@@ -488,7 +492,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
*
* @param response the tab complete response from the backend
*/
public void handleTabCompleteResponse(TabCompleteResponsePacket response) {
public void handleTabCompleteResponse(ClientboundTabCompleteResponsePacket response) {
if (outstandingTabComplete != null && !outstandingTabComplete.isAssumeCommand()) {
if (outstandingTabComplete.getCommand().startsWith("/")) {
this.finishCommandTabComplete(outstandingTabComplete, response);
@@ -502,12 +506,12 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
}
}
private void finishCommandTabComplete(TabCompleteRequestPacket request,
TabCompleteResponsePacket response) {
private void finishCommandTabComplete(ServerboundTabCompleteRequestPacket request,
ClientboundTabCompleteResponsePacket response) {
String command = request.getCommand().substring(1);
server.getCommandManager().offerSuggestions(player, command)
.thenAcceptAsync(offers -> {
boolean legacy = player.getProtocolVersion().compareTo(MINECRAFT_1_13) < 0;
boolean legacy = player.getProtocolVersion().lt(MINECRAFT_1_13);
try {
for (String offer : offers) {
offer = legacy && !offer.startsWith("/") ? "/" + offer : offer;
@@ -532,8 +536,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
});
}
private void finishRegularTabComplete(TabCompleteRequestPacket request,
TabCompleteResponsePacket response) {
private void finishRegularTabComplete(ServerboundTabCompleteRequestPacket request,
ClientboundTabCompleteResponsePacket response) {
List<String> offers = new ArrayList<>();
for (Offer offer : response.getOffers()) {
offers.add(offer.getText());
@@ -563,13 +567,13 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
MinecraftConnection smc = player.ensureAndGetCurrentServer().ensureConnected();
String commandToRun = result.getCommand().orElse(originalCommand);
if (result.isForwardToServer()) {
return CompletableFuture.runAsync(() -> smc.write(ChatPacket.createServerbound("/"
return CompletableFuture.runAsync(() -> smc.write(new ServerboundChatPacket("/"
+ commandToRun)), smc.eventLoop());
} else {
return server.getCommandManager().executeImmediately(player, commandToRun)
.thenAcceptAsync(hasRun -> {
if (!hasRun) {
smc.write(ChatPacket.createServerbound("/" + commandToRun));
smc.write(new ServerboundChatPacket("/" + commandToRun));
}
}, smc.eventLoop());
}
@@ -583,7 +587,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
if (serverConnection != null) {
MinecraftConnection connection = serverConnection.getConnection();
if (connection != null) {
PluginMessagePacket pm;
ServerboundPluginMessagePacket pm;
while ((pm = loginPluginMessages.poll()) != null) {
connection.write(pm);
}

View File

@@ -2,20 +2,20 @@ package com.velocitypowered.proxy.connection.client;
import com.velocitypowered.api.proxy.player.PlayerSettings;
import com.velocitypowered.api.proxy.player.SkinParts;
import com.velocitypowered.proxy.protocol.packet.ClientSettingsPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundClientSettingsPacket;
import java.util.Locale;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ClientSettingsWrapper implements PlayerSettings {
static final PlayerSettings DEFAULT = new ClientSettingsWrapper(
new ClientSettingsPacket("en_US", (byte) 10, 0, true, (short) 127, 1));
new ServerboundClientSettingsPacket("en_US", (byte) 10, 0, true, (short) 127, 1));
private final ClientSettingsPacket settings;
private final ServerboundClientSettingsPacket settings;
private final SkinParts parts;
private @Nullable Locale locale;
ClientSettingsWrapper(ClientSettingsPacket settings) {
ClientSettingsWrapper(ServerboundClientSettingsPacket settings) {
this.settings = settings;
this.parts = new SkinParts((byte) settings.getSkinParts());
}

View File

@@ -36,20 +36,21 @@ import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants;
import com.velocitypowered.proxy.connection.util.ConnectionMessages;
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.ChatPacket;
import com.velocitypowered.proxy.protocol.packet.ClientSettingsPacket;
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
import com.velocitypowered.proxy.protocol.packet.KeepAlivePacket;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.protocol.packet.ResourcePackRequestPacket;
import com.velocitypowered.proxy.protocol.packet.TitlePacket;
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
import com.velocitypowered.proxy.network.PluginMessageUtil;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.StateRegistry;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundChatPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundKeepAlivePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundResourcePackRequestPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTitlePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundChatPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundClientSettingsPacket;
import com.velocitypowered.proxy.server.VelocityRegisteredServer;
import com.velocitypowered.proxy.tablist.VelocityTabList;
import com.velocitypowered.proxy.tablist.VelocityTabListLegacy;
import com.velocitypowered.proxy.util.DurationUtils;
import com.velocitypowered.proxy.util.collect.CappedSet;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
@@ -112,7 +113,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
ConnectedPlayer(VelocityServer server, GameProfile profile, MinecraftConnection connection,
@Nullable InetSocketAddress virtualHost, boolean onlineMode) {
this.server = server;
if (connection.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
if (connection.getProtocolVersion().gte(ProtocolVersion.MINECRAFT_1_8)) {
this.tabList = new VelocityTabList(connection);
} else {
this.tabList = new VelocityTabListLegacy(connection);
@@ -186,7 +187,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
return settings == null ? ClientSettingsWrapper.DEFAULT : this.settings;
}
void setPlayerSettings(ClientSettingsPacket settings) {
void setPlayerSettings(ServerboundClientSettingsPacket settings) {
ClientSettingsWrapper cs = new ClientSettingsWrapper(settings);
this.settings = cs;
server.getEventManager().fireAndForget(new PlayerSettingsChangedEvent(this, cs));
@@ -226,41 +227,40 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
return connection.getProtocolVersion();
}
@Override
public void sendMessage(@NonNull Identity identity, @NonNull Component message) {
connection.write(ChatPacket.createClientbound(identity, message, this.getProtocolVersion()));
}
@Override
public void sendMessage(@NonNull Identity identity, @NonNull Component message,
@NonNull MessageType type) {
Preconditions.checkNotNull(message, "message");
Preconditions.checkNotNull(type, "type");
ChatPacket packet = ChatPacket.createClientbound(identity, message, this.getProtocolVersion());
packet.setType(type == MessageType.CHAT ? ChatPacket.CHAT_TYPE : ChatPacket.SYSTEM_TYPE);
connection.write(packet);
connection.write(new ClientboundChatPacket(
ProtocolUtils.getJsonChatSerializer(this.getProtocolVersion()).serialize(message),
type == MessageType.CHAT
? ClientboundChatPacket.CHAT_TYPE
: ClientboundChatPacket.SYSTEM_TYPE,
identity.uuid()
));
}
@Override
public void sendActionBar(net.kyori.adventure.text.@NonNull Component message) {
ProtocolVersion playerVersion = getProtocolVersion();
if (playerVersion.compareTo(ProtocolVersion.MINECRAFT_1_11) >= 0) {
if (playerVersion.gte(ProtocolVersion.MINECRAFT_1_11)) {
// Use the title packet instead.
TitlePacket pkt = new TitlePacket();
pkt.setAction(TitlePacket.SET_ACTION_BAR);
pkt.setComponent(ProtocolUtils.getJsonChatSerializer(playerVersion)
.serialize(message));
connection.write(pkt);
connection.write(new ClientboundTitlePacket(
ClientboundTitlePacket.SET_ACTION_BAR,
ProtocolUtils.getJsonChatSerializer(playerVersion).serialize(message)
));
} else {
// Due to issues with action bar packets, we'll need to convert the text message into a
// legacy message and then inject the legacy text into a component... yuck!
JsonObject object = new JsonObject();
object.addProperty("text", LegacyComponentSerializer.legacySection().serialize(message));
ChatPacket chat = new ChatPacket();
chat.setMessage(object.toString());
chat.setType(ChatPacket.GAME_INFO_TYPE);
connection.write(chat);
connection.write(new ClientboundChatPacket(
object.toString(),
ClientboundChatPacket.GAME_INFO_TYPE,
Identity.nil().uuid()
));
}
}
@@ -269,36 +269,32 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
GsonComponentSerializer serializer = ProtocolUtils.getJsonChatSerializer(this
.getProtocolVersion());
TitlePacket titlePkt = new TitlePacket();
titlePkt.setAction(TitlePacket.SET_TITLE);
titlePkt.setComponent(serializer.serialize(title.title()));
connection.delayedWrite(titlePkt);
connection.delayedWrite(new ClientboundTitlePacket(
ClientboundTitlePacket.SET_TITLE,
serializer.serialize(title.title())
));
TitlePacket subtitlePkt = new TitlePacket();
subtitlePkt.setAction(TitlePacket.SET_SUBTITLE);
subtitlePkt.setComponent(serializer.serialize(title.subtitle()));
connection.delayedWrite(subtitlePkt);
connection.delayedWrite(new ClientboundTitlePacket(
ClientboundTitlePacket.SET_SUBTITLE,
serializer.serialize(title.subtitle())
));
TitlePacket timesPkt = TitlePacket.timesForProtocolVersion(this.getProtocolVersion());
net.kyori.adventure.title.Title.Times times = title.times();
if (times != null) {
timesPkt.setFadeIn((int) DurationUtils.toTicks(times.fadeIn()));
timesPkt.setStay((int) DurationUtils.toTicks(times.stay()));
timesPkt.setFadeOut((int) DurationUtils.toTicks(times.fadeOut()));
connection.delayedWrite(ClientboundTitlePacket.times(this.getProtocolVersion(), times));
}
connection.delayedWrite(timesPkt);
connection.flush();
}
@Override
public void clearTitle() {
connection.write(TitlePacket.hideForProtocolVersion(this.getProtocolVersion()));
connection.write(ClientboundTitlePacket.hide(this.getProtocolVersion()));
}
@Override
public void resetTitle() {
connection.write(TitlePacket.resetForProtocolVersion(this.getProtocolVersion()));
connection.write(ClientboundTitlePacket.reset(this.getProtocolVersion()));
}
@Override
@@ -343,7 +339,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
public void disconnect0(Component reason, boolean duringLogin) {
logger.info("{} has disconnected: {}", this,
LegacyComponentSerializer.legacySection().serialize(reason));
connection.closeWith(DisconnectPacket.create(reason, this.getProtocolVersion()));
connection.closeWith(ClientboundDisconnectPacket.create(reason, this.getProtocolVersion()));
}
public @Nullable VelocityServerConnection getConnectedServer() {
@@ -402,7 +398,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
* @param disconnect the disconnect packet
* @param safe whether or not we can safely reconnect to a new server
*/
public void handleConnectionException(RegisteredServer server, DisconnectPacket disconnect,
public void handleConnectionException(RegisteredServer server, ClientboundDisconnectPacket disconnect,
boolean safe) {
if (!isActive()) {
// If the connection is no longer active, it makes no sense to try and recover it.
@@ -507,7 +503,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
case SERVER_DISCONNECTED:
Component reason = status.getReason()
.orElse(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR);
handleConnectionException(res.getServer(), DisconnectPacket.create(reason,
handleConnectionException(res.getServer(), ClientboundDisconnectPacket.create(reason,
getProtocolVersion()), ((Impl) status).isSafe());
break;
case SUCCESS:
@@ -664,7 +660,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) {
Preconditions.checkNotNull(identifier, "identifier");
Preconditions.checkNotNull(data, "data");
PluginMessagePacket message = new PluginMessagePacket(identifier.getId(),
ClientboundPluginMessagePacket message = new ClientboundPluginMessagePacket(identifier.getId(),
Unpooled.wrappedBuffer(data));
connection.write(message);
return true;
@@ -672,20 +668,17 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
@Override
public void spoofChatInput(String input) {
Preconditions.checkArgument(input.length() <= ChatPacket.MAX_SERVERBOUND_MESSAGE_LENGTH,
"input cannot be greater than " + ChatPacket.MAX_SERVERBOUND_MESSAGE_LENGTH
Preconditions.checkArgument(input.length() <= ServerboundChatPacket.MAX_MESSAGE_LENGTH,
"input cannot be greater than " + ServerboundChatPacket.MAX_MESSAGE_LENGTH
+ " characters in length");
ensureBackendConnection().write(ChatPacket.createServerbound(input));
ensureBackendConnection().write(new ServerboundChatPacket(input));
}
@Override
public void sendResourcePack(String url) {
Preconditions.checkNotNull(url, "url");
ResourcePackRequestPacket request = new ResourcePackRequestPacket();
request.setUrl(url);
request.setHash("");
connection.write(request);
connection.write(new ClientboundResourcePackRequestPacket(url, ""));
}
@Override
@@ -694,22 +687,17 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
Preconditions.checkNotNull(hash, "hash");
Preconditions.checkArgument(hash.length == 20, "Hash length is not 20");
ResourcePackRequestPacket request = new ResourcePackRequestPacket();
request.setUrl(url);
request.setHash(ByteBufUtil.hexDump(hash));
connection.write(request);
connection.write(new ClientboundResourcePackRequestPacket(url, ByteBufUtil.hexDump(hash)));
}
/**
* Sends a {@link KeepAlivePacket} packet to the player with a random ID.
* Sends a {@link ClientboundKeepAlivePacket} packet to the player with a random ID.
* The response will be ignored by Velocity as it will not match the
* ID last sent by the server.
*/
public void sendKeepAlive() {
if (connection.getState() == StateRegistry.PLAY) {
KeepAlivePacket keepAlive = new KeepAlivePacket();
keepAlive.setRandomId(ThreadLocalRandom.current().nextLong());
connection.write(keepAlive);
connection.write(new ClientboundKeepAlivePacket(ThreadLocalRandom.current().nextLong()));
}
}
@@ -747,11 +735,11 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
* @param message the plugin message to forward to the client
* @return {@code true} if the message can be forwarded, {@code false} otherwise
*/
public boolean canForwardPluginMessage(ProtocolVersion version, PluginMessagePacket message) {
public boolean canForwardPluginMessage(ProtocolVersion version, AbstractPluginMessagePacket<?> message) {
boolean minecraftOrFmlMessage;
// By default, all internal Minecraft and Forge channels are forwarded from the server.
if (version.compareTo(ProtocolVersion.MINECRAFT_1_12_2) <= 0) {
if (version.lte(ProtocolVersion.MINECRAFT_1_12_2)) {
String channel = message.getChannel();
minecraftOrFmlMessage = channel.startsWith("MC|")
|| channel.startsWith(LegacyForgeConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL)
@@ -880,7 +868,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
case SERVER_DISCONNECTED:
Component reason = status.getReason()
.orElse(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR);
handleConnectionException(toConnect, DisconnectPacket.create(reason,
handleConnectionException(toConnect, ClientboundDisconnectPacket.create(reason,
getProtocolVersion()), status.isSafe());
break;
default:

View File

@@ -12,12 +12,12 @@ import com.velocitypowered.proxy.connection.ConnectionTypes;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.HandshakePacket;
import com.velocitypowered.proxy.protocol.packet.legacy.LegacyDisconnectPacket;
import com.velocitypowered.proxy.protocol.packet.legacy.LegacyHandshakePacket;
import com.velocitypowered.proxy.protocol.packet.legacy.LegacyPingPacket;
import com.velocitypowered.proxy.network.StateRegistry;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.legacy.LegacyDisconnectPacket;
import com.velocitypowered.proxy.network.packet.legacy.LegacyHandshakePacket;
import com.velocitypowered.proxy.network.packet.legacy.LegacyPingPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundHandshakePacket;
import io.netty.buffer.ByteBuf;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -58,7 +58,7 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(HandshakePacket handshake) {
public boolean handle(ServerboundHandshakePacket handshake) {
InitialInboundConnection ic = new InitialInboundConnection(connection,
cleanVhost(handshake.getServerAddress()), handshake);
StateRegistry nextState = getStateForProtocol(handshake.getNextStatus());
@@ -97,7 +97,7 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
}
}
private void handleLogin(HandshakePacket handshake, InitialInboundConnection ic) {
private void handleLogin(ServerboundHandshakePacket handshake, InitialInboundConnection ic) {
if (!ProtocolVersion.isSupported(handshake.getProtocolVersion())) {
ic.disconnectQuietly(Component.translatable("multiplayer.disconnect.outdated_client"));
return;
@@ -114,7 +114,7 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
// If the proxy is configured for modern forwarding, we must deny connections from 1.12.2
// and lower, otherwise IP information will never get forwarded.
if (server.getConfiguration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN
&& handshake.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_13) < 0) {
&& handshake.getProtocolVersion().lt(ProtocolVersion.MINECRAFT_1_13)) {
ic.disconnectQuietly(Component.text("This server is only compatible with 1.13 and above."));
return;
}
@@ -123,12 +123,12 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
connection.setSessionHandler(new LoginSessionHandler(server, connection, ic));
}
private ConnectionType getHandshakeConnectionType(HandshakePacket handshake) {
private ConnectionType getHandshakeConnectionType(ServerboundHandshakePacket handshake) {
// Determine if we're using Forge (1.8 to 1.12, may not be the case in 1.13).
if (handshake.getServerAddress().endsWith(LegacyForgeConstants.HANDSHAKE_HOSTNAME_TOKEN)
&& handshake.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_13) < 0) {
&& handshake.getProtocolVersion().lt(ProtocolVersion.MINECRAFT_1_13)) {
return ConnectionTypes.LEGACY_FORGE;
} else if (handshake.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_7_6) <= 0) {
} else if (handshake.getProtocolVersion().lte(ProtocolVersion.MINECRAFT_1_7_6)) {
// 1.7 Forge will not notify us during handshake. UNDETERMINED will listen for incoming
// forge handshake attempts. Also sends a reset handshake packet on every transition.
return ConnectionTypes.UNDETERMINED_17;

View File

@@ -3,8 +3,8 @@ package com.velocitypowered.proxy.connection.client;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.backend.BungeeCordMessageResponder;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
import com.velocitypowered.proxy.network.PluginMessageUtil;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundPluginMessagePacket;
public class InitialConnectSessionHandler implements MinecraftSessionHandler {
@@ -15,7 +15,7 @@ public class InitialConnectSessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(PluginMessagePacket packet) {
public boolean handle(ServerboundPluginMessagePacket packet) {
VelocityServerConnection serverConn = player.getConnectionInFlight();
if (serverConn != null) {
if (player.getPhase().handle(player, packet, serverConn)) {

View File

@@ -4,8 +4,8 @@ import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.connection.InboundConnection;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
import com.velocitypowered.proxy.protocol.packet.HandshakePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundHandshakePacket;
import java.net.InetSocketAddress;
import java.util.Optional;
import net.kyori.adventure.text.Component;
@@ -20,10 +20,10 @@ public final class InitialInboundConnection implements InboundConnection,
private final MinecraftConnection connection;
private final String cleanedAddress;
private final HandshakePacket handshake;
private final ServerboundHandshakePacket handshake;
InitialInboundConnection(MinecraftConnection connection, String cleanedAddress,
HandshakePacket handshake) {
ServerboundHandshakePacket handshake) {
this.connection = connection;
this.cleanedAddress = cleanedAddress;
this.handshake = handshake;
@@ -61,7 +61,7 @@ public final class InitialInboundConnection implements InboundConnection,
public void disconnect(Component reason) {
logger.info("{} has disconnected: {}", this,
LegacyComponentSerializer.legacySection().serialize(reason));
connection.closeWith(DisconnectPacket.create(reason, getProtocolVersion()));
connection.closeWith(ClientboundDisconnectPacket.create(reason, getProtocolVersion()));
}
/**
@@ -69,6 +69,6 @@ public final class InitialInboundConnection implements InboundConnection,
* @param reason the reason for disconnecting
*/
public void disconnectQuietly(Component reason) {
connection.closeWith(DisconnectPacket.create(reason, getProtocolVersion()));
connection.closeWith(ClientboundDisconnectPacket.create(reason, getProtocolVersion()));
}
}

View File

@@ -25,13 +25,13 @@ import com.velocitypowered.proxy.config.PlayerInfoForwarding;
import com.velocitypowered.proxy.config.VelocityConfiguration;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
import com.velocitypowered.proxy.protocol.packet.EncryptionRequestPacket;
import com.velocitypowered.proxy.protocol.packet.EncryptionResponsePacket;
import com.velocitypowered.proxy.protocol.packet.ServerLoginPacket;
import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccessPacket;
import com.velocitypowered.proxy.protocol.packet.SetCompressionPacket;
import com.velocitypowered.proxy.network.StateRegistry;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundEncryptionRequestPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundServerLoginSuccessPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundSetCompressionPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundEncryptionResponsePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundServerLoginPacket;
import io.netty.buffer.ByteBuf;
import java.net.InetSocketAddress;
import java.security.GeneralSecurityException;
@@ -58,7 +58,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
private final VelocityServer server;
private final MinecraftConnection mcConnection;
private final InitialInboundConnection inbound;
private @MonotonicNonNull ServerLoginPacket login;
private @MonotonicNonNull ServerboundServerLoginPacket login;
private byte[] verify = EMPTY_BYTE_ARRAY;
private @MonotonicNonNull ConnectedPlayer connectedPlayer;
@@ -70,15 +70,15 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(ServerLoginPacket packet) {
public boolean handle(ServerboundServerLoginPacket packet) {
this.login = packet;
beginPreLogin();
return true;
}
@Override
public boolean handle(EncryptionResponsePacket packet) {
ServerLoginPacket login = this.login;
public boolean handle(ServerboundEncryptionResponsePacket packet) {
ServerboundServerLoginPacket login = this.login;
if (login == null) {
throw new IllegalStateException("No ServerLogin packet received yet.");
}
@@ -153,7 +153,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
}
private void beginPreLogin() {
ServerLoginPacket login = this.login;
ServerboundServerLoginPacket login = this.login;
if (login == null) {
throw new IllegalStateException("No ServerLogin packet received yet.");
}
@@ -169,7 +169,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
Optional<Component> disconnectReason = result.getReason();
if (disconnectReason.isPresent()) {
// The component is guaranteed to be provided if the connection was denied.
mcConnection.closeWith(DisconnectPacket.create(disconnectReason.get(),
mcConnection.closeWith(ClientboundDisconnectPacket.create(disconnectReason.get(),
inbound.getProtocolVersion()));
return;
}
@@ -177,7 +177,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
if (!result.isForceOfflineMode() && (server.getConfiguration().isOnlineMode() || result
.isOnlineModeAllowed())) {
// Request encryption.
EncryptionRequestPacket request = generateEncryptionRequest();
ClientboundEncryptionRequestPacket request = generateEncryptionRequest();
this.verify = Arrays.copyOf(request.getVerifyToken(), 4);
mcConnection.write(request);
} else {
@@ -190,11 +190,11 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
});
}
private EncryptionRequestPacket generateEncryptionRequest() {
private ClientboundEncryptionRequestPacket generateEncryptionRequest() {
byte[] verify = new byte[4];
ThreadLocalRandom.current().nextBytes(verify);
EncryptionRequestPacket request = new EncryptionRequestPacket();
ClientboundEncryptionRequestPacket request = new ClientboundEncryptionRequestPacket();
request.setPublicKey(server.getServerKeyPair().getPublic().getEncoded());
request.setVerifyToken(verify);
return request;
@@ -242,8 +242,8 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
private void completeLoginProtocolPhaseAndInitialize(ConnectedPlayer player) {
int threshold = server.getConfiguration().getCompressionThreshold();
if (threshold >= 0 && mcConnection.getProtocolVersion().compareTo(MINECRAFT_1_8) >= 0) {
mcConnection.write(new SetCompressionPacket(threshold));
if (threshold >= 0 && mcConnection.getProtocolVersion().gte(MINECRAFT_1_8)) {
mcConnection.write(new ClientboundSetCompressionPacket(threshold));
mcConnection.setCompressionThreshold(threshold);
}
VelocityConfiguration configuration = server.getConfiguration();
@@ -251,10 +251,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
if (configuration.getPlayerInfoForwardingMode() == PlayerInfoForwarding.NONE) {
playerUniqueId = UuidUtils.generateOfflinePlayerUuid(player.getUsername());
}
ServerLoginSuccessPacket success = new ServerLoginSuccessPacket();
success.setUsername(player.getUsername());
success.setUuid(playerUniqueId);
mcConnection.write(success);
mcConnection.write(new ClientboundServerLoginSuccessPacket(playerUniqueId, player.getUsername()));
mcConnection.setAssociation(player);
mcConnection.setState(StateRegistry.PLAY);

View File

@@ -13,11 +13,11 @@ import com.velocitypowered.proxy.config.PingPassthroughMode;
import com.velocitypowered.proxy.config.VelocityConfiguration;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.packet.StatusPingPacket;
import com.velocitypowered.proxy.protocol.packet.StatusRequestPacket;
import com.velocitypowered.proxy.protocol.packet.StatusResponsePacket;
import com.velocitypowered.proxy.protocol.packet.legacy.LegacyDisconnectPacket;
import com.velocitypowered.proxy.protocol.packet.legacy.LegacyPingPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundStatusResponsePacket;
import com.velocitypowered.proxy.network.packet.legacy.LegacyDisconnectPacket;
import com.velocitypowered.proxy.network.packet.legacy.LegacyPingPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundStatusPingPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundStatusRequestPacket;
import com.velocitypowered.proxy.server.VelocityRegisteredServer;
import com.velocitypowered.proxy.util.except.QuietRuntimeException;
import io.netty.buffer.ByteBuf;
@@ -176,13 +176,13 @@ public class StatusSessionHandler implements MinecraftSessionHandler {
}
@Override
public boolean handle(StatusPingPacket packet) {
public boolean handle(ServerboundStatusPingPacket packet) {
connection.closeWith(packet);
return true;
}
@Override
public boolean handle(StatusRequestPacket packet) {
public boolean handle(ServerboundStatusRequestPacket packet) {
if (this.pingReceived) {
throw EXPECTED_AWAITING_REQUEST;
}
@@ -195,7 +195,7 @@ public class StatusSessionHandler implements MinecraftSessionHandler {
StringBuilder json = new StringBuilder();
VelocityServer.getPingGsonInstance(connection.getProtocolVersion())
.toJson(event.getPing(), json);
connection.write(new StatusResponsePacket(json));
connection.write(new ClientboundStatusResponsePacket(json));
},
connection.eventLoop())
.exceptionally((ex) -> {

View File

@@ -6,7 +6,7 @@ import com.velocitypowered.proxy.connection.backend.BackendConnectionPhase;
import com.velocitypowered.proxy.connection.backend.BackendConnectionPhases;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
import javax.annotation.Nullable;
/**
@@ -107,7 +107,7 @@ public enum LegacyForgeHandshakeBackendPhase implements BackendConnectionPhase {
@Override
public final boolean handle(VelocityServerConnection serverConnection,
ConnectedPlayer player,
PluginMessagePacket message) {
AbstractPluginMessagePacket<?> message) {
if (message.getChannel().equals(LegacyForgeConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL)) {
// Get the phase and check if we need to start the next phase.
LegacyForgeHandshakeBackendPhase newPhase = getNewPhase(serverConnection, message);
@@ -162,7 +162,7 @@ public enum LegacyForgeHandshakeBackendPhase implements BackendConnectionPhase {
* @return The phase to transition to, which may be the same as before.
*/
private LegacyForgeHandshakeBackendPhase getNewPhase(VelocityServerConnection serverConnection,
PluginMessagePacket packet) {
AbstractPluginMessagePacket<?> packet) {
if (packetToAdvanceOn != null
&& LegacyForgeUtil.getHandshakePacketDiscriminator(packet) == packetToAdvanceOn) {
LegacyForgeHandshakeBackendPhase phaseToTransitionTo = nextPhase();

View File

@@ -7,7 +7,7 @@ import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.connection.client.ClientConnectionPhase;
import com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
import java.util.List;
import javax.annotation.Nullable;
@@ -39,7 +39,7 @@ public enum LegacyForgeHandshakeClientPhase implements ClientConnectionPhase {
@Override
boolean onHandle(ConnectedPlayer player,
PluginMessagePacket message,
AbstractPluginMessagePacket<?> message,
MinecraftConnection backendConn) {
// If we stay in this phase, we do nothing because it means the packet wasn't handled.
// Returning false indicates this
@@ -73,7 +73,7 @@ public enum LegacyForgeHandshakeClientPhase implements ClientConnectionPhase {
@Override
boolean onHandle(ConnectedPlayer player,
PluginMessagePacket message,
AbstractPluginMessagePacket<?> message,
MinecraftConnection backendConn) {
// Read the mod list if we haven't already.
if (!player.getModInfo().isPresent()) {
@@ -147,7 +147,7 @@ public enum LegacyForgeHandshakeClientPhase implements ClientConnectionPhase {
@Override
boolean onHandle(ConnectedPlayer player,
PluginMessagePacket message,
AbstractPluginMessagePacket<?> message,
MinecraftConnection backendConn) {
super.onHandle(player, message, backendConn);
@@ -180,7 +180,7 @@ public enum LegacyForgeHandshakeClientPhase implements ClientConnectionPhase {
@Override
public final boolean handle(ConnectedPlayer player,
PluginMessagePacket message,
AbstractPluginMessagePacket<?> message,
VelocityServerConnection server) {
if (server != null) {
MinecraftConnection backendConn = server.getConnection();
@@ -211,7 +211,7 @@ public enum LegacyForgeHandshakeClientPhase implements ClientConnectionPhase {
* @return true if handled, false otherwise.
*/
boolean onHandle(ConnectedPlayer player,
PluginMessagePacket message,
AbstractPluginMessagePacket<?> message,
MinecraftConnection backendConn) {
// Send the packet on to the server.
backendConn.write(message.retain());
@@ -241,7 +241,7 @@ public enum LegacyForgeHandshakeClientPhase implements ClientConnectionPhase {
* @param packet The packet
* @return The phase to transition to, which may be the same as before.
*/
private LegacyForgeHandshakeClientPhase getNewPhase(PluginMessagePacket packet) {
private LegacyForgeHandshakeClientPhase getNewPhase(AbstractPluginMessagePacket<?> packet) {
if (packetToAdvanceOn != null
&& LegacyForgeUtil.getHandshakePacketDiscriminator(packet) == packetToAdvanceOn) {
return nextPhase();

View File

@@ -7,8 +7,9 @@ import static com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConst
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.velocitypowered.api.util.ModInfo;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPluginMessagePacket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.List;
@@ -25,7 +26,7 @@ class LegacyForgeUtil {
* @param message The message to analyse
* @return The discriminator
*/
static byte getHandshakePacketDiscriminator(PluginMessagePacket message) {
static byte getHandshakePacketDiscriminator(AbstractPluginMessagePacket<?> message) {
Preconditions.checkArgument(message.getChannel().equals(FORGE_LEGACY_HANDSHAKE_CHANNEL));
Preconditions.checkArgument(message.content().isReadable());
return message.content().getByte(0);
@@ -37,7 +38,7 @@ class LegacyForgeUtil {
* @param message The message
* @return The list of mods. May be empty.
*/
static List<ModInfo.Mod> readModList(PluginMessagePacket message) {
static List<ModInfo.Mod> readModList(AbstractPluginMessagePacket<?> message) {
Preconditions.checkNotNull(message, "message");
Preconditions.checkArgument(message.getChannel().equals(FORGE_LEGACY_HANDSHAKE_CHANNEL),
"message is not a FML HS plugin message");
@@ -65,10 +66,10 @@ class LegacyForgeUtil {
*
* @return A copy of the reset packet
*/
static PluginMessagePacket resetPacket() {
PluginMessagePacket msg = new PluginMessagePacket();
msg.setChannel(FORGE_LEGACY_HANDSHAKE_CHANNEL);
msg.replace(Unpooled.wrappedBuffer(FORGE_LEGACY_HANDSHAKE_RESET_DATA.clone()));
return msg;
static AbstractPluginMessagePacket<?> resetPacket() {
return new ClientboundPluginMessagePacket(
FORGE_LEGACY_HANDSHAKE_CHANNEL,
Unpooled.wrappedBuffer(FORGE_LEGACY_HANDSHAKE_RESET_DATA.clone())
);
}
}

View File

@@ -225,7 +225,7 @@ public final class DimensionData {
String registryIdentifier = dimTag.getString("name");
CompoundBinaryTag details;
Integer dimensionId = null;
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
dimensionId = dimTag.getInt("id");
details = dimTag.getCompound("element");
} else {
@@ -243,7 +243,7 @@ public final class DimensionData {
*/
public CompoundBinaryTag encodeAsCompoundTag(ProtocolVersion version) {
CompoundBinaryTag details = serializeDimensionDetails();
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
if (dimensionId == null) {
throw new IllegalStateException("Tried to serialize a 1.16.2+ dimension registry entry "
+ "without an ID");

View File

@@ -3,7 +3,7 @@ package com.velocitypowered.proxy.connection.util;
import com.velocitypowered.api.proxy.player.ConnectionRequestBuilder;
import com.velocitypowered.api.proxy.player.ConnectionRequestBuilder.Status;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket;
import java.util.Optional;
import javax.annotation.Nullable;
import net.kyori.adventure.text.Component;
@@ -41,12 +41,12 @@ public class ConnectionRequestResults {
return new Impl(Status.SERVER_DISCONNECTED, component, server, true);
}
public static Impl forDisconnect(DisconnectPacket disconnect, RegisteredServer server) {
public static Impl forDisconnect(ClientboundDisconnectPacket disconnect, RegisteredServer server) {
Component deserialized = GsonComponentSerializer.gson().deserialize(disconnect.getReason());
return forDisconnect(deserialized, server);
}
public static Impl forUnsafeDisconnect(DisconnectPacket disconnect, RegisteredServer server) {
public static Impl forUnsafeDisconnect(ClientboundDisconnectPacket disconnect, RegisteredServer server) {
Component deserialized = GsonComponentSerializer.gson().deserialize(disconnect.getReason());
return new Impl(Status.SERVER_DISCONNECTED, deserialized, server, false);
}

View File

@@ -8,12 +8,12 @@ import static com.velocitypowered.proxy.network.Connections.MINECRAFT_ENCODER;
import static com.velocitypowered.proxy.network.Connections.READ_TIMEOUT;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.netty.AutoReadHolderHandler;
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintFrameDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintLengthEncoder;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.pipeline.AutoReadHolderHandler;
import com.velocitypowered.proxy.network.pipeline.MinecraftDecoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftEncoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftVarintFrameDecoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftVarintLengthEncoder;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.timeout.ReadTimeoutHandler;
@@ -37,9 +37,9 @@ public class BackendChannelInitializer extends ChannelInitializer<Channel> {
.addLast(FRAME_DECODER, new MinecraftVarintFrameDecoder())
.addLast(FRAME_ENCODER, MinecraftVarintLengthEncoder.INSTANCE)
.addLast(MINECRAFT_DECODER,
new MinecraftDecoder(ProtocolDirection.CLIENTBOUND))
new MinecraftDecoder(PacketDirection.CLIENTBOUND))
.addLast(FLOW_HANDLER, new AutoReadHolderHandler())
.addLast(MINECRAFT_ENCODER,
new MinecraftEncoder(ProtocolDirection.SERVERBOUND));
new MinecraftEncoder(PacketDirection.SERVERBOUND));
}
}

View File

@@ -6,17 +6,18 @@ import java.util.function.Supplier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class BackendChannelInitializerHolder implements Supplier<ChannelInitializer<Channel>> {
public class ChannelInitializerHolder<C extends Channel> implements Supplier<ChannelInitializer<C>> {
private static final Logger LOGGER = LogManager.getLogger(ChannelInitializerHolder.class);
private final String name;
private ChannelInitializer<C> initializer;
private static final Logger LOGGER = LogManager.getLogger(ConnectionManager.class);
private ChannelInitializer<Channel> initializer;
BackendChannelInitializerHolder(final ChannelInitializer<Channel> initializer) {
ChannelInitializerHolder(final String name, final ChannelInitializer<C> initializer) {
this.name = name;
this.initializer = initializer;
}
@Override
public ChannelInitializer<Channel> get() {
public ChannelInitializer<C> get() {
return this.initializer;
}
@@ -27,8 +28,8 @@ public class BackendChannelInitializerHolder implements Supplier<ChannelInitiali
* @deprecated Internal implementation detail
*/
@Deprecated
public void set(final ChannelInitializer<Channel> initializer) {
LOGGER.warn("The backend channel initializer has been replaced by {}",
public void set(final ChannelInitializer<C> initializer) {
LOGGER.warn("The {} initializer has been replaced by {}", this.name,
Thread.currentThread().getStackTrace()[2]);
this.initializer = initializer;
}

View File

@@ -6,8 +6,8 @@ import static org.asynchttpclient.Dsl.config;
import com.google.common.base.Preconditions;
import com.velocitypowered.natives.util.Natives;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.network.netty.SeparatePoolInetNameResolver;
import com.velocitypowered.proxy.protocol.netty.GS4QueryHandler;
import com.velocitypowered.proxy.network.pipeline.GS4QueryHandler;
import com.velocitypowered.proxy.network.resolver.SeparatePoolInetNameResolver;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
@@ -43,9 +43,9 @@ public final class ConnectionManager {
// These are intentionally made public for plugins like ViaVersion, which inject their own
// protocol logic into the proxy.
@SuppressWarnings("WeakerAccess")
public final ServerChannelInitializerHolder serverChannelInitializer;
public final ChannelInitializerHolder<Channel> serverChannelInitializer;
@SuppressWarnings("WeakerAccess")
public final BackendChannelInitializerHolder backendChannelInitializer;
public final ChannelInitializerHolder<Channel> backendChannelInitializer;
private final SeparatePoolInetNameResolver resolver;
private final AsyncHttpClient httpClient;
@@ -60,9 +60,9 @@ public final class ConnectionManager {
this.transportType = TransportType.bestType();
this.bossGroup = this.transportType.createEventLoopGroup(TransportType.Type.BOSS);
this.workerGroup = this.transportType.createEventLoopGroup(TransportType.Type.WORKER);
this.serverChannelInitializer = new ServerChannelInitializerHolder(
this.serverChannelInitializer = new ChannelInitializerHolder<>("server channel",
new ServerChannelInitializer(this.server));
this.backendChannelInitializer = new BackendChannelInitializerHolder(
this.backendChannelInitializer = new ChannelInitializerHolder<>("backend channel",
new BackendChannelInitializer(this.server));
this.resolver = new SeparatePoolInetNameResolver(GlobalEventExecutor.INSTANCE);
this.httpClient = asyncHttpClient(config()
@@ -198,7 +198,7 @@ public final class ConnectionManager {
return bossGroup;
}
public ServerChannelInitializerHolder getServerChannelInitializer() {
public ChannelInitializerHolder<Channel> getServerChannelInitializer() {
return this.serverChannelInitializer;
}
@@ -206,7 +206,7 @@ public final class ConnectionManager {
return httpClient;
}
public BackendChannelInitializerHolder getBackendChannelInitializer() {
public ChannelInitializerHolder<Channel> getBackendChannelInitializer() {
return this.backendChannelInitializer;
}
}

View File

@@ -1,7 +1,7 @@
package com.velocitypowered.proxy.protocol.util;
package com.velocitypowered.proxy.network;
import com.google.common.base.Strings;
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftDecoder;
import com.velocitypowered.proxy.util.except.QuietDecoderException;
import io.netty.handler.codec.CorruptedFrameException;

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol.util;
package com.velocitypowered.proxy.network;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -6,8 +6,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableList;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.util.ProxyVersion;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.nio.charset.StandardCharsets;
@@ -34,7 +33,7 @@ public final class PluginMessageUtil {
* @param message the plugin message
* @return whether or not this is a brand plugin message
*/
public static boolean isMcBrand(PluginMessagePacket message) {
public static boolean isMcBrand(AbstractPluginMessagePacket<?> message) {
checkNotNull(message, "message");
return message.getChannel().equals(BRAND_CHANNEL_LEGACY) || message.getChannel()
.equals(BRAND_CHANNEL);
@@ -45,7 +44,7 @@ public final class PluginMessageUtil {
* @param message the plugin message
* @return whether we are registering plugin channels or not
*/
public static boolean isRegister(PluginMessagePacket message) {
public static boolean isRegister(AbstractPluginMessagePacket<?> message) {
checkNotNull(message, "message");
return message.getChannel().equals(REGISTER_CHANNEL_LEGACY) || message.getChannel()
.equals(REGISTER_CHANNEL);
@@ -56,7 +55,7 @@ public final class PluginMessageUtil {
* @param message the plugin message
* @return whether we are unregistering plugin channels or not
*/
public static boolean isUnregister(PluginMessagePacket message) {
public static boolean isUnregister(AbstractPluginMessagePacket<?> message) {
checkNotNull(message, "message");
return message.getChannel().equals(UNREGISTER_CHANNEL_LEGACY) || message.getChannel()
.equals(UNREGISTER_CHANNEL);
@@ -67,7 +66,7 @@ public final class PluginMessageUtil {
* @param message the plugin message
* @return whether this is a legacy register message
*/
public static boolean isLegacyRegister(PluginMessagePacket message) {
public static boolean isLegacyRegister(AbstractPluginMessagePacket<?> message) {
checkNotNull(message, "message");
return message.getChannel().equals(REGISTER_CHANNEL_LEGACY);
}
@@ -78,7 +77,7 @@ public final class PluginMessageUtil {
* @param message the plugin message
* @return whether this is a legacy unregister message
*/
public static boolean isLegacyUnregister(PluginMessagePacket message) {
public static boolean isLegacyUnregister(AbstractPluginMessagePacket<?> message) {
checkNotNull(message, "message");
return message.getChannel().equals(UNREGISTER_CHANNEL_LEGACY);
}
@@ -88,7 +87,7 @@ public final class PluginMessageUtil {
* @param message the message to get the channels from
* @return the channels, as an immutable list
*/
public static List<String> getChannels(PluginMessagePacket message) {
public static List<String> getChannels(AbstractPluginMessagePacket<?> message) {
checkNotNull(message, "message");
checkArgument(isRegister(message) || isUnregister(message), "Unknown channel type %s",
message.getChannel());
@@ -107,15 +106,16 @@ public final class PluginMessageUtil {
* @param channels the channels to register
* @return the plugin message to send
*/
public static PluginMessagePacket constructChannelsPacket(ProtocolVersion protocolVersion,
Collection<String> channels) {
public static AbstractPluginMessagePacket<?> constructChannelsPacket(ProtocolVersion protocolVersion,
Collection<String> channels,
AbstractPluginMessagePacket.Factory<?> factory) {
checkNotNull(channels, "channels");
checkArgument(!channels.isEmpty(), "no channels specified");
String channelName = protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_13) >= 0
String channelName = protocolVersion.gte(ProtocolVersion.MINECRAFT_1_13)
? REGISTER_CHANNEL : REGISTER_CHANNEL_LEGACY;
ByteBuf contents = Unpooled.buffer();
contents.writeCharSequence(String.join("\0", channels), StandardCharsets.UTF_8);
return new PluginMessagePacket(channelName, contents);
return factory.create(channelName, contents);
}
/**
@@ -124,9 +124,10 @@ public final class PluginMessageUtil {
* @param version the proxy version
* @return the rewritten plugin message
*/
public static PluginMessagePacket rewriteMinecraftBrand(PluginMessagePacket message,
public static AbstractPluginMessagePacket<?> rewriteMinecraftBrand(AbstractPluginMessagePacket<?> message,
ProxyVersion version,
ProtocolVersion protocolVersion) {
ProtocolVersion protocolVersion,
AbstractPluginMessagePacket.Factory<?> factory) {
checkNotNull(message, "message");
checkNotNull(version, "version");
checkArgument(isMcBrand(message), "message is not a brand plugin message");
@@ -135,13 +136,13 @@ public final class PluginMessageUtil {
String rewrittenBrand = String.format("%s (%s)", currentBrand, version.getName());
ByteBuf rewrittenBuf = Unpooled.buffer();
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
if (protocolVersion.gte(ProtocolVersion.MINECRAFT_1_8)) {
ProtocolUtils.writeString(rewrittenBuf, rewrittenBrand);
} else {
rewrittenBuf.writeCharSequence(rewrittenBrand, StandardCharsets.UTF_8);
}
return new PluginMessagePacket(message.getChannel(), rewrittenBuf);
return factory.create(message.getChannel(), rewrittenBuf);
}
private static String readBrandMessage(ByteBuf content) {

View File

@@ -1,12 +1,12 @@
package com.velocitypowered.proxy.protocol;
package com.velocitypowered.proxy.network;
import static com.google.common.base.Preconditions.checkArgument;
import static com.velocitypowered.proxy.protocol.util.NettyPreconditions.checkFrame;
import static com.velocitypowered.proxy.network.NettyPreconditions.checkFrame;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
import com.velocitypowered.proxy.protocol.util.VelocityLegacyHoverEventSerializer;
import com.velocitypowered.proxy.network.pipeline.MinecraftDecoder;
import com.velocitypowered.proxy.network.serialization.VelocityLegacyHoverEventSerializer;
import com.velocitypowered.proxy.util.except.QuietDecoderException;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
@@ -459,7 +459,7 @@ public enum ProtocolUtils {
* @return the appropriate {@link GsonComponentSerializer}
*/
public static GsonComponentSerializer getJsonChatSerializer(ProtocolVersion version) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
return MODERN_SERIALIZER;
}
return PRE_1_16_SERIALIZER;

View File

@@ -11,13 +11,13 @@ import static com.velocitypowered.proxy.network.Connections.READ_TIMEOUT;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.netty.LegacyPingDecoder;
import com.velocitypowered.proxy.protocol.netty.LegacyPingEncoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintFrameDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintLengthEncoder;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.pipeline.LegacyPingDecoder;
import com.velocitypowered.proxy.network.pipeline.LegacyPingEncoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftDecoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftEncoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftVarintFrameDecoder;
import com.velocitypowered.proxy.network.pipeline.MinecraftVarintLengthEncoder;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.haproxy.HAProxyMessageDecoder;
@@ -43,8 +43,8 @@ public class ServerChannelInitializer extends ChannelInitializer<Channel> {
.addLast(FRAME_DECODER, new MinecraftVarintFrameDecoder())
.addLast(LEGACY_PING_ENCODER, LegacyPingEncoder.INSTANCE)
.addLast(FRAME_ENCODER, MinecraftVarintLengthEncoder.INSTANCE)
.addLast(MINECRAFT_DECODER, new MinecraftDecoder(ProtocolDirection.SERVERBOUND))
.addLast(MINECRAFT_ENCODER, new MinecraftEncoder(ProtocolDirection.CLIENTBOUND));
.addLast(MINECRAFT_DECODER, new MinecraftDecoder(PacketDirection.SERVERBOUND))
.addLast(MINECRAFT_ENCODER, new MinecraftEncoder(PacketDirection.CLIENTBOUND));
final MinecraftConnection connection = new MinecraftConnection(ch, this.server);
connection.setSessionHandler(new HandshakeSessionHandler(connection, this.server));

View File

@@ -1,34 +0,0 @@
package com.velocitypowered.proxy.network;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import java.util.function.Supplier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ServerChannelInitializerHolder implements Supplier<ChannelInitializer<Channel>> {
private static final Logger LOGGER = LogManager.getLogger(ConnectionManager.class);
private ChannelInitializer<Channel> initializer;
ServerChannelInitializerHolder(final ChannelInitializer<Channel> initializer) {
this.initializer = initializer;
}
@Override
public ChannelInitializer<Channel> get() {
return this.initializer;
}
/**
* Sets the channel initializer.
* @param initializer the new initializer to use
* @deprecated Internal implementation detail
*/
@Deprecated
public void set(final ChannelInitializer<Channel> initializer) {
LOGGER.warn("The server channel initializer has been replaced by {}",
Thread.currentThread().getStackTrace()[2]);
this.initializer = initializer;
}
}

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol;
package com.velocitypowered.proxy.network;
import static com.google.common.collect.Iterables.getLast;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_12;
@@ -16,33 +16,41 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINIMUM_VERSION;
import static com.velocitypowered.api.network.ProtocolVersion.SUPPORTED_VERSIONS;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.protocol.packet.AvailableCommandsPacket;
import com.velocitypowered.proxy.protocol.packet.BossBarPacket;
import com.velocitypowered.proxy.protocol.packet.ChatPacket;
import com.velocitypowered.proxy.protocol.packet.ClientSettingsPacket;
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
import com.velocitypowered.proxy.protocol.packet.EncryptionRequestPacket;
import com.velocitypowered.proxy.protocol.packet.EncryptionResponsePacket;
import com.velocitypowered.proxy.protocol.packet.HandshakePacket;
import com.velocitypowered.proxy.protocol.packet.HeaderAndFooterPacket;
import com.velocitypowered.proxy.protocol.packet.JoinGamePacket;
import com.velocitypowered.proxy.protocol.packet.KeepAlivePacket;
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessagePacket;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponsePacket;
import com.velocitypowered.proxy.protocol.packet.PlayerListItemPacket;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.protocol.packet.ResourcePackRequestPacket;
import com.velocitypowered.proxy.protocol.packet.ResourcePackResponsePacket;
import com.velocitypowered.proxy.protocol.packet.RespawnPacket;
import com.velocitypowered.proxy.protocol.packet.ServerLoginPacket;
import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccessPacket;
import com.velocitypowered.proxy.protocol.packet.SetCompressionPacket;
import com.velocitypowered.proxy.protocol.packet.StatusPingPacket;
import com.velocitypowered.proxy.protocol.packet.StatusRequestPacket;
import com.velocitypowered.proxy.protocol.packet.StatusResponsePacket;
import com.velocitypowered.proxy.protocol.packet.TabCompleteRequestPacket;
import com.velocitypowered.proxy.protocol.packet.TabCompleteResponsePacket;
import com.velocitypowered.proxy.protocol.packet.TitlePacket;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketReader;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundAvailableCommandsPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundBossBarPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundChatPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundEncryptionRequestPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundHeaderAndFooterPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundJoinGamePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundKeepAlivePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundLoginPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPlayerListItemPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundResourcePackRequestPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundRespawnPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundServerLoginSuccessPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundSetCompressionPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundStatusPingPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundStatusResponsePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTabCompleteResponsePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTitlePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundChatPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundClientSettingsPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundEncryptionResponsePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundHandshakePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundKeepAlivePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundLoginPluginResponsePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundResourcePackResponsePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundServerLoginPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundStatusPingPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundStatusRequestPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundTabCompleteRequestPacket;
import io.netty.buffer.ByteBuf;
import io.netty.util.collection.IntObjectHashMap;
import io.netty.util.collection.IntObjectMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
@@ -52,133 +60,188 @@ import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
import org.checkerframework.checker.nullness.qual.Nullable;
public enum StateRegistry {
HANDSHAKE {
HANDSHAKE(true) {
{
serverbound.register(HandshakePacket.class, HandshakePacket::new,
map(0x00, MINECRAFT_1_7_2, false));
serverbound.register(
ServerboundHandshakePacket.class,
ServerboundHandshakePacket.DECODER,
map(0x00, MINECRAFT_1_7_2, false)
);
}
},
STATUS {
STATUS(true) {
{
serverbound.register(StatusRequestPacket.class, () -> StatusRequestPacket.INSTANCE,
map(0x00, MINECRAFT_1_7_2, false));
serverbound.register(StatusPingPacket.class, StatusPingPacket::new,
map(0x01, MINECRAFT_1_7_2, false));
serverbound.register(
ServerboundStatusRequestPacket.class,
ServerboundStatusRequestPacket.DECODER,
map(0x00, MINECRAFT_1_7_2, false)
);
serverbound.register(
ServerboundStatusPingPacket.class,
ServerboundStatusPingPacket.DECODER,
map(0x01, MINECRAFT_1_7_2, false)
);
clientbound.register(StatusResponsePacket.class, StatusResponsePacket::new,
map(0x00, MINECRAFT_1_7_2, false));
clientbound.register(StatusPingPacket.class, StatusPingPacket::new,
map(0x01, MINECRAFT_1_7_2, false));
clientbound.register(
ClientboundStatusResponsePacket.class,
ClientboundStatusResponsePacket.DECODER,
map(0x00, MINECRAFT_1_7_2, false)
);
clientbound.register(
ClientboundStatusPingPacket.class,
ClientboundStatusPingPacket.DECODER,
map(0x01, MINECRAFT_1_7_2, false)
);
}
},
PLAY {
PLAY(false) {
{
serverbound.fallback = false;
clientbound.fallback = false;
serverbound.register(TabCompleteRequestPacket.class, TabCompleteRequestPacket::new,
serverbound.register(
ServerboundTabCompleteRequestPacket.class,
ServerboundTabCompleteRequestPacket.DECODER,
map(0x14, MINECRAFT_1_7_2, false),
map(0x01, MINECRAFT_1_9, false),
map(0x02, MINECRAFT_1_12, false),
map(0x01, MINECRAFT_1_12_1, false),
map(0x05, MINECRAFT_1_13, false),
map(0x06, MINECRAFT_1_14, false));
serverbound.register(ChatPacket.class, ChatPacket::new,
map(0x06, MINECRAFT_1_14, false)
);
serverbound.register(
ServerboundChatPacket.class,
ServerboundChatPacket.DECODER,
map(0x01, MINECRAFT_1_7_2, false),
map(0x02, MINECRAFT_1_9, false),
map(0x03, MINECRAFT_1_12, false),
map(0x02, MINECRAFT_1_12_1, false),
map(0x03, MINECRAFT_1_14, false));
serverbound.register(ClientSettingsPacket.class, ClientSettingsPacket::new,
map(0x03, MINECRAFT_1_14, false)
);
serverbound.register(
ServerboundClientSettingsPacket.class,
ServerboundClientSettingsPacket.DECODER,
map(0x15, MINECRAFT_1_7_2, false),
map(0x04, MINECRAFT_1_9, false),
map(0x05, MINECRAFT_1_12, false),
map(0x04, MINECRAFT_1_12_1, false),
map(0x05, MINECRAFT_1_14, false));
serverbound.register(PluginMessagePacket.class, PluginMessagePacket::new,
map(0x05, MINECRAFT_1_14, false)
);
serverbound.register(
ServerboundPluginMessagePacket.class,
ServerboundPluginMessagePacket.DECODER,
map(0x17, MINECRAFT_1_7_2, false),
map(0x09, MINECRAFT_1_9, false),
map(0x0A, MINECRAFT_1_12, false),
map(0x09, MINECRAFT_1_12_1, false),
map(0x0A, MINECRAFT_1_13, false),
map(0x0B, MINECRAFT_1_14, false));
serverbound.register(KeepAlivePacket.class, KeepAlivePacket::new,
map(0x0B, MINECRAFT_1_14, false)
);
serverbound.register(
ServerboundKeepAlivePacket.class,
ServerboundKeepAlivePacket.DECODER,
map(0x00, MINECRAFT_1_7_2, false),
map(0x0B, MINECRAFT_1_9, false),
map(0x0C, MINECRAFT_1_12, false),
map(0x0B, MINECRAFT_1_12_1, false),
map(0x0E, MINECRAFT_1_13, false),
map(0x0F, MINECRAFT_1_14, false),
map(0x10, MINECRAFT_1_16, false));
serverbound.register(ResourcePackResponsePacket.class, ResourcePackResponsePacket::new,
map(0x10, MINECRAFT_1_16, false)
);
serverbound.register(
ServerboundResourcePackResponsePacket.class,
ServerboundResourcePackResponsePacket.DECODER,
map(0x19, MINECRAFT_1_8, false),
map(0x16, MINECRAFT_1_9, false),
map(0x18, MINECRAFT_1_12, false),
map(0x1D, MINECRAFT_1_13, false),
map(0x1F, MINECRAFT_1_14, false),
map(0x20, MINECRAFT_1_16, false),
map(0x21, MINECRAFT_1_16_2, false));
map(0x21, MINECRAFT_1_16_2, false)
);
clientbound.register(BossBarPacket.class, BossBarPacket::new,
clientbound.register(
ClientboundBossBarPacket.class,
ClientboundBossBarPacket.DECODER,
map(0x0C, MINECRAFT_1_9, false),
map(0x0D, MINECRAFT_1_15, false),
map(0x0C, MINECRAFT_1_16, false));
clientbound.register(ChatPacket.class, ChatPacket::new,
map(0x0C, MINECRAFT_1_16, false)
);
clientbound.register(
ClientboundChatPacket.class,
ClientboundChatPacket.DECODER,
map(0x02, MINECRAFT_1_7_2, true),
map(0x0F, MINECRAFT_1_9, true),
map(0x0E, MINECRAFT_1_13, true),
map(0x0F, MINECRAFT_1_15, true),
map(0x0E, MINECRAFT_1_16, true));
clientbound.register(TabCompleteResponsePacket.class, TabCompleteResponsePacket::new,
map(0x0E, MINECRAFT_1_16, true)
);
clientbound.register(
ClientboundTabCompleteResponsePacket.class,
ClientboundTabCompleteResponsePacket.DECODER,
map(0x3A, MINECRAFT_1_7_2, false),
map(0x0E, MINECRAFT_1_9, false),
map(0x10, MINECRAFT_1_13, false),
map(0x11, MINECRAFT_1_15, false),
map(0x10, MINECRAFT_1_16, false),
map(0x0F, MINECRAFT_1_16_2, false));
clientbound.register(AvailableCommandsPacket.class, AvailableCommandsPacket::new,
map(0x0F, MINECRAFT_1_16_2, false)
);
clientbound.register(
ClientboundAvailableCommandsPacket.class,
ClientboundAvailableCommandsPacket.DECODER,
map(0x11, MINECRAFT_1_13, false),
map(0x12, MINECRAFT_1_15, false),
map(0x11, MINECRAFT_1_16, false),
map(0x10, MINECRAFT_1_16_2, false));
clientbound.register(PluginMessagePacket.class, PluginMessagePacket::new,
map(0x10, MINECRAFT_1_16_2, false)
);
clientbound.register(
ClientboundPluginMessagePacket.class,
ClientboundPluginMessagePacket.DECODER,
map(0x3F, MINECRAFT_1_7_2, false),
map(0x18, MINECRAFT_1_9, false),
map(0x19, MINECRAFT_1_13, false),
map(0x18, MINECRAFT_1_14, false),
map(0x19, MINECRAFT_1_15, false),
map(0x18, MINECRAFT_1_16, false),
map(0x17, MINECRAFT_1_16_2, false));
clientbound.register(DisconnectPacket.class, DisconnectPacket::new,
map(0x17, MINECRAFT_1_16_2, false)
);
clientbound.register(
ClientboundDisconnectPacket.class,
ClientboundDisconnectPacket.DECODER,
map(0x40, MINECRAFT_1_7_2, false),
map(0x1A, MINECRAFT_1_9, false),
map(0x1B, MINECRAFT_1_13, false),
map(0x1A, MINECRAFT_1_14, false),
map(0x1B, MINECRAFT_1_15, false),
map(0x1A, MINECRAFT_1_16, false),
map(0x19, MINECRAFT_1_16_2, false));
clientbound.register(KeepAlivePacket.class, KeepAlivePacket::new,
map(0x19, MINECRAFT_1_16_2, false)
);
clientbound.register(
ClientboundKeepAlivePacket.class,
ClientboundKeepAlivePacket.DECODER,
map(0x00, MINECRAFT_1_7_2, false),
map(0x1F, MINECRAFT_1_9, false),
map(0x21, MINECRAFT_1_13, false),
map(0x20, MINECRAFT_1_14, false),
map(0x21, MINECRAFT_1_15, false),
map(0x20, MINECRAFT_1_16, false),
map(0x1F, MINECRAFT_1_16_2, false));
clientbound.register(JoinGamePacket.class, JoinGamePacket::new,
map(0x1F, MINECRAFT_1_16_2, false)
);
clientbound.register(
ClientboundJoinGamePacket.class,
ClientboundJoinGamePacket.DECODER,
map(0x01, MINECRAFT_1_7_2, false),
map(0x23, MINECRAFT_1_9, false),
map(0x25, MINECRAFT_1_13, false),
map(0x25, MINECRAFT_1_14, false),
map(0x26, MINECRAFT_1_15, false),
map(0x25, MINECRAFT_1_16, false),
map(0x24, MINECRAFT_1_16_2, false));
clientbound.register(RespawnPacket.class, RespawnPacket::new,
map(0x24, MINECRAFT_1_16_2, false)
);
clientbound.register(
ClientboundRespawnPacket.class,
ClientboundRespawnPacket.DECODER,
map(0x07, MINECRAFT_1_7_2, true),
map(0x33, MINECRAFT_1_9, true),
map(0x34, MINECRAFT_1_12, true),
@@ -187,8 +250,11 @@ public enum StateRegistry {
map(0x3A, MINECRAFT_1_14, true),
map(0x3B, MINECRAFT_1_15, true),
map(0x3A, MINECRAFT_1_16, true),
map(0x39, MINECRAFT_1_16_2, true));
clientbound.register(ResourcePackRequestPacket.class, ResourcePackRequestPacket::new,
map(0x39, MINECRAFT_1_16_2, true)
);
clientbound.register(
ClientboundResourcePackRequestPacket.class,
ClientboundResourcePackRequestPacket.DECODER,
map(0x48, MINECRAFT_1_8, true),
map(0x32, MINECRAFT_1_9, true),
map(0x33, MINECRAFT_1_12, true),
@@ -197,8 +263,11 @@ public enum StateRegistry {
map(0x39, MINECRAFT_1_14, true),
map(0x3A, MINECRAFT_1_15, true),
map(0x39, MINECRAFT_1_16, true),
map(0x38, MINECRAFT_1_16_2, true));
clientbound.register(HeaderAndFooterPacket.class, HeaderAndFooterPacket::new,
map(0x38, MINECRAFT_1_16_2, true)
);
clientbound.register(
ClientboundHeaderAndFooterPacket.class,
ClientboundHeaderAndFooterPacket.DECODER,
map(0x47, MINECRAFT_1_8, true),
map(0x48, MINECRAFT_1_9, true),
map(0x47, MINECRAFT_1_9_4, true),
@@ -207,8 +276,11 @@ public enum StateRegistry {
map(0x4E, MINECRAFT_1_13, true),
map(0x53, MINECRAFT_1_14, true),
map(0x54, MINECRAFT_1_15, true),
map(0x53, MINECRAFT_1_16, true));
clientbound.register(TitlePacket.class, TitlePacket::new,
map(0x53, MINECRAFT_1_16, true)
);
clientbound.register(
ClientboundTitlePacket.class,
ClientboundTitlePacket.DECODER,
map(0x45, MINECRAFT_1_8, true),
map(0x45, MINECRAFT_1_9, true),
map(0x47, MINECRAFT_1_12, true),
@@ -216,8 +288,11 @@ public enum StateRegistry {
map(0x4B, MINECRAFT_1_13, true),
map(0x4F, MINECRAFT_1_14, true),
map(0x50, MINECRAFT_1_15, true),
map(0x4F, MINECRAFT_1_16, true));
clientbound.register(PlayerListItemPacket.class, PlayerListItemPacket::new,
map(0x4F, MINECRAFT_1_16, true)
);
clientbound.register(
ClientboundPlayerListItemPacket.class,
ClientboundPlayerListItemPacket.DECODER,
map(0x38, MINECRAFT_1_7_2, false),
map(0x2D, MINECRAFT_1_9, false),
map(0x2E, MINECRAFT_1_12_1, false),
@@ -225,49 +300,85 @@ public enum StateRegistry {
map(0x33, MINECRAFT_1_14, false),
map(0x34, MINECRAFT_1_15, false),
map(0x33, MINECRAFT_1_16, false),
map(0x32, MINECRAFT_1_16_2, false));
map(0x32, MINECRAFT_1_16_2, false)
);
}
},
LOGIN {
LOGIN(true) {
{
serverbound.register(ServerLoginPacket.class, ServerLoginPacket::new,
map(0x00, MINECRAFT_1_7_2, false));
serverbound.register(EncryptionResponsePacket.class, EncryptionResponsePacket::new,
map(0x01, MINECRAFT_1_7_2, false));
serverbound.register(LoginPluginResponsePacket.class, LoginPluginResponsePacket::new,
map(0x02, MINECRAFT_1_13, false));
clientbound.register(DisconnectPacket.class, DisconnectPacket::new,
map(0x00, MINECRAFT_1_7_2, false));
clientbound.register(EncryptionRequestPacket.class, EncryptionRequestPacket::new,
map(0x01, MINECRAFT_1_7_2, false));
clientbound.register(ServerLoginSuccessPacket.class, ServerLoginSuccessPacket::new,
map(0x02, MINECRAFT_1_7_2, false));
clientbound.register(SetCompressionPacket.class, SetCompressionPacket::new,
map(0x03, MINECRAFT_1_8, false));
clientbound.register(LoginPluginMessagePacket.class, LoginPluginMessagePacket::new,
map(0x04, MINECRAFT_1_13, false));
serverbound.register(
ServerboundServerLoginPacket.class,
ServerboundServerLoginPacket.DECODER,
map(0x00, MINECRAFT_1_7_2, false)
);
serverbound.register(
ServerboundEncryptionResponsePacket.class,
ServerboundEncryptionResponsePacket.DECODER,
map(0x01, MINECRAFT_1_7_2, false)
);
serverbound.register(
ServerboundLoginPluginResponsePacket.class,
ServerboundLoginPluginResponsePacket.DECODER,
map(0x02, MINECRAFT_1_13, false)
);
clientbound.register(
ClientboundDisconnectPacket.class,
ClientboundDisconnectPacket.DECODER,
map(0x00, MINECRAFT_1_7_2, false)
);
clientbound.register(
ClientboundEncryptionRequestPacket.class,
ClientboundEncryptionRequestPacket.DECODER,
map(0x01, MINECRAFT_1_7_2, false)
);
clientbound.register(
ClientboundServerLoginSuccessPacket.class,
ClientboundServerLoginSuccessPacket.DECODER,
map(0x02, MINECRAFT_1_7_2, false)
);
clientbound.register(
ClientboundSetCompressionPacket.class,
ClientboundSetCompressionPacket.DECODER,
map(0x03, MINECRAFT_1_8, false)
);
clientbound.register(
ClientboundLoginPluginMessagePacket.class,
ClientboundLoginPluginMessagePacket.DECODER,
map(0x04, MINECRAFT_1_13, false)
);
}
};
public static final int STATUS_ID = 1;
public static final int LOGIN_ID = 2;
public final PacketRegistry clientbound = new PacketRegistry(ProtocolDirection.CLIENTBOUND);
public final PacketRegistry serverbound = new PacketRegistry(ProtocolDirection.SERVERBOUND);
public final PacketRegistry clientbound;
public final PacketRegistry serverbound;
public PacketRegistry.ProtocolRegistry getProtocolRegistry(ProtocolDirection direction,
ProtocolVersion version) {
return (direction == ProtocolDirection.SERVERBOUND ? this.serverbound : this.clientbound)
StateRegistry(boolean useMinimumIfVersionNotFound) {
this.clientbound = new PacketRegistry(PacketDirection.CLIENTBOUND, useMinimumIfVersionNotFound);
this.serverbound = new PacketRegistry(PacketDirection.SERVERBOUND, useMinimumIfVersionNotFound);
}
public PacketRegistry.ProtocolRegistry getProtocolRegistry(PacketDirection direction,
ProtocolVersion version) {
return (direction == PacketDirection.SERVERBOUND ? this.serverbound : this.clientbound)
.getProtocolRegistry(version);
}
public static class PacketRegistry {
private final ProtocolDirection direction;
private final PacketDirection direction;
private final Map<ProtocolVersion, ProtocolRegistry> versions;
private boolean fallback = true;
private final boolean useMinimumIfVersionNotFound;
PacketRegistry(ProtocolDirection direction) {
PacketRegistry(PacketDirection direction) {
this(direction, true);
}
PacketRegistry(PacketDirection direction, boolean useMinimumIfVersionNotFound) {
this.direction = direction;
this.useMinimumIfVersionNotFound = useMinimumIfVersionNotFound;
Map<ProtocolVersion, ProtocolRegistry> mutableVersions = new EnumMap<>(ProtocolVersion.class);
for (ProtocolVersion version : ProtocolVersion.values()) {
@@ -282,7 +393,7 @@ public enum StateRegistry {
ProtocolRegistry getProtocolRegistry(final ProtocolVersion version) {
ProtocolRegistry registry = versions.get(version);
if (registry == null) {
if (fallback) {
if (useMinimumIfVersionNotFound) {
return getProtocolRegistry(MINIMUM_VERSION);
}
throw new IllegalArgumentException("Could not find data for protocol version " + version);
@@ -290,7 +401,7 @@ public enum StateRegistry {
return registry;
}
<P extends Packet> void register(Class<P> clazz, Supplier<P> packetSupplier,
<P extends Packet> void register(Class<P> clazz, PacketReader<P> decoder,
PacketMapping... mappings) {
if (mappings.length == 0) {
throw new IllegalArgumentException("At least one mapping must be provided.");
@@ -317,7 +428,7 @@ public enum StateRegistry {
+ current.protocolVersion);
}
if (registry.packetIdToSupplier.containsKey(current.id)) {
if (registry.packetIdToReader.containsKey(current.id)) {
throw new IllegalArgumentException("Can not register class " + clazz.getSimpleName()
+ " with id " + current.id + " for " + registry.version
+ " because another packet is already registered");
@@ -329,7 +440,7 @@ public enum StateRegistry {
}
if (!current.encodeOnly) {
registry.packetIdToSupplier.put(current.id, packetSupplier);
registry.packetIdToReader.put(current.id, decoder);
}
registry.packetClassToId.put(clazz, current.id);
}
@@ -339,7 +450,7 @@ public enum StateRegistry {
public class ProtocolRegistry {
public final ProtocolVersion version;
final IntObjectMap<Supplier<? extends Packet>> packetIdToSupplier =
final IntObjectMap<PacketReader<? extends Packet>> packetIdToReader =
new IntObjectHashMap<>(16, 0.5f);
final Object2IntMap<Class<? extends Packet>> packetClassToId =
new Object2IntOpenHashMap<>(16, 0.5f);
@@ -353,14 +464,18 @@ public enum StateRegistry {
* Attempts to create a packet from the specified {@code id}.
*
* @param id the packet ID
* @param buf the bytebuf
* @param direction the packet direction
* @param version the protocol version
* @return the packet instance, or {@code null} if the ID is not registered
*/
public @Nullable Packet createPacket(final int id) {
final Supplier<? extends Packet> supplier = this.packetIdToSupplier.get(id);
if (supplier == null) {
public @Nullable Packet readPacket(final int id, ByteBuf buf, PacketDirection direction,
ProtocolVersion version) {
final PacketReader<? extends Packet> decoder = this.packetIdToReader.get(id);
if (decoder == null) {
return null;
}
return supplier.get();
return decoder.read(buf, direction, version);
}
/**
@@ -385,9 +500,9 @@ public enum StateRegistry {
public static final class PacketMapping {
private final int id;
private final ProtocolVersion protocolVersion;
private final boolean encodeOnly;
final int id;
final ProtocolVersion protocolVersion;
final boolean encodeOnly;
PacketMapping(int id, ProtocolVersion protocolVersion, boolean packetDecoding) {
this.id = id;

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol.util;
package com.velocitypowered.proxy.network.buffer;
import com.google.common.io.ByteArrayDataInput;
import io.netty.buffer.ByteBuf;

View File

@@ -1,9 +1,8 @@
package com.velocitypowered.proxy.protocol.util;
package com.velocitypowered.proxy.network.buffer;
import com.google.common.io.ByteArrayDataOutput;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;

View File

@@ -0,0 +1,37 @@
package com.velocitypowered.proxy.network.buffer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.DefaultByteBufHolder;
public abstract class TypedDefaultByteBufHolder<S extends TypedDefaultByteBufHolder<S>> extends DefaultByteBufHolder {
protected TypedDefaultByteBufHolder(final ByteBuf data) {
super(data);
}
@Override
public abstract S replace(final ByteBuf content);
@Override
@SuppressWarnings("unchecked")
public S retain() {
return (S) super.retain();
}
@Override
@SuppressWarnings("unchecked")
public S retain(final int increment) {
return (S) super.retain(increment);
}
@Override
@SuppressWarnings("unchecked")
public S touch() {
return (S) super.touch();
}
@Override
@SuppressWarnings("unchecked")
public S touch(final Object hint) {
return (S) super.touch(hint);
}
}

View File

@@ -0,0 +1,51 @@
package com.velocitypowered.proxy.network.packet;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import io.netty.buffer.ByteBuf;
import java.util.function.LongFunction;
public abstract class AbstractKeepAlivePacket implements Packet {
protected static <P extends AbstractKeepAlivePacket> PacketReader<P> decoder(final LongFunction<P> factory) {
return (buf, direction, version) -> {
final long randomId;
if (version.gte(ProtocolVersion.MINECRAFT_1_12_2)) {
randomId = buf.readLong();
} else if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
randomId = ProtocolUtils.readVarInt(buf);
} else {
randomId = buf.readInt();
}
return factory.apply(randomId);
};
}
private final long randomId;
protected AbstractKeepAlivePacket(final long randomId) {
this.randomId = randomId;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (version.gte(ProtocolVersion.MINECRAFT_1_12_2)) {
buf.writeLong(randomId);
} else if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
ProtocolUtils.writeVarInt(buf, (int) randomId);
} else {
buf.writeInt((int) randomId);
}
}
public long getRandomId() {
return randomId;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("randomId", this.randomId)
.toString();
}
}

View File

@@ -0,0 +1,92 @@
package com.velocitypowered.proxy.network.packet;
import static com.velocitypowered.proxy.network.PluginMessageUtil.transformLegacyToModernChannel;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.buffer.TypedDefaultByteBufHolder;
import io.netty.buffer.ByteBuf;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class AbstractPluginMessagePacket<S extends AbstractPluginMessagePacket<S>> extends TypedDefaultByteBufHolder<S> implements Packet {
protected static <P extends AbstractPluginMessagePacket<P>> PacketReader<P> decoder(final Factory<P> factory) {
return (buf, direction, version) -> {
String channel = ProtocolUtils.readString(buf);
if (version.gte(ProtocolVersion.MINECRAFT_1_13)) {
channel = transformLegacyToModernChannel(channel);
}
final ByteBuf data;
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
data = buf.readRetainedSlice(buf.readableBytes());
} else {
data = ProtocolUtils.readRetainedByteBufSlice17(buf);
}
return factory.create(channel, data);
};
}
protected final @Nullable String channel;
protected AbstractPluginMessagePacket(String channel,
@MonotonicNonNull ByteBuf backing) {
super(backing);
this.channel = channel;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (channel == null) {
throw new IllegalStateException("Channel is not specified.");
}
if (version.gte(ProtocolVersion.MINECRAFT_1_13)) {
ProtocolUtils.writeString(buf, transformLegacyToModernChannel(this.channel));
} else {
ProtocolUtils.writeString(buf, this.channel);
}
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
buf.writeBytes(content());
} else {
ProtocolUtils.writeByteBuf17(content(), buf, true); // True for Forge support
}
}
public String getChannel() {
if (channel == null) {
throw new IllegalStateException("Channel is not specified.");
}
return channel;
}
@Override
public boolean equals(final Object other) {
if (this == other) {
return true;
}
if (other == null || this.getClass() != other.getClass()) {
return false;
}
final AbstractPluginMessagePacket<?> that = (AbstractPluginMessagePacket<?>) other;
return Objects.equals(this.channel, that.channel)
&& super.equals(other);
}
@Override
public int hashCode() {
return Objects.hash(this.channel, super.hashCode());
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("channel", this.channel)
.add("data", this.contentToString())
.toString();
}
public interface Factory<P extends AbstractPluginMessagePacket<P>> {
P create(final String channel, final ByteBuf data);
}
}

View File

@@ -0,0 +1,33 @@
package com.velocitypowered.proxy.network.packet;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import java.util.function.LongFunction;
public abstract class AbstractStatusPingPacket implements Packet {
protected static <P extends AbstractStatusPingPacket> PacketReader<P> decoder(final LongFunction<P> factory) {
return (buf, direction, version) -> {
final long randomId = buf.readLong();
return factory.apply(randomId);
};
}
private final long randomId;
protected AbstractStatusPingPacket(final long randomId) {
this.randomId = randomId;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
buf.writeLong(this.randomId);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("randomId", this.randomId)
.toString();
}
}

View File

@@ -0,0 +1,18 @@
package com.velocitypowered.proxy.network.packet;
import com.velocitypowered.api.network.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import java.util.function.Supplier;
public interface Packet {
@Deprecated
default void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion protocolVersion) {
throw new UnsupportedOperationException();
}
void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion protocolVersion);
boolean handle(PacketHandler handler);
}

View File

@@ -0,0 +1,6 @@
package com.velocitypowered.proxy.network.packet;
public enum PacketDirection {
SERVERBOUND,
CLIENTBOUND;
}

View File

@@ -0,0 +1,181 @@
package com.velocitypowered.proxy.network.packet;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundAvailableCommandsPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundBossBarPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundChatPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundEncryptionRequestPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundHeaderAndFooterPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundJoinGamePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundKeepAlivePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundLoginPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPlayerListItemPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundResourcePackRequestPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundRespawnPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundServerLoginSuccessPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundSetCompressionPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundStatusPingPacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundStatusResponsePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTabCompleteResponsePacket;
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundTitlePacket;
import com.velocitypowered.proxy.network.packet.legacy.LegacyHandshakePacket;
import com.velocitypowered.proxy.network.packet.legacy.LegacyPingPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundChatPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundClientSettingsPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundEncryptionResponsePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundHandshakePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundKeepAlivePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundLoginPluginResponsePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundResourcePackResponsePacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundServerLoginPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundStatusPingPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundStatusRequestPacket;
import com.velocitypowered.proxy.network.packet.serverbound.ServerboundTabCompleteRequestPacket;
public interface PacketHandler {
/*
* Clientbound
*/
default boolean handle(ClientboundAvailableCommandsPacket commands) {
return false;
}
default boolean handle(ClientboundBossBarPacket packet) {
return false;
}
default boolean handle(ClientboundChatPacket packet) {
return false;
}
default boolean handle(ClientboundDisconnectPacket packet) {
return false;
}
default boolean handle(ClientboundEncryptionRequestPacket packet) {
return false;
}
default boolean handle(ClientboundHeaderAndFooterPacket packet) {
return false;
}
default boolean handle(ClientboundJoinGamePacket packet) {
return false;
}
default boolean handle(ClientboundKeepAlivePacket packet) {
return false;
}
default boolean handle(ClientboundLoginPluginMessagePacket packet) {
return false;
}
default boolean handle(ClientboundPlayerListItemPacket packet) {
return false;
}
default boolean handle(ClientboundPluginMessagePacket packet) {
return false;
}
default boolean handle(ClientboundResourcePackRequestPacket packet) {
return false;
}
default boolean handle(ClientboundRespawnPacket packet) {
return false;
}
default boolean handle(ClientboundServerLoginSuccessPacket packet) {
return false;
}
default boolean handle(ClientboundSetCompressionPacket packet) {
return false;
}
default boolean handle(ClientboundStatusPingPacket packet) {
return false;
}
default boolean handle(ClientboundStatusResponsePacket packet) {
return false;
}
default boolean handle(ClientboundTabCompleteResponsePacket packet) {
return false;
}
default boolean handle(ClientboundTitlePacket packet) {
return false;
}
/*
* Serverbound
*/
default boolean handle(ServerboundChatPacket packet) {
return false;
}
default boolean handle(ServerboundClientSettingsPacket packet) {
return false;
}
default boolean handle(ServerboundEncryptionResponsePacket packet) {
return false;
}
default boolean handle(ServerboundHandshakePacket packet) {
return false;
}
default boolean handle(ServerboundKeepAlivePacket packet) {
return false;
}
default boolean handle(ServerboundLoginPluginResponsePacket packet) {
return false;
}
default boolean handle(ServerboundPluginMessagePacket packet) {
return false;
}
default boolean handle(ServerboundResourcePackResponsePacket packet) {
return false;
}
default boolean handle(ServerboundServerLoginPacket packet) {
return false;
}
default boolean handle(ServerboundStatusPingPacket packet) {
return false;
}
default boolean handle(ServerboundStatusRequestPacket packet) {
return false;
}
default boolean handle(ServerboundTabCompleteRequestPacket packet) {
return false;
}
/*
* Legacy
*/
default boolean handle(LegacyHandshakePacket packet) {
return false;
}
default boolean handle(LegacyPingPacket packet) {
return false;
}
}

View File

@@ -0,0 +1,28 @@
package com.velocitypowered.proxy.network.packet;
import com.velocitypowered.api.network.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import java.util.function.Supplier;
public interface PacketReader<P extends Packet> {
P read(final ByteBuf buf, final PacketDirection direction, final ProtocolVersion version);
static <P extends Packet> PacketReader<P> unsupported() {
return (buf, direction, version) -> {
throw new UnsupportedOperationException();
};
}
static <P extends Packet> PacketReader<P> instance(final P packet) {
return (buf, direction, version) -> packet;
}
@Deprecated
static <P extends Packet> PacketReader<P> method(final Supplier<P> factory) {
return (buf, direction, version) -> {
final P packet = factory.get();
packet.decode(buf, direction, version);
return packet;
};
}
}

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol.packet;
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
@@ -18,11 +18,12 @@ import com.mojang.brigadier.tree.LiteralCommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentPropertyRegistry;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import com.velocitypowered.proxy.network.serialization.brigadier.ArgumentPropertyRegistry;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
@@ -35,7 +36,9 @@ import java.util.concurrent.CompletableFuture;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
public class AvailableCommandsPacket implements Packet {
public class ClientboundAvailableCommandsPacket implements Packet {
public static final PacketReader<ClientboundAvailableCommandsPacket> DECODER = PacketReader.method(ClientboundAvailableCommandsPacket::new);
private static final Command<CommandSource> PLACEHOLDER_COMMAND = source -> 0;
private static final byte NODE_TYPE_ROOT = 0x00;
@@ -61,7 +64,7 @@ public class AvailableCommandsPacket implements Packet {
}
@Override
public void decode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion protocolVersion) {
public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion protocolVersion) {
int commands = ProtocolUtils.readVarInt(buf);
WireNode[] wireNodes = new WireNode[commands];
for (int i = 0; i < commands; i++) {
@@ -93,7 +96,7 @@ public class AvailableCommandsPacket implements Packet {
}
@Override
public void encode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion protocolVersion) {
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion protocolVersion) {
// Assign all the children an index.
Deque<CommandNode<CommandSource>> childrenQueue = new ArrayDeque<>(ImmutableList.of(rootNode));
Object2IntMap<CommandNode<CommandSource>> idMappings = new Object2IntLinkedOpenHashMap<>();
@@ -163,7 +166,7 @@ public class AvailableCommandsPacket implements Packet {
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}

View File

@@ -1,15 +1,19 @@
package com.velocitypowered.proxy.protocol.packet;
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
public class BossBarPacket implements Packet {
public class ClientboundBossBarPacket implements Packet {
public static final PacketReader<ClientboundBossBarPacket> DECODER = PacketReader.method(ClientboundBossBarPacket::new);
public static final int ADD = 0;
public static final int REMOVE = 1;
@@ -86,20 +90,7 @@ public class BossBarPacket implements Packet {
}
@Override
public String toString() {
return "BossBar{"
+ "uuid=" + uuid
+ ", action=" + action
+ ", name='" + name + '\''
+ ", percent=" + percent
+ ", color=" + color
+ ", overlay=" + overlay
+ ", flags=" + flags
+ '}';
}
@Override
public void decode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
this.uuid = ProtocolUtils.readUuid(buf);
this.action = ProtocolUtils.readVarInt(buf);
switch (action) {
@@ -131,7 +122,7 @@ public class BossBarPacket implements Packet {
}
@Override
public void encode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (uuid == null) {
throw new IllegalStateException("No boss bar UUID specified");
}
@@ -172,14 +163,27 @@ public class BossBarPacket implements Packet {
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public static BossBarPacket createRemovePacket(UUID id) {
BossBarPacket packet = new BossBarPacket();
public static ClientboundBossBarPacket createRemovePacket(UUID id) {
ClientboundBossBarPacket packet = new ClientboundBossBarPacket();
packet.setUuid(id);
packet.setAction(REMOVE);
return packet;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("uuid", this.uuid)
.add("action", this.action)
.add("name", this.name)
.add("percent", this.percent)
.add("color", this.color)
.add("overlay", this.overlay)
.add("flags", this.flags)
.toString();
}
}

View File

@@ -0,0 +1,87 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ClientboundChatPacket implements Packet {
public static final PacketReader<ClientboundChatPacket> DECODER = PacketReader.method(ClientboundChatPacket::new);
public static final byte CHAT_TYPE = (byte) 0;
public static final byte SYSTEM_TYPE = (byte) 1;
public static final byte GAME_INFO_TYPE = (byte) 2;
private @Nullable String message;
private byte type;
private @Nullable UUID sender;
private ClientboundChatPacket() {
}
public ClientboundChatPacket(String message, byte type, UUID sender) {
this.message = message;
this.type = type;
this.sender = sender;
}
@Override
public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
message = ProtocolUtils.readString(buf);
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
type = buf.readByte();
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
sender = ProtocolUtils.readUuid(buf);
}
}
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (message == null) {
throw new IllegalStateException("Message is not specified");
}
ProtocolUtils.writeString(buf, message);
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
buf.writeByte(type);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
ProtocolUtils.writeUuid(buf, sender);
}
}
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public String getMessage() {
if (message == null) {
throw new IllegalStateException("Message is not specified");
}
return message;
}
public byte getType() {
return type;
}
public UUID getSenderUuid() {
return sender;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("message", this.message)
.add("type", this.type)
.add("sender", this.sender)
.toString();
}
}

View File

@@ -0,0 +1,67 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ClientboundDisconnectPacket implements Packet {
public static final PacketReader<ClientboundDisconnectPacket> DECODER = PacketReader.method(ClientboundDisconnectPacket::new);
private @Nullable String reason;
public ClientboundDisconnectPacket() {
}
public ClientboundDisconnectPacket(String reason) {
this.reason = Preconditions.checkNotNull(reason, "reason");
}
public String getReason() {
if (reason == null) {
throw new IllegalStateException("No reason specified");
}
return reason;
}
public void setReason(@Nullable String reason) {
this.reason = reason;
}
@Override
public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
reason = ProtocolUtils.readString(buf);
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (reason == null) {
throw new IllegalStateException("No reason specified.");
}
ProtocolUtils.writeString(buf, reason);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public static ClientboundDisconnectPacket create(Component component, ProtocolVersion version) {
Preconditions.checkNotNull(component, "component");
return new ClientboundDisconnectPacket(ProtocolUtils.getJsonChatSerializer(version).serialize(component));
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("reason", this.reason)
.toString();
}
}

View File

@@ -1,16 +1,18 @@
package com.velocitypowered.proxy.protocol.packet;
package com.velocitypowered.proxy.network.packet.clientbound;
import static com.velocitypowered.proxy.connection.VelocityConstants.EMPTY_BYTE_ARRAY;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import java.util.Arrays;
public class EncryptionRequestPacket implements Packet {
public class ClientboundEncryptionRequestPacket implements Packet {
public static final PacketReader<ClientboundEncryptionRequestPacket> DECODER = PacketReader.method(ClientboundEncryptionRequestPacket::new);
private String serverId = "";
private byte[] publicKey = EMPTY_BYTE_ARRAY;
@@ -33,18 +35,10 @@ public class EncryptionRequestPacket implements Packet {
}
@Override
public String toString() {
return "EncryptionRequest{"
+ "publicKey=" + Arrays.toString(publicKey)
+ ", verifyToken=" + Arrays.toString(verifyToken)
+ '}';
}
@Override
public void decode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
this.serverId = ProtocolUtils.readString(buf, 20);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
publicKey = ProtocolUtils.readByteArray(buf, 256);
verifyToken = ProtocolUtils.readByteArray(buf, 16);
} else {
@@ -54,10 +48,10 @@ public class EncryptionRequestPacket implements Packet {
}
@Override
public void encode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
ProtocolUtils.writeString(buf, this.serverId);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
ProtocolUtils.writeByteArray(buf, publicKey);
ProtocolUtils.writeByteArray(buf, verifyToken);
} else {
@@ -67,7 +61,16 @@ public class EncryptionRequestPacket implements Packet {
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("serverId", this.serverId)
.add("publicKey", this.publicKey)
.add("verifyToken", this.verifyToken)
.toString();
}
}

View File

@@ -0,0 +1,63 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import static com.velocitypowered.proxy.network.ProtocolUtils.writeString;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
public class ClientboundHeaderAndFooterPacket implements Packet {
public static final PacketReader<ClientboundHeaderAndFooterPacket> DECODER = PacketReader.method(ClientboundHeaderAndFooterPacket::new);
private static final String EMPTY_COMPONENT = "{\"translate\":\"\"}";
private static final ClientboundHeaderAndFooterPacket RESET
= new ClientboundHeaderAndFooterPacket();
private final String header;
private final String footer;
public ClientboundHeaderAndFooterPacket() {
this(EMPTY_COMPONENT, EMPTY_COMPONENT);
}
public ClientboundHeaderAndFooterPacket(String header, String footer) {
this.header = Preconditions.checkNotNull(header, "header");
this.footer = Preconditions.checkNotNull(footer, "footer");
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
writeString(buf, header);
writeString(buf, footer);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public String getHeader() {
return header;
}
public String getFooter() {
return footer;
}
public static ClientboundHeaderAndFooterPacket reset() {
return RESET;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("header", this.header)
.add("footer", this.footer)
.toString();
}
}

View File

@@ -1,21 +1,24 @@
package com.velocitypowered.proxy.protocol.packet;
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableSet;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.registry.DimensionData;
import com.velocitypowered.proxy.connection.registry.DimensionInfo;
import com.velocitypowered.proxy.connection.registry.DimensionRegistry;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import net.kyori.adventure.nbt.BinaryTagTypes;
import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.nbt.ListBinaryTag;
import org.checkerframework.checker.nullness.qual.Nullable;
public class JoinGamePacket implements Packet {
public class ClientboundJoinGamePacket implements Packet {
public static final PacketReader<ClientboundJoinGamePacket> DECODER = PacketReader.method(ClientboundJoinGamePacket::new);
private int entityId;
private short gamemode;
@@ -34,140 +37,18 @@ public class JoinGamePacket implements Packet {
private short previousGamemode; // 1.16+
private CompoundBinaryTag biomeRegistry; // 1.16.2+
public int getEntityId() {
return entityId;
}
public void setEntityId(int entityId) {
this.entityId = entityId;
}
public short getGamemode() {
return gamemode;
}
public void setGamemode(short gamemode) {
this.gamemode = gamemode;
}
public int getDimension() {
return dimension;
public void withDimension(int dimension) {
this.dimension = dimension;
}
public void setDimension(int dimension) {
this.dimension = dimension;
}
public long getPartialHashedSeed() {
return partialHashedSeed;
}
public short getDifficulty() {
return difficulty;
}
public void setDifficulty(short difficulty) {
this.difficulty = difficulty;
}
public int getMaxPlayers() {
return maxPlayers;
}
public void setMaxPlayers(int maxPlayers) {
this.maxPlayers = maxPlayers;
}
public @Nullable String getLevelType() {
return levelType;
}
public void setLevelType(String levelType) {
this.levelType = levelType;
}
public int getViewDistance() {
return viewDistance;
}
public void setViewDistance(int viewDistance) {
this.viewDistance = viewDistance;
}
public boolean isReducedDebugInfo() {
return reducedDebugInfo;
}
public void setReducedDebugInfo(boolean reducedDebugInfo) {
this.reducedDebugInfo = reducedDebugInfo;
}
public DimensionInfo getDimensionInfo() {
return dimensionInfo;
}
public void setDimensionInfo(DimensionInfo dimensionInfo) {
this.dimensionInfo = dimensionInfo;
}
public DimensionRegistry getDimensionRegistry() {
return dimensionRegistry;
}
public void setDimensionRegistry(DimensionRegistry dimensionRegistry) {
this.dimensionRegistry = dimensionRegistry;
}
public short getPreviousGamemode() {
return previousGamemode;
}
public void setPreviousGamemode(short previousGamemode) {
this.previousGamemode = previousGamemode;
}
public boolean getIsHardcore() {
return isHardcore;
}
public void setIsHardcore(boolean isHardcore) {
this.isHardcore = isHardcore;
}
public CompoundBinaryTag getBiomeRegistry() {
return biomeRegistry;
}
public void setBiomeRegistry(CompoundBinaryTag biomeRegistry) {
this.biomeRegistry = biomeRegistry;
}
public DimensionData getCurrentDimensionData() {
return currentDimensionData;
}
@Override
public String toString() {
return "JoinGame{"
+ "entityId=" + entityId
+ ", gamemode=" + gamemode
+ ", dimension=" + dimension
+ ", partialHashedSeed=" + partialHashedSeed
+ ", difficulty=" + difficulty
+ ", maxPlayers=" + maxPlayers
+ ", levelType='" + levelType + '\''
+ ", viewDistance=" + viewDistance
+ ", reducedDebugInfo=" + reducedDebugInfo
+ ", dimensionRegistry='" + dimensionRegistry + '\''
+ ", dimensionInfo='" + dimensionInfo + '\''
+ ", previousGamemode=" + previousGamemode
+ '}';
}
@Override
public void decode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
this.entityId = buf.readInt();
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
this.isHardcore = buf.readBoolean();
this.gamemode = buf.readByte();
} else {
@@ -177,12 +58,12 @@ public class JoinGamePacket implements Packet {
}
String dimensionIdentifier = null;
String levelName = null;
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
this.previousGamemode = buf.readByte();
ImmutableSet<String> levelNames = ImmutableSet.copyOf(ProtocolUtils.readStringArray(buf));
CompoundBinaryTag registryContainer = ProtocolUtils.readCompoundTag(buf);
ListBinaryTag dimensionRegistryContainer = null;
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
dimensionRegistryContainer = registryContainer.getCompound("minecraft:dimension_type")
.getList("value", BinaryTagTypes.COMPOUND);
this.biomeRegistry = registryContainer.getCompound("minecraft:worldgen/biome");
@@ -193,7 +74,7 @@ public class JoinGamePacket implements Packet {
ImmutableSet<DimensionData> readData =
DimensionRegistry.fromGameData(dimensionRegistryContainer, version);
this.dimensionRegistry = new DimensionRegistry(readData, levelNames);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
CompoundBinaryTag currentDimDataTag = ProtocolUtils.readCompoundTag(buf);
dimensionIdentifier = ProtocolUtils.readString(buf);
this.currentDimensionData = DimensionData.decodeBaseCompoundTag(currentDimDataTag, version)
@@ -202,35 +83,35 @@ public class JoinGamePacket implements Packet {
dimensionIdentifier = ProtocolUtils.readString(buf);
levelName = ProtocolUtils.readString(buf);
}
} else if (version.compareTo(ProtocolVersion.MINECRAFT_1_9_1) >= 0) {
} else if (version.gte(ProtocolVersion.MINECRAFT_1_9_1)) {
this.dimension = buf.readInt();
} else {
this.dimension = buf.readByte();
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) {
if (version.lte(ProtocolVersion.MINECRAFT_1_13_2)) {
this.difficulty = buf.readUnsignedByte();
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_15)) {
this.partialHashedSeed = buf.readLong();
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
this.maxPlayers = ProtocolUtils.readVarInt(buf);
} else {
this.maxPlayers = buf.readUnsignedByte();
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) < 0) {
if (version.lt(ProtocolVersion.MINECRAFT_1_16)) {
this.levelType = ProtocolUtils.readString(buf, 16);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_14) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_14)) {
this.viewDistance = ProtocolUtils.readVarInt(buf);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
this.reducedDebugInfo = buf.readBoolean();
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_15)) {
this.showRespawnScreen = buf.readBoolean();
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
boolean isDebug = buf.readBoolean();
boolean isFlat = buf.readBoolean();
this.dimensionInfo = new DimensionInfo(dimensionIdentifier, levelName, isFlat, isDebug);
@@ -238,20 +119,20 @@ public class JoinGamePacket implements Packet {
}
@Override
public void encode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
buf.writeInt(entityId);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
buf.writeBoolean(isHardcore);
buf.writeByte(gamemode);
} else {
buf.writeByte(isHardcore ? gamemode | 0x8 : gamemode);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
buf.writeByte(previousGamemode);
ProtocolUtils.writeStringArray(buf, dimensionRegistry.getLevelNames().toArray(new String[0]));
CompoundBinaryTag.Builder registryContainer = CompoundBinaryTag.builder();
ListBinaryTag encodedDimensionRegistry = dimensionRegistry.encodeRegistry(version);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
CompoundBinaryTag.Builder dimensionRegistryEntry = CompoundBinaryTag.builder();
dimensionRegistryEntry.putString("type", "minecraft:dimension_type");
dimensionRegistryEntry.put("value", encodedDimensionRegistry);
@@ -261,52 +142,134 @@ public class JoinGamePacket implements Packet {
registryContainer.put("dimension", encodedDimensionRegistry);
}
ProtocolUtils.writeCompoundTag(buf, registryContainer.build());
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
ProtocolUtils.writeCompoundTag(buf, currentDimensionData.serializeDimensionDetails());
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
} else {
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
ProtocolUtils.writeString(buf, dimensionInfo.getLevelName());
}
} else if (version.compareTo(ProtocolVersion.MINECRAFT_1_9_1) >= 0) {
} else if (version.gte(ProtocolVersion.MINECRAFT_1_9_1)) {
buf.writeInt(dimension);
} else {
buf.writeByte(dimension);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) {
if (version.lte(ProtocolVersion.MINECRAFT_1_13_2)) {
buf.writeByte(difficulty);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_15)) {
buf.writeLong(partialHashedSeed);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
ProtocolUtils.writeVarInt(buf, maxPlayers);
} else {
buf.writeByte(maxPlayers);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) < 0) {
if (version.lt(ProtocolVersion.MINECRAFT_1_16)) {
if (levelType == null) {
throw new IllegalStateException("No level type specified.");
}
ProtocolUtils.writeString(buf, levelType);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_14) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_14)) {
ProtocolUtils.writeVarInt(buf, viewDistance);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
buf.writeBoolean(reducedDebugInfo);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_15)) {
buf.writeBoolean(showRespawnScreen);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
buf.writeBoolean(dimensionInfo.isDebugType());
buf.writeBoolean(dimensionInfo.isFlat());
}
}
public int getEntityId() {
return entityId;
}
public short getGamemode() {
return gamemode;
}
public int getDimension() {
return dimension;
}
public long getPartialHashedSeed() {
return partialHashedSeed;
}
public short getDifficulty() {
return difficulty;
}
public int getMaxPlayers() {
return maxPlayers;
}
public @Nullable String getLevelType() {
return levelType;
}
public int getViewDistance() {
return viewDistance;
}
public boolean isReducedDebugInfo() {
return reducedDebugInfo;
}
public DimensionInfo getDimensionInfo() {
return dimensionInfo;
}
public DimensionRegistry getDimensionRegistry() {
return dimensionRegistry;
}
public short getPreviousGamemode() {
return previousGamemode;
}
public boolean getIsHardcore() {
return isHardcore;
}
public CompoundBinaryTag getBiomeRegistry() {
return biomeRegistry;
}
public DimensionData getCurrentDimensionData() {
return currentDimensionData;
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("entityId", this.entityId)
.add("gamemode", this.gamemode)
.add("dimension", this.dimension)
.add("partialHashedSeed", this.partialHashedSeed)
.add("difficulty", this.difficulty)
.add("isHardcore", this.isHardcore)
.add("maxPlayers", this.maxPlayers)
.add("levelType", this.levelType)
.add("viewDistance", this.viewDistance)
.add("reducedDebugInfo", this.reducedDebugInfo)
.add("showRespawnScreen", this.showRespawnScreen)
.add("dimensionRegistry", this.dimensionRegistry)
.add("dimensionInfo", this.dimensionInfo)
.add("currentDimensionData", this.currentDimensionData)
.add("previousGamemode", this.previousGamemode)
.add("biomeRegistry", this.biomeRegistry)
.toString();
}
}

View File

@@ -0,0 +1,19 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import com.velocitypowered.proxy.network.packet.AbstractKeepAlivePacket;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
public class ClientboundKeepAlivePacket extends AbstractKeepAlivePacket implements Packet {
public static final PacketReader<ClientboundKeepAlivePacket> DECODER = decoder(ClientboundKeepAlivePacket::new);
public ClientboundKeepAlivePacket(final long randomId) {
super(randomId);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
}

View File

@@ -0,0 +1,91 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.DefaultByteBufHolder;
import io.netty.buffer.Unpooled;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ClientboundLoginPluginMessagePacket extends DefaultByteBufHolder implements Packet {
public static final PacketReader<ClientboundLoginPluginMessagePacket> DECODER = (buf, direction, version) -> {
final int id = ProtocolUtils.readVarInt(buf);
final String channel = ProtocolUtils.readString(buf);
final ByteBuf data;
if (buf.isReadable()) {
data = buf.readSlice(buf.readableBytes());
} else {
data = Unpooled.EMPTY_BUFFER;
}
return new ClientboundLoginPluginMessagePacket(id, channel, data);
};
private final int id;
private final @Nullable String channel;
public ClientboundLoginPluginMessagePacket(int id, @Nullable String channel, ByteBuf data) {
super(data);
this.id = id;
this.channel = channel;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
ProtocolUtils.writeVarInt(buf, id);
if (channel == null) {
throw new IllegalStateException("Channel is not specified!");
}
ProtocolUtils.writeString(buf, channel);
buf.writeBytes(content());
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public int getId() {
return id;
}
public String getChannel() {
if (channel == null) {
throw new IllegalStateException("Channel is not specified!");
}
return channel;
}
@Override
public boolean equals(final Object other) {
if (this == other) {
return true;
}
if (other == null || this.getClass() != other.getClass()) {
return false;
}
final ClientboundLoginPluginMessagePacket that = (ClientboundLoginPluginMessagePacket) other;
return this.id == that.id
&& Objects.equals(this.channel, that.channel)
&& super.equals(other);
}
@Override
public int hashCode() {
return Objects.hash(this.id, this.channel, super.hashCode());
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", this.id)
.add("channel", this.channel)
.add("data", this.contentToString())
.toString();
}
}

View File

@@ -1,13 +1,15 @@
package com.velocitypowered.proxy.protocol.packet;
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.player.TabListEntry;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
@@ -16,7 +18,8 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.checkerframework.checker.nullness.qual.Nullable;
public class PlayerListItemPacket implements Packet {
public class ClientboundPlayerListItemPacket implements Packet {
public static final PacketReader<ClientboundPlayerListItemPacket> DECODER = PacketReader.method(ClientboundPlayerListItemPacket::new);
public static final int ADD_PLAYER = 0;
public static final int UPDATE_GAMEMODE = 1;
@@ -26,12 +29,12 @@ public class PlayerListItemPacket implements Packet {
private int action;
private final List<Item> items = new ArrayList<>();
public PlayerListItemPacket(int action, List<Item> items) {
public ClientboundPlayerListItemPacket(int action, List<Item> items) {
this.action = action;
this.items.addAll(items);
}
public PlayerListItemPacket() {
public ClientboundPlayerListItemPacket() {
}
public int getAction() {
@@ -43,8 +46,8 @@ public class PlayerListItemPacket implements Packet {
}
@Override
public void decode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
action = ProtocolUtils.readVarInt(buf);
int length = ProtocolUtils.readVarInt(buf);
@@ -93,8 +96,8 @@ public class PlayerListItemPacket implements Packet {
}
@Override
public void encode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
ProtocolUtils.writeVarInt(buf, action);
ProtocolUtils.writeVarInt(buf, items.size());
for (Item item : items) {
@@ -144,7 +147,7 @@ public class PlayerListItemPacket implements Packet {
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
@@ -157,6 +160,14 @@ public class PlayerListItemPacket implements Packet {
}
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("action", this.action)
.add("items", this.items)
.toString();
}
public static class Item {
private final UUID uuid;

View File

@@ -0,0 +1,26 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
public class ClientboundPluginMessagePacket extends AbstractPluginMessagePacket<ClientboundPluginMessagePacket> implements Packet {
public static final Factory<ClientboundPluginMessagePacket> FACTORY = ClientboundPluginMessagePacket::new;
public static final PacketReader<ClientboundPluginMessagePacket> DECODER = decoder(FACTORY);
public ClientboundPluginMessagePacket(final String channel, final ByteBuf backing) {
super(channel, backing);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
@Override
public ClientboundPluginMessagePacket replace(ByteBuf content) {
return new ClientboundPluginMessagePacket(this.channel, content);
}
}

View File

@@ -0,0 +1,54 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import java.util.Objects;
public class ClientboundResourcePackRequestPacket implements Packet {
public static final PacketReader<ClientboundResourcePackRequestPacket> DECODER = (buf, direction, version) -> {
final String url = ProtocolUtils.readString(buf);
final String hash = ProtocolUtils.readString(buf);
return new ClientboundResourcePackRequestPacket(url, hash);
};
private final String url;
private final String hash;
public ClientboundResourcePackRequestPacket(final String url, final String hash) {
this.url = Objects.requireNonNull(url, "url");
this.hash = Objects.requireNonNull(hash, "hash");
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion protocolVersion) {
ProtocolUtils.writeString(buf, url);
ProtocolUtils.writeString(buf, hash);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public String getUrl() {
return url;
}
public String getHash() {
return hash;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("url", this.url)
.add("hash", this.hash)
.toString();
}
}

View File

@@ -1,16 +1,19 @@
package com.velocitypowered.proxy.protocol.packet;
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.registry.DimensionData;
import com.velocitypowered.proxy.connection.registry.DimensionInfo;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import net.kyori.adventure.nbt.CompoundBinaryTag;
public class RespawnPacket implements Packet {
public class ClientboundRespawnPacket implements Packet {
public static final PacketReader<ClientboundRespawnPacket> DECODER = PacketReader.method(ClientboundRespawnPacket::new);
private int dimension;
private long partialHashedSeed;
@@ -22,12 +25,12 @@ public class RespawnPacket implements Packet {
private short previousGamemode; // 1.16+
private DimensionData currentDimensionData; // 1.16.2+
public RespawnPacket() {
public ClientboundRespawnPacket() {
}
public RespawnPacket(int dimension, long partialHashedSeed, short difficulty, short gamemode,
String levelType, boolean shouldKeepPlayerData, DimensionInfo dimensionInfo,
short previousGamemode, DimensionData currentDimensionData) {
public ClientboundRespawnPacket(int dimension, long partialHashedSeed, short difficulty, short gamemode,
String levelType, boolean shouldKeepPlayerData, DimensionInfo dimensionInfo,
short previousGamemode, DimensionData currentDimensionData) {
this.dimension = dimension;
this.partialHashedSeed = partialHashedSeed;
this.difficulty = difficulty;
@@ -96,27 +99,11 @@ public class RespawnPacket implements Packet {
}
@Override
public String toString() {
return "Respawn{"
+ "dimension=" + dimension
+ ", partialHashedSeed=" + partialHashedSeed
+ ", difficulty=" + difficulty
+ ", gamemode=" + gamemode
+ ", levelType='" + levelType + '\''
+ ", shouldKeepPlayerData=" + shouldKeepPlayerData
+ ", dimensionRegistryName='" + dimensionInfo.toString() + '\''
+ ", dimensionInfo=" + dimensionInfo
+ ", previousGamemode=" + previousGamemode
+ ", dimensionData=" + currentDimensionData
+ '}';
}
@Override
public void decode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
String dimensionIdentifier = null;
String levelName = null;
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
CompoundBinaryTag dimDataTag = ProtocolUtils.readCompoundTag(buf);
dimensionIdentifier = ProtocolUtils.readString(buf);
this.currentDimensionData = DimensionData.decodeBaseCompoundTag(dimDataTag, version)
@@ -128,14 +115,14 @@ public class RespawnPacket implements Packet {
} else {
this.dimension = buf.readInt();
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) {
if (version.lte(ProtocolVersion.MINECRAFT_1_13_2)) {
this.difficulty = buf.readUnsignedByte();
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_15)) {
this.partialHashedSeed = buf.readLong();
}
this.gamemode = buf.readByte();
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
this.previousGamemode = buf.readByte();
boolean isDebug = buf.readBoolean();
boolean isFlat = buf.readBoolean();
@@ -147,9 +134,9 @@ public class RespawnPacket implements Packet {
}
@Override
public void encode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16_2)) {
ProtocolUtils.writeCompoundTag(buf, currentDimensionData.serializeDimensionDetails());
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
} else {
@@ -159,14 +146,14 @@ public class RespawnPacket implements Packet {
} else {
buf.writeInt(dimension);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) {
if (version.lte(ProtocolVersion.MINECRAFT_1_13_2)) {
buf.writeByte(difficulty);
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_15)) {
buf.writeLong(partialHashedSeed);
}
buf.writeByte(gamemode);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
buf.writeByte(previousGamemode);
buf.writeBoolean(dimensionInfo.isDebugType());
buf.writeBoolean(dimensionInfo.isFlat());
@@ -177,7 +164,22 @@ public class RespawnPacket implements Packet {
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("dimension", this.dimension)
.add("partialHashedSeed", this.partialHashedSeed)
.add("difficulty", this.difficulty)
.add("gamemode", this.gamemode)
.add("levelType", this.levelType)
.add("shouldKeepPlayerData", this.shouldKeepPlayerData)
.add("dimensionInfo", this.dimensionInfo)
.add("previousGamemode", this.previousGamemode)
.add("currentDimensionData", this.currentDimensionData)
.toString();
}
}

View File

@@ -0,0 +1,69 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.util.UuidUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import java.util.Objects;
import java.util.UUID;
public class ClientboundServerLoginSuccessPacket implements Packet {
public static final PacketReader<ClientboundServerLoginSuccessPacket> DECODER = (buf, direction, version) -> {
final UUID uuid;
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
uuid = ProtocolUtils.readUuidIntArray(buf);
} else if (version.gte(ProtocolVersion.MINECRAFT_1_7_6)) {
uuid = UUID.fromString(ProtocolUtils.readString(buf, 36));
} else {
uuid = UuidUtils.fromUndashed(ProtocolUtils.readString(buf, 32));
}
final String username = ProtocolUtils.readString(buf, 16);
return new ClientboundServerLoginSuccessPacket(uuid, username);
};
private final UUID uuid;
private final String username;
public ClientboundServerLoginSuccessPacket(final UUID uuid, final String username) {
this.uuid = Objects.requireNonNull(uuid, "uuid");
this.username = Objects.requireNonNull(username, "username");
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (version.gte(ProtocolVersion.MINECRAFT_1_16)) {
ProtocolUtils.writeUuidIntArray(buf, uuid);
} else if (version.gte(ProtocolVersion.MINECRAFT_1_7_6)) {
ProtocolUtils.writeString(buf, uuid.toString());
} else {
ProtocolUtils.writeString(buf, UuidUtils.toUndashed(uuid));
}
ProtocolUtils.writeString(buf, username);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public UUID getUuid() {
return uuid;
}
public String getUsername() {
return username;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("uuid", this.uuid)
.add("username", this.username)
.toString();
}
}

View File

@@ -0,0 +1,44 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
public class ClientboundSetCompressionPacket implements Packet {
public static final PacketReader<ClientboundSetCompressionPacket> DECODER = (buf, direction, version) -> {
final int threshold = ProtocolUtils.readVarInt(buf);
return new ClientboundSetCompressionPacket(threshold);
};
private final int threshold;
public ClientboundSetCompressionPacket(int threshold) {
this.threshold = threshold;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
ProtocolUtils.writeVarInt(buf, threshold);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public int getThreshold() {
return threshold;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("threshold", this.threshold)
.toString();
}
}

View File

@@ -0,0 +1,19 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import com.velocitypowered.proxy.network.packet.AbstractStatusPingPacket;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
public class ClientboundStatusPingPacket extends AbstractStatusPingPacket implements Packet {
public static final PacketReader<ClientboundStatusPingPacket> DECODER = decoder(ClientboundStatusPingPacket::new);
public ClientboundStatusPingPacket(final long randomId) {
super(randomId);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
}

View File

@@ -0,0 +1,51 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ClientboundStatusResponsePacket implements Packet {
public static final PacketReader<ClientboundStatusResponsePacket> DECODER = (buf, direction, version) -> {
final String status = ProtocolUtils.readString(buf, Short.MAX_VALUE);
return new ClientboundStatusResponsePacket(status);
};
private final @Nullable CharSequence status;
public ClientboundStatusResponsePacket(CharSequence status) {
this.status = status;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (status == null) {
throw new IllegalStateException("Status is not specified");
}
ProtocolUtils.writeString(buf, status);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public String getStatus() {
if (status == null) {
throw new IllegalStateException("Status is not specified");
}
return status.toString();
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("status", this.status)
.toString();
}
}

View File

@@ -1,20 +1,20 @@
package com.velocitypowered.proxy.protocol.packet;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_13;
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
public class TabCompleteResponsePacket implements Packet {
public class ClientboundTabCompleteResponsePacket implements Packet {
public static final PacketReader<ClientboundTabCompleteResponsePacket> DECODER = PacketReader.method(ClientboundTabCompleteResponsePacket::new);
private int transactionId;
private int start;
@@ -50,18 +50,8 @@ public class TabCompleteResponsePacket implements Packet {
}
@Override
public String toString() {
return "TabCompleteResponse{"
+ "transactionId=" + transactionId
+ ", start=" + start
+ ", length=" + length
+ ", offers=" + offers
+ '}';
}
@Override
public void decode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
if (version.compareTo(MINECRAFT_1_13) >= 0) {
public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (version.gte(ProtocolVersion.MINECRAFT_1_13)) {
this.transactionId = ProtocolUtils.readVarInt(buf);
this.start = ProtocolUtils.readVarInt(buf);
this.length = ProtocolUtils.readVarInt(buf);
@@ -81,8 +71,8 @@ public class TabCompleteResponsePacket implements Packet {
}
@Override
public void encode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
if (version.compareTo(MINECRAFT_1_13) >= 0) {
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (version.gte(ProtocolVersion.MINECRAFT_1_13)) {
ProtocolUtils.writeVarInt(buf, this.transactionId);
ProtocolUtils.writeVarInt(buf, this.start);
ProtocolUtils.writeVarInt(buf, this.length);
@@ -104,10 +94,20 @@ public class TabCompleteResponsePacket implements Packet {
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("transactionId", this.transactionId)
.add("start", this.start)
.add("length", this.length)
.add("offers", this.offers)
.toString();
}
public static class Offer implements Comparable<Offer> {
private final String text;
private final @Nullable Component tooltip;

View File

@@ -0,0 +1,190 @@
package com.velocitypowered.proxy.network.packet.clientbound;
import com.google.common.base.MoreObjects;
import com.google.common.primitives.Ints;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import com.velocitypowered.proxy.util.DurationUtils;
import io.netty.buffer.ByteBuf;
import java.util.Arrays;
import net.kyori.adventure.title.Title;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ClientboundTitlePacket implements Packet {
public static final PacketReader<ClientboundTitlePacket> DECODER = PacketReader.unsupported();
public static ClientboundTitlePacket hide(final ProtocolVersion version) {
return version.gte(ProtocolVersion.MINECRAFT_1_11)
? Instances.HIDE
: Instances.HIDE_OLD;
}
public static ClientboundTitlePacket reset(final ProtocolVersion version) {
return version.gte(ProtocolVersion.MINECRAFT_1_11)
? Instances.RESET
: Instances.RESET_OLD;
}
public static ClientboundTitlePacket times(final ProtocolVersion version, final Title.Times times) {
final int action = version.gte(ProtocolVersion.MINECRAFT_1_11)
? SET_TIMES
: SET_TIMES_OLD;
return new ClientboundTitlePacket(
action,
(int) DurationUtils.toTicks(times.fadeIn()),
(int) DurationUtils.toTicks(times.stay()),
(int) DurationUtils.toTicks(times.fadeOut())
);
}
public static final int SET_TITLE = 0;
public static final int SET_SUBTITLE = 1;
public static final int SET_ACTION_BAR = 2;
public static final int SET_TIMES = 3;
public static final int HIDE = 4;
public static final int RESET = 5;
public static final int SET_TIMES_OLD = 2;
public static final int HIDE_OLD = 3;
public static final int RESET_OLD = 4;
private final int action;
private final @Nullable String component;
private final int fadeIn;
private final int stay;
private final int fadeOut;
private ClientboundTitlePacket(final int action) {
checkAction(action, HIDE, RESET, HIDE_OLD, RESET_OLD);
this.action = action;
this.component = null;
this.fadeIn = -1;
this.stay = -1;
this.fadeOut = -1;
}
public ClientboundTitlePacket(final int action, final String component) {
checkAction(action, SET_TITLE, SET_SUBTITLE, SET_ACTION_BAR);
this.action = action;
this.component = component;
this.fadeIn = -1;
this.stay = -1;
this.fadeOut = -1;
}
public ClientboundTitlePacket(final int action, final int fadeIn, final int stay, final int fadeOut) {
checkAction(action, SET_TIMES, SET_TIMES_OLD);
this.action = action;
this.component = null;
this.fadeIn = fadeIn;
this.stay = stay;
this.fadeOut = fadeOut;
}
private static void checkAction(final int action, final int... validActions) {
if (!Ints.contains(validActions, action)) {
throw new IllegalArgumentException("Invalid action " + action + ", expected one of: " + Arrays.toString(validActions));
}
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
ProtocolUtils.writeVarInt(buf, action);
if (version.gte(ProtocolVersion.MINECRAFT_1_11)) {
// 1.11+ shifted the action enum by 1 to handle the action bar
switch (action) {
case SET_TITLE:
case SET_SUBTITLE:
case SET_ACTION_BAR:
if (component == null) {
throw new IllegalStateException("No component found for " + action);
}
ProtocolUtils.writeString(buf, component);
break;
case SET_TIMES:
buf.writeInt(fadeIn);
buf.writeInt(stay);
buf.writeInt(fadeOut);
break;
case HIDE:
case RESET:
break;
default:
throw new UnsupportedOperationException("Unknown action " + action);
}
} else {
switch (action) {
case SET_TITLE:
case SET_SUBTITLE:
if (component == null) {
throw new IllegalStateException("No component found for " + action);
}
ProtocolUtils.writeString(buf, component);
break;
case SET_TIMES_OLD:
buf.writeInt(fadeIn);
buf.writeInt(stay);
buf.writeInt(fadeOut);
break;
case HIDE_OLD:
case RESET_OLD:
break;
default:
throw new UnsupportedOperationException("Unknown action " + action);
}
}
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public int getAction() {
return action;
}
public @Nullable String getComponent() {
return component;
}
public int getFadeIn() {
return fadeIn;
}
public int getStay() {
return stay;
}
public int getFadeOut() {
return fadeOut;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("action", this.action)
.add("component", this.component)
.add("fadeIn", this.fadeIn)
.add("stay", this.stay)
.add("fadeOut", this.fadeOut)
.toString();
}
public static final class Instances {
public static final ClientboundTitlePacket HIDE
= new ClientboundTitlePacket(ClientboundTitlePacket.HIDE);
public static final ClientboundTitlePacket RESET
= new ClientboundTitlePacket(ClientboundTitlePacket.RESET);
public static final ClientboundTitlePacket HIDE_OLD = new ClientboundTitlePacket(ClientboundTitlePacket.HIDE_OLD);
public static final ClientboundTitlePacket RESET_OLD = new ClientboundTitlePacket(ClientboundTitlePacket.RESET_OLD);
private Instances() {
}
}
}

View File

@@ -1,14 +1,13 @@
package com.velocitypowered.proxy.protocol.packet.legacy;
package com.velocitypowered.proxy.network.packet.legacy;
import com.google.common.collect.ImmutableList;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.proxy.server.ServerPing.Players;
import com.velocitypowered.proxy.protocol.packet.legacyping.LegacyMinecraftPingVersion;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
public class LegacyDisconnectPacket {
public class LegacyDisconnectPacket implements LegacyPacket {
private static final ServerPing.Players FAKE_PLAYERS = new ServerPing.Players(0, 0,
ImmutableList.of());

View File

@@ -0,0 +1,20 @@
package com.velocitypowered.proxy.network.packet.legacy;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import io.netty.buffer.ByteBuf;
public class LegacyHandshakePacket implements LegacyPacket, Packet {
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
throw new UnsupportedOperationException();
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
}

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol.packet.legacyping;
package com.velocitypowered.proxy.network.packet.legacy;
public enum LegacyMinecraftPingVersion {
MINECRAFT_1_3,

View File

@@ -0,0 +1,4 @@
package com.velocitypowered.proxy.network.packet.legacy;
public interface LegacyPacket {
}

View File

@@ -1,15 +1,14 @@
package com.velocitypowered.proxy.protocol.packet.legacy;
package com.velocitypowered.proxy.network.packet.legacy;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.packet.legacyping.LegacyMinecraftPingVersion;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import io.netty.buffer.ByteBuf;
import java.net.InetSocketAddress;
import org.checkerframework.checker.nullness.qual.Nullable;
public class LegacyPingPacket implements Packet {
public class LegacyPingPacket implements LegacyPacket, Packet {
private final LegacyMinecraftPingVersion version;
private final @Nullable InetSocketAddress vhost;
@@ -24,6 +23,16 @@ public class LegacyPingPacket implements Packet {
this.vhost = vhost;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
throw new UnsupportedOperationException();
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public LegacyMinecraftPingVersion getVersion() {
return version;
}
@@ -31,19 +40,4 @@ public class LegacyPingPacket implements Packet {
public @Nullable InetSocketAddress getVhost() {
return vhost;
}
@Override
public void decode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
throw new UnsupportedOperationException();
}
@Override
public void encode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
throw new UnsupportedOperationException();
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
return handler.handle(this);
}
}

View File

@@ -0,0 +1,46 @@
package com.velocitypowered.proxy.network.packet.serverbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
public class ServerboundChatPacket implements Packet {
public static final PacketReader<ServerboundChatPacket> DECODER = (buf, direction, version) -> {
final String message = ProtocolUtils.readString(buf);
return new ServerboundChatPacket(message);
};
public static final int MAX_MESSAGE_LENGTH = 256;
private final String message;
public ServerboundChatPacket(String message) {
this.message = message;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
ProtocolUtils.writeString(buf, message);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public String getMessage() {
return message;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("message", this.message)
.toString();
}
}

View File

@@ -1,14 +1,17 @@
package com.velocitypowered.proxy.protocol.packet;
package com.velocitypowered.proxy.network.packet.serverbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ClientSettingsPacket implements Packet {
public class ServerboundClientSettingsPacket implements Packet {
public static final PacketReader<ServerboundClientSettingsPacket> DECODER = PacketReader.method(ServerboundClientSettingsPacket::new);
private @Nullable String locale;
private byte viewDistance;
@@ -18,11 +21,11 @@ public class ClientSettingsPacket implements Packet {
private short skinParts;
private int mainHand;
public ClientSettingsPacket() {
public ServerboundClientSettingsPacket() {
}
public ClientSettingsPacket(String locale, byte viewDistance, int chatVisibility, boolean chatColors,
short skinParts, int mainHand) {
public ServerboundClientSettingsPacket(String locale, byte viewDistance, int chatVisibility, boolean chatColors,
short skinParts, int mainHand) {
this.locale = locale;
this.viewDistance = viewDistance;
this.chatVisibility = chatVisibility;
@@ -31,6 +34,50 @@ public class ClientSettingsPacket implements Packet {
this.mainHand = mainHand;
}
@Override
public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
this.locale = ProtocolUtils.readString(buf, 16);
this.viewDistance = buf.readByte();
this.chatVisibility = ProtocolUtils.readVarInt(buf);
this.chatColors = buf.readBoolean();
if (version.lte(ProtocolVersion.MINECRAFT_1_7_6)) {
this.difficulty = buf.readByte();
}
this.skinParts = buf.readUnsignedByte();
if (version.gte(ProtocolVersion.MINECRAFT_1_9)) {
this.mainHand = ProtocolUtils.readVarInt(buf);
}
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (locale == null) {
throw new IllegalStateException("No locale specified");
}
ProtocolUtils.writeString(buf, locale);
buf.writeByte(viewDistance);
ProtocolUtils.writeVarInt(buf, chatVisibility);
buf.writeBoolean(chatColors);
if (version.lte(ProtocolVersion.MINECRAFT_1_7_6)) {
buf.writeByte(difficulty);
}
buf.writeByte(skinParts);
if (version.gte(ProtocolVersion.MINECRAFT_1_9)) {
ProtocolUtils.writeVarInt(buf, mainHand);
}
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public String getLocale() {
if (locale == null) {
throw new IllegalStateException("No locale specified");
@@ -38,103 +85,36 @@ public class ClientSettingsPacket implements Packet {
return locale;
}
public void setLocale(String locale) {
this.locale = locale;
}
public byte getViewDistance() {
return viewDistance;
}
public void setViewDistance(byte viewDistance) {
this.viewDistance = viewDistance;
}
public int getChatVisibility() {
return chatVisibility;
}
public void setChatVisibility(int chatVisibility) {
this.chatVisibility = chatVisibility;
}
public boolean isChatColors() {
return chatColors;
}
public void setChatColors(boolean chatColors) {
this.chatColors = chatColors;
}
public short getSkinParts() {
return skinParts;
}
public void setSkinParts(short skinParts) {
this.skinParts = skinParts;
}
public int getMainHand() {
return mainHand;
}
public void setMainHand(int mainHand) {
this.mainHand = mainHand;
}
@Override
public String toString() {
return "ClientSettings{"
+ "locale='" + locale + '\''
+ ", viewDistance=" + viewDistance
+ ", chatVisibility=" + chatVisibility
+ ", chatColors=" + chatColors
+ ", skinParts=" + skinParts
+ ", mainHand=" + mainHand
+ '}';
}
@Override
public void decode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
this.locale = ProtocolUtils.readString(buf, 16);
this.viewDistance = buf.readByte();
this.chatVisibility = ProtocolUtils.readVarInt(buf);
this.chatColors = buf.readBoolean();
if (version.compareTo(ProtocolVersion.MINECRAFT_1_7_6) <= 0) {
this.difficulty = buf.readByte();
}
this.skinParts = buf.readUnsignedByte();
if (version.compareTo(ProtocolVersion.MINECRAFT_1_9) >= 0) {
this.mainHand = ProtocolUtils.readVarInt(buf);
}
}
@Override
public void encode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
if (locale == null) {
throw new IllegalStateException("No locale specified");
}
ProtocolUtils.writeString(buf, locale);
buf.writeByte(viewDistance);
ProtocolUtils.writeVarInt(buf, chatVisibility);
buf.writeBoolean(chatColors);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_7_6) <= 0) {
buf.writeByte(difficulty);
}
buf.writeByte(skinParts);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_9) >= 0) {
ProtocolUtils.writeVarInt(buf, mainHand);
}
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
return handler.handle(this);
return MoreObjects.toStringHelper(this)
.add("locale", this.locale)
.add("viewDistance", this.viewDistance)
.add("chatVisibility", this.chatVisibility)
.add("chatColors", this.chatColors)
.add("difficulty", this.difficulty)
.add("skinParts", this.skinParts)
.add("mainHand", this.mainHand)
.toString();
}
}

View File

@@ -0,0 +1,65 @@
package com.velocitypowered.proxy.network.packet.serverbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
public class ServerboundEncryptionResponsePacket implements Packet {
public static final PacketReader<ServerboundEncryptionResponsePacket> DECODER = (buf, direction, version) -> {
final byte[] sharedSecret;
final byte[] verifyToken;
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
sharedSecret = ProtocolUtils.readByteArray(buf, 256);
verifyToken = ProtocolUtils.readByteArray(buf, 128);
} else {
sharedSecret = ProtocolUtils.readByteArray17(buf);
verifyToken = ProtocolUtils.readByteArray17(buf);
}
return new ServerboundEncryptionResponsePacket(sharedSecret, verifyToken);
};
private final byte[] sharedSecret;
private final byte[] verifyToken;
private ServerboundEncryptionResponsePacket(final byte[] sharedSecret, final byte[] verifyToken) {
this.sharedSecret = sharedSecret;
this.verifyToken = verifyToken;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (version.gte(ProtocolVersion.MINECRAFT_1_8)) {
ProtocolUtils.writeByteArray(buf, sharedSecret);
ProtocolUtils.writeByteArray(buf, verifyToken);
} else {
ProtocolUtils.writeByteArray17(sharedSecret, buf, false);
ProtocolUtils.writeByteArray17(verifyToken, buf, false);
}
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public byte[] getSharedSecret() {
return sharedSecret.clone();
}
public byte[] getVerifyToken() {
return verifyToken.clone();
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("sharedSecret", this.sharedSecret)
.add("verifyToken", this.verifyToken)
.toString();
}
}

View File

@@ -0,0 +1,95 @@
package com.velocitypowered.proxy.network.packet.serverbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
public class ServerboundHandshakePacket implements Packet {
public static final PacketReader<ServerboundHandshakePacket> DECODER = (buf, direction, version) -> {
int realProtocolVersion = ProtocolUtils.readVarInt(buf);
final ProtocolVersion protocolVersion = ProtocolVersion.getProtocolVersion(realProtocolVersion);
final String hostname = ProtocolUtils.readString(buf);
final int port = buf.readUnsignedShort();
final int nextStatus = ProtocolUtils.readVarInt(buf);
return new ServerboundHandshakePacket(protocolVersion, hostname, port, nextStatus);
};
private ProtocolVersion protocolVersion;
private String serverAddress = "";
private int port;
private int nextStatus;
public ServerboundHandshakePacket() {
}
public ServerboundHandshakePacket(final ProtocolVersion protocolVersion, final String hostname, final int port, final int nextStatus) {
this.protocolVersion = protocolVersion;
this.serverAddress = hostname;
this.port = port;
this.nextStatus = nextStatus;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion ignored) {
ProtocolUtils.writeVarInt(buf, this.protocolVersion.getProtocol());
ProtocolUtils.writeString(buf, this.serverAddress);
buf.writeShort(this.port);
ProtocolUtils.writeVarInt(buf, this.nextStatus);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public ProtocolVersion getProtocolVersion() {
return protocolVersion;
}
@Deprecated
public void setProtocolVersion(ProtocolVersion protocolVersion) {
this.protocolVersion = protocolVersion;
}
public String getServerAddress() {
return serverAddress;
}
@Deprecated
public void setServerAddress(String serverAddress) {
this.serverAddress = serverAddress;
}
public int getPort() {
return port;
}
@Deprecated
public void setPort(int port) {
this.port = port;
}
public int getNextStatus() {
return nextStatus;
}
@Deprecated
public void setNextStatus(int nextStatus) {
this.nextStatus = nextStatus;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("protocolVersion", this.protocolVersion)
.add("serverAddress", this.serverAddress)
.add("port", this.port)
.add("nextStatus", this.nextStatus)
.toString();
}
}

View File

@@ -0,0 +1,19 @@
package com.velocitypowered.proxy.network.packet.serverbound;
import com.velocitypowered.proxy.network.packet.AbstractKeepAlivePacket;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
public class ServerboundKeepAlivePacket extends AbstractKeepAlivePacket implements Packet {
public static final PacketReader<ServerboundKeepAlivePacket> DECODER = decoder(ServerboundKeepAlivePacket::new);
public ServerboundKeepAlivePacket(final long randomId) {
super(randomId);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
}

View File

@@ -0,0 +1,85 @@
package com.velocitypowered.proxy.network.packet.serverbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.DefaultByteBufHolder;
import io.netty.buffer.Unpooled;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public class ServerboundLoginPluginResponsePacket extends DefaultByteBufHolder implements Packet {
public static final PacketReader<ServerboundLoginPluginResponsePacket> DECODER = (buf, direction, version) -> {
final int id = ProtocolUtils.readVarInt(buf);
final boolean success = buf.readBoolean();
final ByteBuf data;
if (buf.isReadable()) {
data = buf.readSlice(buf.readableBytes());
} else {
data = Unpooled.EMPTY_BUFFER;
}
return new ServerboundLoginPluginResponsePacket(id, success, data);
};
private final int id;
private final boolean success;
public ServerboundLoginPluginResponsePacket(int id, boolean success, @MonotonicNonNull ByteBuf buf) {
super(buf);
this.id = id;
this.success = success;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
ProtocolUtils.writeVarInt(buf, id);
buf.writeBoolean(success);
buf.writeBytes(content());
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public int getId() {
return id;
}
public boolean isSuccess() {
return success;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", this.id)
.add("success", this.success)
.add("data", this.contentToString())
.toString();
}
@Override
public boolean equals(final Object other) {
if (this == other) {
return true;
}
if (other == null || this.getClass() != other.getClass()) {
return false;
}
final ServerboundLoginPluginResponsePacket that = (ServerboundLoginPluginResponsePacket) other;
return this.id == that.id
&& Objects.equals(this.success, that.success)
&& super.equals(other);
}
@Override
public int hashCode() {
return Objects.hash(this.id, this.success, super.hashCode());
}
}

View File

@@ -0,0 +1,26 @@
package com.velocitypowered.proxy.network.packet.serverbound;
import com.velocitypowered.proxy.network.packet.AbstractPluginMessagePacket;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
public class ServerboundPluginMessagePacket extends AbstractPluginMessagePacket<ServerboundPluginMessagePacket> implements Packet {
public static final Factory<ServerboundPluginMessagePacket> FACTORY = ServerboundPluginMessagePacket::new;
public static final PacketReader<ServerboundPluginMessagePacket> DECODER = decoder(FACTORY);
public ServerboundPluginMessagePacket(final String channel, final ByteBuf backing) {
super(channel, backing);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
@Override
public ServerboundPluginMessagePacket replace(ByteBuf content) {
return new ServerboundPluginMessagePacket(this.channel, content);
}
}

View File

@@ -0,0 +1,58 @@
package com.velocitypowered.proxy.network.packet.serverbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.event.player.PlayerResourcePackStatusEvent.Status;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ServerboundResourcePackResponsePacket implements Packet {
public static final PacketReader<ServerboundResourcePackResponsePacket> DECODER = (buf, direction, version) -> {
final String hash;
if (version.lte(ProtocolVersion.MINECRAFT_1_9_4)) {
hash = ProtocolUtils.readString(buf);
} else {
hash = null;
}
final Status status = Status.values()[ProtocolUtils.readVarInt(buf)];
return new ServerboundResourcePackResponsePacket(hash, status);
};
private final @Nullable String hash;
private final Status status;
public ServerboundResourcePackResponsePacket(final @Nullable String hash, final Status status) {
this.hash = hash;
this.status = status;
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion protocolVersion) {
if (protocolVersion.lte(ProtocolVersion.MINECRAFT_1_9_4)) {
ProtocolUtils.writeString(buf, hash);
}
ProtocolUtils.writeVarInt(buf, status.ordinal());
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public Status getStatus() {
return status;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("hash", this.hash)
.add("status", this.status)
.toString();
}
}

View File

@@ -0,0 +1,51 @@
package com.velocitypowered.proxy.network.packet.serverbound;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import com.velocitypowered.proxy.util.except.QuietDecoderException;
import io.netty.buffer.ByteBuf;
import java.util.Objects;
public class ServerboundServerLoginPacket implements Packet {
private static final QuietDecoderException EMPTY_USERNAME = new QuietDecoderException("Empty username!");
public static final PacketReader<ServerboundServerLoginPacket> DECODER = (buf, direction, version) -> {
final String username = ProtocolUtils.readString(buf, 16);
if (username.isEmpty()) {
throw EMPTY_USERNAME;
}
return new ServerboundServerLoginPacket(username);
};
private final String username;
public ServerboundServerLoginPacket(String username) {
this.username = Objects.requireNonNull(username, "username");
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
ProtocolUtils.writeString(buf, username);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
public String getUsername() {
return username;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("username", this.username)
.toString();
}
}

View File

@@ -0,0 +1,19 @@
package com.velocitypowered.proxy.network.packet.serverbound;
import com.velocitypowered.proxy.network.packet.AbstractStatusPingPacket;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
public class ServerboundStatusPingPacket extends AbstractStatusPingPacket implements Packet {
public static final PacketReader<ServerboundStatusPingPacket> DECODER = decoder(ServerboundStatusPingPacket::new);
public ServerboundStatusPingPacket(final long randomId) {
super(randomId);
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
}

View File

@@ -0,0 +1,31 @@
package com.velocitypowered.proxy.network.packet.serverbound;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
public class ServerboundStatusRequestPacket implements Packet {
public static final ServerboundStatusRequestPacket INSTANCE = new ServerboundStatusRequestPacket();
public static final PacketReader<ServerboundStatusRequestPacket> DECODER = PacketReader.instance(INSTANCE);
private ServerboundStatusRequestPacket() {
}
@Override
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
// There is no data to decode.
}
@Override
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
@Override
public String toString() {
return "StatusRequestPacket";
}
}

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol.packet;
package com.velocitypowered.proxy.network.packet.serverbound;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_13;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8;
@@ -6,14 +6,16 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9;
import com.google.common.base.MoreObjects;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.network.packet.PacketHandler;
import com.velocitypowered.proxy.network.packet.PacketReader;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public class TabCompleteRequestPacket implements Packet {
public class ServerboundTabCompleteRequestPacket implements Packet {
public static final PacketReader<ServerboundTabCompleteRequestPacket> DECODER = PacketReader.method(ServerboundTabCompleteRequestPacket::new);
private static final int VANILLA_MAX_TAB_COMPLETE_LEN = 2048;
@@ -67,27 +69,16 @@ public class TabCompleteRequestPacket implements Packet {
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("command", command)
.add("transactionId", transactionId)
.add("assumeCommand", assumeCommand)
.add("hasPosition", hasPosition)
.add("position", position)
.toString();
}
@Override
public void decode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
if (version.compareTo(MINECRAFT_1_13) >= 0) {
public void decode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (version.gte(MINECRAFT_1_13)) {
this.transactionId = ProtocolUtils.readVarInt(buf);
this.command = ProtocolUtils.readString(buf, VANILLA_MAX_TAB_COMPLETE_LEN);
} else {
this.command = ProtocolUtils.readString(buf, VANILLA_MAX_TAB_COMPLETE_LEN);
if (version.compareTo(MINECRAFT_1_9) >= 0) {
if (version.gte(MINECRAFT_1_9)) {
this.assumeCommand = buf.readBoolean();
}
if (version.compareTo(MINECRAFT_1_8) >= 0) {
if (version.gte(MINECRAFT_1_8)) {
this.hasPosition = buf.readBoolean();
if (hasPosition) {
this.position = buf.readLong();
@@ -97,20 +88,20 @@ public class TabCompleteRequestPacket implements Packet {
}
@Override
public void encode(ByteBuf buf, ProtocolDirection direction, ProtocolVersion version) {
public void encode(ByteBuf buf, PacketDirection direction, ProtocolVersion version) {
if (command == null) {
throw new IllegalStateException("Command is not specified");
}
if (version.compareTo(MINECRAFT_1_13) >= 0) {
if (version.gte(MINECRAFT_1_13)) {
ProtocolUtils.writeVarInt(buf, transactionId);
ProtocolUtils.writeString(buf, command);
} else {
ProtocolUtils.writeString(buf, command);
if (version.compareTo(MINECRAFT_1_9) >= 0) {
if (version.gte(MINECRAFT_1_9)) {
buf.writeBoolean(assumeCommand);
}
if (version.compareTo(MINECRAFT_1_8) >= 0) {
if (version.gte(MINECRAFT_1_8)) {
buf.writeBoolean(hasPosition);
if (hasPosition) {
buf.writeLong(position);
@@ -120,7 +111,18 @@ public class TabCompleteRequestPacket implements Packet {
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
public boolean handle(PacketHandler handler) {
return handler.handle(this);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("command", command)
.add("transactionId", transactionId)
.add("assumeCommand", assumeCommand)
.add("hasPosition", hasPosition)
.add("position", position)
.toString();
}
}

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import static com.velocitypowered.api.event.connection.ProxyQueryEvent.QueryType.BASIC;
import static com.velocitypowered.api.event.connection.ProxyQueryEvent.QueryType.FULL;

View File

@@ -1,10 +1,10 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import static com.velocitypowered.proxy.protocol.util.NettyPreconditions.checkFrame;
import static com.velocitypowered.proxy.network.NettyPreconditions.checkFrame;
import com.velocitypowered.proxy.protocol.packet.legacy.LegacyHandshakePacket;
import com.velocitypowered.proxy.protocol.packet.legacy.LegacyPingPacket;
import com.velocitypowered.proxy.protocol.packet.legacyping.LegacyMinecraftPingVersion;
import com.velocitypowered.proxy.network.packet.legacy.LegacyHandshakePacket;
import com.velocitypowered.proxy.network.packet.legacy.LegacyMinecraftPingVersion;
import com.velocitypowered.proxy.network.packet.legacy.LegacyPingPacket;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

View File

@@ -1,6 +1,6 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import com.velocitypowered.proxy.protocol.packet.legacy.LegacyDisconnectPacket;
import com.velocitypowered.proxy.network.packet.legacy.LegacyDisconnectPacket;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import com.google.common.base.Preconditions;
import com.velocitypowered.natives.encryption.VelocityCipher;

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import com.google.common.base.Preconditions;
import com.velocitypowered.natives.encryption.VelocityCipher;

View File

@@ -1,11 +1,11 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import static com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible;
import static com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer;
import static com.velocitypowered.proxy.protocol.util.NettyPreconditions.checkFrame;
import static com.velocitypowered.proxy.network.NettyPreconditions.checkFrame;
import com.velocitypowered.natives.compression.VelocityCompressor;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;

View File

@@ -1,8 +1,8 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import com.velocitypowered.natives.compression.VelocityCompressor;
import com.velocitypowered.natives.util.MoreByteBufUtils;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

View File

@@ -1,11 +1,11 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.StateRegistry;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import com.velocitypowered.proxy.util.except.QuietDecoderException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
@@ -19,7 +19,7 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
new QuietDecoderException("A packet did not decode successfully (invalid data). If you are a "
+ "developer, launch Velocity with -Dvelocity.packet-decode-logging=true to see more.");
private final ProtocolDirection direction;
private final PacketDirection direction;
private StateRegistry state;
private StateRegistry.PacketRegistry.ProtocolRegistry registry;
@@ -28,7 +28,7 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
*
* @param direction the direction from which we decode from
*/
public MinecraftDecoder(ProtocolDirection direction) {
public MinecraftDecoder(PacketDirection direction) {
this.direction = Preconditions.checkNotNull(direction, "direction");
this.registry = StateRegistry.HANDSHAKE.getProtocolRegistry(direction,
ProtocolVersion.MINIMUM_VERSION);
@@ -53,18 +53,17 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
int originalReaderIndex = buf.readerIndex();
int packetId = ProtocolUtils.readVarInt(buf);
Packet packet = this.registry.createPacket(packetId);
Packet packet = null;
try {
packet = this.registry.readPacket(packetId, buf, direction, registry.version);
} catch (Exception e) {
throw handleDecodeFailure(e, packet, packetId); // TODO: packet is always null
}
if (packet == null) {
buf.readerIndex(originalReaderIndex);
ctx.fireChannelRead(buf);
} else {
try {
try {
packet.decode(buf, direction, registry.version);
} catch (Exception e) {
throw handleDecodeFailure(e, packet, packetId);
}
if (buf.isReadable()) {
throw handleNotReadEnough(packet, packetId);
}

View File

@@ -1,18 +1,18 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.protocol.Packet;
import com.velocitypowered.proxy.protocol.ProtocolDirection;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.network.ProtocolUtils;
import com.velocitypowered.proxy.network.StateRegistry;
import com.velocitypowered.proxy.network.packet.Packet;
import com.velocitypowered.proxy.network.packet.PacketDirection;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
public class MinecraftEncoder extends MessageToByteEncoder<Packet> {
private final ProtocolDirection direction;
private final PacketDirection direction;
private StateRegistry state;
private StateRegistry.PacketRegistry.ProtocolRegistry registry;
@@ -21,7 +21,7 @@ public class MinecraftEncoder extends MessageToByteEncoder<Packet> {
*
* @param direction the direction to encode to
*/
public MinecraftEncoder(ProtocolDirection direction) {
public MinecraftEncoder(PacketDirection direction) {
this.direction = Preconditions.checkNotNull(direction, "direction");
this.registry = StateRegistry.HANDSHAKE
.getProtocolRegistry(direction, ProtocolVersion.MINIMUM_VERSION);

View File

@@ -1,6 +1,6 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import com.velocitypowered.proxy.protocol.netty.VarintByteDecoder.DecodeResult;
import com.velocitypowered.proxy.network.pipeline.VarintByteDecoder.DecodeResult;
import com.velocitypowered.proxy.util.except.QuietDecoderException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

View File

@@ -1,8 +1,8 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import com.velocitypowered.natives.encryption.JavaVelocityCipher;
import com.velocitypowered.natives.util.Natives;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.network.ProtocolUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol.netty;
package com.velocitypowered.proxy.network.pipeline;
import io.netty.util.ByteProcessor;

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.network.netty;
package com.velocitypowered.proxy.network.resolver;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

View File

@@ -1,4 +1,4 @@
package com.velocitypowered.proxy.protocol.util;
package com.velocitypowered.proxy.network.serialization;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;

Some files were not shown because too many files have changed in this diff Show More