convert some more packets to records

This commit is contained in:
Andrew Steinborn
2025-10-19 18:29:13 -04:00
parent ae877918f9
commit f390682e18
21 changed files with 110 additions and 299 deletions

View File

@@ -55,7 +55,6 @@ import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;

View File

@@ -158,7 +158,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
@Override @Override
public boolean handle(KeepAlivePacket packet) { public boolean handle(KeepAlivePacket packet) {
serverConn.getPendingPings().put(packet.getRandomId(), System.nanoTime()); serverConn.getPendingPings().put(packet.randomId(), System.nanoTime());
return false; // forwards on return false; // forwards on
} }
@@ -178,10 +178,10 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
@Override @Override
public boolean handle(BossBarPacket packet) { public boolean handle(BossBarPacket packet) {
if (serverConn.getPlayer().getProtocolVersion().lessThan(ProtocolVersion.MINECRAFT_1_20_2)) { if (serverConn.getPlayer().getProtocolVersion().lessThan(ProtocolVersion.MINECRAFT_1_20_2)) {
if (packet.getAction() == BossBarPacket.ADD) { if (packet.action() == BossBarPacket.ADD) {
playerSessionHandler.getServerBossBars().add(packet.getUuid()); playerSessionHandler.getServerBossBars().add(packet.uuid());
} else if (packet.getAction() == BossBarPacket.REMOVE) { } else if (packet.action() == BossBarPacket.REMOVE) {
playerSessionHandler.getServerBossBars().remove(packet.getUuid()); playerSessionHandler.getServerBossBars().remove(packet.uuid());
} }
} }
return false; // forward return false; // forward
@@ -190,13 +190,13 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
@Override @Override
public boolean handle(final ResourcePackRequestPacket packet) { public boolean handle(final ResourcePackRequestPacket packet) {
final ResourcePackInfo.Builder builder = new VelocityResourcePackInfo.BuilderImpl( final ResourcePackInfo.Builder builder = new VelocityResourcePackInfo.BuilderImpl(
Preconditions.checkNotNull(packet.getUrl())) Preconditions.checkNotNull(packet.url()))
.setId(packet.getId()) .setId(packet.id())
.setPrompt(packet.getPrompt() == null ? null : packet.getPrompt().getComponent()) .setPrompt(packet.prompt() == null ? null : packet.prompt().getComponent())
.setShouldForce(packet.isRequired()) .setShouldForce(packet.isRequired())
.setOrigin(ResourcePackInfo.Origin.DOWNSTREAM_SERVER); .setOrigin(ResourcePackInfo.Origin.DOWNSTREAM_SERVER);
final String hash = packet.getHash(); final String hash = packet.hash();
if (hash != null && !hash.isEmpty()) { if (hash != null && !hash.isEmpty()) {
if (PLAUSIBLE_SHA1_HASH.matcher(hash).matches()) { if (PLAUSIBLE_SHA1_HASH.matcher(hash).matches()) {
builder.setHash(ByteBufUtil.decodeHexDump(hash)); builder.setHash(ByteBufUtil.decodeHexDump(hash));
@@ -222,14 +222,14 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
// Do not apply a resource pack that has already been applied // Do not apply a resource pack that has already been applied
if (serverConn.getConnection() != null) { if (serverConn.getConnection() != null) {
serverConn.getConnection().write(new ResourcePackResponsePacket( serverConn.getConnection().write(new ResourcePackResponsePacket(
packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.ACCEPTED)); packet.id(), packet.hash(), PlayerResourcePackStatusEvent.Status.ACCEPTED));
if (serverConn.getConnection().getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_20_3)) { if (serverConn.getConnection().getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_20_3)) {
serverConn.getConnection().write(new ResourcePackResponsePacket( serverConn.getConnection().write(new ResourcePackResponsePacket(
packet.getId(), packet.getHash(), packet.id(), packet.hash(),
PlayerResourcePackStatusEvent.Status.DOWNLOADED)); PlayerResourcePackStatusEvent.Status.DOWNLOADED));
} }
serverConn.getConnection().write(new ResourcePackResponsePacket( serverConn.getConnection().write(new ResourcePackResponsePacket(
packet.getId(), packet.getHash(), packet.id(), packet.hash(),
PlayerResourcePackStatusEvent.Status.SUCCESSFUL)); PlayerResourcePackStatusEvent.Status.SUCCESSFUL));
} }
if (modifiedPack) { if (modifiedPack) {
@@ -241,16 +241,16 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
} }
} else if (serverConn.getConnection() != null) { } else if (serverConn.getConnection() != null) {
serverConn.getConnection().write(new ResourcePackResponsePacket( serverConn.getConnection().write(new ResourcePackResponsePacket(
packet.getId(), packet.id(),
packet.getHash(), packet.hash(),
PlayerResourcePackStatusEvent.Status.DECLINED PlayerResourcePackStatusEvent.Status.DECLINED
)); ));
} }
}, playerConnection.eventLoop()).exceptionally((ex) -> { }, playerConnection.eventLoop()).exceptionally((ex) -> {
if (serverConn.getConnection() != null) { if (serverConn.getConnection() != null) {
serverConn.getConnection().write(new ResourcePackResponsePacket( serverConn.getConnection().write(new ResourcePackResponsePacket(
packet.getId(), packet.id(),
packet.getHash(), packet.hash(),
PlayerResourcePackStatusEvent.Status.DECLINED PlayerResourcePackStatusEvent.Status.DECLINED
)); ));
} }

View File

@@ -141,7 +141,7 @@ public class ConfigSessionHandler implements MinecraftSessionHandler {
@Override @Override
public boolean handle(KeepAlivePacket packet) { public boolean handle(KeepAlivePacket packet) {
serverConn.getPendingPings().put(packet.getRandomId(), System.nanoTime()); serverConn.getPendingPings().put(packet.randomId(), System.nanoTime());
serverConn.getPlayer().getConnection().write(packet); serverConn.getPlayer().getConnection().write(packet);
return true; return true;
} }
@@ -171,11 +171,11 @@ public class ConfigSessionHandler implements MinecraftSessionHandler {
if (serverConn.getConnection() != null) { if (serverConn.getConnection() != null) {
// We can technically skip these first 2 states, however, for conformity to normal state flow expectations... // We can technically skip these first 2 states, however, for conformity to normal state flow expectations...
serverConn.getConnection().write(new ResourcePackResponsePacket( serverConn.getConnection().write(new ResourcePackResponsePacket(
packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.ACCEPTED)); packet.id(), packet.hash(), PlayerResourcePackStatusEvent.Status.ACCEPTED));
serverConn.getConnection().write(new ResourcePackResponsePacket( serverConn.getConnection().write(new ResourcePackResponsePacket(
packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.DOWNLOADED)); packet.id(), packet.hash(), PlayerResourcePackStatusEvent.Status.DOWNLOADED));
serverConn.getConnection().write(new ResourcePackResponsePacket( serverConn.getConnection().write(new ResourcePackResponsePacket(
packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.SUCCESSFUL)); packet.id(), packet.hash(), PlayerResourcePackStatusEvent.Status.SUCCESSFUL));
} }
if (modifiedPack) { if (modifiedPack) {
logger.warn("A plugin has tried to modify a ResourcePack provided by the backend server " logger.warn("A plugin has tried to modify a ResourcePack provided by the backend server "
@@ -187,12 +187,12 @@ public class ConfigSessionHandler implements MinecraftSessionHandler {
} }
} else if (serverConn.getConnection() != null) { } else if (serverConn.getConnection() != null) {
serverConn.getConnection().write(new ResourcePackResponsePacket( serverConn.getConnection().write(new ResourcePackResponsePacket(
packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.DECLINED)); packet.id(), packet.hash(), PlayerResourcePackStatusEvent.Status.DECLINED));
} }
}, playerConnection.eventLoop()).exceptionally((ex) -> { }, playerConnection.eventLoop()).exceptionally((ex) -> {
if (serverConn.getConnection() != null) { if (serverConn.getConnection() != null) {
serverConn.getConnection().write(new ResourcePackResponsePacket( serverConn.getConnection().write(new ResourcePackResponsePacket(
packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.DECLINED)); packet.id(), packet.hash(), PlayerResourcePackStatusEvent.Status.DECLINED));
} }
logger.error("Exception while handling resource pack send for {}", playerConnection, ex); logger.error("Exception while handling resource pack send for {}", playerConnection, ex);
return null; return null;

View File

@@ -195,7 +195,7 @@ public class AuthSessionHandler implements MinecraftSessionHandler {
@Override @Override
public boolean handle(ServerboundCookieResponsePacket packet) { public boolean handle(ServerboundCookieResponsePacket packet) {
server.getEventManager() server.getEventManager()
.fire(new CookieReceiveEvent(connectedPlayer, packet.getKey(), packet.getPayload())) .fire(new CookieReceiveEvent(connectedPlayer, packet.key(), packet.payload()))
.thenAcceptAsync(event -> { .thenAcceptAsync(event -> {
if (event.getResult().isAllowed()) { if (event.getResult().isAllowed()) {
// The received cookie must have been requested by a proxy plugin in login phase, // The received cookie must have been requested by a proxy plugin in login phase,

View File

@@ -188,7 +188,7 @@ public class ClientConfigSessionHandler implements MinecraftSessionHandler {
@Override @Override
public boolean handle(ServerboundCookieResponsePacket packet) { public boolean handle(ServerboundCookieResponsePacket packet) {
server.getEventManager() server.getEventManager()
.fire(new CookieReceiveEvent(player, packet.getKey(), packet.getPayload())) .fire(new CookieReceiveEvent(player, packet.key(), packet.payload()))
.thenAcceptAsync(event -> { .thenAcceptAsync(event -> {
if (event.getResult().isAllowed()) { if (event.getResult().isAllowed()) {
final VelocityServerConnection serverConnection = player.getConnectionInFlight(); final VelocityServerConnection serverConnection = player.getConnectionInFlight();

View File

@@ -735,7 +735,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
return; return;
} }
Component disconnectReason = disconnect.getReason().getComponent(); Component disconnectReason = disconnect.reason().getComponent();
String plainTextReason = PASS_THRU_TRANSLATE.serialize(disconnectReason); String plainTextReason = PASS_THRU_TRANSLATE.serialize(disconnectReason);
if (connectedServer != null && connectedServer.getServerInfo().equals(server.getServerInfo())) { if (connectedServer != null && connectedServer.getServerInfo().equals(server.getServerInfo())) {
if (this.server.getConfiguration().isLogPlayerConnections()) { if (this.server.getConfiguration().isLogPlayerConnections()) {
@@ -1349,7 +1349,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
private boolean sendKeepAliveToBackend(final @Nullable VelocityServerConnection serverConnection, final @NotNull KeepAlivePacket packet) { private boolean sendKeepAliveToBackend(final @Nullable VelocityServerConnection serverConnection, final @NotNull KeepAlivePacket packet) {
if (serverConnection != null) { if (serverConnection != null) {
final Long sentTime = serverConnection.getPendingPings().remove(packet.getRandomId()); final Long sentTime = serverConnection.getPendingPings().remove(packet.randomId());
if (sentTime != null) { if (sentTime != null) {
final MinecraftConnection smc = serverConnection.getConnection(); final MinecraftConnection smc = serverConnection.getConnection();
if (smc != null) { if (smc != null) {

View File

@@ -61,12 +61,12 @@ public final class InitialInboundConnection implements VelocityInboundConnection
@Override @Override
public Optional<InetSocketAddress> getVirtualHost() { public Optional<InetSocketAddress> getVirtualHost() {
return Optional.of(InetSocketAddress.createUnresolved(cleanedAddress, handshake.getPort())); return Optional.of(InetSocketAddress.createUnresolved(cleanedAddress, handshake.port()));
} }
@Override @Override
public Optional<String> getRawVirtualHost() { public Optional<String> getRawVirtualHost() {
return Optional.of(handshake.getServerAddress()); return Optional.of(handshake.serverAddress());
} }
@Override @Override
@@ -101,7 +101,7 @@ public final class InitialInboundConnection implements VelocityInboundConnection
@Override @Override
public HandshakeIntent getHandshakeIntent() { public HandshakeIntent getHandshakeIntent() {
return handshake.getIntent(); return handshake.intent();
} }
/** /**

View File

@@ -120,7 +120,7 @@ public class InitialLoginSessionHandler implements MinecraftSessionHandler {
inbound.setPlayerKey(playerKey); inbound.setPlayerKey(playerKey);
this.login = packet; this.login = packet;
final PreLoginEvent event = new PreLoginEvent(inbound, login.getUsername(), login.holderUuid()); final PreLoginEvent event = new PreLoginEvent(inbound, login.username(), login.holderUuid());
server.getEventManager().fire(event).thenRunAsync(() -> { server.getEventManager().fire(event).thenRunAsync(() -> {
if (mcConnection.isClosed()) { if (mcConnection.isClosed()) {
// The player was disconnected // The player was disconnected
@@ -146,13 +146,13 @@ public class InitialLoginSessionHandler implements MinecraftSessionHandler {
&& (server.getConfiguration().isOnlineMode() || result.isOnlineModeAllowed())) { && (server.getConfiguration().isOnlineMode() || result.isOnlineModeAllowed())) {
// Request encryption. // Request encryption.
EncryptionRequestPacket request = generateEncryptionRequest(); EncryptionRequestPacket request = generateEncryptionRequest();
this.verify = Arrays.copyOf(request.getVerifyToken(), 4); this.verify = Arrays.copyOf(request.verifyToken(), 4);
mcConnection.write(request); mcConnection.write(request);
this.currentState = LoginState.ENCRYPTION_REQUEST_SENT; this.currentState = LoginState.ENCRYPTION_REQUEST_SENT;
} else { } else {
mcConnection.setActiveSessionHandler(StateRegistry.LOGIN, mcConnection.setActiveSessionHandler(StateRegistry.LOGIN,
new AuthSessionHandler(server, inbound, new AuthSessionHandler(server, inbound,
GameProfile.forOfflinePlayer(login.getUsername()), false)); GameProfile.forOfflinePlayer(login.username()), false));
} }
}); });
}); });
@@ -203,7 +203,7 @@ public class InitialLoginSessionHandler implements MinecraftSessionHandler {
String playerIp = ((InetSocketAddress) mcConnection.getRemoteAddress()).getHostString(); String playerIp = ((InetSocketAddress) mcConnection.getRemoteAddress()).getHostString();
String url = String.format(MOJANG_HASJOINED_URL, String url = String.format(MOJANG_HASJOINED_URL,
urlFormParameterEscaper().escape(login.getUsername()), serverId); urlFormParameterEscaper().escape(login.username()), serverId);
if (server.getConfiguration().shouldPreventClientProxyConnections()) { if (server.getConfiguration().shouldPreventClientProxyConnections()) {
url += "&ip=" + urlFormParameterEscaper().escape(playerIp); url += "&ip=" + urlFormParameterEscaper().escape(playerIp);
@@ -263,7 +263,7 @@ public class InitialLoginSessionHandler implements MinecraftSessionHandler {
// Something else went wrong // Something else went wrong
logger.error( logger.error(
"Got an unexpected error code {} whilst contacting Mojang to log in {} ({})", "Got an unexpected error code {} whilst contacting Mojang to log in {} ({})",
response.statusCode(), login.getUsername(), playerIp); response.statusCode(), login.username(), playerIp);
inbound.disconnect(Component.translatable("multiplayer.disconnect.authservers_down")); inbound.disconnect(Component.translatable("multiplayer.disconnect.authservers_down"));
} }
}, mcConnection.eventLoop()) }, mcConnection.eventLoop())

View File

@@ -133,10 +133,10 @@ public class LoginInboundConnection implements LoginPhaseConnection, KeyIdentifi
} }
void handleLoginPluginResponse(final LoginPluginResponsePacket response) { void handleLoginPluginResponse(final LoginPluginResponsePacket response) {
final MessageConsumer consumer = this.outstandingResponses.remove(response.getId()); final MessageConsumer consumer = this.outstandingResponses.remove(response.id());
if (consumer != null) { if (consumer != null) {
try { try {
consumer.onMessageResponse(response.isSuccess() ? ByteBufUtil.getBytes(response.content()) consumer.onMessageResponse(response.success() ? ByteBufUtil.getBytes(response.content())
: null); : null);
} finally { } finally {
final Runnable onAllMessagesHandled = this.onAllMessagesHandled; final Runnable onAllMessagesHandled = this.onAllMessagesHandled;

View File

@@ -63,11 +63,11 @@ public class ConnectionRequestResults {
} }
public static Impl forDisconnect(DisconnectPacket disconnect, RegisteredServer server) { public static Impl forDisconnect(DisconnectPacket disconnect, RegisteredServer server) {
return forDisconnect(disconnect.getReason().getComponent(), server); return forDisconnect(disconnect.reason().getComponent(), server);
} }
public static Impl forUnsafeDisconnect(DisconnectPacket disconnect, RegisteredServer server) { public static Impl forUnsafeDisconnect(DisconnectPacket disconnect, RegisteredServer server) {
return new Impl(Status.SERVER_DISCONNECTED, disconnect.getReason().getComponent(), server, return new Impl(Status.SERVER_DISCONNECTED, disconnect.reason().getComponent(), server,
false); false);
} }

View File

@@ -65,14 +65,6 @@ public record BossBarPacket(UUID uuid, int action, @Nullable ComponentHolder nam
public static final int UPDATE_STYLE = 4; public static final int UPDATE_STYLE = 4;
public static final int UPDATE_PROPERTIES = 5; public static final int UPDATE_PROPERTIES = 5;
public UUID getUuid() {
return uuid;
}
public int getAction() {
return action;
}
public static BossBarPacket createAddPacket( public static BossBarPacket createAddPacket(
final UUID id, final UUID id,
final BossBar bar, final BossBar bar,

View File

@@ -28,36 +28,11 @@ import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
public final class DisconnectPacket implements MinecraftPacket { public record DisconnectPacket(StateRegistry state, ComponentHolder reason)
implements MinecraftPacket {
private final ComponentHolder reason; public DisconnectPacket {
private final StateRegistry state; Preconditions.checkNotNull(reason, "reason");
public DisconnectPacket(StateRegistry state, ComponentHolder reason) {
this.state = state;
this.reason = Preconditions.checkNotNull(reason, "reason");
}
public ComponentHolder reason() {
if (reason == null) {
throw new IllegalStateException("No reason specified");
}
return reason;
}
public ComponentHolder getReason() {
return reason();
}
public StateRegistry state() {
return state;
}
@Override
public String toString() {
return "Disconnect{"
+ "reason='" + reason + '\''
+ '}';
} }
@Override @Override

View File

@@ -24,7 +24,6 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.PacketCodec; import com.velocitypowered.proxy.protocol.PacketCodec;
import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import java.util.Arrays;
public final class EncryptionRequestPacket implements MinecraftPacket { public final class EncryptionRequestPacket implements MinecraftPacket {
@@ -57,22 +56,6 @@ public final class EncryptionRequestPacket implements MinecraftPacket {
return shouldAuthenticate; return shouldAuthenticate;
} }
public byte[] getPublicKey() {
return publicKey();
}
public byte[] getVerifyToken() {
return verifyToken();
}
@Override
public String toString() {
return "EncryptionRequest{"
+ "publicKey=" + Arrays.toString(publicKey)
+ ", verifyToken=" + Arrays.toString(verifyToken)
+ '}';
}
@Override @Override
public boolean handle(MinecraftSessionHandler handler) { public boolean handle(MinecraftSessionHandler handler) {
return handler.handle(this); return handler.handle(this);

View File

@@ -27,75 +27,19 @@ import com.velocitypowered.proxy.protocol.PacketCodec;
import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
public final class HandshakePacket implements MinecraftPacket { public record HandshakePacket(ProtocolVersion protocolVersion, String serverAddress, int port,
HandshakeIntent intent)
implements MinecraftPacket {
// This size was chosen to ensure Forge clients can still connect even with very long hostnames. // This size was chosen to ensure Forge clients can still connect even with very long hostnames.
// While DNS technically allows any character to be used, in practice ASCII is used. // While DNS technically allows any character to be used, in practice ASCII is used.
private static final int MAXIMUM_HOSTNAME_LENGTH = 255 + HANDSHAKE_HOSTNAME_TOKEN.length() + 1; private static final int MAXIMUM_HOSTNAME_LENGTH = 255 + HANDSHAKE_HOSTNAME_TOKEN.length() + 1;
private final ProtocolVersion protocolVersion; public static final HandshakePacket DEFAULT = new HandshakePacket(ProtocolVersion.MINIMUM_VERSION, "", 0,
private final String serverAddress; HandshakeIntent.LOGIN);
private final int port;
private final HandshakeIntent intent;
private final int nextStatus;
public HandshakePacket() {
this(ProtocolVersion.MINIMUM_VERSION, "", 0, HandshakeIntent.LOGIN);
}
public HandshakePacket(ProtocolVersion protocolVersion, String serverAddress, int port,
HandshakeIntent intent) {
this.protocolVersion = protocolVersion;
this.serverAddress = serverAddress;
this.port = port;
this.intent = intent;
this.nextStatus = intent.id();
}
public ProtocolVersion protocolVersion() {
return protocolVersion;
}
public String serverAddress() {
return serverAddress;
}
public int port() {
return port;
}
public int nextStatus() { public int nextStatus() {
return this.nextStatus; return intent.id();
}
public HandshakeIntent intent() {
return this.intent;
}
public ProtocolVersion getProtocolVersion() {
return protocolVersion();
}
public String getServerAddress() {
return serverAddress();
}
public int getPort() {
return port();
}
public HandshakeIntent getIntent() {
return intent();
}
@Override
public String toString() {
return "Handshake{"
+ "protocolVersion=" + protocolVersion
+ ", serverAddress='" + serverAddress + '\''
+ ", port=" + port
+ ", nextStatus=" + nextStatus
+ '}';
} }
@Override @Override
@@ -121,10 +65,10 @@ public final class HandshakePacket implements MinecraftPacket {
@Override @Override
public void encode(HandshakePacket packet, ByteBuf buf, ProtocolUtils.Direction direction, public void encode(HandshakePacket packet, ByteBuf buf, ProtocolUtils.Direction direction,
ProtocolVersion ignored) { ProtocolVersion ignored) {
ProtocolUtils.writeVarInt(buf, packet.protocolVersion.getProtocol()); ProtocolUtils.writeVarInt(buf, packet.protocolVersion().getProtocol());
ProtocolUtils.writeString(buf, packet.serverAddress); ProtocolUtils.writeString(buf, packet.serverAddress());
buf.writeShort(packet.port); buf.writeShort(packet.port());
ProtocolUtils.writeVarInt(buf, packet.nextStatus); ProtocolUtils.writeVarInt(buf, packet.nextStatus());
} }
@Override @Override

View File

@@ -26,17 +26,6 @@ import io.netty.buffer.ByteBuf;
public record KeepAlivePacket(long randomId) implements MinecraftPacket { public record KeepAlivePacket(long randomId) implements MinecraftPacket {
public long getRandomId() {
return randomId;
}
@Override
public String toString() {
return "KeepAlive{"
+ "randomId=" + randomId
+ '}';
}
@Override @Override
public boolean handle(MinecraftSessionHandler handler) { public boolean handle(MinecraftSessionHandler handler) {
return handler.handle(this); return handler.handle(this);

View File

@@ -47,14 +47,6 @@ public final class LoginPluginResponsePacket extends DefaultByteBufHolder
return success; return success;
} }
public int getId() {
return id();
}
public boolean isSuccess() {
return success();
}
@Override @Override
public String toString() { public String toString() {
return "LoginPluginResponse{" return "LoginPluginResponse{"

View File

@@ -33,54 +33,25 @@ import java.util.UUID;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
public final class ResourcePackRequestPacket implements MinecraftPacket { public record ResourcePackRequestPacket(
@Nullable UUID id, // 1.20.3+
private final @Nullable UUID id; // 1.20.3+ String url,
private final String url; String hash,
private final String hash; boolean isRequired, // 1.17+
private final boolean isRequired; // 1.17+ @Nullable ComponentHolder prompt // 1.17+
private final @Nullable ComponentHolder prompt; // 1.17+ ) implements MinecraftPacket {
private static final Pattern PLAUSIBLE_SHA1_HASH = Pattern.compile("^[a-z0-9]{40}$"); // 1.20.2+ private static final Pattern PLAUSIBLE_SHA1_HASH = Pattern.compile("^[a-z0-9]{40}$"); // 1.20.2+
public ResourcePackRequestPacket(@Nullable UUID id, String url, String hash,
boolean isRequired, @Nullable ComponentHolder prompt) {
this.id = id;
this.url = url;
this.hash = hash;
this.isRequired = isRequired;
this.prompt = prompt;
}
public @Nullable UUID getId() {
return id;
}
public String getUrl() {
return url;
}
public boolean isRequired() {
return isRequired;
}
public String getHash() {
return hash;
}
public @Nullable ComponentHolder getPrompt() {
return prompt;
}
public VelocityResourcePackInfo toServerPromptedPack() { public VelocityResourcePackInfo toServerPromptedPack() {
final ResourcePackInfo.Builder builder = final ResourcePackInfo.Builder builder =
new VelocityResourcePackInfo.BuilderImpl(Preconditions.checkNotNull(url)) new VelocityResourcePackInfo.BuilderImpl(Preconditions.checkNotNull(url()))
.setId(id).setPrompt(prompt == null ? null : prompt.getComponent()) .setId(id()).setPrompt(prompt() == null ? null : prompt().getComponent())
.setShouldForce(isRequired).setOrigin(ResourcePackInfo.Origin.DOWNSTREAM_SERVER); .setShouldForce(isRequired()).setOrigin(ResourcePackInfo.Origin.DOWNSTREAM_SERVER);
if (hash != null && !hash.isEmpty()) { if (hash() != null && !hash().isEmpty()) {
if (PLAUSIBLE_SHA1_HASH.matcher(hash).matches()) { if (PLAUSIBLE_SHA1_HASH.matcher(hash()).matches()) {
builder.setHash(ByteBufUtil.decodeHexDump(hash)); builder.setHash(ByteBufUtil.decodeHexDump(hash()));
} }
} }
return (VelocityResourcePackInfo) builder.build(); return (VelocityResourcePackInfo) builder.build();
@@ -129,21 +100,21 @@ public final class ResourcePackRequestPacket implements MinecraftPacket {
public void encode(ResourcePackRequestPacket packet, ByteBuf buf, Direction direction, public void encode(ResourcePackRequestPacket packet, ByteBuf buf, Direction direction,
ProtocolVersion protocolVersion) { ProtocolVersion protocolVersion) {
if (protocolVersion.noLessThan(ProtocolVersion.MINECRAFT_1_20_3)) { if (protocolVersion.noLessThan(ProtocolVersion.MINECRAFT_1_20_3)) {
if (packet.id == null) { if (packet.id() == null) {
throw new IllegalStateException("Resource pack id not set yet!"); throw new IllegalStateException("Resource pack id not set yet!");
} }
ProtocolUtils.writeUuid(buf, packet.id); ProtocolUtils.writeUuid(buf, packet.id());
} }
if (packet.url == null || packet.hash == null) { if (packet.url() == null || packet.hash() == null) {
throw new IllegalStateException("Packet not fully filled in yet!"); throw new IllegalStateException("Packet not fully filled in yet!");
} }
ProtocolUtils.writeString(buf, packet.url); ProtocolUtils.writeString(buf, packet.url());
ProtocolUtils.writeString(buf, packet.hash); ProtocolUtils.writeString(buf, packet.hash());
if (protocolVersion.noLessThan(ProtocolVersion.MINECRAFT_1_17)) { if (protocolVersion.noLessThan(ProtocolVersion.MINECRAFT_1_17)) {
buf.writeBoolean(packet.isRequired); buf.writeBoolean(packet.isRequired());
if (packet.prompt != null) { if (packet.prompt() != null) {
buf.writeBoolean(true); buf.writeBoolean(true);
packet.prompt.write(buf); packet.prompt().write(buf);
} else { } else {
buf.writeBoolean(false); buf.writeBoolean(false);
} }

View File

@@ -28,55 +28,29 @@ import io.netty.buffer.ByteBuf;
import java.util.UUID; import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
public final class ServerLoginPacket implements MinecraftPacket { public record ServerLoginPacket(
String username,
@Nullable IdentifiedKey playerKey, // Introduced in 1.19.3
@Nullable UUID holderUuid // Used for key revision 2
) implements MinecraftPacket {
private static final QuietDecoderException EMPTY_USERNAME = new QuietDecoderException( private static final QuietDecoderException EMPTY_USERNAME = new QuietDecoderException(
"Empty username!"); "Empty username!");
private final String username; /**
private final @Nullable IdentifiedKey playerKey; // Introduced in 1.19.3 * Creates a ServerLoginPacket with a player key.
private final @Nullable UUID holderUuid; // Used for key revision 2 */
public ServerLoginPacket(String username, @Nullable IdentifiedKey playerKey) { public ServerLoginPacket(String username, @Nullable IdentifiedKey playerKey) {
this(username, playerKey, null); this(username, playerKey, null);
} }
/**
* Creates a ServerLoginPacket with a holder UUID.
*/
public ServerLoginPacket(String username, @Nullable UUID holderUuid) { public ServerLoginPacket(String username, @Nullable UUID holderUuid) {
this(username, null, holderUuid); this(username, null, holderUuid);
} }
private ServerLoginPacket(String username, @Nullable IdentifiedKey playerKey,
@Nullable UUID holderUuid) {
this.username = username;
this.playerKey = playerKey;
this.holderUuid = holderUuid;
}
public String username() {
return username;
}
public String getUsername() {
return username();
}
public @Nullable IdentifiedKey playerKey() {
return this.playerKey;
}
public @Nullable UUID holderUuid() {
return holderUuid;
}
@Override
public String toString() {
return "ServerLogin{"
+ "username='" + username + '\''
+ "playerKey='" + playerKey + '\''
+ "holderUUID='" + holderUuid + '\''
+ '}';
}
@Override @Override
public boolean handle(MinecraftSessionHandler handler) { public boolean handle(MinecraftSessionHandler handler) {
return handler.handle(this); return handler.handle(this);
@@ -127,33 +101,33 @@ public final class ServerLoginPacket implements MinecraftPacket {
@Override @Override
public void encode(ServerLoginPacket packet, ByteBuf buf, ProtocolUtils.Direction direction, public void encode(ServerLoginPacket packet, ByteBuf buf, ProtocolUtils.Direction direction,
ProtocolVersion version) { ProtocolVersion version) {
if (packet.username == null) { if (packet.username() == null) {
throw new IllegalStateException("No username found!"); throw new IllegalStateException("No username found!");
} }
ProtocolUtils.writeString(buf, packet.username); ProtocolUtils.writeString(buf, packet.username());
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) {
if (version.lessThan(ProtocolVersion.MINECRAFT_1_19_3)) { if (version.lessThan(ProtocolVersion.MINECRAFT_1_19_3)) {
if (packet.playerKey != null) { if (packet.playerKey() != null) {
buf.writeBoolean(true); buf.writeBoolean(true);
ProtocolUtils.writePlayerKey(buf, packet.playerKey); ProtocolUtils.writePlayerKey(buf, packet.playerKey());
} else { } else {
buf.writeBoolean(false); buf.writeBoolean(false);
} }
} }
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_2)) { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_2)) {
ProtocolUtils.writeUuid(buf, packet.holderUuid); ProtocolUtils.writeUuid(buf, packet.holderUuid());
return; return;
} }
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)) { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)) {
if (packet.playerKey != null && packet.playerKey.getSignatureHolder() != null) { if (packet.playerKey() != null && packet.playerKey().getSignatureHolder() != null) {
buf.writeBoolean(true); buf.writeBoolean(true);
ProtocolUtils.writeUuid(buf, packet.playerKey.getSignatureHolder()); ProtocolUtils.writeUuid(buf, packet.playerKey().getSignatureHolder());
} else if (packet.holderUuid != null) { } else if (packet.holderUuid() != null) {
buf.writeBoolean(true); buf.writeBoolean(true);
ProtocolUtils.writeUuid(buf, packet.holderUuid); ProtocolUtils.writeUuid(buf, packet.holderUuid());
} else { } else {
buf.writeBoolean(false); buf.writeBoolean(false);
} }

View File

@@ -30,14 +30,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public record ServerboundCookieResponsePacket(Key key, public record ServerboundCookieResponsePacket(Key key,
byte @Nullable [] payload) implements MinecraftPacket { byte @Nullable [] payload) implements MinecraftPacket {
public Key getKey() {
return key;
}
public byte @Nullable [] getPayload() {
return payload;
}
@Override @Override
public boolean handle(MinecraftSessionHandler handler) { public boolean handle(MinecraftSessionHandler handler) {
return handler.handle(this); return handler.handle(this);

View File

@@ -42,7 +42,7 @@ public final class TabCompleteResponsePacket implements MinecraftPacket {
this.transactionId = transactionId; this.transactionId = transactionId;
this.start = start; this.start = start;
this.length = length; this.length = length;
this.offers = offers; this.offers = List.copyOf(offers);
} }
public int transactionId() { public int transactionId() {

View File

@@ -71,7 +71,7 @@ class PacketRegistryTest {
assertNotNull(packet, "Packet was not found in registry"); assertNotNull(packet, "Packet was not found in registry");
assertEquals(HandshakePacket.Codec.class, packet.getClass(), "Registry returned wrong class"); assertEquals(HandshakePacket.Codec.class, packet.getClass(), "Registry returned wrong class");
assertEquals(0, registry.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket()), assertEquals(0, registry.forVersion(MINECRAFT_1_12).getPacketId(HandshakePacket.DEFAULT),
"Registry did not return the correct packet ID"); "Registry did not return the correct packet ID");
} }
@@ -81,7 +81,7 @@ class PacketRegistryTest {
PacketCodec<?> packet = registry.forVersion(MINECRAFT_1_12_1).getCodec(0); PacketCodec<?> packet = registry.forVersion(MINECRAFT_1_12_1).getCodec(0);
assertNotNull(packet, "Packet was not found in registry"); assertNotNull(packet, "Packet was not found in registry");
assertEquals(HandshakePacket.Codec.class, packet.getClass(), "Registry returned wrong class"); assertEquals(HandshakePacket.Codec.class, packet.getClass(), "Registry returned wrong class");
HandshakePacket handshakePacket = new HandshakePacket(); HandshakePacket handshakePacket = HandshakePacket.DEFAULT;
assertEquals(0, registry.forVersion(MINECRAFT_1_12_1).getPacketId(handshakePacket), assertEquals(0, registry.forVersion(MINECRAFT_1_12_1).getPacketId(handshakePacket),
"Registry did not return the correct packet ID"); "Registry did not return the correct packet ID");
assertEquals(0, registry.forVersion(MINECRAFT_1_14_2).getPacketId(handshakePacket), assertEquals(0, registry.forVersion(MINECRAFT_1_14_2).getPacketId(handshakePacket),
@@ -227,9 +227,9 @@ class PacketRegistryTest {
.build(); .build();
// 1.12 should have ID 0x00 // 1.12 should have ID 0x00
assertEquals(0x00, registry.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket())); assertEquals(0x00, registry.forVersion(MINECRAFT_1_12).getPacketId(HandshakePacket.DEFAULT));
// 1.13 should have ID 0x01 // 1.13 should have ID 0x01
assertEquals(0x01, registry.forVersion(MINECRAFT_1_13).getPacketId(new HandshakePacket())); assertEquals(0x01, registry.forVersion(MINECRAFT_1_13).getPacketId(HandshakePacket.DEFAULT));
} }
@Test @Test
@@ -242,7 +242,7 @@ class PacketRegistryTest {
VersionRange.of(MINECRAFT_1_12, 0x01)) VersionRange.of(MINECRAFT_1_12, 0x01))
.build(); .build();
assertEquals(0x00, registry.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket())); assertEquals(0x00, registry.forVersion(MINECRAFT_1_12).getPacketId(HandshakePacket.DEFAULT));
assertEquals(0x01, registry.forVersion(MINECRAFT_1_12).getPacketId(new StatusPingPacket(0L))); assertEquals(0x01, registry.forVersion(MINECRAFT_1_12).getPacketId(new StatusPingPacket(0L)));
assertNotNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x00)); assertNotNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x00));
assertNotNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x01)); assertNotNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x01));
@@ -311,7 +311,7 @@ class PacketRegistryTest {
@Test @Test
void canDecodePacketReturnsTrue() { void canDecodePacketReturnsTrue() {
MultiVersionPacketRegistry registry = setupRegistry(); MultiVersionPacketRegistry registry = setupRegistry();
assertTrue(registry.forVersion(MINECRAFT_1_12).canDecodePacket(new HandshakePacket()), assertTrue(registry.forVersion(MINECRAFT_1_12).canDecodePacket(HandshakePacket.DEFAULT),
"Should be able to decode HandshakePacket in 1.12"); "Should be able to decode HandshakePacket in 1.12");
} }
@@ -330,7 +330,7 @@ class PacketRegistryTest {
.build(); .build();
// Encode-only packets can still be identified by class for encoding purposes // Encode-only packets can still be identified by class for encoding purposes
assertTrue(registry.forVersion(MINECRAFT_1_12).canDecodePacket(new HandshakePacket()), assertTrue(registry.forVersion(MINECRAFT_1_12).canDecodePacket(HandshakePacket.DEFAULT),
"Encode-only packets can be identified for encoding"); "Encode-only packets can be identified for encoding");
// But cannot be decoded by ID (not in packetIdToCodec) // But cannot be decoded by ID (not in packetIdToCodec)
assertNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x00), assertNull(registry.forVersion(MINECRAFT_1_12).getCodec(0x00),
@@ -364,7 +364,7 @@ class PacketRegistryTest {
SimplePacketRegistry registry = new SimplePacketRegistry(ProtocolUtils.Direction.CLIENTBOUND); SimplePacketRegistry registry = new SimplePacketRegistry(ProtocolUtils.Direction.CLIENTBOUND);
registry.register(0x42, HandshakePacket.class, new HandshakePacket.Codec()); registry.register(0x42, HandshakePacket.class, new HandshakePacket.Codec());
int id = registry.getPacketId(new HandshakePacket()); int id = registry.getPacketId(HandshakePacket.DEFAULT);
assertEquals(0x42, id, "Should return correct packet ID"); assertEquals(0x42, id, "Should return correct packet ID");
} }
@@ -383,7 +383,7 @@ class PacketRegistryTest {
SimplePacketRegistry registry = new SimplePacketRegistry(ProtocolUtils.Direction.CLIENTBOUND); SimplePacketRegistry registry = new SimplePacketRegistry(ProtocolUtils.Direction.CLIENTBOUND);
registry.register(0x00, HandshakePacket.class, new HandshakePacket.Codec()); registry.register(0x00, HandshakePacket.class, new HandshakePacket.Codec());
assertTrue(registry.canDecodePacket(new HandshakePacket()), assertTrue(registry.canDecodePacket(HandshakePacket.DEFAULT),
"Should be able to decode registered packet"); "Should be able to decode registered packet");
assertFalse(registry.canDecodePacket(new StatusPingPacket(0L)), assertFalse(registry.canDecodePacket(new StatusPingPacket(0L)),
"Should not be able to decode unregistered packet"); "Should not be able to decode unregistered packet");
@@ -405,8 +405,8 @@ class PacketRegistryTest {
VersionRange.of(MINECRAFT_1_12, 0x01)) VersionRange.of(MINECRAFT_1_12, 0x01))
.build(); .build();
assertEquals(0x00, clientbound.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket())); assertEquals(0x00, clientbound.forVersion(MINECRAFT_1_12).getPacketId(HandshakePacket.DEFAULT));
assertEquals(0x01, serverbound.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket())); assertEquals(0x01, serverbound.forVersion(MINECRAFT_1_12).getPacketId(HandshakePacket.DEFAULT));
} }
// ==================== Wide Version Range Tests ==================== // ==================== Wide Version Range Tests ====================
@@ -420,9 +420,9 @@ class PacketRegistryTest {
.build(); .build();
// Should work for all supported versions in range // Should work for all supported versions in range
assertEquals(0x00, registry.forVersion(MINECRAFT_1_8).getPacketId(new HandshakePacket())); assertEquals(0x00, registry.forVersion(MINECRAFT_1_8).getPacketId(HandshakePacket.DEFAULT));
assertEquals(0x00, registry.forVersion(MINECRAFT_1_12).getPacketId(new HandshakePacket())); assertEquals(0x00, registry.forVersion(MINECRAFT_1_12).getPacketId(HandshakePacket.DEFAULT));
assertEquals(0x00, registry.forVersion(MINECRAFT_1_16_2).getPacketId(new HandshakePacket())); assertEquals(0x00, registry.forVersion(MINECRAFT_1_16_2).getPacketId(HandshakePacket.DEFAULT));
} }
@Test @Test
@@ -433,7 +433,7 @@ class PacketRegistryTest {
VersionRange.of(MINECRAFT_1_15, 0x00)) VersionRange.of(MINECRAFT_1_15, 0x00))
.build(); .build();
assertEquals(0x00, registry.forVersion(MINECRAFT_1_15).getPacketId(new HandshakePacket())); assertEquals(0x00, registry.forVersion(MINECRAFT_1_15).getPacketId(HandshakePacket.DEFAULT));
assertEquals(0x00, registry.forVersion(MINECRAFT_1_16_2).getPacketId(new HandshakePacket())); assertEquals(0x00, registry.forVersion(MINECRAFT_1_16_2).getPacketId(HandshakePacket.DEFAULT));
} }
} }