Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-16 21:10:30 +01:00
1.20.5 Support (#1198)
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:
Ursprung
be678840de
Commit
8f4adb1cec
@ -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
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
@ -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>
|
||||
*/
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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(
|
||||
|
@ -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());
|
||||
|
@ -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");
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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+
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren