13
0
geforkt von Mirrors/Velocity
Added support to Minecraft 1.20.5 (Release Candidate 3)

* Initial 1.20.5 update

* Snapshot 24w03a

* Handle Transfer Handshake intent

* Snapshot 24w03b

* Implement PreTransferEvent

* 24w04a

* Updated EncryptionRequestPacket, JoinGamePacket and ServerDataPacket to 24w04a

* Snapshot 24w05a

* Snapshot 24w05b

* Snapshot 24w06a

* Added migration to add new configuration option

* Snapshot 24w07a

* Snapshot 24w09a

* Snapshot 24w10a

* Snapshot 24w12a

* Snapshot 24w14a

* 1.20.5-rc1

* fix unsigned commands

* fix NPE

* fix respawn packet id

* 1.20.5 Release Candidate 2

* Restored old ConnectionHandshakeEvent constructor

* Added `-Dvelocity.strictErrorHandling` system property

* 1.20.5 Release Candidate 3

---------

Co-authored-by: Gero <gecam59@gmail.com>
Dieser Commit ist enthalten in:
Adrian 2024-04-22 21:12:25 -05:00 committet von GitHub
Ursprung be678840de
Commit 8f4adb1cec
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: B5690EEEBB952194
36 geänderte Dateien mit 782 neuen und 142 gelöschten Zeilen

Datei anzeigen

@ -8,6 +8,7 @@
package com.velocitypowered.api.event.connection;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.network.HandshakeIntent;
import com.velocitypowered.api.proxy.InboundConnection;
/**
@ -18,19 +19,39 @@ import com.velocitypowered.api.proxy.InboundConnection;
public final class ConnectionHandshakeEvent {
private final InboundConnection connection;
private final HandshakeIntent intent;
public ConnectionHandshakeEvent(InboundConnection connection, HandshakeIntent intent) {
this.connection = Preconditions.checkNotNull(connection, "connection");
this.intent = Preconditions.checkNotNull(intent, "intent");
}
/**
* This method is only retained to avoid breaking plugins
* that have not yet updated their integration tests.
*
* @param connection the inbound connection
* @deprecated use {@link #ConnectionHandshakeEvent(InboundConnection, HandshakeIntent)}
*/
@Deprecated(forRemoval = true)
public ConnectionHandshakeEvent(InboundConnection connection) {
this.connection = Preconditions.checkNotNull(connection, "connection");
this.intent = HandshakeIntent.LOGIN;
}
public InboundConnection getConnection() {
return connection;
}
public HandshakeIntent getIntent() {
return this.intent;
}
@Override
public String toString() {
return "ConnectionHandshakeEvent{"
+ "connection=" + connection
+ ", intent=" + intent
+ '}';
}
}

Datei anzeigen

@ -0,0 +1,100 @@
/*
* Copyright (C) 2024 Velocity Contributors
*
* The Velocity API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the api top-level directory.
*/
package com.velocitypowered.api.event.connection;
import static java.util.Objects.requireNonNull;
import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.event.annotation.AwaitingEvent;
import com.velocitypowered.api.proxy.Player;
import java.net.InetSocketAddress;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
/**
* This event is executed before sending a player to another host,
* either by the backend server or by a plugin using
* the {@link Player#transferToHost(InetSocketAddress)} method.
*/
@AwaitingEvent
@ApiStatus.Experimental
public final class PreTransferEvent implements ResultedEvent<PreTransferEvent.TransferResult> {
private final InetSocketAddress originalAddress;
private final Player player;
private TransferResult result = TransferResult.ALLOWED;
public PreTransferEvent(final Player player, final InetSocketAddress address) {
this.player = requireNonNull(player);
this.originalAddress = requireNonNull(address);
}
public Player player() {
return this.player;
}
public InetSocketAddress originalAddress() {
return this.originalAddress;
}
@Override
public TransferResult getResult() {
return this.result;
}
@Override
public void setResult(final TransferResult result) {
requireNonNull(result);
this.result = result;
}
/**
* Transfer Result of a player to another host.
*/
public static class TransferResult implements ResultedEvent.Result {
private static final TransferResult ALLOWED = new TransferResult(true, null);
private static final TransferResult DENIED = new TransferResult(false, null);
private final InetSocketAddress address;
private final boolean allowed;
private TransferResult(final boolean allowed, final InetSocketAddress address) {
this.address = address;
this.allowed = allowed;
}
public static TransferResult allowed() {
return ALLOWED;
}
public static TransferResult denied() {
return DENIED;
}
/**
* Sets the result of transfer to a specific host.
*
* @param address the address specified
* @return a new TransferResult
*/
public static TransferResult transferTo(final InetSocketAddress address) {
requireNonNull(address);
return new TransferResult(true, address);
}
@Override
public boolean isAllowed() {
return this.allowed;
}
@Nullable
public InetSocketAddress address() {
return this.address;
}
}
}

Datei anzeigen

@ -0,0 +1,42 @@
/*
* Copyright (C) 2024 Velocity Contributors
*
* The Velocity API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the api top-level directory.
*/
package com.velocitypowered.api.network;
/**
* Represents the ClientIntent of a client in the Handshake state.
*/
public enum HandshakeIntent {
STATUS(1),
LOGIN(2),
TRANSFER(3);
private final int id;
HandshakeIntent(int id) {
this.id = id;
}
public int id() {
return this.id;
}
/**
* Obtain the HandshakeIntent by ID.
*
* @param id the intent id
* @return the HandshakeIntent desired
*/
public static HandshakeIntent getById(int id) {
return switch (id) {
case 1 -> STATUS;
case 2 -> LOGIN;
case 3 -> TRANSFER;
default -> null;
};
}
}

Datei anzeigen

@ -16,14 +16,15 @@ package com.velocitypowered.api.network;
public enum ProtocolState {
/**
* Initial connection State.
* <p>This status can be caused by a STATUS, LOGIN or TRANSFER intent.</p>
* <p>This status can be caused by a {@link HandshakeIntent#STATUS},
* {@link HandshakeIntent#LOGIN} or {@link HandshakeIntent#TRANSFER} intent.</p>
* If the intent is LOGIN or TRANSFER, the next state will be {@link #LOGIN},
* otherwise, it will go to the {@link #STATUS} state.
*/
HANDSHAKE,
/**
* Ping State of a connection.
* <p>Connections with the STATUS HandshakeIntent will pass through this state
* <p>Connections with the {@link HandshakeIntent#STATUS} intent will pass through this state
* and be disconnected after it requests the ping from the server
* and the server responds with the respective ping.</p>
*/

Datei anzeigen

@ -85,7 +85,8 @@ public enum ProtocolVersion implements Ordered<ProtocolVersion> {
MINECRAFT_1_19_4(762, "1.19.4"),
MINECRAFT_1_20(763, "1.20", "1.20.1"),
MINECRAFT_1_20_2(764, "1.20.2"),
MINECRAFT_1_20_3(765, "1.20.3", "1.20.4");
MINECRAFT_1_20_3(765, "1.20.3", "1.20.4"),
MINECRAFT_1_20_5(-1, 191, "1.20.5"); // Future Minecraft 1.20.5 | Protocol 766 | Release Candidate 3
private static final int SNAPSHOT_BIT = 30;

Datei anzeigen

@ -20,6 +20,7 @@ import com.velocitypowered.api.proxy.player.TabList;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.api.util.ModInfo;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
@ -426,4 +427,13 @@ public interface Player extends
@Override
default void openBook(@NotNull Book book) {
}
/**
* Transfers a Player to a host.
*
* @param address the host address
* @throws IllegalArgumentException if the player is from a version lower than 1.20.5
* @since 3.3.0
*/
void transferToHost(@NotNull InetSocketAddress address);
}

Datei anzeigen

@ -17,6 +17,7 @@
package com.velocitypowered.proxy;
import com.velocitypowered.proxy.util.VelocityProperties;
import io.netty.util.ResourceLeakDetector;
import io.netty.util.ResourceLeakDetector.Level;
import java.text.DecimalFormat;
@ -42,13 +43,13 @@ public class Velocity {
// If Velocity's natives are being extracted to a different temporary directory, make sure the
// Netty natives are extracted there as well
if (System.getProperty("velocity.natives-tmpdir") != null) {
if (VelocityProperties.hasProperty("velocity.natives-tmpdir")) {
System.setProperty("io.netty.native.workdir", System.getProperty("velocity.natives-tmpdir"));
}
// Disable the resource leak detector by default as it reduces performance. Allow the user to
// override this if desired.
if (System.getProperty("io.netty.leakDetection.level") == null) {
if (!VelocityProperties.hasProperty("io.netty.leakDetection.level")) {
ResourceLeakDetector.setLevel(Level.DISABLED);
}
}

Datei anzeigen

@ -30,6 +30,7 @@ import com.velocitypowered.proxy.config.migration.ConfigurationMigration;
import com.velocitypowered.proxy.config.migration.ForwardingMigration;
import com.velocitypowered.proxy.config.migration.KeyAuthenticationMigration;
import com.velocitypowered.proxy.config.migration.MotdMigration;
import com.velocitypowered.proxy.config.migration.TransferIntegrationMigration;
import com.velocitypowered.proxy.util.AddressUtil;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
@ -398,6 +399,10 @@ public class VelocityConfiguration implements ProxyConfig {
return advanced.isLogPlayerConnections();
}
public boolean isAcceptTransfers() {
return this.advanced.isAcceptTransfers();
}
public boolean isForceKeyAuthentication() {
return forceKeyAuthentication;
}
@ -456,7 +461,8 @@ public class VelocityConfiguration implements ProxyConfig {
final ConfigurationMigration[] migrations = {
new ForwardingMigration(),
new KeyAuthenticationMigration(),
new MotdMigration()
new MotdMigration(),
new TransferIntegrationMigration()
};
for (final ConfigurationMigration migration : migrations) {
@ -708,6 +714,8 @@ public class VelocityConfiguration implements ProxyConfig {
private boolean logCommandExecutions = false;
@Expose
private boolean logPlayerConnections = true;
@Expose
private boolean acceptTransfers = false;
private Advanced() {
}
@ -732,6 +740,7 @@ public class VelocityConfiguration implements ProxyConfig {
this.announceProxyCommands = config.getOrElse("announce-proxy-commands", true);
this.logCommandExecutions = config.getOrElse("log-command-executions", false);
this.logPlayerConnections = config.getOrElse("log-player-connections", true);
this.acceptTransfers = config.getOrElse("accepts-transfers", false);
}
}
@ -791,6 +800,10 @@ public class VelocityConfiguration implements ProxyConfig {
return logPlayerConnections;
}
public boolean isAcceptTransfers() {
return this.acceptTransfers;
}
@Override
public String toString() {
return "Advanced{"
@ -807,6 +820,7 @@ public class VelocityConfiguration implements ProxyConfig {
+ ", announceProxyCommands=" + announceProxyCommands
+ ", logCommandExecutions=" + logCommandExecutions
+ ", logPlayerConnections=" + logPlayerConnections
+ ", acceptTransfers=" + acceptTransfers
+ '}';
}
}

Datei anzeigen

@ -25,7 +25,10 @@ import org.apache.logging.log4j.Logger;
* Configuration Migration interface.
*/
public sealed interface ConfigurationMigration
permits ForwardingMigration, KeyAuthenticationMigration, MotdMigration {
permits ForwardingMigration,
KeyAuthenticationMigration,
MotdMigration,
TransferIntegrationMigration {
boolean shouldMigrate(CommentedFileConfig config);
void migrate(CommentedFileConfig config, Logger logger) throws IOException;

Datei anzeigen

@ -0,0 +1,40 @@
/*
* Copyright (C) 2024 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.config.migration;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import org.apache.logging.log4j.Logger;
/**
* Creation of the configuration option "accepts-transfers".
*/
public final class TransferIntegrationMigration implements ConfigurationMigration {
@Override
public boolean shouldMigrate(final CommentedFileConfig config) {
return configVersion(config) < 2.7;
}
@Override
public void migrate(final CommentedFileConfig config, final Logger logger) {
config.set("advanced.accepts-transfers", false);
config.setComment("advanced.accepts-transfers", """
Allows players transferred from other hosts via the
Transfer packet (Minecraft 1.20.5) to be received.""");
config.set("config-version", "2.7");
}
}

Datei anzeigen

@ -51,6 +51,7 @@ 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.TransferPacket;
import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfoPacket;
import com.velocitypowered.proxy.protocol.packet.chat.ChatAcknowledgementPacket;
import com.velocitypowered.proxy.protocol.packet.chat.PlayerChatCompletionPacket;
@ -329,4 +330,8 @@ public interface MinecraftSessionHandler {
default boolean handle(BundleDelimiterPacket bundleDelimiterPacket) {
return false;
}
default boolean handle(TransferPacket transfer) {
return false;
}
}

Datei anzeigen

@ -25,6 +25,7 @@ import com.mojang.brigadier.tree.RootCommandNode;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.event.command.PlayerAvailableCommandsEvent;
import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.event.connection.PreTransferEvent;
import com.velocitypowered.api.event.player.PlayerResourcePackStatusEvent;
import com.velocitypowered.api.event.player.ServerResourcePackSendEvent;
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
@ -57,6 +58,7 @@ import com.velocitypowered.proxy.protocol.packet.ResourcePackRequestPacket;
import com.velocitypowered.proxy.protocol.packet.ResourcePackResponsePacket;
import com.velocitypowered.proxy.protocol.packet.ServerDataPacket;
import com.velocitypowered.proxy.protocol.packet.TabCompleteResponsePacket;
import com.velocitypowered.proxy.protocol.packet.TransferPacket;
import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfoPacket;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import com.velocitypowered.proxy.protocol.packet.config.StartUpdatePacket;
@ -66,6 +68,7 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.handler.timeout.ReadTimeoutException;
import java.net.InetSocketAddress;
import java.util.regex.Pattern;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -363,6 +366,30 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
return true;
}
@Override
public boolean handle(TransferPacket packet) {
final InetSocketAddress originalAddress = packet.address();
if (originalAddress == null) {
logger.error("""
Unexpected nullable address received in TransferPacket \
from Backend Server in Play State""");
return true;
}
this.server.getEventManager()
.fire(new PreTransferEvent(this.serverConn.getPlayer(), originalAddress))
.thenAcceptAsync(event -> {
if (event.getResult().isAllowed()) {
InetSocketAddress resultedAddress = event.getResult().address();
if (resultedAddress == null) {
resultedAddress = originalAddress;
}
this.playerConnection.write(new TransferPacket(
resultedAddress.getHostName(), resultedAddress.getPort()));
}
}, playerConnection.eventLoop());
return true;
}
@Override
public void handleGeneric(MinecraftPacket packet) {
if (packet instanceof PluginMessagePacket) {

Datei anzeigen

@ -17,6 +17,7 @@
package com.velocitypowered.proxy.connection.backend;
import com.velocitypowered.api.event.connection.PreTransferEvent;
import com.velocitypowered.api.event.player.PlayerResourcePackStatusEvent;
import com.velocitypowered.api.event.player.ServerResourcePackSendEvent;
import com.velocitypowered.api.network.ProtocolVersion;
@ -38,12 +39,14 @@ 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.ResourcePackResponsePacket;
import com.velocitypowered.proxy.protocol.packet.TransferPacket;
import com.velocitypowered.proxy.protocol.packet.config.FinishedUpdatePacket;
import com.velocitypowered.proxy.protocol.packet.config.RegistrySyncPacket;
import com.velocitypowered.proxy.protocol.packet.config.StartUpdatePacket;
import com.velocitypowered.proxy.protocol.packet.config.TagsUpdatePacket;
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.CompletableFuture;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -224,6 +227,30 @@ public class ConfigSessionHandler implements MinecraftSessionHandler {
return true;
}
@Override
public boolean handle(TransferPacket packet) {
final InetSocketAddress originalAddress = packet.address();
if (originalAddress == null) {
logger.error("""
Unexpected nullable address received in TransferPacket \
from Backend Server in Configuration State""");
return true;
}
this.server.getEventManager()
.fire(new PreTransferEvent(this.serverConn.getPlayer(), originalAddress))
.thenAcceptAsync(event -> {
if (event.getResult().isAllowed()) {
InetSocketAddress resultedAddress = event.getResult().address();
if (resultedAddress == null) {
resultedAddress = originalAddress;
}
serverConn.getPlayer().getConnection().write(new TransferPacket(
resultedAddress.getHostName(), resultedAddress.getPort()));
}
}, serverConn.ensureConnected().eventLoop());
return true;
}
@Override
public void disconnected() {
resultFuture.completeExceptionally(

Datei anzeigen

@ -22,6 +22,7 @@ import static com.velocitypowered.proxy.network.Connections.HANDLER;
import static java.util.Objects.requireNonNull;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.network.HandshakeIntent;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
@ -171,7 +172,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
.getHostString();
HandshakePacket handshake = new HandshakePacket();
handshake.setNextStatus(StateRegistry.LOGIN_ID);
handshake.setIntent(HandshakeIntent.LOGIN);
handshake.setProtocolVersion(protocolVersion);
if (forwardingMode == PlayerInfoForwarding.LEGACY) {
handshake.setServerAddress(createLegacyForwardingAddress());

Datei anzeigen

@ -26,6 +26,7 @@ import com.google.common.base.Preconditions;
import com.google.gson.JsonObject;
import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.connection.DisconnectEvent.LoginStatus;
import com.velocitypowered.api.event.connection.PreTransferEvent;
import com.velocitypowered.api.event.player.KickedFromServerEvent;
import com.velocitypowered.api.event.player.KickedFromServerEvent.DisconnectPlayer;
import com.velocitypowered.api.event.player.KickedFromServerEvent.Notify;
@ -69,6 +70,7 @@ import com.velocitypowered.proxy.protocol.packet.HeaderAndFooterPacket;
import com.velocitypowered.proxy.protocol.packet.KeepAlivePacket;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.protocol.packet.RemoveResourcePackPacket;
import com.velocitypowered.proxy.protocol.packet.TransferPacket;
import com.velocitypowered.proxy.protocol.packet.chat.ChatQueue;
import com.velocitypowered.proxy.protocol.packet.chat.ChatType;
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
@ -987,6 +989,25 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
this.clientBrand = clientBrand;
}
@Override
public void transferToHost(final InetSocketAddress address) {
Preconditions.checkNotNull(address);
Preconditions.checkArgument(
this.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_20_5) >= 0,
"Player version must be 1.20.5 to be able to transfer to another host");
server.getEventManager().fire(new PreTransferEvent(this, address)).thenAccept((event) -> {
if (event.getResult().isAllowed()) {
InetSocketAddress resultedAddress = event.getResult().address();
if (resultedAddress == null) {
resultedAddress = address;
}
connection.write(new TransferPacket(
resultedAddress.getHostName(), resultedAddress.getPort()));
}
});
}
@Override
public void addCustomChatCompletions(@NotNull Collection<String> completions) {
Preconditions.checkNotNull(completions, "completions");

Datei anzeigen

@ -20,6 +20,7 @@ package com.velocitypowered.proxy.connection.client;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.event.connection.ConnectionHandshakeEvent;
import com.velocitypowered.api.network.HandshakeIntent;
import com.velocitypowered.api.network.ProtocolState;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.VelocityServer;
@ -93,6 +94,11 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
} else {
final InitialInboundConnection ic = new InitialInboundConnection(connection,
cleanVhost(handshake.getServerAddress()), handshake);
if (handshake.getIntent() == HandshakeIntent.TRANSFER
&& !server.getConfiguration().isAcceptTransfers()) {
ic.disconnect(Component.translatable("multiplayer.disconnect.transfers_disabled"));
return true;
}
connection.setProtocolVersion(handshake.getProtocolVersion());
connection.setAssociation(ic);
@ -112,7 +118,7 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
private static @Nullable StateRegistry getStateForProtocol(int status) {
return switch (status) {
case StateRegistry.STATUS_ID -> StateRegistry.STATUS;
case StateRegistry.LOGIN_ID -> StateRegistry.LOGIN;
case StateRegistry.LOGIN_ID, StateRegistry.TRANSFER_ID -> StateRegistry.LOGIN;
default -> null;
};
}
@ -150,7 +156,8 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
}
final LoginInboundConnection lic = new LoginInboundConnection(ic);
server.getEventManager().fireAndForget(new ConnectionHandshakeEvent(lic));
server.getEventManager().fireAndForget(
new ConnectionHandshakeEvent(lic, handshake.getIntent()));
connection.setActiveSessionHandler(StateRegistry.LOGIN,
new InitialLoginSessionHandler(server, connection, lic));
}

Datei anzeigen

@ -40,6 +40,7 @@ import com.velocitypowered.proxy.protocol.packet.EncryptionRequestPacket;
import com.velocitypowered.proxy.protocol.packet.EncryptionResponsePacket;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponsePacket;
import com.velocitypowered.proxy.protocol.packet.ServerLoginPacket;
import com.velocitypowered.proxy.util.VelocityProperties;
import io.netty.buffer.ByteBuf;
import java.net.InetSocketAddress;
import java.net.URI;
@ -82,9 +83,8 @@ public class InitialLoginSessionHandler implements MinecraftSessionHandler {
this.server = Preconditions.checkNotNull(server, "server");
this.mcConnection = Preconditions.checkNotNull(mcConnection, "mcConnection");
this.inbound = Preconditions.checkNotNull(inbound, "inbound");
this.forceKeyAuthentication = System.getProperties().containsKey("auth.forceSecureProfiles")
? Boolean.getBoolean("auth.forceSecureProfiles")
: server.getConfiguration().isForceKeyAuthentication();
this.forceKeyAuthentication = VelocityProperties.readBoolean(
"auth.forceSecureProfiles", server.getConfiguration().isForceKeyAuthentication());
}
@Override

Datei anzeigen

@ -18,6 +18,7 @@
package com.velocitypowered.proxy.connection.registry;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.network.ProtocolVersion;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
@ -40,11 +41,11 @@ public final class DimensionInfo {
* @param isDebugType if true constrains the world to the very limited debug-type world
*/
public DimensionInfo(String registryIdentifier, @Nullable String levelName,
boolean isFlat, boolean isDebugType) {
this.registryIdentifier = Preconditions.checkNotNull(
registryIdentifier, "registryIdentifier cannot be null");
Preconditions.checkArgument(registryIdentifier.length() > 0,
"registryIdentifier cannot be empty");
boolean isFlat, boolean isDebugType, ProtocolVersion protocolVersion) {
this.registryIdentifier = Preconditions.checkNotNull(registryIdentifier, "registryIdentifier cannot be null");
if (protocolVersion.lessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
Preconditions.checkArgument(!registryIdentifier.isEmpty(), "registryIdentifier cannot be empty");
}
this.levelName = levelName;
this.isFlat = isFlat;
this.isDebugType = isDebugType;

Datei anzeigen

@ -35,6 +35,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_3;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_4;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_2;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_3;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_5;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_7_2;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9;
@ -78,6 +79,7 @@ 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.TransferPacket;
import com.velocitypowered.proxy.protocol.packet.UpsertPlayerInfoPacket;
import com.velocitypowered.proxy.protocol.packet.chat.ChatAcknowledgementPacket;
import com.velocitypowered.proxy.protocol.packet.chat.PlayerChatCompletionPacket;
@ -87,6 +89,7 @@ import com.velocitypowered.proxy.protocol.packet.chat.keyed.KeyedPlayerCommandPa
import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChatPacket;
import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerChatPacket;
import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerCommandPacket;
import com.velocitypowered.proxy.protocol.packet.chat.session.UnsignedPlayerCommandPacket;
import com.velocitypowered.proxy.protocol.packet.config.ActiveFeaturesPacket;
import com.velocitypowered.proxy.protocol.packet.config.FinishedUpdatePacket;
import com.velocitypowered.proxy.protocol.packet.config.RegistrySyncPacket;
@ -144,49 +147,66 @@ public enum StateRegistry {
map(0x00, MINECRAFT_1_20_2, false));
serverbound.register(
PluginMessagePacket.class, PluginMessagePacket::new,
map(0x01, MINECRAFT_1_20_2, false));
map(0x01, MINECRAFT_1_20_2, false),
map(0x02, MINECRAFT_1_20_5, false));
serverbound.register(
FinishedUpdatePacket.class, () -> FinishedUpdatePacket.INSTANCE,
map(0x02, MINECRAFT_1_20_2, false));
map(0x02, MINECRAFT_1_20_2, false),
map(0x03, MINECRAFT_1_20_5, false));
serverbound.register(KeepAlivePacket.class, KeepAlivePacket::new,
map(0x03, MINECRAFT_1_20_2, false));
map(0x03, MINECRAFT_1_20_2, false),
map(0x04, MINECRAFT_1_20_5, false));
serverbound.register(
PingIdentifyPacket.class, PingIdentifyPacket::new,
map(0x04, MINECRAFT_1_20_2, false));
map(0x04, MINECRAFT_1_20_2, false),
map(0x05, MINECRAFT_1_20_5, false));
serverbound.register(
ResourcePackResponsePacket.class,
ResourcePackResponsePacket::new,
map(0x05, MINECRAFT_1_20_2, false));
map(0x05, MINECRAFT_1_20_2, false),
map(0x06, MINECRAFT_1_20_5, false));
clientbound.register(
PluginMessagePacket.class, PluginMessagePacket::new,
map(0x00, MINECRAFT_1_20_2, false));
map(0x00, MINECRAFT_1_20_2, false),
map(0x01, MINECRAFT_1_20_5, false));
clientbound.register(
DisconnectPacket.class, () -> new DisconnectPacket(this),
map(0x01, MINECRAFT_1_20_2, false));
map(0x01, MINECRAFT_1_20_2, false),
map(0x02, MINECRAFT_1_20_5, false));
clientbound.register(
FinishedUpdatePacket.class, () -> FinishedUpdatePacket.INSTANCE,
map(0x02, MINECRAFT_1_20_2, false));
map(0x02, MINECRAFT_1_20_2, false),
map(0x03, MINECRAFT_1_20_5, false));
clientbound.register(KeepAlivePacket.class, KeepAlivePacket::new,
map(0x03, MINECRAFT_1_20_2, false));
map(0x03, MINECRAFT_1_20_2, false),
map(0x04, MINECRAFT_1_20_5, false));
clientbound.register(
PingIdentifyPacket.class, PingIdentifyPacket::new,
map(0x04, MINECRAFT_1_20_2, false));
map(0x04, MINECRAFT_1_20_2, false),
map(0x05, MINECRAFT_1_20_5, false));
clientbound.register(
RegistrySyncPacket.class, RegistrySyncPacket::new,
map(0x05, MINECRAFT_1_20_2, false));
map(0x05, MINECRAFT_1_20_2, false),
map(0x07, MINECRAFT_1_20_5, false));
clientbound.register(
RemoveResourcePackPacket.class, RemoveResourcePackPacket::new,
map(0x06, MINECRAFT_1_20_3, false));
map(0x06, MINECRAFT_1_20_3, false),
map(0x08, MINECRAFT_1_20_5, false));
clientbound.register(ResourcePackRequestPacket.class, ResourcePackRequestPacket::new,
map(0x06, MINECRAFT_1_20_2, false),
map(0x07, MINECRAFT_1_20_3, false));
map(0x07, MINECRAFT_1_20_3, false),
map(0x09, MINECRAFT_1_20_5, false));
clientbound.register(TransferPacket.class, TransferPacket::new,
map(0x0B, MINECRAFT_1_20_5, false));
clientbound.register(ActiveFeaturesPacket.class, ActiveFeaturesPacket::new,
map(0x07, MINECRAFT_1_20_2, false),
map(0x08, MINECRAFT_1_20_3, false));
map(0x08, MINECRAFT_1_20_3, false),
map(0x0C, MINECRAFT_1_20_5, false));
clientbound.register(TagsUpdatePacket.class, TagsUpdatePacket::new,
map(0x08, MINECRAFT_1_20_2, false),
map(0x09, MINECRAFT_1_20_3, false));
map(0x09, MINECRAFT_1_20_3, false),
map(0x0D, MINECRAFT_1_20_5, false));
}
},
PLAY {
@ -205,7 +225,8 @@ public enum StateRegistry {
map(0x09, MINECRAFT_1_19_1, false),
map(0x08, MINECRAFT_1_19_3, false),
map(0x09, MINECRAFT_1_19_4, false),
map(0x0A, MINECRAFT_1_20_2, false));
map(0x0A, MINECRAFT_1_20_2, false),
map(0x0B, MINECRAFT_1_20_5, false));
serverbound.register(
LegacyChatPacket.class,
LegacyChatPacket::new,
@ -225,11 +246,15 @@ public enum StateRegistry {
map(0x04, MINECRAFT_1_19, false),
map(0x05, MINECRAFT_1_19_1, MINECRAFT_1_19_1, false));
serverbound.register(SessionPlayerCommandPacket.class, SessionPlayerCommandPacket::new,
map(0x04, MINECRAFT_1_19_3, false));
map(0x04, MINECRAFT_1_19_3, false),
map(0x05, MINECRAFT_1_20_5, false));
serverbound.register(UnsignedPlayerCommandPacket.class, UnsignedPlayerCommandPacket::new,
map(0x04, MINECRAFT_1_20_5, false));
serverbound.register(
SessionPlayerChatPacket.class,
SessionPlayerChatPacket::new,
map(0x05, MINECRAFT_1_19_3, false));
map(0x05, MINECRAFT_1_19_3, false),
map(0x06, MINECRAFT_1_20_5, false));
serverbound.register(
ClientSettingsPacket.class,
ClientSettingsPacket::new,
@ -242,7 +267,8 @@ public enum StateRegistry {
map(0x08, MINECRAFT_1_19_1, false),
map(0x07, MINECRAFT_1_19_3, false),
map(0x08, MINECRAFT_1_19_4, false),
map(0x09, MINECRAFT_1_20_2, false));
map(0x09, MINECRAFT_1_20_2, false),
map(0x0A, MINECRAFT_1_20_5, false));
serverbound.register(
PluginMessagePacket.class,
PluginMessagePacket::new,
@ -258,7 +284,8 @@ public enum StateRegistry {
map(0x0C, MINECRAFT_1_19_3, false),
map(0x0D, MINECRAFT_1_19_4, false),
map(0x0F, MINECRAFT_1_20_2, false),
map(0x10, MINECRAFT_1_20_3, false));
map(0x10, MINECRAFT_1_20_3, false),
map(0x12, MINECRAFT_1_20_5, false));
serverbound.register(
KeepAlivePacket.class,
KeepAlivePacket::new,
@ -275,7 +302,8 @@ public enum StateRegistry {
map(0x11, MINECRAFT_1_19_3, false),
map(0x12, MINECRAFT_1_19_4, false),
map(0x14, MINECRAFT_1_20_2, false),
map(0x15, MINECRAFT_1_20_3, false));
map(0x15, MINECRAFT_1_20_3, false),
map(0x18, MINECRAFT_1_20_5, false));
serverbound.register(
ResourcePackResponsePacket.class,
ResourcePackResponsePacket::new,
@ -289,10 +317,12 @@ public enum StateRegistry {
map(0x23, MINECRAFT_1_19, false),
map(0x24, MINECRAFT_1_19_1, false),
map(0x27, MINECRAFT_1_20_2, false),
map(0x28, MINECRAFT_1_20_3, false));
map(0x28, MINECRAFT_1_20_3, false),
map(0x2B, MINECRAFT_1_20_5, false));
serverbound.register(
FinishedUpdatePacket.class, () -> FinishedUpdatePacket.INSTANCE,
map(0x0B, MINECRAFT_1_20_2, false));
map(0x0B, MINECRAFT_1_20_2, false),
map(0x0C, MINECRAFT_1_20_5, false));
clientbound.register(
BossBarPacket.class,
@ -352,7 +382,8 @@ public enum StateRegistry {
map(0x16, MINECRAFT_1_19_1, false),
map(0x15, MINECRAFT_1_19_3, false),
map(0x17, MINECRAFT_1_19_4, false),
map(0x18, MINECRAFT_1_20_2, false));
map(0x18, MINECRAFT_1_20_2, false),
map(0x19, MINECRAFT_1_20_5, false));
clientbound.register(
DisconnectPacket.class,
() -> new DisconnectPacket(this),
@ -368,7 +399,8 @@ public enum StateRegistry {
map(0x19, MINECRAFT_1_19_1, false),
map(0x17, MINECRAFT_1_19_3, false),
map(0x1A, MINECRAFT_1_19_4, false),
map(0x1B, MINECRAFT_1_20_2, false));
map(0x1B, MINECRAFT_1_20_2, false),
map(0x1D, MINECRAFT_1_20_5, false));
clientbound.register(
KeepAlivePacket.class,
KeepAlivePacket::new,
@ -384,7 +416,8 @@ public enum StateRegistry {
map(0x20, MINECRAFT_1_19_1, false),
map(0x1F, MINECRAFT_1_19_3, false),
map(0x23, MINECRAFT_1_19_4, false),
map(0x24, MINECRAFT_1_20_2, false));
map(0x24, MINECRAFT_1_20_2, false),
map(0x26, MINECRAFT_1_20_5, false));
clientbound.register(
JoinGamePacket.class,
JoinGamePacket::new,
@ -400,7 +433,8 @@ public enum StateRegistry {
map(0x25, MINECRAFT_1_19_1, false),
map(0x24, MINECRAFT_1_19_3, false),
map(0x28, MINECRAFT_1_19_4, false),
map(0x29, MINECRAFT_1_20_2, false));
map(0x29, MINECRAFT_1_20_2, false),
map(0x2B, MINECRAFT_1_20_5, false));
clientbound.register(
RespawnPacket.class,
RespawnPacket::new,
@ -419,11 +453,13 @@ public enum StateRegistry {
map(0x3D, MINECRAFT_1_19_3, true),
map(0x41, MINECRAFT_1_19_4, true),
map(0x43, MINECRAFT_1_20_2, true),
map(0x45, MINECRAFT_1_20_3, true));
map(0x45, MINECRAFT_1_20_3, true),
map(0x47, MINECRAFT_1_20_5, true));
clientbound.register(
RemoveResourcePackPacket.class,
RemoveResourcePackPacket::new,
map(0x43, MINECRAFT_1_20_3, false));
map(0x43, MINECRAFT_1_20_3, false),
map(0x45, MINECRAFT_1_20_5, false));
clientbound.register(
ResourcePackRequestPacket.class,
ResourcePackRequestPacket::new,
@ -442,7 +478,8 @@ public enum StateRegistry {
map(0x3C, MINECRAFT_1_19_3, false),
map(0x40, MINECRAFT_1_19_4, false),
map(0x42, MINECRAFT_1_20_2, false),
map(0x44, MINECRAFT_1_20_3, false));
map(0x44, MINECRAFT_1_20_3, false),
map(0x46, MINECRAFT_1_20_5, false));
clientbound.register(
HeaderAndFooterPacket.class,
HeaderAndFooterPacket::new,
@ -462,7 +499,8 @@ public enum StateRegistry {
map(0x61, MINECRAFT_1_19_3, true),
map(0x65, MINECRAFT_1_19_4, true),
map(0x68, MINECRAFT_1_20_2, true),
map(0x6A, MINECRAFT_1_20_3, true));
map(0x6A, MINECRAFT_1_20_3, true),
map(0x6D, MINECRAFT_1_20_5, true));
clientbound.register(
LegacyTitlePacket.class,
LegacyTitlePacket::new,
@ -481,7 +519,8 @@ public enum StateRegistry {
map(0x59, MINECRAFT_1_19_3, true),
map(0x5D, MINECRAFT_1_19_4, true),
map(0x5F, MINECRAFT_1_20_2, true),
map(0x61, MINECRAFT_1_20_3, true));
map(0x61, MINECRAFT_1_20_3, true),
map(0x63, MINECRAFT_1_20_5, true));
clientbound.register(
TitleTextPacket.class,
TitleTextPacket::new,
@ -491,7 +530,8 @@ public enum StateRegistry {
map(0x5B, MINECRAFT_1_19_3, true),
map(0x5F, MINECRAFT_1_19_4, true),
map(0x61, MINECRAFT_1_20_2, true),
map(0x63, MINECRAFT_1_20_3, true));
map(0x63, MINECRAFT_1_20_3, true),
map(0x65, MINECRAFT_1_20_5, true));
clientbound.register(
TitleActionbarPacket.class,
TitleActionbarPacket::new,
@ -501,7 +541,8 @@ public enum StateRegistry {
map(0x42, MINECRAFT_1_19_3, true),
map(0x46, MINECRAFT_1_19_4, true),
map(0x48, MINECRAFT_1_20_2, true),
map(0x4A, MINECRAFT_1_20_3, true));
map(0x4A, MINECRAFT_1_20_3, true),
map(0x4C, MINECRAFT_1_20_5, true));
clientbound.register(
TitleTimesPacket.class,
TitleTimesPacket::new,
@ -511,7 +552,8 @@ public enum StateRegistry {
map(0x5C, MINECRAFT_1_19_3, true),
map(0x60, MINECRAFT_1_19_4, true),
map(0x62, MINECRAFT_1_20_2, true),
map(0x64, MINECRAFT_1_20_3, true));
map(0x64, MINECRAFT_1_20_3, true),
map(0x66, MINECRAFT_1_20_5, true));
clientbound.register(
TitleClearPacket.class,
TitleClearPacket::new,
@ -537,13 +579,15 @@ public enum StateRegistry {
clientbound.register(RemovePlayerInfoPacket.class, RemovePlayerInfoPacket::new,
map(0x35, MINECRAFT_1_19_3, false),
map(0x39, MINECRAFT_1_19_4, false),
map(0x3B, MINECRAFT_1_20_2, false));
map(0x3B, MINECRAFT_1_20_2, false),
map(0x3D, MINECRAFT_1_20_5, false));
clientbound.register(
UpsertPlayerInfoPacket.class,
UpsertPlayerInfoPacket::new,
map(0x36, MINECRAFT_1_19_3, false),
map(0x3A, MINECRAFT_1_19_4, false),
map(0x3C, MINECRAFT_1_20_2, false));
map(0x3C, MINECRAFT_1_20_2, false),
map(0x3E, MINECRAFT_1_20_5, false));
clientbound.register(
SystemChatPacket.class,
SystemChatPacket::new,
@ -552,14 +596,16 @@ public enum StateRegistry {
map(0x60, MINECRAFT_1_19_3, true),
map(0x64, MINECRAFT_1_19_4, true),
map(0x67, MINECRAFT_1_20_2, true),
map(0x69, MINECRAFT_1_20_3, true));
map(0x69, MINECRAFT_1_20_3, true),
map(0x6C, MINECRAFT_1_20_5, true));
clientbound.register(
PlayerChatCompletionPacket.class,
PlayerChatCompletionPacket::new,
map(0x15, MINECRAFT_1_19_1, true),
map(0x14, MINECRAFT_1_19_3, true),
map(0x16, MINECRAFT_1_19_4, true),
map(0x17, MINECRAFT_1_20_2, true));
map(0x17, MINECRAFT_1_20_2, true),
map(0x18, MINECRAFT_1_20_5, true));
clientbound.register(
ServerDataPacket.class,
ServerDataPacket::new,
@ -568,16 +614,23 @@ public enum StateRegistry {
map(0x41, MINECRAFT_1_19_3, false),
map(0x45, MINECRAFT_1_19_4, false),
map(0x47, MINECRAFT_1_20_2, false),
map(0x49, MINECRAFT_1_20_3, false));
map(0x49, MINECRAFT_1_20_3, false),
map(0x4B, MINECRAFT_1_20_5, false));
clientbound.register(
StartUpdatePacket.class,
() -> StartUpdatePacket.INSTANCE,
map(0x65, MINECRAFT_1_20_2, false),
map(0x67, MINECRAFT_1_20_3, false));
map(0x67, MINECRAFT_1_20_3, false),
map(0x69, MINECRAFT_1_20_5, false));
clientbound.register(
BundleDelimiterPacket.class,
() -> BundleDelimiterPacket.INSTANCE,
map(0x00, MINECRAFT_1_19_4, false));
clientbound.register(
TransferPacket.class,
TransferPacket::new,
map(0x73, MINECRAFT_1_20_5, false)
);
}
},
LOGIN {
@ -616,6 +669,7 @@ public enum StateRegistry {
public static final int STATUS_ID = 1;
public static final int LOGIN_ID = 2;
public static final int TRANSFER_ID = 3;
protected final PacketRegistry clientbound = new PacketRegistry(CLIENTBOUND, this);
protected final PacketRegistry serverbound = new PacketRegistry(SERVERBOUND, this);

Datei anzeigen

@ -31,6 +31,7 @@ public class EncryptionRequestPacket implements MinecraftPacket {
private String serverId = "";
private byte[] publicKey = EMPTY_BYTE_ARRAY;
private byte[] verifyToken = EMPTY_BYTE_ARRAY;
private boolean shouldAuthenticate = true;
public byte[] getPublicKey() {
return publicKey.clone();
@ -63,6 +64,9 @@ public class EncryptionRequestPacket implements MinecraftPacket {
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_8)) {
publicKey = ProtocolUtils.readByteArray(buf, 256);
verifyToken = ProtocolUtils.readByteArray(buf, 16);
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
shouldAuthenticate = buf.readBoolean();
}
} else {
publicKey = ProtocolUtils.readByteArray17(buf);
verifyToken = ProtocolUtils.readByteArray17(buf);
@ -76,6 +80,9 @@ public class EncryptionRequestPacket implements MinecraftPacket {
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_8)) {
ProtocolUtils.writeByteArray(buf, publicKey);
ProtocolUtils.writeByteArray(buf, verifyToken);
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
buf.writeBoolean(shouldAuthenticate);
}
} else {
ProtocolUtils.writeByteArray17(publicKey, buf, false);
ProtocolUtils.writeByteArray17(verifyToken, buf, false);

Datei anzeigen

@ -19,6 +19,7 @@ package com.velocitypowered.proxy.protocol.packet;
import static com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants.HANDSHAKE_HOSTNAME_TOKEN;
import com.velocitypowered.api.network.HandshakeIntent;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
@ -33,6 +34,7 @@ public class HandshakePacket implements MinecraftPacket {
private ProtocolVersion protocolVersion;
private String serverAddress = "";
private int port;
private HandshakeIntent intent;
private int nextStatus;
public ProtocolVersion getProtocolVersion() {
@ -60,11 +62,16 @@ public class HandshakePacket implements MinecraftPacket {
}
public int getNextStatus() {
return nextStatus;
return this.nextStatus;
}
public void setNextStatus(int nextStatus) {
this.nextStatus = nextStatus;
public void setIntent(HandshakeIntent intent) {
this.intent = intent;
this.nextStatus = intent.id();
}
public HandshakeIntent getIntent() {
return this.intent;
}
@Override
@ -84,6 +91,7 @@ public class HandshakePacket implements MinecraftPacket {
this.serverAddress = ProtocolUtils.readString(buf, MAXIMUM_HOSTNAME_LENGTH);
this.port = buf.readUnsignedShort();
this.nextStatus = ProtocolUtils.readVarInt(buf);
this.intent = HandshakeIntent.getById(nextStatus);
}
@Override

Datei anzeigen

@ -51,6 +51,7 @@ public class JoinGamePacket implements MinecraftPacket {
private int simulationDistance; // 1.18+
private @Nullable Pair<String, Long> lastDeathPosition; // 1.19+
private int portalCooldown; // 1.20+
private boolean enforcesSecureChat; // 1.20.5+
public int getEntityId() {
return entityId;
@ -180,6 +181,14 @@ public class JoinGamePacket implements MinecraftPacket {
this.portalCooldown = portalCooldown;
}
public boolean getEnforcesSecureChat() {
return this.enforcesSecureChat;
}
public void setEnforcesSecureChat(final boolean enforcesSecureChat) {
this.enforcesSecureChat = enforcesSecureChat;
}
public CompoundBinaryTag getRegistry() {
return registry;
}
@ -284,7 +293,7 @@ public class JoinGamePacket implements MinecraftPacket {
boolean isDebug = buf.readBoolean();
boolean isFlat = buf.readBoolean();
this.dimensionInfo = new DimensionInfo(dimensionIdentifier, levelName, isFlat, isDebug);
this.dimensionInfo = new DimensionInfo(dimensionIdentifier, levelName, isFlat, isDebug, version);
// optional death location
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19) && buf.readBoolean()) {
@ -296,6 +305,7 @@ public class JoinGamePacket implements MinecraftPacket {
}
}
@SuppressWarnings("checkstyle:VariableDeclarationUsageDistance")
private void decode1202Up(ByteBuf buf, ProtocolVersion version) {
this.entityId = buf.readInt();
this.isHardcore = buf.readBoolean();
@ -311,7 +321,12 @@ public class JoinGamePacket implements MinecraftPacket {
this.showRespawnScreen = buf.readBoolean();
this.doLimitedCrafting = buf.readBoolean();
String dimensionIdentifier = ProtocolUtils.readString(buf);
String dimensionKey = "";
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
dimension = ProtocolUtils.readVarInt(buf);
} else {
dimensionKey = ProtocolUtils.readString(buf);
}
String levelName = ProtocolUtils.readString(buf);
this.partialHashedSeed = buf.readLong();
@ -320,7 +335,7 @@ public class JoinGamePacket implements MinecraftPacket {
boolean isDebug = buf.readBoolean();
boolean isFlat = buf.readBoolean();
this.dimensionInfo = new DimensionInfo(dimensionIdentifier, levelName, isFlat, isDebug);
this.dimensionInfo = new DimensionInfo(dimensionKey, levelName, isFlat, isDebug, version);
// optional death location
if (buf.readBoolean()) {
@ -328,6 +343,9 @@ public class JoinGamePacket implements MinecraftPacket {
}
this.portalCooldown = ProtocolUtils.readVarInt(buf);
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
this.enforcesSecureChat = buf.readBoolean();
}
}
@Override
@ -391,8 +409,7 @@ public class JoinGamePacket implements MinecraftPacket {
ProtocolUtils.writeStringArray(buf, levelNames.toArray(String[]::new));
ProtocolUtils.writeBinaryTag(buf, version, this.registry);
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_16_2)
&& version.lessThan(ProtocolVersion.MINECRAFT_1_19)) {
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_16_2) && version.lessThan(ProtocolVersion.MINECRAFT_1_19)) {
ProtocolUtils.writeBinaryTag(buf, version, currentDimensionData);
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
} else {
@ -449,7 +466,11 @@ public class JoinGamePacket implements MinecraftPacket {
buf.writeBoolean(showRespawnScreen);
buf.writeBoolean(doLimitedCrafting);
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
ProtocolUtils.writeVarInt(buf, dimension);
} else {
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
}
ProtocolUtils.writeString(buf, dimensionInfo.getLevelName());
buf.writeLong(partialHashedSeed);
@ -469,6 +490,10 @@ public class JoinGamePacket implements MinecraftPacket {
}
ProtocolUtils.writeVarInt(buf, portalCooldown);
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
buf.writeBoolean(this.enforcesSecureChat);
}
}
@Override

Datei anzeigen

@ -160,15 +160,19 @@ public class RespawnPacket implements MinecraftPacket {
@Override
public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) {
String dimensionIdentifier = null;
String dimensionKey = "";
String levelName = null;
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_16)) {
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_16_2)
&& version.lessThan(ProtocolVersion.MINECRAFT_1_19)) {
this.currentDimensionData = ProtocolUtils.readCompoundTag(buf, version, BinaryTagIO.reader());
dimensionIdentifier = ProtocolUtils.readString(buf);
dimensionKey = ProtocolUtils.readString(buf);
} else {
dimensionIdentifier = ProtocolUtils.readString(buf);
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
dimension = ProtocolUtils.readVarInt(buf);
} else {
dimensionKey = ProtocolUtils.readString(buf);
}
levelName = ProtocolUtils.readString(buf);
}
} else {
@ -185,7 +189,7 @@ public class RespawnPacket implements MinecraftPacket {
this.previousGamemode = buf.readByte();
boolean isDebug = buf.readBoolean();
boolean isFlat = buf.readBoolean();
this.dimensionInfo = new DimensionInfo(dimensionIdentifier, levelName, isFlat, isDebug);
this.dimensionInfo = new DimensionInfo(dimensionKey, levelName, isFlat, isDebug, version);
if (version.lessThan(ProtocolVersion.MINECRAFT_1_19_3)) {
this.dataToKeep = (byte) (buf.readBoolean() ? 1 : 0);
} else if (version.lessThan(ProtocolVersion.MINECRAFT_1_20_2)) {
@ -213,7 +217,11 @@ public class RespawnPacket implements MinecraftPacket {
ProtocolUtils.writeBinaryTag(buf, version, currentDimensionData);
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
} else {
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
ProtocolUtils.writeVarInt(buf, dimension);
} else {
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
}
ProtocolUtils.writeString(buf, dimensionInfo.getLevelName());
}
} else {

Datei anzeigen

@ -32,7 +32,7 @@ public class ServerDataPacket implements MinecraftPacket {
private @Nullable ComponentHolder description;
private @Nullable Favicon favicon;
private boolean secureChatEnforced; // Added in 1.19.1
private boolean secureChatEnforced; // Added in 1.19.1 - Removed in 1.20.5
public ServerDataPacket() {
}
@ -63,7 +63,8 @@ public class ServerDataPacket implements MinecraftPacket {
if (protocolVersion.lessThan(ProtocolVersion.MINECRAFT_1_19_3)) {
buf.readBoolean();
}
if (protocolVersion.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)) {
if (protocolVersion.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)
&& protocolVersion.lessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
this.secureChatEnforced = buf.readBoolean();
}
}
@ -94,7 +95,8 @@ public class ServerDataPacket implements MinecraftPacket {
if (protocolVersion.lessThan(ProtocolVersion.MINECRAFT_1_19_3)) {
buf.writeBoolean(false);
}
if (protocolVersion.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)) {
if (protocolVersion.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)
&& protocolVersion.lessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
buf.writeBoolean(this.secureChatEnforced);
}
}
@ -115,4 +117,8 @@ public class ServerDataPacket implements MinecraftPacket {
public boolean isSecureChatEnforced() {
return secureChatEnforced;
}
public void setSecureChatEnforced(boolean secureChatEnforced) {
this.secureChatEnforced = secureChatEnforced;
}
}

Datei anzeigen

@ -26,9 +26,8 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
import com.velocitypowered.proxy.util.except.QuietDecoderException;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ServerLoginPacket implements MinecraftPacket {
@ -75,10 +74,10 @@ public class ServerLoginPacket implements MinecraftPacket {
@Override
public String toString() {
return "ServerLogin{"
+ "username='" + username + '\''
+ "uuid='" + holderUuid + '\''
+ "playerKey='" + playerKey + '\''
+ '}';
+ "username='" + username + '\''
+ "playerKey='" + playerKey + '\''
+ "holderUUID='" + holderUuid + '\''
+ '}';
}
@Override

Datei anzeigen

@ -23,8 +23,8 @@ import com.velocitypowered.api.util.UuidUtils;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.util.VelocityProperties;
import io.netty.buffer.ByteBuf;
import java.util.List;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -34,6 +34,8 @@ public class ServerLoginSuccessPacket implements MinecraftPacket {
private @Nullable UUID uuid;
private @Nullable String username;
private @Nullable List<GameProfile.Property> properties;
private static final boolean strictErrorHandling = VelocityProperties
.readBoolean("velocity.strictErrorHandling", true);
public UUID getUuid() {
if (uuid == null) {
@ -90,6 +92,9 @@ public class ServerLoginSuccessPacket implements MinecraftPacket {
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) {
properties = ProtocolUtils.readProperties(buf);
}
if (version == ProtocolVersion.MINECRAFT_1_20_5) {
buf.readBoolean();
}
}
@Override
@ -118,6 +123,9 @@ public class ServerLoginSuccessPacket implements MinecraftPacket {
ProtocolUtils.writeProperties(buf, properties);
}
}
if (version == ProtocolVersion.MINECRAFT_1_20_5) {
buf.writeBoolean(strictErrorHandling);
}
}
@Override

Datei anzeigen

@ -0,0 +1,64 @@
/*
* Copyright (C) 2024 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.protocol.packet;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf;
import java.net.InetSocketAddress;
import org.jetbrains.annotations.Nullable;
public class TransferPacket implements MinecraftPacket {
private String host;
private int port;
public TransferPacket() {
}
public TransferPacket(final String host, final int port) {
this.host = host;
this.port = port;
}
@Nullable
public InetSocketAddress address() {
if (host == null) {
return null;
}
return new InetSocketAddress(host, port);
}
@Override
public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) {
this.host = ProtocolUtils.readString(buf);
this.port = ProtocolUtils.readVarInt(buf);
}
@Override
public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) {
ProtocolUtils.writeString(buf, host);
ProtocolUtils.writeVarInt(buf, port);
}
@Override
public boolean handle(MinecraftSessionHandler handler) {
return handler.handle(this);
}
}

Datei anzeigen

@ -21,6 +21,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_3;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_4;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_3;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_5;
import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier.id;
import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier.mapSet;
import static com.velocitypowered.proxy.protocol.packet.brigadier.DoubleArgumentPropertySerializer.DOUBLE;
@ -190,8 +191,7 @@ public class ArgumentPropertyRegistry {
});
register(id("brigadier:float", mapSet(MINECRAFT_1_19, 1)), FloatArgumentType.class, FLOAT);
register(id("brigadier:double", mapSet(MINECRAFT_1_19, 2)), DoubleArgumentType.class, DOUBLE);
register(id("brigadier:integer", mapSet(MINECRAFT_1_19, 3)), IntegerArgumentType.class,
INTEGER);
register(id("brigadier:integer", mapSet(MINECRAFT_1_19, 3)), IntegerArgumentType.class, INTEGER);
register(id("brigadier:long", mapSet(MINECRAFT_1_19, 4)), LongArgumentType.class, LONG);
register(id("brigadier:string", mapSet(MINECRAFT_1_19, 5)), StringArgumentType.class, STRING);
@ -209,77 +209,65 @@ public class ArgumentPropertyRegistry {
empty(id("minecraft:component", mapSet(MINECRAFT_1_19, 17)));
empty(id("minecraft:style", mapSet(MINECRAFT_1_20_3, 18))); // added 1.20.3
empty(id("minecraft:message", mapSet(MINECRAFT_1_20_3, 19), mapSet(MINECRAFT_1_19, 18)));
empty(id("minecraft:nbt_compound_tag", mapSet(MINECRAFT_1_20_3, 20),
mapSet(MINECRAFT_1_19, 19))); // added in 1.14
empty(id("minecraft:nbt_tag", mapSet(MINECRAFT_1_20_3, 21),
mapSet(MINECRAFT_1_19, 20))); // added in 1.14
empty(id("minecraft:nbt_compound_tag", mapSet(MINECRAFT_1_20_3, 20), mapSet(MINECRAFT_1_19, 19))); // added in 1.14
empty(id("minecraft:nbt_tag", mapSet(MINECRAFT_1_20_3, 21), mapSet(MINECRAFT_1_19, 20))); // added in 1.14
empty(id("minecraft:nbt_path", mapSet(MINECRAFT_1_20_3, 22), mapSet(MINECRAFT_1_19, 21)));
empty(id("minecraft:objective", mapSet(MINECRAFT_1_20_3, 23), mapSet(MINECRAFT_1_19, 22)));
empty(id("minecraft:objective_criteria", mapSet(MINECRAFT_1_20_3, 24),
mapSet(MINECRAFT_1_19, 23)));
empty(id("minecraft:objective_criteria", mapSet(MINECRAFT_1_20_3, 24), mapSet(MINECRAFT_1_19, 23)));
empty(id("minecraft:operation", mapSet(MINECRAFT_1_20_3, 25), mapSet(MINECRAFT_1_19, 24)));
empty(id("minecraft:particle", mapSet(MINECRAFT_1_20_3, 26), mapSet(MINECRAFT_1_19, 25)));
empty(id("minecraft:angle", mapSet(MINECRAFT_1_20_3, 27),
mapSet(MINECRAFT_1_19, 26))); // added in 1.16.2
empty(id("minecraft:angle", mapSet(MINECRAFT_1_20_3, 27), mapSet(MINECRAFT_1_19, 26))); // added in 1.16.2
empty(id("minecraft:rotation", mapSet(MINECRAFT_1_20_3, 28), mapSet(MINECRAFT_1_19, 27)));
empty(
id("minecraft:scoreboard_slot", mapSet(MINECRAFT_1_20_3, 29), mapSet(MINECRAFT_1_19, 28)));
empty(id("minecraft:score_holder", mapSet(MINECRAFT_1_20_3, 30), mapSet(MINECRAFT_1_19, 29)),
ByteArgumentPropertySerializer.BYTE);
empty(id("minecraft:scoreboard_slot", mapSet(MINECRAFT_1_20_3, 29), mapSet(MINECRAFT_1_19, 28)));
empty(id("minecraft:score_holder", mapSet(MINECRAFT_1_20_3, 30), mapSet(MINECRAFT_1_19, 29)), ByteArgumentPropertySerializer.BYTE);
empty(id("minecraft:swizzle", mapSet(MINECRAFT_1_20_3, 31), mapSet(MINECRAFT_1_19, 30)));
empty(id("minecraft:team", mapSet(MINECRAFT_1_20_3, 32), mapSet(MINECRAFT_1_19, 31)));
empty(id("minecraft:item_slot", mapSet(MINECRAFT_1_20_3, 33), mapSet(MINECRAFT_1_19, 32)));
empty(id("minecraft:resource_location", mapSet(MINECRAFT_1_20_3, 34),
mapSet(MINECRAFT_1_19, 33)));
empty(id("minecraft:item_slots", mapSet(MINECRAFT_1_20_5, 34))); // added 1.20.5
empty(id("minecraft:resource_location", mapSet(MINECRAFT_1_20_5, 35), mapSet(MINECRAFT_1_20_3, 34), mapSet(MINECRAFT_1_19, 33)));
empty(id("minecraft:mob_effect", mapSet(MINECRAFT_1_19_3, -1), mapSet(MINECRAFT_1_19, 34)));
empty(id("minecraft:function", mapSet(MINECRAFT_1_20_3, 35), mapSet(MINECRAFT_1_19_3, 34),
empty(id("minecraft:function", mapSet(MINECRAFT_1_20_5, 36), mapSet(MINECRAFT_1_20_3, 35), mapSet(MINECRAFT_1_19_3, 34),
mapSet(MINECRAFT_1_19, 35)));
empty(id("minecraft:entity_anchor", mapSet(MINECRAFT_1_20_3, 36), mapSet(MINECRAFT_1_19_3, 35),
empty(id("minecraft:entity_anchor", mapSet(MINECRAFT_1_20_5, 37), mapSet(MINECRAFT_1_20_3, 36), mapSet(MINECRAFT_1_19_3, 35),
mapSet(MINECRAFT_1_19, 36)));
empty(id("minecraft:int_range", mapSet(MINECRAFT_1_20_3, 37), mapSet(MINECRAFT_1_19_3, 36),
empty(id("minecraft:int_range", mapSet(MINECRAFT_1_20_5, 38), mapSet(MINECRAFT_1_20_3, 37), mapSet(MINECRAFT_1_19_3, 36),
mapSet(MINECRAFT_1_19, 37)));
empty(id("minecraft:float_range", mapSet(MINECRAFT_1_20_3, 38), mapSet(MINECRAFT_1_19_3, 37),
empty(id("minecraft:float_range", mapSet(MINECRAFT_1_20_5, 39), mapSet(MINECRAFT_1_20_3, 38), mapSet(MINECRAFT_1_19_3, 37),
mapSet(MINECRAFT_1_19, 38)));
empty(
id("minecraft:item_enchantment", mapSet(MINECRAFT_1_19_3, -1), mapSet(MINECRAFT_1_19, 39)));
empty(id("minecraft:item_enchantment", mapSet(MINECRAFT_1_19_3, -1), mapSet(MINECRAFT_1_19, 39)));
empty(id("minecraft:entity_summon", mapSet(MINECRAFT_1_19_3, -1), mapSet(MINECRAFT_1_19, 40)));
empty(id("minecraft:dimension", mapSet(MINECRAFT_1_20_3, 39), mapSet(MINECRAFT_1_19_3, 38),
empty(id("minecraft:dimension", mapSet(MINECRAFT_1_20_5, 40), mapSet(MINECRAFT_1_20_3, 39), mapSet(MINECRAFT_1_19_3, 38),
mapSet(MINECRAFT_1_19, 41)));
empty(id("minecraft:gamemode", mapSet(MINECRAFT_1_20_3, 40),
mapSet(MINECRAFT_1_19_3, 39))); // 1.19.3
empty(id("minecraft:gamemode", mapSet(MINECRAFT_1_20_5, 41), mapSet(MINECRAFT_1_20_3, 40), mapSet(MINECRAFT_1_19_3, 39))); // 1.19.3
empty(id("minecraft:time", mapSet(MINECRAFT_1_20_3, 41), mapSet(MINECRAFT_1_19_3, 40),
empty(id("minecraft:time", mapSet(MINECRAFT_1_20_5, 42), mapSet(MINECRAFT_1_20_3, 41), mapSet(MINECRAFT_1_19_3, 40),
mapSet(MINECRAFT_1_19, 42)), TimeArgumentSerializer.TIME); // added in 1.14
register(
id("minecraft:resource_or_tag", mapSet(MINECRAFT_1_20_3, 42), mapSet(MINECRAFT_1_19_3, 41),
mapSet(MINECRAFT_1_19, 43)),
RegistryKeyArgument.class, RegistryKeyArgumentSerializer.REGISTRY);
register(id("minecraft:resource_or_tag_key", mapSet(MINECRAFT_1_20_3, 43),
mapSet(MINECRAFT_1_19_3, 42)),
register(id("minecraft:resource_or_tag", mapSet(MINECRAFT_1_20_5, 43), mapSet(MINECRAFT_1_20_3, 42), mapSet(MINECRAFT_1_19_3, 41),
mapSet(MINECRAFT_1_19, 43)), RegistryKeyArgument.class, RegistryKeyArgumentSerializer.REGISTRY);
register(id("minecraft:resource_or_tag_key", mapSet(MINECRAFT_1_20_5, 44), mapSet(MINECRAFT_1_20_3, 43), mapSet(MINECRAFT_1_19_3, 42)),
RegistryKeyArgumentList.ResourceOrTagKey.class,
RegistryKeyArgumentList.ResourceOrTagKey.Serializer.REGISTRY);
register(id("minecraft:resource", mapSet(MINECRAFT_1_20_3, 44), mapSet(MINECRAFT_1_19_3, 43),
mapSet(MINECRAFT_1_19, 44)),
register(id("minecraft:resource", mapSet(MINECRAFT_1_20_5, 45), mapSet(MINECRAFT_1_20_3, 44), mapSet(MINECRAFT_1_19_3, 43),
mapSet(MINECRAFT_1_19, 44)),
RegistryKeyArgument.class, RegistryKeyArgumentSerializer.REGISTRY);
register(
id("minecraft:resource_key", mapSet(MINECRAFT_1_20_3, 45), mapSet(MINECRAFT_1_19_3, 44)),
register(id("minecraft:resource_key", mapSet(MINECRAFT_1_20_5, 46), mapSet(MINECRAFT_1_20_3, 45), mapSet(MINECRAFT_1_19_3, 44)),
RegistryKeyArgumentList.ResourceKey.class,
RegistryKeyArgumentList.ResourceKey.Serializer.REGISTRY);
empty(id("minecraft:template_mirror", mapSet(MINECRAFT_1_20_3, 46),
mapSet(MINECRAFT_1_19, 45))); // 1.19
empty(id("minecraft:template_rotation", mapSet(MINECRAFT_1_20_3, 47),
mapSet(MINECRAFT_1_19, 46))); // 1.19
empty(id("minecraft:heightmap", mapSet(MINECRAFT_1_20_3, 49),
mapSet(MINECRAFT_1_19_4, 47))); // 1.19.4
empty(id("minecraft:template_mirror", mapSet(MINECRAFT_1_20_5, 47), mapSet(MINECRAFT_1_20_3, 46), mapSet(MINECRAFT_1_19, 45))); // 1.19
empty(id("minecraft:template_rotation", mapSet(MINECRAFT_1_20_5, 48), mapSet(MINECRAFT_1_20_3, 47), mapSet(MINECRAFT_1_19, 46))); // 1.19
empty(id("minecraft:heightmap", mapSet(MINECRAFT_1_20_3, 49), mapSet(MINECRAFT_1_19_4, 47))); // 1.19.4
empty(id("minecraft:uuid", mapSet(MINECRAFT_1_20_3, 48), mapSet(MINECRAFT_1_19_4, 48),
empty(id("minecraft:uuid", mapSet(MINECRAFT_1_20_5, 53), mapSet(MINECRAFT_1_20_3, 48), mapSet(MINECRAFT_1_19_4, 48),
mapSet(MINECRAFT_1_19, 47))); // added in 1.16
empty(id("minecraft:loot_table", mapSet(MINECRAFT_1_20_5, 50)), RegistryIdArgumentSerializer.REGISTRY_ID);
empty(id("minecraft:loot_predicate", mapSet(MINECRAFT_1_20_5, 51)), RegistryIdArgumentSerializer.REGISTRY_ID);
empty(id("minecraft:loot_modifier", mapSet(MINECRAFT_1_20_5, 52)), RegistryIdArgumentSerializer.REGISTRY_ID);
// Crossstitch support
register(id("crossstitch:mod_argument", mapSet(MINECRAFT_1_19, -256)),
ModArgumentProperty.class, MOD);
register(id("crossstitch:mod_argument", mapSet(MINECRAFT_1_19, -256)), ModArgumentProperty.class, MOD);
empty(id("minecraft:nbt")); // No longer in 1.19+
}

Datei anzeigen

@ -0,0 +1,37 @@
/*
* Copyright (C) 2018-2023 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.protocol.packet.brigadier;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf;
public class RegistryIdArgumentSerializer implements ArgumentPropertySerializer<Integer> {
static final RegistryIdArgumentSerializer REGISTRY_ID = new RegistryIdArgumentSerializer();
@Override
public Integer deserialize(ByteBuf buf, ProtocolVersion protocolVersion) {
return ProtocolUtils.readVarInt(buf);
}
@Override
public void serialize(Integer object, ByteBuf buf, ProtocolVersion protocolVersion) {
ProtocolUtils.writeVarInt(buf, object);
}
}

Datei anzeigen

@ -42,13 +42,19 @@ public class SessionChatBuilder extends ChatBuilderV2 {
@Override
public MinecraftPacket toServer() {
if (message.startsWith("/")) {
SessionPlayerCommandPacket command = new SessionPlayerCommandPacket();
command.command = message.substring(1);
command.salt = 0L;
command.timeStamp = timestamp;
command.argumentSignatures = new SessionPlayerCommandPacket.ArgumentSignatures();
command.lastSeenMessages = new LastSeenMessages();
return command;
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
UnsignedPlayerCommandPacket command = new UnsignedPlayerCommandPacket();
command.command = message.substring(1);
return command;
} else {
SessionPlayerCommandPacket command = new SessionPlayerCommandPacket();
command.command = message.substring(1);
command.salt = 0L;
command.timeStamp = timestamp;
command.argumentSignatures = new SessionPlayerCommandPacket.ArgumentSignatures();
command.lastSeenMessages = new LastSeenMessages();
return command;
}
} else {
SessionPlayerChatPacket chat = new SessionPlayerChatPacket();
chat.message = message;

Datei anzeigen

@ -108,7 +108,7 @@ public class SessionCommandHandler implements CommandHandler<SessionPlayerComman
.toServer();
}
}
if (player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_19_3)) {
if (player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_19_3) && packet.lastSeenMessages != null) {
return new ChatAcknowledgementPacket(packet.lastSeenMessages.getOffset());
}
return null;

Datei anzeigen

@ -37,8 +37,7 @@ public class SessionPlayerCommandPacket implements MinecraftPacket {
protected LastSeenMessages lastSeenMessages;
@Override
public void decode(ByteBuf buf, ProtocolUtils.Direction direction,
ProtocolVersion protocolVersion) {
public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) {
this.command = ProtocolUtils.readString(buf, 256);
this.timeStamp = Instant.ofEpochMilli(buf.readLong());
this.salt = buf.readLong();
@ -47,8 +46,7 @@ public class SessionPlayerCommandPacket implements MinecraftPacket {
}
@Override
public void encode(ByteBuf buf, ProtocolUtils.Direction direction,
ProtocolVersion protocolVersion) {
public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) {
ProtocolUtils.writeString(buf, this.command);
buf.writeLong(this.timeStamp.toEpochMilli());
buf.writeLong(this.salt);

Datei anzeigen

@ -0,0 +1,46 @@
/*
* Copyright (C) 2022-2023 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.protocol.packet.chat.session;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf;
public class UnsignedPlayerCommandPacket extends SessionPlayerCommandPacket {
@Override
public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) {
this.command = ProtocolUtils.readString(buf, 256);
}
@Override
public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) {
ProtocolUtils.writeString(buf, this.command);
}
public boolean isSigned() {
return false;
}
@Override
public String toString() {
return "UnsignedPlayerCommandPacket{" +
"command='" + command + '\'' +
'}';
}
}

Datei anzeigen

@ -17,6 +17,7 @@
package com.velocitypowered.proxy.server;
import com.velocitypowered.api.network.HandshakeIntent;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerPing;
@ -54,7 +55,7 @@ public class PingSessionHandler implements MinecraftSessionHandler {
@Override
public void activated() {
HandshakePacket handshake = new HandshakePacket();
handshake.setNextStatus(StateRegistry.STATUS_ID);
handshake.setIntent(HandshakeIntent.STATUS);
handshake.setServerAddress(server.getServerInfo().getAddress().getHostString());
handshake.setPort(server.getServerInfo().getAddress().getPort());
handshake.setProtocolVersion(version);

Datei anzeigen

@ -0,0 +1,59 @@
/*
* Copyright (C) 2024 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.util;
import static java.util.Objects.requireNonNull;
/**
* Utils for easy handling of properties.
*
* @since 3.3.0
*/
public final class VelocityProperties {
/**
* Attempts to read a system property as boolean.
*
* @param property the system property to read
* @param defaultValue the default value
* @return the default value if the property is not set,
* if the string is present and is "true" (case-insensitive),
* it will return {@code true}, otherwise, it will return false.
* @since 3.3.0
*/
public static boolean readBoolean(final String property, final boolean defaultValue) {
requireNonNull(property);
final String value = System.getProperty(property);
if (value == null) {
return defaultValue;
}
return Boolean.parseBoolean(value);
}
/**
* Check if there is a value assigned to this system property.
*
* @param property the system property to check
* @return if a value is assigned to this system property
* @since 3.3.0
*/
public static boolean hasProperty(final String property) {
requireNonNull(property);
return System.getProperty(property) != null;
}
}

Datei anzeigen

@ -1,5 +1,5 @@
# Config version. Do not change this
config-version = "2.6"
config-version = "2.7"
# What port should the proxy be bound to? By default, we'll bind to all addresses on port 25577.
bind = "0.0.0.0:25577"
@ -141,6 +141,10 @@ log-command-executions = false
# and disconnecting from the proxy.
log-player-connections = true
# Allows players transferred from other hosts via the
# Transfer packet (Minecraft 1.20.5) to be received.
accepts-transfers = false
[query]
# Whether to enable responding to GameSpy 4 query responses or not.
enabled = false