From 62c6ec044e6eaddfc5a057ce5c9d3859053d0b9c Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Sat, 2 Mar 2024 15:05:35 +0000 Subject: [PATCH 01/28] Make sure that the backend server knows the pack application was successful accepted, is just the first expected state, we also need to tell that the pack was actually applied on the client in order to allow it to progress in the connection process --- .../proxy/connection/backend/ConfigSessionHandler.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java index 1617fb138f..32c07c042b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java @@ -137,8 +137,13 @@ public boolean handle(final ResourcePackRequestPacket packet) { if (serverConn.getPlayer().resourcePackHandler().hasPackAppliedByHash(toSend.getHash())) { // Do not apply a resource pack that has already been applied if (serverConn.getConnection() != null) { + // We can technically skip these first 2 states, however, for conformity to normal state flow expectations... serverConn.getConnection().write(new ResourcePackResponsePacket( packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.ACCEPTED)); + serverConn.getConnection().write(new ResourcePackResponsePacket( + packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.DOWNLOADED)); + serverConn.getConnection().write(new ResourcePackResponsePacket( + packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.SUCCESSFUL)); } if (modifiedPack) { logger.warn("A plugin has tried to modify a ResourcePack provided by the backend server " From 2c8355fc455c8d23692c91c70e0edb50e83c83e0 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Sun, 3 Mar 2024 13:38:40 +0000 Subject: [PATCH 02/28] Update spotless --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 72b86cea77..a3d0523dcb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ netty = "4.1.106.Final" [plugins] indra-publishing = "net.kyori.indra.publishing:2.0.6" shadow = "io.github.goooler.shadow:8.1.5" -spotless = "com.diffplug.spotless:6.12.0" +spotless = "com.diffplug.spotless:6.25.0" [libraries] adventure-bom = "net.kyori:adventure-bom:4.16.0" From c34dafe2a293ee9cae116d9024c7b2132be6201f Mon Sep 17 00:00:00 2001 From: Adrian <68704415+4drian3d@users.noreply.github.com> Date: Sun, 3 Mar 2024 16:21:22 -0500 Subject: [PATCH 03/28] Implement ProtocolState API (#1224) * Implement ProtocolState API * Renamed method to #getProtocolState * Added sinceMinecraft javadoc tag * Fixed PreLoginEvent#getUniqueId documentation --- api/build.gradle.kts | 3 +- .../api/event/connection/PreLoginEvent.java | 5 +- .../api/network/ProtocolState.java | 52 +++++++++++++++++++ .../api/proxy/InboundConnection.java | 8 +++ .../com/velocitypowered/api/proxy/Player.java | 2 +- .../api/proxy/player/PlayerSettings.java | 1 + .../connection/client/ConnectedPlayer.java | 6 +++ .../client/HandshakeSessionHandler.java | 10 +++- .../client/InitialInboundConnection.java | 6 +++ .../client/LoginInboundConnection.java | 6 +++ .../proxy/protocol/StateRegistry.java | 16 ++++++ 11 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 api/src/main/java/com/velocitypowered/api/network/ProtocolState.java diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 56bb3c49cb..aa6778fca2 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -73,7 +73,8 @@ tasks { o.tags( "apiNote:a:API Note:", "implSpec:a:Implementation Requirements:", - "implNote:a:Implementation Note:" + "implNote:a:Implementation Note:", + "sinceMinecraft:a:Since Minecraft:" ) // Disable the crazy super-strict doclint tool in Java 8 diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/PreLoginEvent.java b/api/src/main/java/com/velocitypowered/api/event/connection/PreLoginEvent.java index 6ac3f57e18..952cb091b7 100644 --- a/api/src/main/java/com/velocitypowered/api/event/connection/PreLoginEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/connection/PreLoginEvent.java @@ -72,9 +72,12 @@ public String getUsername() { } /** - * Returns the UUID of the connecting player. This value is {@code null} on 1.19.1 and lower. + * Returns the UUID of the connecting player. + *

This value is {@code null} on 1.19.2 and lower, + * up to 1.20.1 it is optional and from 1.20.2 it will always be available.

* * @return the uuid + * @sinceMinecraft 1.19.3 */ public @Nullable UUID getUniqueId() { return uuid; diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolState.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolState.java new file mode 100644 index 0000000000..f5df6fa592 --- /dev/null +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolState.java @@ -0,0 +1,52 @@ +/* + * 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; + +/** + * Representation of the state of the protocol + * in which a connection can be present. + * + * @since 3.3.0 + */ +public enum ProtocolState { + /** + * Initial connection State. + *

This status can be caused by a STATUS, LOGIN or TRANSFER intent.

+ * 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. + *

Connections with the STATUS HandshakeIntent will pass through this state + * and be disconnected after it requests the ping from the server + * and the server responds with the respective ping.

+ */ + STATUS, + /** + * Authentication State of a connection. + *

At this moment the player is authenticating with the authentication servers.

+ */ + LOGIN, + /** + * Configuration State of a connection. + *

At this point the player allows the server to send information + * such as resource packs and plugin messages, at the same time the player + * will send his client brand and the respective plugin messages + * if it is a modded client.

+ * + * @sinceMinecraft 1.20.2 + */ + CONFIGURATION, + /** + * Game State of a connection. + *

In this state is where the whole game runs, the server is able to change + * the player's state to {@link #CONFIGURATION} as needed in versions 1.20.2 and higher.

+ */ + PLAY +} diff --git a/api/src/main/java/com/velocitypowered/api/proxy/InboundConnection.java b/api/src/main/java/com/velocitypowered/api/proxy/InboundConnection.java index e92c38bc70..224abbd6e6 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/InboundConnection.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/InboundConnection.java @@ -7,6 +7,7 @@ package com.velocitypowered.api.proxy; +import com.velocitypowered.api.network.ProtocolState; import com.velocitypowered.api.network.ProtocolVersion; import java.net.InetSocketAddress; import java.util.Optional; @@ -43,4 +44,11 @@ public interface InboundConnection { * @return the protocol version the connection uses */ ProtocolVersion getProtocolVersion(); + + /** + * Returns the current protocol state of this connection. + * + * @return the protocol state of the connection + */ + ProtocolState getProtocolState(); } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/Player.java b/api/src/main/java/com/velocitypowered/api/proxy/Player.java index eb41401b26..a73ff451b8 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/Player.java @@ -190,7 +190,7 @@ default void clearHeaderAndFooter() { * * @param reason component with the reason */ - void disconnect(net.kyori.adventure.text.Component reason); + void disconnect(Component reason); /** * Sends chat input onto the players current server as if they typed it into the client chat box. diff --git a/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java b/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java index 4745eea176..320b1c2036 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java @@ -64,6 +64,7 @@ public interface PlayerSettings { * This feature was introduced in 1.18. * * @return whether or not the client explicitly allows listing. Always false on older clients. + * @sinceMinecraft 1.18 */ boolean isClientListingAllowed(); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 79ad816364..935a3c4817 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -33,6 +33,7 @@ import com.velocitypowered.api.event.player.PlayerModInfoEvent; import com.velocitypowered.api.event.player.PlayerSettingsChangedEvent; import com.velocitypowered.api.event.player.ServerPreConnectEvent; +import com.velocitypowered.api.network.ProtocolState; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.permission.PermissionFunction; import com.velocitypowered.api.permission.PermissionProvider; @@ -1170,6 +1171,11 @@ private class IdentityImpl implements Identity { } } + @Override + public ProtocolState getProtocolState() { + return connection.getState().toProtocolState(); + } + private final class ConnectionRequestBuilderImpl implements ConnectionRequestBuilder { private final RegisteredServer toConnect; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java index f1fc2d49f1..5c5e928fe8 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java @@ -20,6 +20,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.velocitypowered.api.event.connection.ConnectionHandshakeEvent; +import com.velocitypowered.api.network.ProtocolState; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.config.PlayerInfoForwarding; @@ -247,9 +248,9 @@ public ProtocolVersion getProtocolVersion() { @Override public String toString() { - boolean isPlayerAddressLoggingEnabled = connection.server.getConfiguration() + final boolean isPlayerAddressLoggingEnabled = connection.server.getConfiguration() .isPlayerAddressLoggingEnabled(); - String playerIp = + final String playerIp = isPlayerAddressLoggingEnabled ? this.getRemoteAddress().toString() : ""; return "[legacy connection] " + playerIp; @@ -259,5 +260,10 @@ public String toString() { public MinecraftConnection getConnection() { return connection; } + + @Override + public ProtocolState getProtocolState() { + return connection.getState().toProtocolState(); + } } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialInboundConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialInboundConnection.java index 504368ca42..2441e2ac5a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialInboundConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialInboundConnection.java @@ -17,6 +17,7 @@ package com.velocitypowered.proxy.connection.client; +import com.velocitypowered.api.network.ProtocolState; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.InboundConnection; import com.velocitypowered.proxy.connection.MinecraftConnection; @@ -87,6 +88,11 @@ public MinecraftConnection getConnection() { return connection; } + @Override + public ProtocolState getProtocolState() { + return connection.getState().toProtocolState(); + } + /** * Disconnects the connection from the server. * diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginInboundConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginInboundConnection.java index 997cf46201..93064a790a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginInboundConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginInboundConnection.java @@ -17,6 +17,7 @@ package com.velocitypowered.proxy.connection.client; +import com.velocitypowered.api.network.ProtocolState; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.LoginPhaseConnection; import com.velocitypowered.api.proxy.crypto.IdentifiedKey; @@ -166,4 +167,9 @@ public void setPlayerKey(IdentifiedKey playerKey) { public IdentifiedKey getIdentifiedKey() { return playerKey; } + + @Override + public ProtocolState getProtocolState() { + return delegate.getProtocolState(); + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index 74fc26b0d5..f53604a5a3 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -45,6 +45,7 @@ import static com.velocitypowered.proxy.protocol.ProtocolUtils.Direction.CLIENTBOUND; import static com.velocitypowered.proxy.protocol.ProtocolUtils.Direction.SERVERBOUND; +import com.velocitypowered.api.network.ProtocolState; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.protocol.packet.AvailableCommandsPacket; import com.velocitypowered.proxy.protocol.packet.BossBarPacket; @@ -623,6 +624,21 @@ public StateRegistry.PacketRegistry.ProtocolRegistry getProtocolRegistry(Directi return (direction == SERVERBOUND ? serverbound : clientbound).getProtocolRegistry(version); } + /** + * Gets the API representation of the StateRegistry. + * + * @return the API representation + */ + public ProtocolState toProtocolState() { + return switch (this) { + case HANDSHAKE -> ProtocolState.HANDSHAKE; + case STATUS -> ProtocolState.STATUS; + case LOGIN -> ProtocolState.LOGIN; + case CONFIG -> ProtocolState.CONFIGURATION; + case PLAY -> ProtocolState.PLAY; + }; + } + /** * Packet registry. */ From 8891faa52c85c165ce37540adc236f4678617b69 Mon Sep 17 00:00:00 2001 From: Joo200 Date: Tue, 5 Mar 2024 16:11:17 +0100 Subject: [PATCH 04/28] Added event when a command is executed from Velocity (#984) * feat: added event for command invocation This event is called when a command invocation attempt on the proxy occurs * Fix javadoc issue --- .../api/command/CommandResult.java | 31 +++++++ .../command/PostCommandInvocationEvent.java | 82 +++++++++++++++++++ .../proxy/command/VelocityCommandManager.java | 14 +++- 3 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 api/src/main/java/com/velocitypowered/api/command/CommandResult.java create mode 100644 api/src/main/java/com/velocitypowered/api/event/command/PostCommandInvocationEvent.java diff --git a/api/src/main/java/com/velocitypowered/api/command/CommandResult.java b/api/src/main/java/com/velocitypowered/api/command/CommandResult.java new file mode 100644 index 0000000000..88a409eb44 --- /dev/null +++ b/api/src/main/java/com/velocitypowered/api/command/CommandResult.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020-2021 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.command; + +/** + * The result of a command invocation attempt. + */ +public enum CommandResult { + /** + * The command was successfully executed by the proxy. + */ + EXECUTED, + /** + * The command was forwarded to the backend server. + * The command may be successfully executed or not + */ + FORWARDED, + /** + * The provided command input contained syntax errors. + */ + SYNTAX_ERROR, + /** + * An unexpected exception occurred while executing the command in the proxy. + */ + EXCEPTION +} diff --git a/api/src/main/java/com/velocitypowered/api/event/command/PostCommandInvocationEvent.java b/api/src/main/java/com/velocitypowered/api/event/command/PostCommandInvocationEvent.java new file mode 100644 index 0000000000..feeb9e0504 --- /dev/null +++ b/api/src/main/java/com/velocitypowered/api/event/command/PostCommandInvocationEvent.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2020-2023 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.command; + +import com.google.common.base.Preconditions; +import com.velocitypowered.api.command.CommandResult; +import com.velocitypowered.api.command.CommandSource; +import org.jetbrains.annotations.NotNull; + +/** + * This event is fired when velocity executed a command. This event is called after the event + * is handled. + * + *

Commands can be cancelled or forwarded to backend servers in {@link CommandExecuteEvent}. + * This will prevent firing this event.

+ * + * @since 3.3.0 + */ +public final class PostCommandInvocationEvent { + + private final CommandSource commandSource; + private final String command; + private final CommandResult result; + + /** + * Constructs a PostCommandInvocationEvent. + * + * @param commandSource the source executing the command + * @param command the command being executed without first slash + * @param result the result of this command + */ + public PostCommandInvocationEvent( + final @NotNull CommandSource commandSource, + final @NotNull String command, + final @NotNull CommandResult result + ) { + this.commandSource = Preconditions.checkNotNull(commandSource, "commandSource"); + this.command = Preconditions.checkNotNull(command, "command"); + this.result = Preconditions.checkNotNull(result, "result"); + } + + /** + * Get the source of this executed command. + * + * @return the source + */ + public @NotNull CommandSource getCommandSource() { + return commandSource; + } + + /** + * Gets the original command line executed without the first slash. + * + * @return the original command + * @see CommandExecuteEvent#getCommand() + */ + public @NotNull String getCommand() { + return command; + } + + /** + * Returns the result of the command execution. + * + * @return the execution result + */ + public @NotNull CommandResult getResult() { + return result; + } + + @Override + public String toString() { + return "PostCommandInvocationEvent{" + + "commandSource=" + commandSource + + ", command=" + command + + '}'; + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java index c4cacaf5fa..80fef3d4e8 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java @@ -31,9 +31,10 @@ import com.velocitypowered.api.command.Command; import com.velocitypowered.api.command.CommandManager; import com.velocitypowered.api.command.CommandMeta; +import com.velocitypowered.api.command.CommandResult; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.event.command.CommandExecuteEvent; -import com.velocitypowered.api.event.command.CommandExecuteEvent.CommandResult; +import com.velocitypowered.api.event.command.PostCommandInvocationEvent; import com.velocitypowered.proxy.command.registrar.BrigadierCommandRegistrar; import com.velocitypowered.proxy.command.registrar.CommandRegistrar; import com.velocitypowered.proxy.command.registrar.RawCommandRegistrar; @@ -220,23 +221,30 @@ private boolean executeImmediately0(final CommandSource source, final String cmd Preconditions.checkNotNull(cmdLine, "cmdLine"); final String normalizedInput = VelocityCommands.normalizeInput(cmdLine, true); + CommandResult result = CommandResult.EXCEPTION; try { // The parse can fail if the requirement predicates throw final ParseResults parse = this.parse(normalizedInput, source); - return dispatcher.execute(parse) != BrigadierCommand.FORWARD; + boolean executed = dispatcher.execute(parse) != BrigadierCommand.FORWARD; + result = executed ? CommandResult.EXECUTED : CommandResult.FORWARDED; + return executed; } catch (final CommandSyntaxException e) { boolean isSyntaxError = !e.getType().equals( CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand()); if (isSyntaxError) { source.sendMessage(Component.text(e.getMessage(), NamedTextColor.RED)); + result = com.velocitypowered.api.command.CommandResult.SYNTAX_ERROR; // This is, of course, a lie, but the API will need to change... return true; } else { + result = CommandResult.FORWARDED; return false; } } catch (final Throwable e) { // Ugly, ugly swallowing of everything Throwable, because plugins are naughty. throw new RuntimeException("Unable to invoke command " + cmdLine + " for " + source, e); + } finally { + eventManager.fireAndForget(new PostCommandInvocationEvent(source, cmdLine, result)); } } @@ -246,7 +254,7 @@ public CompletableFuture executeAsync(final CommandSource source, final Preconditions.checkNotNull(cmdLine, "cmdLine"); return callCommandEvent(source, cmdLine).thenApplyAsync(event -> { - CommandResult commandResult = event.getResult(); + CommandExecuteEvent.CommandResult commandResult = event.getResult(); if (commandResult.isForwardToServer() || !commandResult.isAllowed()) { return false; } From 8bdfb5899bb539bf653fc96535b707f36fd4a601 Mon Sep 17 00:00:00 2001 From: Triassic Date: Mon, 11 Mar 2024 15:21:21 +0200 Subject: [PATCH 05/28] [ci skip] Update GitHub Actions and use cache (#1237) --- .github/workflows/gradle.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index ab1dc2fcd4..c3cce5bd1e 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -9,14 +9,13 @@ jobs: build-17: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: gradle/wrapper-validation-action@v1 + - uses: actions/checkout@v4 + - uses: gradle/wrapper-validation-action@v2 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: 17 distribution: 'temurin' - - name: Grant execute permission for gradlew - run: chmod +x gradlew + cache: 'gradle' - name: Build with Gradle run: ./gradlew build From 3b7b902bf5afb89c0834ea44c7d6f80bf7ef5cdb Mon Sep 17 00:00:00 2001 From: LightningReflex <59992415+LightningReflex@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:21:39 +0100 Subject: [PATCH 06/28] [ci skip] Fixed typo in KickedFromServerEvent.java (#1266) --- .../velocitypowered/api/event/player/KickedFromServerEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java index 4f03a35df5..576cbbdd0d 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java @@ -150,7 +150,7 @@ public static DisconnectPlayer create(Component reason) { @Override public String toString() { - return "KickedFromServerEvent#DisconnectPlater{isAllowed=%s,component=%s}" + return "KickedFromServerEvent#DisconnectPlayer{isAllowed=%s,component=%s}" .formatted(isAllowed(), component); } } From 75d6dcc1b8830861656565f95f33d15d78d2523c Mon Sep 17 00:00:00 2001 From: Limbo <35357032+limbo-app@users.noreply.github.com> Date: Sun, 17 Mar 2024 22:20:03 -0700 Subject: [PATCH 07/28] New Crowdin updates (#1201) * New translations messages.properties (Romanian) * New translations messages.properties (French) * New translations messages.properties (Spanish) * New translations messages.properties (Arabic) * New translations messages.properties (Bulgarian) * New translations messages.properties (Czech) * New translations messages.properties (Danish) * New translations messages.properties (German) * New translations messages.properties (Finnish) * New translations messages.properties (Hebrew) * New translations messages.properties (Hungarian) * New translations messages.properties (Italian) * New translations messages.properties (Japanese) * New translations messages.properties (Korean) * New translations messages.properties (Dutch) * New translations messages.properties (Polish) * New translations messages.properties (Russian) * New translations messages.properties (Slovak) * New translations messages.properties (Albanian) * New translations messages.properties (Swedish) * New translations messages.properties (Turkish) * New translations messages.properties (Ukrainian) * New translations messages.properties (Chinese Simplified) * New translations messages.properties (Chinese Traditional) * New translations messages.properties (Vietnamese) * New translations messages.properties (Portuguese, Brazilian) * New translations messages.properties (Norwegian Nynorsk) * New translations messages.properties (Estonian) * New translations messages.properties (Tagalog) * New translations messages.properties (Chinese Traditional, Hong Kong) * New translations messages.properties (Norwegian Bokmal) * New translations messages.properties (Serbian (Latin)) * New translations messages.properties (German) * New translations messages.properties (Finnish) * New translations messages.properties (Chinese Traditional) * New translations messages.properties (German) * New translations messages.properties (Finnish) * New translations messages.properties (Korean) * New translations messages.properties (Chinese Traditional) * New translations messages.properties (Ukrainian) * New translations messages.properties (French) * New translations messages.properties (French) * New translations messages.properties (Polish) * New translations messages.properties (French) * New translations messages.properties (Chinese Simplified) * New translations messages.properties (Dutch) * New translations messages.properties (Dutch) * New translations messages.properties (Swedish) * New translations messages.properties (Swedish) * New translations messages.properties (Korean) * New translations messages.properties (Czech) * New translations messages.properties (Czech) --- .../proxy/l10n/messages_ar_SA.properties | 7 +- .../proxy/l10n/messages_bg_BG.properties | 87 +++++++++--------- .../proxy/l10n/messages_cs_CZ.properties | 7 +- .../proxy/l10n/messages_da_DK.properties | 15 ++-- .../proxy/l10n/messages_de_DE.properties | 13 ++- .../proxy/l10n/messages_es_ES.properties | 7 +- .../proxy/l10n/messages_et_EE.properties | 7 +- .../proxy/l10n/messages_fi_FI.properties | 13 ++- .../proxy/l10n/messages_fr_FR.properties | 23 +++-- .../proxy/l10n/messages_he_IL.properties | 25 +++--- .../proxy/l10n/messages_hu_HU.properties | 11 ++- .../proxy/l10n/messages_it_IT.properties | 7 +- .../proxy/l10n/messages_ja_JP.properties | 7 +- .../proxy/l10n/messages_ko_KR.properties | 55 ++++++------ .../proxy/l10n/messages_nb_NO.properties | 7 +- .../proxy/l10n/messages_nl_NL.properties | 19 ++-- .../proxy/l10n/messages_nn_NO.properties | 7 +- .../proxy/l10n/messages_pl_PL.properties | 63 +++++++------ .../proxy/l10n/messages_pt_BR.properties | 7 +- .../proxy/l10n/messages_ro_RO.properties | 65 ++++++++++++++ .../proxy/l10n/messages_ru_RU.properties | 15 ++-- .../proxy/l10n/messages_sk_SK.properties | 7 +- .../proxy/l10n/messages_sq_AL.properties | 7 +- .../proxy/l10n/messages_sr_Latn.properties | 65 ++++++++++++++ .../proxy/l10n/messages_sv_SE.properties | 89 ++++++++++--------- .../proxy/l10n/messages_tl_PH.properties | 7 +- .../proxy/l10n/messages_tr_TR.properties | 9 +- .../proxy/l10n/messages_uk_UA.properties | 65 ++++++++++++++ .../proxy/l10n/messages_vi_VN.properties | 65 ++++++++++++++ .../proxy/l10n/messages_zh_CN.properties | 7 +- .../proxy/l10n/messages_zh_HK.properties | 75 ++++++++-------- .../proxy/l10n/messages_zh_TW.properties | 7 +- 32 files changed, 634 insertions(+), 236 deletions(-) create mode 100644 proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ro_RO.properties create mode 100644 proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sr_Latn.properties create mode 100644 proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_uk_UA.properties create mode 100644 proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_vi_VN.properties diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ar_SA.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ar_SA.properties index c4ecba29ec..103ae08a3b 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ar_SA.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ar_SA.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=هذا السيرفر متوا velocity.error.modern-forwarding-failed=السيرفر الخاص بك لم يرسل طلب إعادة توجيه إلى الوكيل. تأكد من إعداد الخادم لإعادة التوجيه بـVelocity. velocity.error.moved-to-new-server=لقد تم طردك من {0}\: {1} velocity.error.no-available-servers=لا توجد سيرفرات متاحة للاتصال. حاول مرة أخرى أو اتصل بالأدمِن. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=حدث خطأ أثناء تنفيذ هذا الأمر. velocity.command.command-does-not-exist=هذا الأمر غير موجود. velocity.command.players-only=يمكن للاعبين فقط تشغيل هذا الأمر. velocity.command.server-does-not-exist=السيرفر المطلوب {0} غير موجود. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=أنت الآن متصل بـ{0} velocity.command.server-too-many=هناك العديد من السيرفرات المتاحة، استخدم البحث بزر tab لتصفح قائمة السيرفرات. velocity.command.server-available=السيرفرات المتاحة\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=حدث خطأ أثناء الاتصال بسي velocity.command.dump-success=تم إنشاء تقرير مفصل يحتوي على معلومات مفيدة عن الوكيل الخاص بك. إذا طلبه المطور، يمكنك مشاركة الرابط التالي معه\: velocity.command.dump-will-expire=تنتهي صلاحية هذا الرابط خلال بضعة أيام. velocity.command.dump-server-error=حدث خطأ في سيرفر Velocity و تعذر إكمال مشاركة البيانات. الرجاء الاتصال بطاقم Velocity حيال هذه المشكلة وتقديم التفاصيل الخطأ من الـconsole أو log السيرفر. -velocity.command.dump-offline=السبب المحتمل\: إعدادات الـDNS غير صالحة أو لا يوجد اتصال بالإنترنت \ No newline at end of file +velocity.command.dump-offline=السبب المحتمل\: إعدادات الـDNS غير صالحة أو لا يوجد اتصال بالإنترنت +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_bg_BG.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_bg_BG.properties index 33d8333dde..013fd92c7f 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_bg_BG.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_bg_BG.properties @@ -15,46 +15,51 @@ # along with this program. If not, see . # -velocity.error.already-connected=You are already connected to this server\! -velocity.error.already-connected-proxy=You are already connected to this proxy\! -velocity.error.already-connecting=You are already trying to connect to a server\! -velocity.error.cant-connect=Unable to connect to {0}\: {1} -velocity.error.connecting-server-error=Unable to connect you to {0}. Please try again later. -velocity.error.connected-server-error=Your connection to {0} encountered a problem. -velocity.error.internal-server-connection-error=An internal server connection error occurred. -velocity.error.logging-in-too-fast=You are logging in too fast, try again later. -velocity.error.online-mode-only=You are not logged into your Minecraft account. If you are logged into your Minecraft account, try restarting your Minecraft client. -velocity.error.player-connection-error=An internal error occurred in your connection. -velocity.error.modern-forwarding-needs-new-client=This server is only compatible with Minecraft 1.13 and above. -velocity.error.modern-forwarding-failed=Your server did not send a forwarding request to the proxy. Make sure the server is configured for Velocity forwarding. -velocity.error.moved-to-new-server=You were kicked from {0}\: {1} -velocity.error.no-available-servers=There are no available servers to connect you to. Try again later or contact an admin. +velocity.error.already-connected=Вече сте свързани към този сървър\! +velocity.error.already-connected-proxy=Вече сте свързани към това прокси\! +velocity.error.already-connecting=Вече се опитвате да се свържете към сървър\! +velocity.error.cant-connect=Не успяхме да Ви свържем към {0}\: {1} +velocity.error.connecting-server-error=Не успяхме да Ви свържем към {0}. Моля, опитайте по-късно. +velocity.error.connected-server-error=Възникна грешка, докато бяхте свързан към {0}. +velocity.error.internal-server-connection-error=Възникна вътрешна грешка със сървърната връзка. +velocity.error.logging-in-too-fast=Опитвате се да влизате твърде бързо - моля, опитайте по-късно. +velocity.error.online-mode-only=Не сте влезли в своя Minecraft акаунт. Ако вече сте го направили, опитайте да рестартирате играта и лаунчера и опитайте отново. +velocity.error.player-connection-error=Възникна грешка с вашата връзка. +velocity.error.modern-forwarding-needs-new-client=Този сървър е съвместим само с Minecraft 1.13 или по-нова версия. +velocity.error.modern-forwarding-failed=Сървъра Ви не изпрати заявка за препращане на информация към проксито. Моля, убедете се, че сървъра Ви е настроен за работа с Velocity. +velocity.error.moved-to-new-server=Ти беше изхвърлен от {0}\: {1} +velocity.error.no-available-servers=Няма налични сървъри, км които да Ви свържем. Моля, опитайте по-късно, или се свържете с администратор. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands -velocity.command.generic-error=An error occurred while running this command. -velocity.command.command-does-not-exist=This command does not exist. -velocity.command.players-only=Only players can run this command. -velocity.command.server-does-not-exist=The specified server {0} does not exist. -velocity.command.server-current-server=You are currently connected to {0}. -velocity.command.server-too-many=There are too many servers set up. Use tab completion to view all servers available. -velocity.command.server-available=Available servers\: -velocity.command.server-tooltip-player-online={0} player online -velocity.command.server-tooltip-players-online={0} players online -velocity.command.server-tooltip-current-server=Currently connected to this server -velocity.command.server-tooltip-offer-connect-server=Click to connect to this server -velocity.command.glist-player-singular={0} player is currently connected to the proxy. -velocity.command.glist-player-plural={0} players are currently connected to the proxy. -velocity.command.glist-view-all=To view all players on servers, use /glist all. -velocity.command.reload-success=Velocity configuration successfully reloaded. -velocity.command.reload-failure=Unable to reload your Velocity configuration. Check the console for more details. +velocity.command.generic-error=Възникна грешка при изпълняването на командата. +velocity.command.command-does-not-exist=Тази команда не съществува. +velocity.command.players-only=Само играчи могат да изпълняват тази команда. +velocity.command.server-does-not-exist=Сървър с името {0} не съществува. +velocity.command.player-not-found=The specified player {0} does not exist. +velocity.command.server-current-server=В момента сте свързан към {0}. +velocity.command.server-too-many=Има прекалено много регистрирани сървъри. Използвайте TAB, за да видите всички налични сървъри. +velocity.command.server-available=Налични сървъри\: +velocity.command.server-tooltip-player-online={0} играч на линия +velocity.command.server-tooltip-players-online={0} играчи на линия +velocity.command.server-tooltip-current-server=В момента сте свързани към този сървър +velocity.command.server-tooltip-offer-connect-server=Натиснете тук, за да Ви свържем към този сървър +velocity.command.glist-player-singular={0} играч е свързан към проксито. +velocity.command.glist-player-plural={0} играчи са свързани към проксито. +velocity.command.glist-view-all=За да видите всички играчи, разпределени по сървъри, използвайте /glist all. +velocity.command.reload-success=Настройките на Velocity бяха презаредени успешно. +velocity.command.reload-failure=Не успяхме да презаредим настройките на Velocity. Моля, проверете конзолата за повече информация. velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} is licensed under the terms of the GNU General Public License v3. -velocity.command.no-plugins=There are no plugins currently installed. -velocity.command.plugins-list=Plugins\: {0} -velocity.command.plugin-tooltip-website=Website\: {0} -velocity.command.plugin-tooltip-author=Author\: {0} -velocity.command.plugin-tooltip-authors=Authors\: {0} -velocity.command.dump-uploading=Uploading gathered information... -velocity.command.dump-send-error=An error occurred while communicating with the Velocity servers. The servers may be temporarily unavailable or there is an issue with your network settings. You can find more information in the log or console of your Velocity server. -velocity.command.dump-success=Created an anonymised report containing useful information about this proxy. If a developer requested it, you may share the following link with them\: -velocity.command.dump-will-expire=This link will expire in a few days. -velocity.command.dump-server-error=An error occurred on the Velocity servers and the dump could not be completed. Please contact the Velocity staff about this problem and provide the details about this error from the Velocity console or server log. -velocity.command.dump-offline=Likely cause\: Invalid system DNS settings or no internet connection \ No newline at end of file +velocity.command.no-plugins=За момента няма инсталирани добавки. +velocity.command.plugins-list=Добавки\: {0} +velocity.command.plugin-tooltip-website=Уебсайт\: {0} +velocity.command.plugin-tooltip-author=Автор\: {0} +velocity.command.plugin-tooltip-authors=Автори\: {0} +velocity.command.dump-uploading=Качваме събраната информация... +velocity.command.dump-send-error=Възникна грешка при комуникацията със сървърите на Velocity. Сървърите може временно да не са налични, или да имате проблем с мрежовите настройки. Ще откриете повече информация в логовете или конзолата на Вашето Velocity прокси. +velocity.command.dump-success=Създадохме анонимен доклад, съдържащ полезна информация относно това прокси. Ако разработчик Ви го е поискал, може да споделите този линк с тях\: +velocity.command.dump-will-expire=Този линк ще изтече след няколко дена. +velocity.command.dump-server-error=Възникна грешка при сървърите на Velocity и доклада не може да бъде завършен. Моля, уведомете разработващия екип на Velocity относно този проблем и осигурете детайли за грешката от конзолата или логовете. +velocity.command.dump-offline=Вероятна причина\: Невалидни системни DNS настройки или липса на Интернет връзка +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Проксито се изключва. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_cs_CZ.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_cs_CZ.properties index 6e6a0fe4d2..99d4f38a4f 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_cs_CZ.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_cs_CZ.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Tento server je kompatibilní velocity.error.modern-forwarding-failed=Tvůj server neodeslal přesměrovávací požadavek na proxy server. Ujisti se, že je server nastaven na Velocity přesměrování. velocity.error.moved-to-new-server=Byl jsi vyhozen ze serveru {0}\: {1} velocity.error.no-available-servers=Nejsou k dispozici žádné servery, ke kterým by ses mohl připojit. Zkus to později nebo kontaktuj správce. +velocity.error.illegal-chat-characters=Nepovolené znaky v chatu # Commands velocity.command.generic-error=Při vykonávání tohoto příkazu nastala chyba. velocity.command.command-does-not-exist=Tento příkaz neexistuje. velocity.command.players-only=Tento příkaz mohou vykonávat pouze hráči. velocity.command.server-does-not-exist=Zadaný server {0} neexistuje. +velocity.command.player-not-found=Zadaný hráč {0} neexistuje. velocity.command.server-current-server=Právě jsi připojen k serveru {0}. velocity.command.server-too-many=Je nastaveno příliš mnoho serverů. Klávesa tab ukáže všechny dostupné servery. velocity.command.server-available=Dostupné servery\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=Nastala chyba při komunikaci s Velocity server velocity.command.dump-success=Byla vytvořena anonymizovaná zpráva obsahující užitečné informace o tomto serveru. Vyžádal-li si je vývojář, můžeš mu poslat nasledující odkaz\: velocity.command.dump-will-expire=Za několik dnů tento odkaz vyprší. velocity.command.dump-server-error=Na Velocity serverech se vyskytla chyba a výpis nebylo možné vytvořit. Prosím kontaktuj Velocity tým o tomto problému a poskytni mu o této chybě podrobnosti z Velocity konzole nebo z logu na serveru. -velocity.command.dump-offline=Pravděpodobná příčina\: Neplatné systémové DNS nastavení nebo není připojení k internetu \ No newline at end of file +velocity.command.dump-offline=Pravděpodobná příčina\: Neplatné systémové DNS nastavení nebo není připojení k internetu +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy se vypíná. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_da_DK.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_da_DK.properties index 4205eb1672..c593076e52 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_da_DK.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_da_DK.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Denne server er kun kompatibel velocity.error.modern-forwarding-failed=Din server sendte ikke en viderestillingsanmodning til proxyen. Sørg for, at serveren er konfigureret til Velocity forwarding. velocity.error.moved-to-new-server=Du blev smidt ud fra {0}\: {1} velocity.error.no-available-servers=Der er ingen tilgængelige servere at forbinde dig til. Prøv igen senere eller kontakt en administrator. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands -velocity.command.generic-error=Der opstod en fejl under kørsel af denne kommando. +velocity.command.generic-error=Der opstod en fejl da du kørte kommandoen. velocity.command.command-does-not-exist=Denne kommando eksisterer ikke. velocity.command.players-only=Kun spillere kan køre denne kommando. velocity.command.server-does-not-exist=Den angivne server {0} findes ikke. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=Du er i øjeblikket forbundet til {0}. velocity.command.server-too-many=Der er sat for mange servere op. Brug tab færdiggørelse til at se alle tilgængelige servere. velocity.command.server-available=Tilgængelige servere\: @@ -44,17 +46,20 @@ velocity.command.server-tooltip-offer-connect-server=Klik for at forbinde til de velocity.command.glist-player-singular={0} spiller er i øjeblikket forbundet til proxyen. velocity.command.glist-player-plural={0} spillere er i øjeblikket forbundet til proxyen. velocity.command.glist-view-all=For at se alle spillere på servere, brug /glist all. -velocity.command.reload-success=Velocity konfiguration blev indlæst. +velocity.command.reload-success=Velocity konfiguration blev genindlæst. velocity.command.reload-failure=Kan ikke genindlæse din Velocity konfiguration. Tjek konsollen for flere detaljer. velocity.command.version-copyright=Ophavsret 2018-2023 {0}. {1} er licenseret under betingelserne i GNU General Public License v3. velocity.command.no-plugins=Der er ingen plugins installeret i øjeblikket. velocity.command.plugins-list=Plugins\: {0} velocity.command.plugin-tooltip-website=Hjemmeside\: {0} -velocity.command.plugin-tooltip-author=Skaber\: {0} +velocity.command.plugin-tooltip-author=Forfatter\: {0} velocity.command.plugin-tooltip-authors=Skabere\: {0} velocity.command.dump-uploading=Uploader indsamlet information... velocity.command.dump-send-error=Der opstod en fejl under kommunikation med Velocity serverne. Serverne kan være midlertidigt utilgængelige, eller der er et problem med dine netværksindstillinger. Du kan finde mere information i loggen eller konsollen på din Velocity server. velocity.command.dump-success=Oprettet en anonymiseret rapport med nyttige oplysninger om denne proxy. Hvis en udvikler anmodede om det, kan du dele følgende link med dem\: velocity.command.dump-will-expire=Dette link udløber om et par dage. -velocity.command.dump-server-error=Der opstod en fejl på Velocity serverne og dump kunne ikke fuldføres. Kontakt venligst Velocity personalet om dette problem og giv oplysninger om denne fejl fra Velocity konsollen eller server loggen. -velocity.command.dump-offline=Sandsynlig årsag\: Ugyldig system DNS-indstillinger eller ingen internetforbindelse \ No newline at end of file +velocity.command.dump-server-error=Der opstod en fejl på Velocity serverne og udskrivningen af fejl logbogen kunne ikke fuldføres. Kontakt venligst Velocity personalet om dette problem og giv oplysninger om denne fejl fra Velocity konsollen eller server loggen. +velocity.command.dump-offline=Sandsynlig årsag\: Ugyldig system DNS indstillinger eller ingen internetforbindelse +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy lukker ned. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_de_DE.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_de_DE.properties index fe42c07a7d..f2d6872ace 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_de_DE.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_de_DE.properties @@ -17,9 +17,9 @@ velocity.error.already-connected=Du bist bereits mit diesem Server verbunden\! velocity.error.already-connected-proxy=Du bist bereits mit diesem Proxy verbunden\! -velocity.error.already-connecting=Du versuchst bereits eine Verbindung mit dem Server herzustellen\! +velocity.error.already-connecting=Du versuchst dich bereits mit einem Server zu verbinden\! velocity.error.cant-connect=Kein Verbindungsaufbau zu {0} möglich\: {1} -velocity.error.connecting-server-error=Es ist derzeit nicht möglich eine Verbindung mit {0} herzustellen. Bitte versuche es später erneut. +velocity.error.connecting-server-error=Kein Verbindungsaufbau zu {0} möglich. Bitte versuche es später erneut. velocity.error.connected-server-error=Bei der Verbindung zu {0} ist ein Problem aufgetreten. velocity.error.internal-server-connection-error=Bei der Verbindung mit dem Server ist ein interner Fehler aufgetreten. velocity.error.logging-in-too-fast=Du meldest dich zu schnell an, versuche es später noch einmal. @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Dieser Server ist nur mit der velocity.error.modern-forwarding-failed=Dein Server hat keine Weiterleitungsanforderung an den Proxy gesendet. Stelle sicher, dass der Server für die Velocity Weiterleitung konfiguriert ist. velocity.error.moved-to-new-server=Du wurdest von {0} vom Server geworfen\: {1} velocity.error.no-available-servers=Es gibt keine verfügbaren Server mit denen du dich verbinden kannst. Versuche es später erneut oder kontaktiere einen Admin. +velocity.error.illegal-chat-characters=Ungültige Zeichen im Chat # Commands velocity.command.generic-error=Beim Ausführen des Befehls ist ein Fehler aufgetreten. velocity.command.command-does-not-exist=Dieser Befehl existiert nicht. velocity.command.players-only=Nur Spieler können diesen Befehl ausführen. velocity.command.server-does-not-exist=Der angegebene Server {0} existiert nicht. +velocity.command.player-not-found=Der angegebene Spieler {0} existiert nicht. velocity.command.server-current-server=Du bist derzeit mit {0} verbunden. velocity.command.server-too-many=Es sind zu viele Server eingerichtet. Verwende die Tabvervollständigung, um alle verfügbaren Server aufzulisten. velocity.command.server-available=Verfügbare Server\: @@ -54,7 +56,10 @@ velocity.command.plugin-tooltip-author=Entwickler\: {0} velocity.command.plugin-tooltip-authors=Entwickler\: {0} velocity.command.dump-uploading=Erfasste Daten werden hochgeladen... velocity.command.dump-send-error=Bei der Kommunikation mit den Velocity-Servern ist ein Fehler aufgetreten. Diese Server sind möglicherweise vorübergehend nicht verfügbar oder es gibt ein Problem mit deinen Netzwerkeinstellungen. Weitere Informationen findest du in der Log-Datei oder in der Konsole deines Velocity-Servers. -velocity.command.dump-success=Ein anonymisierter Bericht mit nützlichen Informationen über diesen Proxy wurde erstellt. Wenn ein Entwickler den Bericht angefordert hat, kannst über folgenden Link diesen mit ihm teilen\: +velocity.command.dump-success=Ein anonymisierter Bericht mit nützlichen Informationen über diesen Proxy wurde erstellt. Wenn ein Entwickler den Bericht angefordert hat, kannst du diesen über folgenden Link mit ihm teilen\: velocity.command.dump-will-expire=Dieser Link wird in ein paar Tagen ablaufen. velocity.command.dump-server-error=Auf den Velocity-Servern ist ein Fehler aufgetreten und der Dump konnte nicht abgeschlossen werden. Bitte kontaktiere die Velocity-Mitarbeiter über das Problem mit Details zu diesem Fehler aus der Velocity-Konsole oder dem Serverprotokoll. -velocity.command.dump-offline=Wahrscheinliche Ursache\: Ungültige System-DNS-Einstellungen oder keine Internetverbindung \ No newline at end of file +velocity.command.dump-offline=Wahrscheinliche Ursache\: Ungültige System-DNS-Einstellungen oder keine Internetverbindung +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy fährt herunter. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_es_ES.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_es_ES.properties index 5c73de752e..910e54cf26 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_es_ES.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_es_ES.properties @@ -29,13 +29,14 @@ velocity.error.modern-forwarding-needs-new-client=Este servidor solo es compatib velocity.error.modern-forwarding-failed=El servidor no ha enviado una solicitud de reenvío al proxy. Asegúrate de que tu servidor está configurado para usar el método de reenvío de Velocity. velocity.error.moved-to-new-server=Has sido echado de {0}\: {1} velocity.error.no-available-servers=No hay servidores disponibles a los que conectarte. Inténtalo de nuevo más tarde o contacta con un administrador. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=Se ha producido un error al ejecutar este comando. velocity.command.command-does-not-exist=Este comando no existe. velocity.command.players-only=Solo los jugadores pueden ejecutar este comando. velocity.command.server-does-not-exist=El servidor especificado {0} no existe. -velocity.command.server-current-server=Estás conectado a {0}. velocity.command.player-not-found=El jugador especificado {0} no existe. +velocity.command.server-current-server=Estás conectado a {0}. velocity.command.server-too-many=Hay demasiados servidores registrados. Usa la finalización con tabulación para ver todos los servidores disponibles. velocity.command.server-available=Servidores disponibles\: velocity.command.server-tooltip-player-online={0} jugador conectado @@ -59,4 +60,6 @@ velocity.command.dump-success=Se ha creado un informe anónimo que contiene info velocity.command.dump-will-expire=Este enlace caducará en unos días. velocity.command.dump-server-error=Se ha producido un error en los servidores de Velocity y la subida no se ha podido completar. Notifica al equipo de Velocity sobre este problema y proporciona los detalles sobre este error disponibles en el archivo de registro o la consola de tu servidor Velocity. velocity.command.dump-offline=Causa probable\: la configuración DNS del sistema no es válida o no hay conexión a internet -velocity.command.send-usage=/send \ No newline at end of file +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_et_EE.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_et_EE.properties index 9a2581296f..246419b997 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_et_EE.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_et_EE.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=This server is only compatible velocity.error.modern-forwarding-failed=Your server did not send a forwarding request to the proxy. Make sure the server is configured for Velocity forwarding. velocity.error.moved-to-new-server=You were kicked from {0}\: {1} velocity.error.no-available-servers=There are no available servers to connect you to. Try again later or contact an admin. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=An error occurred while running this command. velocity.command.command-does-not-exist=Antud käsklust ei eksisteeri. velocity.command.players-only=Ainult mängijad saavad antud käsklust kasutada. velocity.command.server-does-not-exist=Server {0} ei eksisteeri. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=Sa oled hetkel ühendatud serveriga {0}. velocity.command.server-too-many=There are too many servers set up. Use tab completion to view all servers available. velocity.command.server-available=Saadaolevad serverid\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=An error occurred while communicating with the velocity.command.dump-success=Created an anonymised report containing useful information about this proxy. If a developer requested it, you may share the following link with them\: velocity.command.dump-will-expire=Link aegub paari päeva pärast. velocity.command.dump-server-error=An error occurred on the Velocity servers and the dump could not be completed. Please contact the Velocity staff about this problem and provide the details about this error from the Velocity console or server log. -velocity.command.dump-offline=Likely cause\: Invalid system DNS settings or no internet connection \ No newline at end of file +velocity.command.dump-offline=Likely cause\: Invalid system DNS settings or no internet connection +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fi_FI.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fi_FI.properties index 725a7c8494..84b6d593db 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fi_FI.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fi_FI.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Tämä palvelin on yhteensopiv velocity.error.modern-forwarding-failed=Valitsemasi palvelin ei lähettänyt välityspyyntöä välityspalvelimelle. Tarkista että palvelin on määritetty oikein Velocityä varten. velocity.error.moved-to-new-server=Sinut potkittiin pois palvelimelta {0}\: {1} velocity.error.no-available-servers=Yhtään palvelinta ei ole tällä hetkellä saatavilla. Yritä myöhemmin uudelleen tai ota yhteyttä palvelimen ylläpitäjään. +velocity.error.illegal-chat-characters=Kiellettyjä merkkejä chatissa # Commands velocity.command.generic-error=Tämän komennon suorittamisessa tapahtui virhe. velocity.command.command-does-not-exist=Tuota komentoa ei ole olemassa. velocity.command.players-only=Vain pelaajat voivat käyttää tuota komentoa. velocity.command.server-does-not-exist=Palvelinta {0} ei ole olemassa. +velocity.command.player-not-found=Annettua pelaajaa {0} ei ole olemassa. velocity.command.server-current-server=Olet tällä hetkellä yhdistettynä palvelimeen {0}. velocity.command.server-too-many=Liian monta palvelinta on määritetty. Paina Tab -näppäintä nähdäksesi kaikki saatavilla olevat palvelimet. velocity.command.server-available=Saatavilla olevat palvelimet\: @@ -41,9 +43,9 @@ velocity.command.server-tooltip-player-online={0} pelaaja paikalla velocity.command.server-tooltip-players-online={0} pelaajaa paikalla velocity.command.server-tooltip-current-server=Tällä hetkellä yhdistetty tähän palvelimeen velocity.command.server-tooltip-offer-connect-server=Napsauta yhdistääksesi tähän palvelimeen -velocity.command.glist-player-singular={0} pelaaja on tällä hetkellä paikalla verkostossa. -velocity.command.glist-player-plural={0} pelaajaa on tällä hetkellä paikalla verkostossa. -velocity.command.glist-view-all=Nähdäksesi pelaajat kaikilta palvelimilta, käytä komentoa /glist all. +velocity.command.glist-player-singular={0} pelaaja on tällä hetkellä yhdistänyt välityspalvelimelle. +velocity.command.glist-player-plural={0} pelaajaa on tällä hetkellä yhdistänyt välityspalvelimelle. +velocity.command.glist-view-all=Nähdäksesi pelaajat kaikilla palvelimilla, käytä komentoa /glist all. velocity.command.reload-success=Velocityn konfiguraatio uudelleenladattiin onnistuneesti. velocity.command.reload-failure=Velocityn konfiguraation uudelleenlataus epäonnistui. Katso tarkemmat lisätiedot konsolista. velocity.command.version-copyright=Tekijänoikeus 2018-2023 {0}. {1} on lisensoitu GNU General Public License v3\:n ehtojen mukaisesti. @@ -57,4 +59,7 @@ velocity.command.dump-send-error=Velocity-palvelimien kanssa kommunikoidessa tap velocity.command.dump-success=Luotiin anonyymi raportti, joka sisältää hyödyllistä tietoa tästä välityspalvelimesta. Jos jokin kehittäjä on pyytänyt sitä, voit jakaa seuraavan linkin heidän kanssaan\: velocity.command.dump-will-expire=Tämä linkki vanhenee muutaman päivän kuluttua. velocity.command.dump-server-error=Virhe tapahtui Velocity-palvelimissa ja tiedonkeruuta ei voitu suorittaa loppuun. Ota yhteyttä Velocityn henkilökuntaan liittyen tästä ongelmasta, ja lisää yksityiskohdat virheestä Velocityn konsolista tai palvelimen lokista. -velocity.command.dump-offline=Todennäköinen syy\: DNS-asetukset ovat virheelliset tai internet-yhteyttä ei ole \ No newline at end of file +velocity.command.dump-offline=Todennäköinen syy\: DNS-asetukset ovat virheelliset tai internet-yhteyttä ei ole +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Sammutetaan välityspalvelinta. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fr_FR.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fr_FR.properties index 9de65eba73..024f37ad01 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fr_FR.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fr_FR.properties @@ -18,7 +18,7 @@ velocity.error.already-connected=Vous êtes déjà connecté(e) à ce serveur \! velocity.error.already-connected-proxy=Vous êtes déjà connecté(e) à ce proxy \! velocity.error.already-connecting=Vous êtes déjà en train d'essayer de vous connecter à un serveur \! -velocity.error.cant-connect=Impossible de se connecter à {0} \: {1} +velocity.error.cant-connect=Impossible de se connecter à {0} \: {1} velocity.error.connecting-server-error=Impossible de vous connecter à {0}. Veuillez réessayer ultérieurement. velocity.error.connected-server-error=Votre connexion à {0} a rencontré un problème. velocity.error.internal-server-connection-error=Une erreur interne s'est produite lors de la connexion au serveur. @@ -27,16 +27,18 @@ velocity.error.online-mode-only=Vous n'êtes pas connecté(e) à votre compte Mi velocity.error.player-connection-error=Une erreur interne s'est produite lors de votre connexion. velocity.error.modern-forwarding-needs-new-client=Ce serveur est uniquement compatible avec Minecraft 1.13 et les versions ultérieures. velocity.error.modern-forwarding-failed=Votre serveur n'a pas envoyé de requête de transfert vers le proxy. Assurez-vous que le serveur est configuré pour le transfert Velocity. -velocity.error.moved-to-new-server=Vous avez été expulsé(e) de {0} \: {1} +velocity.error.moved-to-new-server=Vous avez été expulsé(e) de {0} \: {1} velocity.error.no-available-servers=Il n'y a pas de serveurs disponibles auxquels vous connecter. Réessayez ultérieurement ou contactez un administrateur. +velocity.error.illegal-chat-characters=Caractères interdits dans le chat # Commands velocity.command.generic-error=Une erreur est survenue lors de l'exécution de cette commande. velocity.command.command-does-not-exist=Cette commande n'existe pas. velocity.command.players-only=Seuls les joueurs peuvent exécuter cette commande. -velocity.command.server-does-not-exist=Le serveur spécifié {0} n''existe pas. +velocity.command.server-does-not-exist=Le serveur spécifié {0} n'existe pas. +velocity.command.player-not-found=Le joueur spécifié {0} n'existe pas. velocity.command.server-current-server=Vous êtes actuellement connecté(e) à {0}. velocity.command.server-too-many=Il y a trop de serveurs configurés. Utilisez la saisie semi-automatique via la touche Tab pour afficher tous les serveurs disponibles. -velocity.command.server-available=Serveurs disponibles \: +velocity.command.server-available=Serveurs disponibles \: velocity.command.server-tooltip-player-online={0} joueur connecté velocity.command.server-tooltip-players-online={0} joueurs connectés velocity.command.server-tooltip-current-server=Actuellement connecté(e) à ce serveur @@ -48,13 +50,16 @@ velocity.command.reload-success=Configuration de Velocity rechargée avec succè velocity.command.reload-failure=Impossible de recharger votre configuration de Velocity. Consultez la console pour plus de détails. velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} est sous la licence GNU General Public License v3. velocity.command.no-plugins=Il n'y a aucun plugin actuellement installé. -velocity.command.plugins-list=Plugins \: {0} -velocity.command.plugin-tooltip-website=Site Internet \: {0} -velocity.command.plugin-tooltip-author=Auteur \: {0} -velocity.command.plugin-tooltip-authors=Auteurs \: {0} +velocity.command.plugins-list=Plugins \: {0} +velocity.command.plugin-tooltip-website=Site Internet \: {0} +velocity.command.plugin-tooltip-author=Auteur \: {0} +velocity.command.plugin-tooltip-authors=Auteurs \: {0} velocity.command.dump-uploading=Envoi des informations collectées... velocity.command.dump-send-error=Une erreur est survenue lors de la communication avec les serveurs Velocity. Soit les serveurs sont temporairement indisponibles, soit il y a un problème avec les paramètres de votre réseau. Vous trouverez plus d'informations dans le journal ou la console de votre serveur Velocity. velocity.command.dump-success=Un rapport anonyme contenant des informations utiles sur ce proxy a été créé. Si un développeur vous le demande, vous pouvez le partager avec le lien suivant \: velocity.command.dump-will-expire=Ce lien expirera dans quelques jours. velocity.command.dump-server-error=Une erreur s'est produite sur les serveurs Velocity et le dump n'a pas pu être terminé. Veuillez contacter l'équipe de Velocity et leur communiquer les détails sur cette erreur à partir de la console de Velocity ou du journal du serveur. -velocity.command.dump-offline=Cause probable \: paramètres DNS non valides ou aucune connexion Internet \ No newline at end of file +velocity.command.dump-offline=Cause probable \: paramètres DNS non valides ou aucune connexion Internet +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Arrêt du proxy. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_he_IL.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_he_IL.properties index 809682225c..3b0b8c6973 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_he_IL.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_he_IL.properties @@ -20,20 +20,22 @@ velocity.error.already-connected-proxy=אתה כבר מחובר ל- proxy זה\! velocity.error.already-connecting=אתה כבר מנסה להתחבר לשרת\! velocity.error.cant-connect=לא ניתן להתחבר ל- {0}\: {1} velocity.error.connecting-server-error=לא ניתן לחבר אותך ל- {0}. אנא נסה שנית מאוחר יותר. -velocity.error.connected-server-error=החיבר שלך ל- {0} נתקל בבעיה. -velocity.error.internal-server-connection-error=התרחש שגיאת חיבור שרת פנימית. +velocity.error.connected-server-error=החיבור שלך ל- {0} נתקל בבעיה. +velocity.error.internal-server-connection-error=התרחשה שגיאת חיבור שרת פנימית. velocity.error.logging-in-too-fast=אתה נכנס מהר מדי, נסה שוב מאוחר יותר. velocity.error.online-mode-only=אינך מחובר לחשבון Minecraft שלך. אם אתה מחובר לחשבון Minecraft שלך, נסה להפעיל מחדש את המשחק שלך. -velocity.error.player-connection-error=התרחש שגיאה פנימית בחיבור שלך. +velocity.error.player-connection-error=התרחשה שגיאה פנימית בחיבור שלך. velocity.error.modern-forwarding-needs-new-client=שרת זה תואם רק עם Minecraft 1.13 ומעלה. velocity.error.modern-forwarding-failed=השרת שלך לא שלח בקשת העברה ל- proxy. ודא שתצורת השרת נקבעה להעברת Velocity. -velocity.error.moved-to-new-server=אתה הורחקתה מ- {0}\: {1} +velocity.error.moved-to-new-server=אתה הורחקת מ- {0}\: {1} velocity.error.no-available-servers=אין שרתים זמינים אליהם יש לחבר אותך. נסה שוב מאוחר יותר או פנה למנהל מערכת. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands -velocity.command.generic-error=התרחש שגיאה בעת הפעלת פקודה זו. +velocity.command.generic-error=התרחשה שגיאה בעת הפעלת פקודה זו. velocity.command.command-does-not-exist=פקודה זו אינה קיימת. velocity.command.players-only=רק שחקנים יכולים להפעיל פקודה זו. velocity.command.server-does-not-exist=השרת {0} שצוין אינו קיים. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=אתה מחובר כעת ל- {0}. velocity.command.server-too-many=הוגדרו שרתים רבים מדי. השתמש בהשלמת כרטיסיה כדי להציג את כל השרתים הזמינים. velocity.command.server-available=שרתים זמינים\: @@ -43,7 +45,7 @@ velocity.command.server-tooltip-current-server=מחובר כעת לשרת זה velocity.command.server-tooltip-offer-connect-server=לחץ על מנת להתחבר לשרת זה velocity.command.glist-player-singular=שחקן {0} כעת מחובר ל- proxy. velocity.command.glist-player-plural={0} שחקנים מחוברים כעת ל- proxy. -velocity.command.glist-view-all=כדי להציג את כל השחקנים בשרתים, השתמש ב- /glist all. +velocity.command.glist-view-all=כדי להציג את כל השחקנים בשרתים, השתמש ב- glist all/. velocity.command.reload-success=תצורת Velocity נטענה מחדש בהצלחה. velocity.command.reload-failure=אין אפשרות לטעון מחדש את תצורת ה- Velocity שלך. עיין בקונסולה לקבלת פרטים נוספים. velocity.command.version-copyright=זכויות יוצרים 2018-2023 {0}. {1} מורשה על פי תנאי v3 הרישיון הציבורי הכללי של GNU. @@ -51,10 +53,13 @@ velocity.command.no-plugins=לא מותקנים כעת תוספים. velocity.command.plugins-list=תוספים\: {0} velocity.command.plugin-tooltip-website=אתר אינטרנט\: {0} velocity.command.plugin-tooltip-author=יוצר\: {0} -velocity.command.plugin-tooltip-authors=יוצר\: {0} +velocity.command.plugin-tooltip-authors=יוצרים\: {0} velocity.command.dump-uploading=מעלה מידע שנאסף... -velocity.command.dump-send-error=התרחש שגיאה בעת קיום תקשורת עם שרתי ה- Velocity. ייתכן שהשרתים אינם זמינים באופן זמני או שקיימת בעיה בהגדרות הרשת שלך. באפשרותך למצוא מידע נוסף ביומן הרישום או בקונסולה של שרת ה- Velocity שלך. +velocity.command.dump-send-error=התרחשה שגיאה בעת קיום תקשורת עם שרתי ה- Velocity. ייתכן שהשרתים אינם זמינים באופן זמני או שקיימת בעיה בהגדרות הרשת שלך. באפשרותך למצוא מידע נוסף ביומן הרישום או בקונסולה של שרת ה- Velocity שלך. velocity.command.dump-success=נוצר דוח אנונימיות המכיל מידע שימושי אודות proxy זה. אם מפתח ביקש זאת, באפשרותך לשתף איתם את הקישור הבא\: velocity.command.dump-will-expire=קישור זה יפוג בעוד מספר ימים. -velocity.command.dump-server-error=התרחש שגיאה בשרתי ה- Velocity ולא הייתה אפשרות להשלים את קובץ ה- dump. אנא צור קשר עם צוות ה- Velocity בנוגע לבעיה זו ולספק את הפרטים אודות שגיאה זו מקונסולה ה- Velocity או מיומן השרת. -velocity.command.dump-offline=סביר להניח\: הגדרות DNS לא חוקיות של המערכת או ללא חיבור לאינטרנט \ No newline at end of file +velocity.command.dump-server-error=התרחשה שגיאה בשרתי ה- Velocity ולא הייתה אפשרות להשלים את קובץ ה- dump. אנא צור קשר עם צוות ה- Velocity בנוגע לבעיה זו ולספק את הפרטים אודות שגיאה זו מקונסולה ה- Velocity או מיומן השרת. +velocity.command.dump-offline=סביר להניח\: הגדרות DNS לא חוקיות של המערכת או ללא חיבור לאינטרנט +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy בתהליך כיבוי. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_hu_HU.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_hu_HU.properties index ce11388b96..e5cb5b1c8a 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_hu_HU.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_hu_HU.properties @@ -22,18 +22,20 @@ velocity.error.cant-connect=Nem lehet csatlakozni a(z) {0} szerverhez\: {1} velocity.error.connecting-server-error=Nem tudunk csatlakoztatni a(z) {0} szerverhez. Kérlek próbáld újra később. velocity.error.connected-server-error=A kapcsolatod a(z) {0} szerverhez hibába ütközött. velocity.error.internal-server-connection-error=Egy szerveroldali hiba történt. -velocity.error.logging-in-too-fast=Túl gyorsan próbálsz csatlakozni, kérlek próbáld újra később. +velocity.error.logging-in-too-fast=Túl gyorsan próbálsz csatlakozni, próbáld újra később. velocity.error.online-mode-only=Nem vagy belépve a Minecraft profilodba. Ha mégis be vagy lépve, kérlek próbáld újraindítani a Minecraft kliensedet. velocity.error.player-connection-error=Egy belső hiba keletkezett a kapcsolatodban. velocity.error.modern-forwarding-needs-new-client=Ez a szerver csak a Minecraft 1.13 és afölötti verziókkal kompatibilis. velocity.error.modern-forwarding-failed=A szerver ahonnan csatlakoztál nem küldött modern átirányítási kérelmet a proxy felé. Bizonyosodj meg róla, hogy a szerver be van állítva a modern Velocity átirányítás használatára. velocity.error.moved-to-new-server=Ki lettél rúgva a(z) {0} szerverről\: {1} velocity.error.no-available-servers=Jelenleg nincs elérhető szerver ahová csatlakoztatni tudnánk. Próbáld újra később, vagy lépj kapcsolatba egy adminisztrátorral. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=Hiba történt a parancs futtatása közben. velocity.command.command-does-not-exist=Ilyen parancs nem létezik. velocity.command.players-only=Ezt a parancsot csak játékosok használhatják. velocity.command.server-does-not-exist=A megadott szerver ({0}) nem létezik. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=Jelenleg a(z) {0} szerveren tartózkodsz. velocity.command.server-too-many=Túl sok szerver van beállítva. Használd a tab parancs befejező funkciót, hogy megnézd az összes elérhető szervert. velocity.command.server-available=Elérhető szerverek\: @@ -56,5 +58,8 @@ velocity.command.dump-uploading=Az összegyűjtött információ feltöltése... velocity.command.dump-send-error=Egy hiba lépett fel miközben kommunikálni próbáltunk a Velocity szerverekkel. Lehetséges, hogy a szerver(ek) ideiglenesen elérhetetlenek, vagy ez egy hiba a te hálózati beállításaiddal. Több információt a logban, vagy a Velocity konzoljában találsz. velocity.command.dump-success=Egy anonimizált jelentés sikeresen el lett készítve erről a proxyról. Ha egy fejlesztő kérte, akkor innen kimásolhatod a linket, és megoszthatod velük\: velocity.command.dump-will-expire=Ez a link egy pár napon belül le fog járni. -velocity.command.dump-server-error=Egy hiba lépett fel a Velocity szervereken, és a jelentést nem tudtuk elkészíteni. Kérlek lépj kapcsolatba egy Velocity személyzeti taggal ezzel a problémával kapcsolatban, és adj információt ezzel a hibával kapcsolatban a Veloctiy logokból, vagy a szerver konzolból. -velocity.command.dump-offline=Valószínűleg a következő a hiba okozója\: Hibás DNS beállítások, vagy nincs internetkapcsolat. \ No newline at end of file +velocity.command.dump-server-error=Egy hiba lépett fel a Velocity szervereken, és a jelentést nem tudtuk elkészíteni. Kérlek lépj kapcsolatba egy Velocity személyzeti taggal ezzel a problémával kapcsolatban, és adj információt ezzel a hibával kapcsolatban a Velocity logokból, vagy a szerver konzolból. +velocity.command.dump-offline=Valószínűleg a következő a hiba okozója\: Hibás DNS beállítások, vagy nincs internetkapcsolat. +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_it_IT.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_it_IT.properties index e4e2843362..0c72f5e1d1 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_it_IT.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_it_IT.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Questo server è compatibile s velocity.error.modern-forwarding-failed=Il server non ha inviato una richiesta di inoltro al proxy. Assicurati che il server sia configurato per l'inoltro di Velocity. velocity.error.moved-to-new-server=Sei stato cacciato da {0}\: {1} velocity.error.no-available-servers=Non ci sono server disponibili per connetterti. Riprova più tardi o contatta un amministratore. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=Si è verificato un errore durante l'esecuzione di questo comando. velocity.command.command-does-not-exist=Questo comando non esiste. velocity.command.players-only=Solo i giocatori possono eseguire questo comando. velocity.command.server-does-not-exist=Il server {0} non esiste. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=Sei già connesso a {0}. velocity.command.server-too-many=Ci sono troppi server impostati. Usa il completamento con il tasto tab per visualizzare tutti i server disponibili. velocity.command.server-available=Server disponibili\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=Si è verificato un errore durante la comunicaz velocity.command.dump-success=Creato un report anonimo contenente informazioni utili su questo proxy. Se uno sviluppatore lo richiede, è possibile condividere con loro il seguente link\: velocity.command.dump-will-expire=Questo link scadrà tra pochi giorni. velocity.command.dump-server-error=Si è verificato un errore sui server Velocity e il dump non può essere completato. Contattare lo staff di Velocity per questo problema e fornire i dettagli relativi a questo errore dalla console di Velocity o dai log del server. -velocity.command.dump-offline=Probabile causa\: Impostazioni DNS di sistema non valide o nessuna connessione internet \ No newline at end of file +velocity.command.dump-offline=Probabile causa\: Impostazioni DNS di sistema non valide o nessuna connessione internet +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Il server è in fase di arresto. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ja_JP.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ja_JP.properties index b0eca4bd22..a16b0605e0 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ja_JP.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ja_JP.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=このサーバーは Minecraf velocity.error.modern-forwarding-failed=サーバーがプロキシに転送要求を送信しませんでした。 サーバーが Velocity 用に構成されていることを確認してください。 velocity.error.moved-to-new-server=あなたは {0} からキックされました\: {1} velocity.error.no-available-servers=接続できるサーバーがありません。後でもう一度試すか、管理者にお問い合わせください。 +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=このコマンドの実行中にエラーが発生しました。 velocity.command.command-does-not-exist=未知のコマンドです。 velocity.command.players-only=このコマンドはプレイヤーのみ実行できます。 velocity.command.server-does-not-exist=指定されたサーバー {0} は存在しません。 +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=現在 {0} に接続しています。 velocity.command.server-too-many=設定されているサーバー数が多すぎます。タブ補完を使い、利用可能なすべてのサーバーを表示してください。 velocity.command.server-available=利用可能なサーバー\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=Velocityサーバーとの通信中にエラー velocity.command.dump-success=このプロキシに関する有用な情報を含む匿名化されたレポートを作成しました。開発者が要求した場合は、次のリンクを共有してください\: velocity.command.dump-will-expire=このリンクは数日後に期限切れになります。 velocity.command.dump-server-error=Velocityサーバーでエラーが発生し、ダンプが完了できませんでした。 この問題についてはVelocityスタッフに連絡し、コンソールまたはサーバーログからこのエラーの詳細を提供してください。 -velocity.command.dump-offline=考えられる原因\: システムのDNS設定が無効であるか、インターネットに接続されていません \ No newline at end of file +velocity.command.dump-offline=考えられる原因\: システムのDNS設定が無効であるか、インターネットに接続されていません +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=プロキシをシャットダウンしています。 \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ko_KR.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ko_KR.properties index b98f490c3a..6bb66d1ceb 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ko_KR.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ko_KR.properties @@ -18,43 +18,48 @@ velocity.error.already-connected=이미 이 서버에 연결되어 있습니다\! velocity.error.already-connected-proxy=이미 이 프록시에 연결되어 있습니다\! velocity.error.already-connecting=이미 이 서버에 연결하는 중입니다\! -velocity.error.cant-connect={0}\: {1} 에 연결할 수 없습니다. -velocity.error.connecting-server-error={0} 에 연결할 수 없습니다. 나중에 다시 시도해주세요. -velocity.error.connected-server-error={0} 에 연결하던 도중 문제가 발생했습니다. -velocity.error.internal-server-connection-error=내부 오류가 발생했습니다. -velocity.error.logging-in-too-fast=너무 빠르게 로그인을 시도했습니다. 나중에 다시 시도해주세요. -velocity.error.online-mode-only=Minecraft 계정에 로그인되어 있지 않습니다. 만약 로그인중이 맞다면, 클라이언트를 재실행해보세요. +velocity.error.cant-connect={0}에 연결할 수 없습니다\: {1} +velocity.error.connecting-server-error={0}에 연결할 수 없습니다. 나중에 다시 시도하세요. +velocity.error.connected-server-error={0}에 연결하던 도중 문제가 발생했습니다. +velocity.error.internal-server-connection-error=내부 서버 연결 오류가 발생했습니다. +velocity.error.logging-in-too-fast=너무 빠르게 로그인을 시도했습니다. 나중에 다시 시도하세요. +velocity.error.online-mode-only=Minecraft 계정에 로그인하지 않았습니다. Minecraft 계정에 로그인한 경우, Minecraft 클라이언트를 다시 시작해보세요. velocity.error.player-connection-error=연결에 내부 오류가 발생했습니다. velocity.error.modern-forwarding-needs-new-client=이 서버는 Minecraft 1.13 이상만 지원합니다. -velocity.error.modern-forwarding-failed=서버가 프록시에 포워딩 요청을 보내지 않았습니다. 서버가 Velocity 포워딩이 설정되어 있는지 확인하세요. -velocity.error.moved-to-new-server={0}\: {1} 에서 추방됐습니다. +velocity.error.modern-forwarding-failed=서버가 프록시에 포워딩 요청을 보내지 않았습니다. 서버가 Velocity 포워딩을 사용하도록 설정되어 있는지 확인하세요. +velocity.error.moved-to-new-server={0}에서 추방됐습니다\: {1} velocity.error.no-available-servers=연결할 수 있는 서버가 없습니다. 나중에 다시 시도하거나 관리자에게 문의하세요. +velocity.error.illegal-chat-characters=채팅에 올바르지 않은 문자가 있습니다. # Commands velocity.command.generic-error=명령어를 실행하는 도중 오류가 발생했습니다. -velocity.command.command-does-not-exist=그 명령어는 존재하지 않습니다. +velocity.command.command-does-not-exist=존재하지 않는 명령어입니다. velocity.command.players-only=이 명령어는 플레이어만 사용할 수 있습니다. -velocity.command.server-does-not-exist=서버 {0} (은)는 존재하지 않습니다. -velocity.command.server-current-server={0} 에 연결되어 있습니다. -velocity.command.server-too-many=너무 많은 서버가 존재합니다. tab 자동완성으로 가능한 모든 서버를 보세요. +velocity.command.server-does-not-exist=지정한 서버 {0} 이(가) 존재하지 않습니다. +velocity.command.player-not-found=지정한 플레이어 {0} 이(가) 존재하지 않습니다. +velocity.command.server-current-server=현재 {0}에 연결되어 있습니다. +velocity.command.server-too-many=너무 많은 서버가 존재합니다. tab 자동완성으로 사용 가능한 모든 서버를 볼 수 있습니다. velocity.command.server-available=사용 가능한 서버\: -velocity.command.server-tooltip-player-online={0} 플레이어 접속중 -velocity.command.server-tooltip-players-online={0} 플레이어 접속중 -velocity.command.server-tooltip-current-server=이 서버에 연결되어 있습니다 -velocity.command.server-tooltip-offer-connect-server=클릭해 이 서버에 연결합니다. -velocity.command.glist-player-singular={0} 플레이어가 현재 프록시에 연결되어 있습니다. -velocity.command.glist-player-plural={0} 플레이어가 현재 프록시에 연결되어 있습니다. -velocity.command.glist-view-all=서버에 있는 모든 플레이어를 보려면, /glist all 를 사용하세요. -velocity.command.reload-success=Velocity 설정이 성공적으로 리로드되었습니다. -velocity.command.reload-failure=Velocity 설정을 리로드할 수 없습니다. 콘솔에서 더 많은 정보를 확인하세요. +velocity.command.server-tooltip-player-online=플레이어 {0}명 접속 중 +velocity.command.server-tooltip-players-online=플레이어 {0}명 접속 중 +velocity.command.server-tooltip-current-server=현재 이 서버에 연결되어 있습니다 +velocity.command.server-tooltip-offer-connect-server=이 서버에 연결하려면 클릭하세요 +velocity.command.glist-player-singular=플레이어 {0}명이 현재 프록시에 연결되어 있습니다. +velocity.command.glist-player-plural=플레이어 {0}명이 현재 프록시에 연결되어 있습니다. +velocity.command.glist-view-all=서버에 있는 모든 플레이어를 보려면, /glist all을 사용하세요. +velocity.command.reload-success=Velocity 설정을 성공적으로 다시 불러왔습니다. +velocity.command.reload-failure=Velocity 설정을 다시 불러올 수 없습니다. 자세한 내용은 콘솔을 확인하세요. velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} 는 GNU General Public License v3 라이센스의 약관을 따릅니다. velocity.command.no-plugins=설치된 플러그인이 없습니다. velocity.command.plugins-list=플러그인\: {0} velocity.command.plugin-tooltip-website=웹사이트\: {0} velocity.command.plugin-tooltip-author=제작자\: {0} velocity.command.plugin-tooltip-authors=제작자\: {0} -velocity.command.dump-uploading=모인 정보를 업로드하는 중... -velocity.command.dump-send-error=Velocity 서버와 통신하는데 오류가 발생했습니다. 서버가 일시적으로 사용할 수 없거나 네트워크 설정에 문제가 있습니다. Velocity 서버의 콘솔 또는 로그에서 자세한 정보를 찾아볼 수 있습니다. +velocity.command.dump-uploading=수집된 정보를 업로드하는 중... +velocity.command.dump-send-error=Velocity 서버와 통신하는 동안 오류가 발생했습니다. 서버를 일시적으로 사용할 수 없거나 네트워크 설정에 문제가 있을 수 있습니다. Velocity 서버의 로그 또는 콘솔에서 자세한 정보를 찾아볼 수 있습니다. velocity.command.dump-success=이 프록시와 관련된 유용한 정보를 담은 익명 보고서를 만들었습니다. 만약 개발자가 요청한다면, 다음 링크를 그들에게 공유해보세요\: -velocity.command.dump-will-expire=이 링크는 수 일 안에 만료됩니다. +velocity.command.dump-will-expire=이 링크는 며칠 후에 만료됩니다. velocity.command.dump-server-error=Velocity 서버에 문제가 발생했으며 덤프가 완료되지 않았습니다. Velocity 스태프에게 연락해 이 문제에 대해 설명하고 Velocity 콘솔 또는 서버 로그를 제공해주세요. -velocity.command.dump-offline=가능성 높은 원인\: 잘못된 DNS 설정 또는 인터넷 연결 없음 \ No newline at end of file +velocity.command.dump-offline=가능성 높은 원인\: 잘못된 DNS 설정 또는 인터넷 연결 없음 +velocity.command.send-usage=/send <플레이어> <서버> +# Kick +velocity.kick.shutdown=프록시가 종료됩니다. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nb_NO.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nb_NO.properties index 9c4f85d972..ef7794e5a0 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nb_NO.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nb_NO.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Denne serveren er bare kompati velocity.error.modern-forwarding-failed=Din server sendte ikke en viderekoblingsforespørsel til proxyen. Pass på at serveren er konfigurert for Velocity viderekobling. velocity.error.moved-to-new-server=Du ble sparket ut fra {0}\: {1} velocity.error.no-available-servers=Det finnes ingen tilgjengelige servere å koble deg til. Prøv igjen senere eller kontakt en administrator. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=En feil oppstod under gjennomføringen av denne kommandoen. velocity.command.command-does-not-exist=Denne kommandoen finnes ikke. velocity.command.players-only=Bare spillere kan utføre denne kommandoen. velocity.command.server-does-not-exist=Den spesifiserte serveren {0} finnes ikke. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=Du er for øyeblikket tilkoblet {0}. velocity.command.server-too-many=Det er for mange servere satt opp. Bruk tabfullførelse for å se alle tilgjengelige servere. velocity.command.server-available=Tilgjengelige servere\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=En feil oppstod under kommunikasjon med Velocit velocity.command.dump-success=Skapte en anonymisert rapport med utfyllende informasjon om denne proxyen. Om en utvikler forespurte den, kan du dele følgende lenke med dem\: velocity.command.dump-will-expire=Denne lenken kommer til å fjernes om noen dager. velocity.command.dump-server-error=En feil oppstod på Velocityserverne og en diagnostisk informasjonsinnsamling kunne ikke gennomføres. Vennligst kontakt organisasjonen bak Velocity om problemet og oppgi alle detaljene du kan finne i Velocitykonsollen eller loggen. -velocity.command.dump-offline=Sannsynlig årsak\: Ugyldige DNS innstillinger eller manglende internettforbindelse \ No newline at end of file +velocity.command.dump-offline=Sannsynlig årsak\: Ugyldige DNS innstillinger eller manglende internettforbindelse +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy slår seg av. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nl_NL.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nl_NL.properties index efb5ced5f2..44d12b0821 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nl_NL.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nl_NL.properties @@ -23,19 +23,21 @@ velocity.error.connecting-server-error=Kan je niet verbinden met {0}. Probeer he velocity.error.connected-server-error=Er is een probleem opgetreden bij je verbinding met {0}. velocity.error.internal-server-connection-error=Er is een interne serververbindingsfout opgetreden. velocity.error.logging-in-too-fast=Je logt te snel in, probeer het later opnieuw. -velocity.error.online-mode-only=Je bent niet aangemeld bij je Minecraft-account. Indien dit wel het geval is, probeer dan je Minecraft-client opnieuw op te starten. +velocity.error.online-mode-only=Je bent niet aangemeld bij je Minecraft-account. Als je wel bent ingelogd bij je Minecraft account, probeer dan je Minecraft-client opnieuw op te starten. velocity.error.player-connection-error=Er is een interne fout opgetreden bij je verbinding. -velocity.error.modern-forwarding-needs-new-client=Deze server is alleen compatibel met Minecraft 1.13 en nieuwer. -velocity.error.modern-forwarding-failed=Je server heeft geen forwarding request naar de proxy gestuurd. Zorg ervoor dat de server is geconfigureerd voor Velocity forwarding. +velocity.error.modern-forwarding-needs-new-client=Deze server ondersteunt alleen Minecraft 1.13 en nieuwer. +velocity.error.modern-forwarding-failed=Je server heeft geen forwarding verzoek naar de proxy gestuurd. Zorg ervoor dat de server is geconfigureerd voor Velocity forwarding. velocity.error.moved-to-new-server=Je bent verwijderd van {0}\: {1} velocity.error.no-available-servers=Er zijn geen beschikbare servers om je met te verbinden. Probeer het later opnieuw of neem contact op met een administrator. +velocity.error.illegal-chat-characters=Ongeldige karakters in de chat # Commands velocity.command.generic-error=Er is een fout opgetreden bij het uitvoeren van dit commando. velocity.command.command-does-not-exist=Dit commando bestaat niet. velocity.command.players-only=Alleen spelers kunnen dit commando uitvoeren. velocity.command.server-does-not-exist=De opgegeven server {0} bestaat niet. +velocity.command.player-not-found=De opgegeven speler {0} bestaat niet. velocity.command.server-current-server=Je bent op dit moment verbonden met {0}. -velocity.command.server-too-many=Er zijn te veel servers ingesteld. Gebruik tabvervollediging om alle beschikbare servers te bekijken. +velocity.command.server-too-many=Er zijn te veel servers ingesteld. Gebruik tab-aanvulling om alle beschikbare servers te bekijken. velocity.command.server-available=Beschikbare servers\: velocity.command.server-tooltip-player-online={0} speler online velocity.command.server-tooltip-players-online={0} spelers online @@ -45,7 +47,7 @@ velocity.command.glist-player-singular={0} speler is momenteel verbonden met de velocity.command.glist-player-plural={0} spelers zijn momenteel verbonden met de proxy. velocity.command.glist-view-all=Om alle spelers op de servers te bekijken, gebruik /glist all. velocity.command.reload-success=Velocity configuratie succesvol herladen. -velocity.command.reload-failure=De Velocity-configuratie kan niet opnieuw worden geladen. Kijk op de console voor meer details. +velocity.command.reload-failure=De Velocity-configuratie kan niet opnieuw worden geladen. Kijk in de console voor meer details. velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} is gelicentieerd onder de voorwaarden van de GNU General Public License v3. velocity.command.no-plugins=Er zijn momenteel geen plugins geïnstalleerd. velocity.command.plugins-list=Plugins\: {0} @@ -56,5 +58,8 @@ velocity.command.dump-uploading=Verzamelde informatie uploaden... velocity.command.dump-send-error=Er is een fout opgetreden tijdens de communicatie met de Velocity-servers. De servers zijn mogelijk tijdelijk niet beschikbaar of er is een probleem met je netwerkinstellingen. Je kunt meer informatie vinden in de logs of de console van je Velocity-server. velocity.command.dump-success=Een anoniem rapport is gemaakt met nuttige informatie over deze proxy. Als een ontwikkelaar dit heeft verzocht, kun je de volgende link delen\: velocity.command.dump-will-expire=Deze link verloopt over een paar dagen. -velocity.command.dump-server-error=Er is een fout opgetreden op de Velocity-servers en de dump kan niet worden voltooid. Neem contact op met het Velocity-personeel over dit probleem en geef de details over deze fout op vanuit de Velocity-console of de logs. -velocity.command.dump-offline=Waarschijnlijke oorzaak\: ongeldige DNS-instellingen van het systeem of geen internetverbinding \ No newline at end of file +velocity.command.dump-server-error=Er is een fout opgetreden op de Velocity-servers en de dump kan niet worden voltooid. Neem contact op met het Velocity team over dit probleem en geef de details over deze fout op vanuit de Velocity-console of de logs. +velocity.command.dump-offline=Waarschijnlijke oorzaak\: ongeldige DNS-instellingen van het systeem of geen internetverbinding +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy wordt afgesloten. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nn_NO.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nn_NO.properties index c525f916d4..eb6bfa3872 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nn_NO.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_nn_NO.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Denne sørvaren er bare kompat velocity.error.modern-forwarding-failed=Din server sende ikkje ein vidarekoplingsførespurnad til proxyen. Pass på at sørvaren er konfigurert for Velocity vidarekopling. velocity.error.moved-to-new-server=Du blei sparka ut frå {0}\: {1} velocity.error.no-available-servers=Det finst ingen tilgjengelege sørvarar å kopla deg til. Prøv igjen seinare eller kontakt ein administrator. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=Ein feil oppstod under utføringa av denne kommandoen. velocity.command.command-does-not-exist=Denne kommandoen finst ikkje. velocity.command.players-only=Bare spelarar kan utføra denne kommandoen. velocity.command.server-does-not-exist=Den oppgjevne sørvaren {0} finst ikkje. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=Du er for augneblinken tilkopla {0}. velocity.command.server-too-many=Det er for mange sørvarar sette opp. Bruk tabfullføring for å sjå alle tilgjengelege sørvarar. velocity.command.server-available=Tilgjengelege sørvarar\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=An error occurred while communicating with the velocity.command.dump-success=Created an anonymised report containing useful information about this proxy. If a developer requested it, you may share the following link with them\: velocity.command.dump-will-expire=This link will expire in a few days. velocity.command.dump-server-error=An error occurred on the Velocity servers and the dump could not be completed. Please contact the Velocity staff about this problem and provide the details about this error from the Velocity console or server log. -velocity.command.dump-offline=Likely cause\: Invalid system DNS settings or no internet connection \ No newline at end of file +velocity.command.dump-offline=Likely cause\: Invalid system DNS settings or no internet connection +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pl_PL.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pl_PL.properties index d4c0f73ffe..c3e2cfcfa2 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pl_PL.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pl_PL.properties @@ -15,46 +15,51 @@ # along with this program. If not, see . # -velocity.error.already-connected=Już jesteś połączony z tym serwerem\! -velocity.error.already-connected-proxy=Już jesteś połączony z tym serwerem proxy\! -velocity.error.already-connecting=Już próbujesz połączyć się z serwerem\! +velocity.error.already-connected=Jesteś już połączony z tym serwerem\! +velocity.error.already-connected-proxy=Jesteś już połączony z tym proxy\! +velocity.error.already-connecting=Jesteś już w trakcie łączenia się do serwera\! velocity.error.cant-connect=Nie udało się połączyć z serwerem {0}\: {1} -velocity.error.connecting-server-error=Nie udało się Ciebie połączyć z serwerem {0}. Spróbuj ponownie później. -velocity.error.connected-server-error=Podczas łączenia z serwerem {0} wystąpił błąd. -velocity.error.internal-server-connection-error=W łączeniu się z serwerem wystąpił błąd wewnętrzny. -velocity.error.logging-in-too-fast=Wysyłasz zbyt wiele prób zalogowania, spróbuj ponownie później. -velocity.error.online-mode-only=Nie jesteś zalogowany za pomocą konta Minecraft. Jeżeli jesteś zalogowany, spróbuj zrestartować grę. -velocity.error.player-connection-error=Wystąpił błąd wewnętrzny w twoim połączeniu. -velocity.error.modern-forwarding-needs-new-client=Ten serwer jest kompatybilny tylko z wersją Minecraft 1.13 lub nowszymi. -velocity.error.modern-forwarding-failed=Twój serwer nie wysłał żądania przekazania do serwera proxy. Upewnij się, że serwer jest skonfigurowany do przekazywania Velocity. -velocity.error.moved-to-new-server=Zostałeś wyrzucony z serwera {0}\: {1} -velocity.error.no-available-servers=Brak dostępnych serwerów, z którymi można by Cię połączyć. Spróbuj ponownie później lub skontaktuj się z administratorem. +velocity.error.connecting-server-error=Nie udało się połączyć cię z serwerem {0}. Spróbuj ponownie później. +velocity.error.connected-server-error=Podczas łączenia cię z serwerem {0} wystąpił problem. +velocity.error.internal-server-connection-error=Wystąpił wewnętrzny błąd połączenia serwera. +velocity.error.logging-in-too-fast=Logujesz się zbyt szybko, spróbuj ponownie później. +velocity.error.online-mode-only=Nie jesteś zalogowany do swojego konta Minecraft. Jeżeli jesteś zalogowany, spróbuj zrestartować grę. +velocity.error.player-connection-error=Wystąpił wewnętrzny błąd w twoim połączeniu. +velocity.error.modern-forwarding-needs-new-client=Ten serwer wspiera tylko wersje Minecraft 1.13 lub nowsze. +velocity.error.modern-forwarding-failed=Twój serwer nie wysłał żądania o przekazanie danych do proxy. Upewnij się, że serwer jest skonfigurowany do nowoczesnego przekazywania Velocity. +velocity.error.moved-to-new-server=Zostałeś wyrzucony z {0}\: {1} +velocity.error.no-available-servers=Nie ma dostępnych serwerów, do których można cię połączyć. Spróbuj ponownie później lub skontaktuj się z administratorem. +velocity.error.illegal-chat-characters=Niedozwolone znaki na czacie # Commands -velocity.command.generic-error=Podczas wykonywania tego polecenia wystąpił błąd. +velocity.command.generic-error=Wystąpił błąd podczas wykonywania tego polecenia. velocity.command.command-does-not-exist=To polecenie nie istnieje. -velocity.command.players-only=Jedynie gracze mogą wykonywać to polecenie. +velocity.command.players-only=Tylko gracze mogą wykonać to polecenie. velocity.command.server-does-not-exist=Wybrany serwer {0} nie istnieje. -velocity.command.server-current-server=Jesteś obecnie połączony z serwerem {0}. -velocity.command.server-too-many=Skonfigurowano zbyt wiele serwerów. Użyj uzupełniania klawiszem tab, aby wyświetlić wszystkie dostępne serwery. +velocity.command.player-not-found=Gracz {0} nie istnieje. +velocity.command.server-current-server=Jesteś obecnie połączony z {0}. +velocity.command.server-too-many=Skonfigurowano zbyt wiele serwerów. Użyj autouzupełniania, aby wyświetlić wszystkie dostępne serwery. velocity.command.server-available=Dostępne serwery\: velocity.command.server-tooltip-player-online={0} gracz online velocity.command.server-tooltip-players-online={0} graczy online velocity.command.server-tooltip-current-server=Jesteś obecnie połączony z tym serwerem velocity.command.server-tooltip-offer-connect-server=Kliknij, aby połączyć się z tym serwerem -velocity.command.glist-player-singular=Z tym „proxy” jest obecnie połączony {0} gracz. -velocity.command.glist-player-plural=Liczba graczy obecnie połączonych z tym „proxy”\: {0} -velocity.command.glist-view-all=Aby zobaczyć wszystkich graczy na serwerach, użyj /glist all. +velocity.command.glist-player-singular=Z tym proxy jest obecnie połączony {0} gracz. +velocity.command.glist-player-plural=Z tym proxy jest obecnie połączonych {0} graczy. +velocity.command.glist-view-all=Aby zobaczyć wszystkich graczy na wszystkich serwerach, użyj /glist all. velocity.command.reload-success=Konfiguracja Velocity została pomyślnie załadowana ponownie. -velocity.command.reload-failure=Nie udało się załadować konfiguracji Velocity. Sprawdź konsolę, aby uzyskać więcej informacji. +velocity.command.reload-failure=Nie udało się ponownie załadować twojej konfiguracji Velocity. Sprawdź konsolę po więcej szczegółów. velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} jest objęty licencją na warunkach GNU General Public License v3. -velocity.command.no-plugins=Brak zainstalowanych wtyczek. -velocity.command.plugins-list=Wtyczki\: {0} +velocity.command.no-plugins=Obecnie nie ma zainstalowanych żadnych pluginów. +velocity.command.plugins-list=Pluginy\: {0} velocity.command.plugin-tooltip-website=Strona internetowa\: {0} -velocity.command.plugin-tooltip-author=Twórca\: {0} -velocity.command.plugin-tooltip-authors=Twórcy\: {0} +velocity.command.plugin-tooltip-author=Autor\: {0} +velocity.command.plugin-tooltip-authors=Autorzy\: {0} velocity.command.dump-uploading=Przesyłanie zebranych informacji… -velocity.command.dump-send-error=Wystąpił błąd podczas komunikacji z serwerami Velocity. Serwery mogą być chwilowo niedostępne lub wystąpił problem z ustawieniami sieci. Więcej informacji można znaleźć w dzienniku lub konsoli serwera Velocity. -velocity.command.dump-success=Utworzono zanonimizowany raport zawierający przydatne informacje o tym proxy. Jeśli programista o to poprosił, możesz udostępnić mu następujący link\: +velocity.command.dump-send-error=Wystąpił błąd podczas komunikacji z serwerami Velocity. Serwery mogą być chwilowo niedostępne lub wystąpił problem z ustawieniami sieci. Możesz znaleźć więcej informacji w logach lub konsoli swojego serwera Velocity. +velocity.command.dump-success=Utworzono anonimowy raport zawierający przydatne informacje o tym proxy. Możesz udostępnić deweloperowi następujący odnośnik, jeśli o niego poprosił\: velocity.command.dump-will-expire=Ten odnośnik wygaśnie za kilka dni. -velocity.command.dump-server-error=Wystąpił błąd na serwerach Velocity i nie można było ukończyć przekazania. Skontaktuj się z personelem Velocity w sprawie tego problemu i podaj szczegółowe informacje o tym błędzie z konsoli Velocity lub dziennika serwera. -velocity.command.dump-offline=Prawdopodobna przyczyna\: nieprawidłowe ustawienia DNS systemu lub brak połączenia internetowego \ No newline at end of file +velocity.command.dump-server-error=Wystąpił błąd na serwerach Velocity i nie udało się przesłać raportu. Skontaktuj się z zespołem Velocity w sprawie tego problemu i podaj szczegółowe informacje o tym błędzie z konsoli Velocity lub logów serwera. +velocity.command.dump-offline=Prawdopodobna przyczyna\: nieprawidłowe ustawienia DNS lub brak połączenia internetowego +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Wyłączanie serwera proxy. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pt_BR.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pt_BR.properties index d1c4faecbc..5fb79912b6 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pt_BR.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pt_BR.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Este servidor é compatível a velocity.error.modern-forwarding-failed=Seu servidor não enviou uma solicitação de encaminhamento para o proxy. Certifique-se de que o servidor está configurado para encaminhamento Velocity. velocity.error.moved-to-new-server=Você foi expulso de {0}\: {1} velocity.error.no-available-servers=Não há servidores disponíveis para conectá-lo. Tente novamente mais tarde ou contate um administrador. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=Ocorreu um erro ao executar este comando. velocity.command.command-does-not-exist=Esse comando não existe. velocity.command.players-only=Apenas jogadores podem executar esse comando. velocity.command.server-does-not-exist=O servidor {0} não existe. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=Você está atualmente conectado a {0}. velocity.command.server-too-many=Há muitos servidores configurados. Utilize o auto-preenchimento tab para ver todos os servidores disponíveis. velocity.command.server-available=Servidores disponíveis\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=Ocorreu um erro ao se comunicar com os servidor velocity.command.dump-success=Foi criado um relatório anônimo contendo informações úteis sobre este proxy. Se um desenvolvedor o solicitou, você pode compartilhar o seguinte link com eles\: velocity.command.dump-will-expire=Este link irá expirar em alguns dias. velocity.command.dump-server-error=Ocorreu um erro nos servidores Velocity e o dump não pôde ser concluído. Por favor, entre em contato com a staff do Velocity sobre este problema e forneça detalhes sobre esse erro a partir do log do console Velocity ou do servidor. -velocity.command.dump-offline=Causa provavel\: configurações de DNS do sistema inválidas ou sem conexão de internet \ No newline at end of file +velocity.command.dump-offline=Causa provavel\: configurações de DNS do sistema inválidas ou sem conexão de internet +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ro_RO.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ro_RO.properties new file mode 100644 index 0000000000..8f28b91b7d --- /dev/null +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ro_RO.properties @@ -0,0 +1,65 @@ +# +# Copyright (C) 2018 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 . +# + +velocity.error.already-connected=You are already connected to this server\! +velocity.error.already-connected-proxy=You are already connected to this proxy\! +velocity.error.already-connecting=You are already trying to connect to a server\! +velocity.error.cant-connect=Unable to connect to {0}\: {1} +velocity.error.connecting-server-error=Unable to connect you to {0}. Please try again later. +velocity.error.connected-server-error=Your connection to {0} encountered a problem. +velocity.error.internal-server-connection-error=An internal server connection error occurred. +velocity.error.logging-in-too-fast=You are logging in too fast, try again later. +velocity.error.online-mode-only=You are not logged into your Minecraft account. If you are logged into your Minecraft account, try restarting your Minecraft client. +velocity.error.player-connection-error=An internal error occurred in your connection. +velocity.error.modern-forwarding-needs-new-client=This server is only compatible with Minecraft 1.13 and above. +velocity.error.modern-forwarding-failed=Your server did not send a forwarding request to the proxy. Make sure the server is configured for Velocity forwarding. +velocity.error.moved-to-new-server=You were kicked from {0}\: {1} +velocity.error.no-available-servers=There are no available servers to connect you to. Try again later or contact an admin. +velocity.error.illegal-chat-characters=Illegal characters in chat +# Commands +velocity.command.generic-error=An error occurred while running this command. +velocity.command.command-does-not-exist=This command does not exist. +velocity.command.players-only=Only players can run this command. +velocity.command.server-does-not-exist=The specified server {0} does not exist. +velocity.command.player-not-found=The specified player {0} does not exist. +velocity.command.server-current-server=You are currently connected to {0}. +velocity.command.server-too-many=There are too many servers set up. Use tab completion to view all servers available. +velocity.command.server-available=Available servers\: +velocity.command.server-tooltip-player-online={0} player online +velocity.command.server-tooltip-players-online={0} players online +velocity.command.server-tooltip-current-server=Currently connected to this server +velocity.command.server-tooltip-offer-connect-server=Click to connect to this server +velocity.command.glist-player-singular={0} player is currently connected to the proxy. +velocity.command.glist-player-plural={0} players are currently connected to the proxy. +velocity.command.glist-view-all=To view all players on servers, use /glist all. +velocity.command.reload-success=Velocity configuration successfully reloaded. +velocity.command.reload-failure=Unable to reload your Velocity configuration. Check the console for more details. +velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} is licensed under the terms of the GNU General Public License v3. +velocity.command.no-plugins=There are no plugins currently installed. +velocity.command.plugins-list=Plugins\: {0} +velocity.command.plugin-tooltip-website=Website\: {0} +velocity.command.plugin-tooltip-author=Author\: {0} +velocity.command.plugin-tooltip-authors=Authors\: {0} +velocity.command.dump-uploading=Uploading gathered information... +velocity.command.dump-send-error=An error occurred while communicating with the Velocity servers. The servers may be temporarily unavailable or there is an issue with your network settings. You can find more information in the log or console of your Velocity server. +velocity.command.dump-success=Created an anonymised report containing useful information about this proxy. If a developer requested it, you may share the following link with them\: +velocity.command.dump-will-expire=This link will expire in a few days. +velocity.command.dump-server-error=An error occurred on the Velocity servers and the dump could not be completed. Please contact the Velocity staff about this problem and provide the details about this error from the Velocity console or server log. +velocity.command.dump-offline=Likely cause\: Invalid system DNS settings or no internet connection +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy se închide. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ru_RU.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ru_RU.properties index 80339767a2..14913c743f 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ru_RU.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ru_RU.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Этот сервер совм velocity.error.modern-forwarding-failed=Ваш сервер не посылал запрос на переадресацию на прокси-сервер. Убедитесь, что сервер настроен на переадресацию Velocity. velocity.error.moved-to-new-server=Вы были кикнуты с сервера {0}\: {1} velocity.error.no-available-servers=Нет серверов, доступных для подключения. Попробуйте позже или свяжитесь с администратором. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=Во время выполнения этой команды произошла ошибка. velocity.command.command-does-not-exist=Этой команды не существует. velocity.command.players-only=Только игроки могут использовать эту команду. velocity.command.server-does-not-exist=Указанный сервер {0} не существует. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=На данный момент вы подключены к серверу {0}. velocity.command.server-too-many=Настроено слишком много серверов. Для просмотра всех доступных серверов, используйте автозаполнение клавишей Tab. velocity.command.server-available=Доступные серверы\: @@ -45,16 +47,19 @@ velocity.command.glist-player-singular={0} игрок подключен к пр velocity.command.glist-player-plural={0} игрок(а, ов) подключены к прокси на данный момент. velocity.command.glist-view-all=Чтобы просмотреть всех игроков на серверах, используйте /glist all. velocity.command.reload-success=Конфигурация Velocity успешно перезагружена. -velocity.command.reload-failure=Не удалось перезагрузить конфигурацию Velocity. Проверьте консоль для подробностей. +velocity.command.reload-failure=Не удалось перезагрузить конфигурацию Velocity. Проверьте консоль для получения более подробной информации. velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} лицензирована на условиях GNU General Public License v3. velocity.command.no-plugins=Ни одного плагина не установлено. velocity.command.plugins-list=Плагины\: {0} -velocity.command.plugin-tooltip-website=Вебсайт\: {0} +velocity.command.plugin-tooltip-website=Веб-сайт\: {0} velocity.command.plugin-tooltip-author=Автор\: {0} velocity.command.plugin-tooltip-authors=Авторы\: {0} velocity.command.dump-uploading=Загрузка полученной информации... -velocity.command.dump-send-error=Во время связи с серверами Velocity произошла ошибка. Возможно, серверы временно недоступны или проблема в настройках вашей сети. Более подробную информацию можно найти в логе или консоли вашего сервера Velocity. +velocity.command.dump-send-error=Произошла ошибка при попытке связаться с серверами Velocity. Возможно, серверы временно недоступны или ваша сеть настроена неправильно. Более подробную информацию можно найти в логах или консоли вашего сервера Velocity. velocity.command.dump-success=Создан анонимный отчет, содержащий полезную информацию об этом прокси. Если этот отчёт запросил разработчик, вы можете поделиться с ним следующей ссылкой\: velocity.command.dump-will-expire=Срок действия этой ссылки истечёт через несколько дней. -velocity.command.dump-server-error=На серверах Velocity произошла ошибка, и дамп не удалось завершить. Пожалуйста, свяжитесь с сотрудниками Velocity по поводу этой проблемы и сообщите подробности, а также предоставьте подробную информацию об этой ошибке из консоли Velocity или лога сервера. -velocity.command.dump-offline=Вероятная причина\: Неверные настройки DNS или отсутствие подключения к Интернету \ No newline at end of file +velocity.command.dump-server-error=Не удалось завершить дамп, так как на серверах Velocity произошла ошибка. Пожалуйста, свяжитесь с командой Velocity по поводу этой проблемы и сообщите подробности, а также предоставьте подробную информацию об этой ошибке из консоли Velocity или логов сервера. +velocity.command.dump-offline=Вероятная причина\: Неверные настройки DNS или отсутствие подключения к интернету +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Прокси-сервер выключается. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sk_SK.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sk_SK.properties index 66f86f05db..f7a89585d0 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sk_SK.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sk_SK.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Tento server je kompatibilný velocity.error.modern-forwarding-failed=Tvoj server neodoslal presmerovaciu požiadavku proxy serveru. Uisti sa, že server je nastavený na presmerovanie Velocity. velocity.error.moved-to-new-server=Bol si odpojený z {0}\: {1} velocity.error.no-available-servers=Nie sú k dispozícii žiadne servery na pripojenie. Skús to neskôr alebo kontaktuj admina. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=Nastala chyba pri vykonávaní tohto príkazu. velocity.command.command-does-not-exist=Tento príkaz neexistuje. velocity.command.players-only=Len hráči môžu vykonať tento príkaz. velocity.command.server-does-not-exist=Zadaný server {0} neexistuje. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=Aktuálne si pripojený na {0}. velocity.command.server-too-many=Je nastavených príliš veľa serverov. Použi tab pre zobrazenie dostupných serverov. velocity.command.server-available=Dostupné servery\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=Nastala chyba pri komunikácii s Velocity serve velocity.command.dump-success=Bol vytvorený anonymný záznam o tomto serveri. Ak si ho vyžiadal developer, môžeš mu poslať nasledujúci odkaz\: velocity.command.dump-will-expire=Tento odkaz vyprší za niekoľko dní. velocity.command.dump-server-error=Nastala chyba vo Velocity serveroch a záznam nebolo možné vytvoriť. Prosím kontaktuj tím Velocity a poskytni detaily o tejto chybe z konzoly Velocity alebo z logu servera. -velocity.command.dump-offline=Pravdepodobná príčina\: Neplatné systémové nastavenie DNS alebo chýbajúce pripojenie na internet \ No newline at end of file +velocity.command.dump-offline=Pravdepodobná príčina\: Neplatné systémové nastavenie DNS alebo chýbajúce pripojenie na internet +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sq_AL.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sq_AL.properties index a0f2295467..64e6b2b148 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sq_AL.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sq_AL.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Ky server është i pajtueshë velocity.error.modern-forwarding-failed=Serveri juaj nuk i dërgoi një kërkesë për transferim përfaqësuesit. Sigurohuni që serveri të jetë konfiguruar për transferimin e shpejtësisë. velocity.error.moved-to-new-server=Ju kanë dëbuar nga {0}\: {1} velocity.error.no-available-servers=Nuk ka servera të disponueshëm për t'ju lidhur. Provo përsëri më vonë ose kontakto një administrator. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=Ndodhi një gabim gjatë ekzekutimit të kësaj komande. velocity.command.command-does-not-exist=Kjo komandë nuk ekziston. velocity.command.players-only=Vetëm lojtarët mund ta drejtojnë këtë komandë. velocity.command.server-does-not-exist=Serveri i specifikuar {0} nuk ekziston. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=Aktualisht jeni i lidhur me {0}. velocity.command.server-too-many=Ka shumë servera të konfiguruar. Përdorni përfundimin e skedave për të parë të gjithë serverat e disponueshëm. velocity.command.server-available=Serverat e disponueshëm\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=An error occurred while communicating with the velocity.command.dump-success=Created an anonymised report containing useful information about this proxy. If a developer requested it, you may share the following link with them\: velocity.command.dump-will-expire=This link will expire in a few days. velocity.command.dump-server-error=An error occurred on the Velocity servers and the dump could not be completed. Please contact the Velocity staff about this problem and provide the details about this error from the Velocity console or server log. -velocity.command.dump-offline=Likely cause\: Invalid system DNS settings or no internet connection \ No newline at end of file +velocity.command.dump-offline=Likely cause\: Invalid system DNS settings or no internet connection +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sr_Latn.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sr_Latn.properties new file mode 100644 index 0000000000..313aa9135d --- /dev/null +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sr_Latn.properties @@ -0,0 +1,65 @@ +# +# Copyright (C) 2018 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 . +# + +velocity.error.already-connected=Već ste povezani na ovaj server\! +velocity.error.already-connected-proxy=Već ste povezani na ovaj proxy\! +velocity.error.already-connecting=Već pokušavate da se povežete na server\! +velocity.error.cant-connect=Nije moguće povezati se na {0}\: {1} +velocity.error.connecting-server-error=Nije moguće povezati Vas na {0}. Molimo pokušajte ponovo kasnije. +velocity.error.connected-server-error=Došlo je do problema sa Vašom vezom sa {0}. +velocity.error.internal-server-connection-error=Dogodila se interna greška sa konekcijom sa serverom. +velocity.error.logging-in-too-fast=Logujete se prebrzo, molimo pokušajte kasnije. +velocity.error.online-mode-only=Niste ulogovani na Vaš Minecraft nalog. Ako ipak jeste, probajte da restartujete Minecraft klijent. +velocity.error.player-connection-error=Dogodila se interna greška sa Vašom konekcijom. +velocity.error.modern-forwarding-needs-new-client=Ovaj server je kompatibilan samo sa Minecraft-om 1.13 i višim verzijama. +velocity.error.modern-forwarding-failed=Vaš server nije poslao zahtev za prosleđivanje na proxy. Proverite je li server konfigurisan za Velocity prosleđivanje. +velocity.error.moved-to-new-server=Izbačeni ste iz {0}\: {1} +velocity.error.no-available-servers=Nema dostupnih servera za povezati Vas. Pokušajte ponovo kasnije ili kontaktirajte nekog admina. +velocity.error.illegal-chat-characters=Illegal characters in chat +# Commands +velocity.command.generic-error=Došlo je do greške pri pokretanju te komande. +velocity.command.command-does-not-exist=Ta komanda ne postoji. +velocity.command.players-only=Tu komandu mogu pokrenuti samo igrači. +velocity.command.server-does-not-exist=Navedeni server {0} ne postoji. +velocity.command.player-not-found=The specified player {0} does not exist. +velocity.command.server-current-server=Trenutno ste povezani na {0}. +velocity.command.server-too-many=Postoji mnogo servera. Koristite tab dovršavanje za pregled svih dostupnih servera. +velocity.command.server-available=Dostupni serveri\: +velocity.command.server-tooltip-player-online={0} igrač online +velocity.command.server-tooltip-players-online={0} igrača online +velocity.command.server-tooltip-current-server=Trenutno ste povezani na ovaj server +velocity.command.server-tooltip-offer-connect-server=Kliknite za povezivanje na ovaj server +velocity.command.glist-player-singular={0} igrač je trenutno povezan na proxy. +velocity.command.glist-player-plural={0} igrača je trenutno povezano na proxy. +velocity.command.glist-view-all=Za pregled svih igrača na serverima koristite /glist all. +velocity.command.reload-success=Velocity konfiguracija uspešno ponovno učitana. +velocity.command.reload-failure=Nije moguće ponovo učitati Vašu Velocity konfiguraciju. Proverite konzolu za više detalja. +velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} is licensed under the terms of the GNU General Public License v3. +velocity.command.no-plugins=Trenutno nema instaliranih plugin-a. +velocity.command.plugins-list=Plugin-i\: {0} +velocity.command.plugin-tooltip-website=Web stranica\: {0} +velocity.command.plugin-tooltip-author=Autor\: {0} +velocity.command.plugin-tooltip-authors=Autori\: {0} +velocity.command.dump-uploading=Otpremanje prikupljenih informacija... +velocity.command.dump-send-error=Dogodila se greška pri komunikaciji sa Velocity serverima. Serveri su ili trenutno nedostupni, ili postoji problem sa Vašim mrežnim podešavanjima. Možete saznati više informacija u log-u ili konzoli Vašeg Velocity servera. +velocity.command.dump-success=Kreiran anonimiziran izveštaj koji sadrži korisne informacije o ovom proxy-u. Ako ga developer zatraži, možete mu poslati ovaj link\: +velocity.command.dump-will-expire=Ovaj link će isteći za nekoliko dana. +velocity.command.dump-server-error=Dogodila se greška na Velocity serverima i nije moguće završiti dump. Molimo kontaktirajte Velocity staff u pitanju ovog problema i pružite detalje o ovoj grešci iz Velocity konzole ili server log-a. +velocity.command.dump-offline=Verovatan uzrok\: Nevalidan sistem DNS podešavanja ili nema internet konekcije +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sv_SE.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sv_SE.properties index 33d8333dde..fca663fa95 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sv_SE.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_sv_SE.properties @@ -15,46 +15,51 @@ # along with this program. If not, see . # -velocity.error.already-connected=You are already connected to this server\! -velocity.error.already-connected-proxy=You are already connected to this proxy\! -velocity.error.already-connecting=You are already trying to connect to a server\! -velocity.error.cant-connect=Unable to connect to {0}\: {1} -velocity.error.connecting-server-error=Unable to connect you to {0}. Please try again later. -velocity.error.connected-server-error=Your connection to {0} encountered a problem. -velocity.error.internal-server-connection-error=An internal server connection error occurred. -velocity.error.logging-in-too-fast=You are logging in too fast, try again later. -velocity.error.online-mode-only=You are not logged into your Minecraft account. If you are logged into your Minecraft account, try restarting your Minecraft client. -velocity.error.player-connection-error=An internal error occurred in your connection. -velocity.error.modern-forwarding-needs-new-client=This server is only compatible with Minecraft 1.13 and above. -velocity.error.modern-forwarding-failed=Your server did not send a forwarding request to the proxy. Make sure the server is configured for Velocity forwarding. -velocity.error.moved-to-new-server=You were kicked from {0}\: {1} -velocity.error.no-available-servers=There are no available servers to connect you to. Try again later or contact an admin. +velocity.error.already-connected=Du är redan ansluten till den här servern\! +velocity.error.already-connected-proxy=Du är redan ansluten till den här proxyn\! +velocity.error.already-connecting=Du försöker redan ansluta till en server\! +velocity.error.cant-connect=Det går inte att ansluta till {0}\: {1} +velocity.error.connecting-server-error=Det går inte att ansluta dig till {0}. Snälla försök igen senare. +velocity.error.connected-server-error=Din anslutning till {0} stötte på ett problem. +velocity.error.internal-server-connection-error=Ett internt serveranslutningsfel uppstod. +velocity.error.logging-in-too-fast=Du loggar in för snabbt, Försök igen senare. +velocity.error.online-mode-only=Du är inte inloggad på ditt Minecraft konto. Om du är inloggad på ditt Minecraft konto, prova att starta om din Minecraft klient. +velocity.error.player-connection-error=Ett internt fel uppstod i din anslutning. +velocity.error.modern-forwarding-needs-new-client=Denna server är endast kompatibel med Minecraft 1.13 och högre. +velocity.error.modern-forwarding-failed=Din server skickade inte en vidarebefordrings begäran till proxyn. Se till att servern är konfigurerad för Velocity vidarebefordrings begäran. +velocity.error.moved-to-new-server=Du blev sparkad från {0}\: {1} +velocity.error.no-available-servers=Det finns inga tillgängliga servrar att ansluta dig till. Försök igen senare eller kontakta en admin. +velocity.error.illegal-chat-characters=Olagliga tecken i chatten # Commands -velocity.command.generic-error=An error occurred while running this command. -velocity.command.command-does-not-exist=This command does not exist. -velocity.command.players-only=Only players can run this command. -velocity.command.server-does-not-exist=The specified server {0} does not exist. -velocity.command.server-current-server=You are currently connected to {0}. -velocity.command.server-too-many=There are too many servers set up. Use tab completion to view all servers available. -velocity.command.server-available=Available servers\: -velocity.command.server-tooltip-player-online={0} player online -velocity.command.server-tooltip-players-online={0} players online -velocity.command.server-tooltip-current-server=Currently connected to this server -velocity.command.server-tooltip-offer-connect-server=Click to connect to this server -velocity.command.glist-player-singular={0} player is currently connected to the proxy. -velocity.command.glist-player-plural={0} players are currently connected to the proxy. -velocity.command.glist-view-all=To view all players on servers, use /glist all. -velocity.command.reload-success=Velocity configuration successfully reloaded. -velocity.command.reload-failure=Unable to reload your Velocity configuration. Check the console for more details. -velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} is licensed under the terms of the GNU General Public License v3. -velocity.command.no-plugins=There are no plugins currently installed. -velocity.command.plugins-list=Plugins\: {0} -velocity.command.plugin-tooltip-website=Website\: {0} -velocity.command.plugin-tooltip-author=Author\: {0} -velocity.command.plugin-tooltip-authors=Authors\: {0} -velocity.command.dump-uploading=Uploading gathered information... -velocity.command.dump-send-error=An error occurred while communicating with the Velocity servers. The servers may be temporarily unavailable or there is an issue with your network settings. You can find more information in the log or console of your Velocity server. -velocity.command.dump-success=Created an anonymised report containing useful information about this proxy. If a developer requested it, you may share the following link with them\: -velocity.command.dump-will-expire=This link will expire in a few days. -velocity.command.dump-server-error=An error occurred on the Velocity servers and the dump could not be completed. Please contact the Velocity staff about this problem and provide the details about this error from the Velocity console or server log. -velocity.command.dump-offline=Likely cause\: Invalid system DNS settings or no internet connection \ No newline at end of file +velocity.command.generic-error=Ett fel uppstod när det här kommandot kördes. +velocity.command.command-does-not-exist=Detta kommando finns inte. +velocity.command.players-only=Bara spelare kan använda detta kommando. +velocity.command.server-does-not-exist=Den angivna servern {0} finns inte. +velocity.command.player-not-found=Den angivna spelaren {0} finns inte. +velocity.command.server-current-server=Du är just nu ansluten till {0}. +velocity.command.server-too-many=Det finns för många servrar som är konfigurerade. Använd tab färdigställandet för att se alla tillgängliga servrar. +velocity.command.server-available=Tillgängliga servrar\: +velocity.command.server-tooltip-player-online={0} spelare online +velocity.command.server-tooltip-players-online={0} spelare online +velocity.command.server-tooltip-current-server=Just nu ansluten till denna servern +velocity.command.server-tooltip-offer-connect-server=Klicka för att ansluta till servern +velocity.command.glist-player-singular={0} spelare är just nu ansluten till proxyn. +velocity.command.glist-player-plural={0} spelare är just nu ansluten till proxyn. +velocity.command.glist-view-all=För att se alla spelare på servrar, använd /glist all. +velocity.command.reload-success=Velocity konfigurationen har laddats om. +velocity.command.reload-failure=Det gick inte att ladda om din Velocity konfiguration. Kontrollera konsolen för mer information. +velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} är licensierad enligt villkoren i GNU General Public License v3. +velocity.command.no-plugins=Det finns inga tillägg installerade. +velocity.command.plugins-list=Tillägg\: {0} +velocity.command.plugin-tooltip-website=Webbsida\: {0} +velocity.command.plugin-tooltip-author=Utgivare\: {0} +velocity.command.plugin-tooltip-authors=Utgivare\: {0} +velocity.command.dump-uploading=Laddar upp insamlad information... +velocity.command.dump-send-error=Ett fel uppstod under kommunikationen med Velocity servrarna. Servrarna kan vara tillfälligt otillgängliga eller så finns det ett problem med dina nätverksinställningar. Du kan hitta mer information i loggen eller konsolen på din Velocity server. +velocity.command.dump-success=Skapade en anonymiserad rapport med användbar information om denna proxy. Om en utvecklare begärde det, kan du dela följande länk med dem\: +velocity.command.dump-will-expire=Denna länk kommer att gå ut om några dagar. +velocity.command.dump-server-error=Ett fel uppstod på Velocity servrarna och dumpen kunde inte slutföras. Vänligen kontakta Velocity personalen om detta problem och ge dem information om detta fel från Velocity konsolen eller serverloggen. +velocity.command.dump-offline=Sannolik orsak\: Ogiltiga system DNS inställningar eller ingen internetanslutning +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy stänger ner. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_tl_PH.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_tl_PH.properties index 240af05f9d..a9e5c15ba4 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_tl_PH.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_tl_PH.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Ang server na ito magkasundo l velocity.error.modern-forwarding-failed=Hindi ipadala ang serbidor mo ng forwarding request sa proxy. Dapat nae-ensure mo ng naka-configure ang server para ng forwarding ng Velocity. velocity.error.moved-to-new-server=Nanipa ka mula sa {0} dahil {1} velocity.error.no-available-servers=Wala na ang mga serbidor na magagamit para sa'yo. Paki-ulitin mo ulit o magcontact ka isang admin. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=Nangyari isang pagkakamali kapag sinubukan ng serbidor magamit ang komando ng ito. velocity.command.command-does-not-exist=Walang komando sa serbidor. velocity.command.players-only=Mga manlalaro lang makagamit ang komando ito. velocity.command.server-does-not-exist=Walang serbidor {0}. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=Nakakonekta ka sa {0}. velocity.command.server-too-many=Meron masyadong serbidor sa konfig. Magamit ka ng tab completion sa makita lahat ng serbidor na magagamit. velocity.command.server-available=Magagamit na mga serbidor\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=Nangyari isang pagkakamali sa panahon ng koneks velocity.command.dump-success=Lumikha isang report ng hindi nagpapakilala ng may impormasyon mahalaga tungkol sa proxy ng ito. Kung hingin ito ng developer, makashare ka ang link na ito kasama siya\: velocity.command.dump-will-expire=Magwakas ang link na ito sa ilang araw. velocity.command.dump-server-error=Nangyari isang pagkakamali sa mga serbidor ng Velocity at hindi nakakumpleto ang dump. Paki-kumontak ka ng staff ng Velocity tungkol sa problema ng ito at ka maglaan ang mga detalye ng pagkakamali ng ito mula sa konsole ng Velocity o log ng serbidor. -velocity.command.dump-offline=Ang malamang sanhi\: Hindi wasto ang mga setting ng DNS sa system mo o wala koneksiyon ka sa Internet \ No newline at end of file +velocity.command.dump-offline=Ang malamang sanhi\: Hindi wasto ang mga setting ng DNS sa system mo o wala koneksiyon ka sa Internet +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_tr_TR.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_tr_TR.properties index affab97fe2..5ae8c98dd5 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_tr_TR.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_tr_TR.properties @@ -19,7 +19,7 @@ velocity.error.already-connected=Bu sunucuya zaten bağlısın\! velocity.error.already-connected-proxy=Bu sunucuya zaten bağlısın\! velocity.error.already-connecting=Bu sunucuya zaten bağlanmaya çalışıyorsun\! velocity.error.cant-connect={0}\:{1} ile bağlantı kurulamadı -velocity.error.connecting-server-error=Seni {0}''ye bağlayamadık. Lütfen daha sonra tekrar deneyiniz. +velocity.error.connecting-server-error=Seni {0}'ye bağlayamadık. Lütfen daha sonra tekrar deneyiniz. velocity.error.connected-server-error={0} ile bağlantında bir problem meydana geldi. velocity.error.internal-server-connection-error=Dahili sunucu bağlantısında bir hata meydana geldi. velocity.error.logging-in-too-fast=Çok hızlı bağlanmaya çalışıyorsun, daha sonra tekrar dene. @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Bu sunucuya Minecraft'ın sade velocity.error.modern-forwarding-failed=Sunucun Velocity'ye yönlendirme isteğinde bulunmadı. Sunucunun Velocity'nin ayarlarında ayarlandığına emin ol. velocity.error.moved-to-new-server={0}\:{1} sunucusundan atıldınız velocity.error.no-available-servers=Seni bağlayabileceğimiz bir sunucu bulamadık. Lütfen daha sonra tekrar dene veya bir yetkili ile iletişime geç. +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands velocity.command.generic-error=Bu komutu çalıştırırken bir hata meydana geldi. velocity.command.command-does-not-exist=Böyle bir komut yok. velocity.command.players-only=Sadece oyuncular bu komutu çalıştırabilir. velocity.command.server-does-not-exist=Belirlenmiş sunucu {0} bulunmuyor. +velocity.command.player-not-found=The specified player {0} does not exist. velocity.command.server-current-server=Şu anda {0} sunucusuna bağlısın. velocity.command.server-too-many=Ayarlanmış birçok sunucu mevcut. Mevcut bütün sunucuları görmek için tamamlama özelliğini kullan. velocity.command.server-available=Müsait sunucular\: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=Velocity sunucuları ile iletişim sırasında velocity.command.dump-success=Bu proxy hakkında faydalı bilgiler içeren anonim bir rapor oluşturdu. Bir geliştirici talep ettiyse, aşağıdaki bağlantıyı onlarla paylaşabilirsiniz\: velocity.command.dump-will-expire=Bu bağlantı birkaç gün içinde geçersiz olacak. velocity.command.dump-server-error=Velocity sunucularında bir hata oluştu ve döküm tamamlanamadı. Lütfen bu sorunla ilgili olarak Velocity ekibiyle iletişime geçin ve bu hatayla ilgili ayrıntıları Velocity konsolundan veya sunucu logundan sağlayın. -velocity.command.dump-offline=Olası neden\: Geçersiz sistem DNS ayarları veya internet bağlantısı yok \ No newline at end of file +velocity.command.dump-offline=Olası neden\: Geçersiz sistem DNS ayarları veya internet bağlantısı yok +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy kapatılıyor. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_uk_UA.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_uk_UA.properties new file mode 100644 index 0000000000..18be5e9c61 --- /dev/null +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_uk_UA.properties @@ -0,0 +1,65 @@ +# +# Copyright (C) 2018 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 . +# + +velocity.error.already-connected=Ви вже підключені до цього серверу\! +velocity.error.already-connected-proxy=Ви вже приєднані до даного проксі\! +velocity.error.already-connecting=Ви вже приєднуєтесь до сервера\! +velocity.error.cant-connect=Не вдалося приєднатись до сервера {0}\: {1} +velocity.error.connecting-server-error=Не вдалося приєднати вас до сервера {0}. Будь ласка, спробуйте пізніше. +velocity.error.connected-server-error=З вашим приєднанням до сервера {0} виникла проблема. +velocity.error.internal-server-connection-error=На сервері виникла внутрішня помилка приєднання. +velocity.error.logging-in-too-fast=Ви приєднуєтесь дуже швидко. Будь ласка, спробуйте пізніше. +velocity.error.online-mode-only=Ви не увійшли у свій профіль Minecraft. Якщо ви впевнені, що увійшли у профіль, спробуйте перезапустити свій клієнт Minecraft. +velocity.error.player-connection-error=У вашому підключенні виникла внутрішня помилка. +velocity.error.modern-forwarding-needs-new-client=Даний сервер сумісний з версією Minecraft 1.13 і вище. +velocity.error.modern-forwarding-failed=Ваш сервер не давав запит на переадресацію на проксі-сервер. Упевніться, що сервер налаштований на переадресацію Velocity. +velocity.error.moved-to-new-server=Ви кікнуті з сервера {0}\: {1} +velocity.error.no-available-servers=Нема серверів, доступних до приєднання. Спробуйте пізніше чи зв'яжіться з адміністратором. +velocity.error.illegal-chat-characters=Заборонені символи у чаті +# Commands +velocity.command.generic-error=Під час виконання даної команди виникла помилка. +velocity.command.command-does-not-exist=Цієї команди не існує. +velocity.command.players-only=Тільки гравці можуть використовувати цю команду. +velocity.command.server-does-not-exist=Вказаного серверу {0} не існує. +velocity.command.player-not-found=Вказаного гравця {0} не існує. +velocity.command.server-current-server=Зараз ви приєднані до сервера {0}. +velocity.command.server-too-many=Налаштовано дуже багато серверів. Для перегляду всіх доступних серверів, використовуйте автозаповнення клавішею Tab. +velocity.command.server-available=Доступні сервери\: +velocity.command.server-tooltip-player-online={0} гравець онлайн +velocity.command.server-tooltip-players-online={0} гравець(ця, ців) онлайн +velocity.command.server-tooltip-current-server=Приєднаний до даного серверу +velocity.command.server-tooltip-offer-connect-server=Натисніть, щоб приєднатись до даного серверу +velocity.command.glist-player-singular={0} Гравець приєднаний до проксі на даний момент. +velocity.command.glist-player-plural={0} гравець(ця, ців) приєднані до проксі на даний момент. +velocity.command.glist-view-all=Щоб переглянути всіх гравців на серверах, використовуйте /glist all. +velocity.command.reload-success=Конфігурація Velocity успішно перезавантажена. +velocity.command.reload-failure=Не вдалося перезантажити конфігурацію Velocity. Перевірте консоль для подробиць. +velocity.command.version-copyright=Авторське право 2018-2023 {0}. {1} ліцензовано на умовах GNU General Public License v3. +velocity.command.no-plugins=Плагіни відсутні. +velocity.command.plugins-list=Плагіни\: {0} +velocity.command.plugin-tooltip-website=Веб-сайт\: {0} +velocity.command.plugin-tooltip-author=Автор\: {0} +velocity.command.plugin-tooltip-authors=Автори\: {0} +velocity.command.dump-uploading=Завантаження отриманої інформації... +velocity.command.dump-send-error=Під час зв'язку з серверами Velocity виникла помилка. Можливо, сервери тимчасово недоступні або проблема з налаштування ми вашої мережі. Більше інформації ви можете знайти в журнвлі або консолі вашого серверу Velocity. +velocity.command.dump-success=Створено анонімний звіт, що містить корисну інформацію про проксі. Якщо цей звіт запросив розробник, ви можете поділитися з ним наступним посиланням\: +velocity.command.dump-will-expire=Термін дії цього посилання спливе за кілька днів. +velocity.command.dump-server-error=На серверах Velocity сталася помилка і дамп не вдалося завершити. Будь ласка, зв'яжіться зі співробітниками Velocity з приводу цієї проблеми та повідомте подробиці, а також надайте детальну інформацію про цю помилку з консолі Velocity чи журналу сервера. +velocity.command.dump-offline=Ймовірна причина\: Неправильні налаштування DNS або відсутність підключення до Інтернету +velocity.command.send-usage=/send <гравець> <сервер> +# Kick +velocity.kick.shutdown=Проксі вимкнено. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_vi_VN.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_vi_VN.properties new file mode 100644 index 0000000000..7e46f1914f --- /dev/null +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_vi_VN.properties @@ -0,0 +1,65 @@ +# +# Copyright (C) 2018 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 . +# + +velocity.error.already-connected=Bạn đã kết nối đến máy chủ này\! +velocity.error.already-connected-proxy=Bạn đã kết nối đến proxy này\! +velocity.error.already-connecting=Bạn đang kết nối đến một máy chủ\! +velocity.error.cant-connect=Không thể kết nối đến {0}\: {1} +velocity.error.connecting-server-error=Không thể kết nối bạn đến {0}. Vui lòng thử lại sau. +velocity.error.connected-server-error=Kết nối của bạn đến {0} đã gặp một vấn đề. +velocity.error.internal-server-connection-error=Đã xảy ra một lỗi kết nối máy chủ nội bộ. +velocity.error.logging-in-too-fast=Bạn đang đăng nhập quá nhanh, vui lòng thử lại sau. +velocity.error.online-mode-only=Bạn chưa đăng nhập vào tài khoản Minecraft của bạn. Nếu bạn đã đăng nhập vào tài khoản Minecraft của bạn, hãy thử khởi động lại Minecraft. +velocity.error.player-connection-error=Đã xảy ra một lỗi nội bộ trong kết nối của bạn. +velocity.error.modern-forwarding-needs-new-client=Máy chủ này chỉ tương thích với phiên bản Minecraft 1.13 và trở lên. +velocity.error.modern-forwarding-failed=Máy chủ của bạn đã không gửi yêu cầu chuyển tiếp đến proxy. Hãy bảo đảm máy chủ đã được điều chỉnh cho chuyển tiếp đến Velocity. +velocity.error.moved-to-new-server=Bạn đã bị đá khỏi {0}\: {1} +velocity.error.no-available-servers=Không có máy chủ nào cho bạn để kết nối. Vui lòng thử lại sau hoặc liên lạc một quản trị viên. +velocity.error.illegal-chat-characters=Illegal characters in chat +# Commands +velocity.command.generic-error=Đã có lỗi xảy ra khi thực hiện lệnh này. +velocity.command.command-does-not-exist=Lệnh này không tồn tại. +velocity.command.players-only=Chỉ có người chơi có thể thực hiện lệnh này. +velocity.command.server-does-not-exist=Máy chủ chỉ định {0} không tồn tại. +velocity.command.player-not-found=The specified player {0} does not exist. +velocity.command.server-current-server=Hiện bạn đang kết nối đến {0}. +velocity.command.server-too-many=Có quá nhiều máy chủ được cài đặt. Dùng tab để xem hết tất cả máy chủ đang có. +velocity.command.server-available=Máy chủ có sẵn\: +velocity.command.server-tooltip-player-online={0} người chơi online +velocity.command.server-tooltip-players-online={0} người chơi online +velocity.command.server-tooltip-current-server=Hiện tại đang kết nối đến máy chủ này +velocity.command.server-tooltip-offer-connect-server=Click để kết nối đến máy chủ này +velocity.command.glist-player-singular={0} người chơi hiện đang kết nối đến proxy. +velocity.command.glist-player-plural={0} người chơi hiện đang kết nối đến proxy. +velocity.command.glist-view-all=Để xem tất cả người chơi trên toàn bộ máy chủ, dùng /glist all. +velocity.command.reload-success=Điều chỉnh Velocity đã tải lại thành công. +velocity.command.reload-failure=Không thể tải lại điều chỉnh Velocity. Kiểm tra console để xem thêm chi tiết. +velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} is licensed under the terms of the GNU General Public License v3. +velocity.command.no-plugins=Hiện tại không có plugin được cài đặt. +velocity.command.plugins-list=Plugins\: {0} +velocity.command.plugin-tooltip-website=Website\: {0} +velocity.command.plugin-tooltip-author=Tác giả\: {0} +velocity.command.plugin-tooltip-authors=Các tác giả\: {0} +velocity.command.dump-uploading=Đang tải lên thông tin đã thu thập... +velocity.command.dump-send-error=Đã xảy ra lỗi khi giao tiếp với máy chủ Velocity. Các máy chủ có thể tạm thời không khả dụng hoặc có sự cố với cài đặt mạng của bạn. Bạn có thể tìm thêm thông tin trong nhật ký hoặc bảng điều khiển của máy chủ Velocity của mình. +velocity.command.dump-success=Đã tạo một báo cáo ẩn danh chứa thông tin hữu ích về proxy này. Nếu một nhà phát triển yêu cầu nó, bạn có thể chia sẻ liên kết sau với họ\: +velocity.command.dump-will-expire=Đường dẫn sẽ hết hạn trong vài ngày. +velocity.command.dump-server-error=Một sự cố đã xảy ra trên những máy chủ Velocity và dump không thể hoàn tất. Vui lòng liên lạc quản trị viên của Velocity về sự cố này và đưa thông tin chi tiết về lỗi này từ console của Velocity hoặc log của máy chủ. +velocity.command.dump-offline=Nguyên nhân có thể\: Cài đặt DNS không hợp lệ hoặc không có kết nối internet +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy đang tắt. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_CN.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_CN.properties index 528cad3f22..f26dea88bb 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_CN.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_CN.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=此服务器仅兼容 Minecraf velocity.error.modern-forwarding-failed=您的服务器未向代理服务器转发请求,请确保已配置 Velocity 转发。 velocity.error.moved-to-new-server=您已被踢出 {0}:{1} velocity.error.no-available-servers=您当前没有可连接的服务器,请稍后重试或联系管理员。 +velocity.error.illegal-chat-characters=聊天中出现非法字符 # Commands velocity.command.generic-error=执行此命令时发生错误。 velocity.command.command-does-not-exist=此命令不存在。 velocity.command.players-only=只有玩家才能执行此命令。 velocity.command.server-does-not-exist=指定的服务器 {0} 不存在。 +velocity.command.player-not-found=指定的玩家 {0} 不存在。 velocity.command.server-current-server=您已连接至 {0}。 velocity.command.server-too-many=设置的服务器过多,请使用 Tab 键补全来查看所有可用的服务器。 velocity.command.server-available=可用的服务器: @@ -57,4 +59,7 @@ velocity.command.dump-send-error=与 Velocity 服务器通信时发生错误, velocity.command.dump-success=已创建关于此代理的匿名反馈数据。若开发者需要,您可与其分享以下链接: velocity.command.dump-will-expire=此链接将于几天后过期。 velocity.command.dump-server-error=Velocity 服务器发生错误,无法完成内存转储。请联系 Velocity 开发者并从 Velocity 控制台或日志中提供详细错误信息。 -velocity.command.dump-offline=可能原因:系统 DNS 设置无效或无网络连接 \ No newline at end of file +velocity.command.dump-offline=可能原因:系统 DNS 设置无效或无网络连接 +velocity.command.send-usage=/send <玩家> <服务器> +# Kick +velocity.kick.shutdown=正在关闭代理。 \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_HK.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_HK.properties index 96ec4bf269..dc58d3f8e1 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_HK.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_HK.properties @@ -15,37 +15,39 @@ # along with this program. If not, see . # -velocity.error.already-connected=You are already connected to this server\! -velocity.error.already-connected-proxy=You are already connected to this proxy\! -velocity.error.already-connecting=You are already trying to connect to a server\! -velocity.error.cant-connect=Unable to connect to {0}\: {1} -velocity.error.connecting-server-error=Unable to connect you to {0}. Please try again later. -velocity.error.connected-server-error=Your connection to {0} encountered a problem. -velocity.error.internal-server-connection-error=An internal server connection error occurred. -velocity.error.logging-in-too-fast=You are logging in too fast, try again later. -velocity.error.online-mode-only=You are not logged into your Minecraft account. If you are logged into your Minecraft account, try restarting your Minecraft client. -velocity.error.player-connection-error=An internal error occurred in your connection. -velocity.error.modern-forwarding-needs-new-client=This server is only compatible with Minecraft 1.13 and above. -velocity.error.modern-forwarding-failed=Your server did not send a forwarding request to the proxy. Make sure the server is configured for Velocity forwarding. -velocity.error.moved-to-new-server=You were kicked from {0}\: {1} -velocity.error.no-available-servers=There are no available servers to connect you to. Try again later or contact an admin. +velocity.error.already-connected=你已經連接到這個伺服器\! +velocity.error.already-connected-proxy=您已經連接到此代理伺服器了! +velocity.error.already-connecting=您已經在嘗試連接伺服器了! +velocity.error.cant-connect=無法法連接至 {0}:{1} +velocity.error.connecting-server-error=無法將您連接至 {0},請稍后再試。 +velocity.error.connected-server-error=你與 {0} 的連線出現問題 +velocity.error.internal-server-connection-error=出現內部伺服器連線問題 +velocity.error.logging-in-too-fast=你登錄太快,請稍後再試 +velocity.error.online-mode-only=你沒有登入你的Minecraft賬號。如果你已經登入,請嘗試重啟你的Minecraft用戶端。 +velocity.error.player-connection-error=你的連線發生內部錯誤 +velocity.error.modern-forwarding-needs-new-client=此伺服器只兼容Minecraft版本1.13以上 +velocity.error.modern-forwarding-failed=你的伺服器未向代理伺服器發送轉發請求,請確保你的伺服器已配置Velocity轉發 +velocity.error.moved-to-new-server=你已被踢出{0}\:{1} +velocity.error.no-available-servers=當前沒有可以連接你的伺服器,請稍後再試或聯繫管理員 +velocity.error.illegal-chat-characters=Illegal characters in chat # Commands -velocity.command.generic-error=An error occurred while running this command. -velocity.command.command-does-not-exist=This command does not exist. -velocity.command.players-only=Only players can run this command. -velocity.command.server-does-not-exist=The specified server {0} does not exist. -velocity.command.server-current-server=You are currently connected to {0}. -velocity.command.server-too-many=There are too many servers set up. Use tab completion to view all servers available. -velocity.command.server-available=Available servers\: -velocity.command.server-tooltip-player-online={0} player online -velocity.command.server-tooltip-players-online={0} players online -velocity.command.server-tooltip-current-server=Currently connected to this server -velocity.command.server-tooltip-offer-connect-server=Click to connect to this server -velocity.command.glist-player-singular={0} player is currently connected to the proxy. -velocity.command.glist-player-plural={0} players are currently connected to the proxy. -velocity.command.glist-view-all=To view all players on servers, use /glist all. -velocity.command.reload-success=Velocity configuration successfully reloaded. -velocity.command.reload-failure=Unable to reload your Velocity configuration. Check the console for more details. +velocity.command.generic-error=執行命令時發生錯誤 +velocity.command.command-does-not-exist=此命令不存在 +velocity.command.players-only=只有玩家能執行此命令 +velocity.command.server-does-not-exist=指定的伺服器 {0} 不存在 +velocity.command.player-not-found=The specified player {0} does not exist. +velocity.command.server-current-server=您已連接至 {0}。 +velocity.command.server-too-many=設置的伺服器國多,請使用 Tab 鍵補全以查看所有可用的服务器。 +velocity.command.server-available=可用的伺服器: +velocity.command.server-tooltip-player-online={0} 個玩家在線 +velocity.command.server-tooltip-players-online={0} 個玩家在線 +velocity.command.server-tooltip-current-server=當前已連接至此伺服器 +velocity.command.server-tooltip-offer-connect-server=點擊連接至此伺服器 +velocity.command.glist-player-singular=共有 {0} 個玩家已連接至此代理伺服器。 +velocity.command.glist-player-plural=共有 {0} 個玩家已連接至此代理伺服器。 +velocity.command.glist-view-all=使用 /glist all 命令來查看所有伺服器的玩家列表。 +velocity.command.reload-success=Velocity 配置重新加載完成。 +velocity.command.reload-failure=無法重新加載 Velocity 配置,請查看控制台了解詳情。 velocity.command.version-copyright=Copyright 2018-2023 {0} ( {1} 的授權條款爲: GNU 通用公共授權條款第三版) velocity.command.no-plugins=目前未有安裝任何 Velocity 插件。 velocity.command.plugins-list=插件: {0} @@ -53,8 +55,11 @@ velocity.command.plugin-tooltip-website=網站: {0} velocity.command.plugin-tooltip-author=作者: {0} velocity.command.plugin-tooltip-authors=作者: {0} velocity.command.dump-uploading=正在收集並上載 Velocity 設定資料... -velocity.command.dump-send-error=An error occurred while communicating with the Velocity servers. The servers may be temporarily unavailable or there is an issue with your network settings. You can find more information in the log or console of your Velocity server. -velocity.command.dump-success=Created an anonymised report containing useful information about this proxy. If a developer requested it, you may share the following link with them\: -velocity.command.dump-will-expire=This link will expire in a few days. -velocity.command.dump-server-error=An error occurred on the Velocity servers and the dump could not be completed. Please contact the Velocity staff about this problem and provide the details about this error from the Velocity console or server log. -velocity.command.dump-offline=Likely cause\: Invalid system DNS settings or no internet connection \ No newline at end of file +velocity.command.dump-send-error=與 Velocity 伺服器通信時發生錯誤,伺服器可能暫時不可用或您的網路設置存在問題。您可在 Velocity 伺服器日志或控制台中了解詳情。 +velocity.command.dump-success=已創建關於此代理的匿名反饋數據。若開發人員需要,您可與其分享以下鏈接: +velocity.command.dump-will-expire=此鏈接將於幾天後后過期。 +velocity.command.dump-server-error=Velocity 伺服器發生錯誤,無法完成轉儲數據。請聯繫 Velocity 開發人員並從 Velocity 控制台或日志中提供詳細的錯誤信息。 +velocity.command.dump-offline=可能原因:系统 DNS 設置無效或無網絡連接 +velocity.command.send-usage=/send +# Kick +velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_TW.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_TW.properties index a046bb38c6..49ed391623 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_TW.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_zh_TW.properties @@ -29,11 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=此伺服器僅相容 Minecraf velocity.error.modern-forwarding-failed=您的伺服器未向代理伺服器轉發請求,請確保已配置 Velocity 轉發。 velocity.error.moved-to-new-server=您已被踢出 {0}:{1} velocity.error.no-available-servers=您當前沒有可連線的伺服器,請稍後重試或聯絡管理員。 -# Command +velocity.error.illegal-chat-characters=聊天欄中出現不允許的字符 +# Commands velocity.command.generic-error=執行此指令時發生錯誤。 velocity.command.command-does-not-exist=此指令不存在。 velocity.command.players-only=只有玩家才能執行這個指令。 velocity.command.server-does-not-exist=指定的伺服器 {0} 不存在。 +velocity.command.player-not-found=指定的玩家 {0} 不存在。 velocity.command.server-current-server=您已連線到 {0}。 velocity.command.server-too-many=設定的伺服器過多,請使用 Tab 鍵補全來查看所有可用的伺服器。 velocity.command.server-available=可用的伺服器: @@ -58,3 +60,6 @@ velocity.command.dump-success=已創建關於此代理的匿名反饋資料。 velocity.command.dump-will-expire=此連結將於幾天後過期。 velocity.command.dump-server-error=Velocity 伺服器發生錯誤,無法完成記憶體轉存。請聯絡 Velocity 開發者並從 Velocity 控制台或日誌中提供詳細錯誤訊息。 velocity.command.dump-offline=可能原因:系統 DNS 設置無效或無網路連線 +velocity.command.send-usage=/send <玩家> <伺服器> +# Kick +velocity.kick.shutdown=正在關閉代理伺服器。 \ No newline at end of file From 716da9eaf66624a8ad5d83e3312e2b92d484e97a Mon Sep 17 00:00:00 2001 From: Kichura <68134602+Kichura@users.noreply.github.com> Date: Sat, 23 Mar 2024 05:52:39 +0100 Subject: [PATCH 08/28] [ci skip] Update Gradle to 8.7. (#1274) The "org.gradle.toolchains.foojay-resolver-convention" dependency has been skipped however as it is already up-to-date. --- gradle/wrapper/gradle-wrapper.jar | Bin 43462 -> 43453 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew.bat | 184 +++++++++++------------ 3 files changed, 93 insertions(+), 93 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917707c1f8861d8cb53dd15194d4248596..e6441136f3d4ba8a0da8d277868979cfbc8ad796 100644 GIT binary patch delta 34118 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 delta 34176 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 SGW6ptSs!X7{rG*o_g?|vpSEZK diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a80b22ce5c..b82aa23a4f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f13..7101f8e467 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,92 +1,92 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From 615b575d911383934fc3ea70e7a937d7d9768822 Mon Sep 17 00:00:00 2001 From: Adrian <68704415+4drian3d@users.noreply.github.com> Date: Sat, 23 Mar 2024 13:51:44 -0500 Subject: [PATCH 09/28] [ci skip] Add plugin version info to event exception handler (#1263) --- .../velocitypowered/proxy/event/VelocityEventManager.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java b/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java index 85bb7cceba..ae02956538 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java @@ -33,6 +33,7 @@ import com.velocitypowered.api.event.PostOrder; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.plugin.PluginContainer; +import com.velocitypowered.api.plugin.PluginDescription; import com.velocitypowered.api.plugin.PluginManager; import com.velocitypowered.proxy.event.UntargetedEventHandler.EventTaskHandler; import com.velocitypowered.proxy.event.UntargetedEventHandler.VoidHandler; @@ -621,8 +622,9 @@ private void fire(final @Nullable CompletableFuture future, final E event private static void logHandlerException( final HandlerRegistration registration, final Throwable t) { - logger.error("Couldn't pass {} to {}", registration.eventType.getSimpleName(), - registration.plugin.getDescription().getId(), t); + final PluginDescription pluginDescription = registration.plugin.getDescription(); + logger.error("Couldn't pass {} to {} {}", registration.eventType.getSimpleName(), + pluginDescription.getId(), pluginDescription.getVersion().orElse(""), t); } public boolean shutdown() throws InterruptedException { From ad50582836abb664b649728becd15441369c7d1c Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Tue, 2 Apr 2024 13:20:13 +0100 Subject: [PATCH 10/28] Send downloaded/successful resource pack status when already applied (Fixes #1280) --- .../proxy/connection/backend/BackendPlaySessionHandler.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java index 6cd62e296b..051a7cbcfa 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java @@ -209,6 +209,10 @@ public boolean handle(final ResourcePackRequestPacket packet) { if (serverConn.getConnection() != null) { serverConn.getConnection().write(new ResourcePackResponsePacket( packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.ACCEPTED)); + serverConn.getConnection().write(new ResourcePackResponsePacket( + packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.DOWNLOADED)); + serverConn.getConnection().write(new ResourcePackResponsePacket( + packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.SUCCESSFUL)); } if (modifiedPack) { logger.warn("A plugin has tried to modify a ResourcePack provided by the backend server " From d4077ddc1ad2b89d8ef5269749c74c2baef2ff00 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Tue, 2 Apr 2024 13:53:22 +0100 Subject: [PATCH 11/28] only send extended resource pack states on supported versions --- .../backend/BackendPlaySessionHandler.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java index 051a7cbcfa..44a3839bc0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java @@ -28,6 +28,7 @@ import com.velocitypowered.api.event.player.PlayerResourcePackStatusEvent; import com.velocitypowered.api.event.player.ServerResourcePackSendEvent; import com.velocitypowered.api.event.proxy.ProxyPingEvent; +import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.api.proxy.player.ResourcePackInfo; import com.velocitypowered.proxy.VelocityServer; @@ -209,10 +210,14 @@ public boolean handle(final ResourcePackRequestPacket packet) { if (serverConn.getConnection() != null) { serverConn.getConnection().write(new ResourcePackResponsePacket( packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.ACCEPTED)); - serverConn.getConnection().write(new ResourcePackResponsePacket( - packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.DOWNLOADED)); - serverConn.getConnection().write(new ResourcePackResponsePacket( - packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.SUCCESSFUL)); + if (serverConn.getConnection().getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_20_3)) { + serverConn.getConnection().write(new ResourcePackResponsePacket( + packet.getId(), packet.getHash(), + PlayerResourcePackStatusEvent.Status.DOWNLOADED)); + serverConn.getConnection().write(new ResourcePackResponsePacket( + packet.getId(), packet.getHash(), + PlayerResourcePackStatusEvent.Status.SUCCESSFUL)); + } } if (modifiedPack) { logger.warn("A plugin has tried to modify a ResourcePack provided by the backend server " From 3bce4d8576a99ceb1f1bf50a161b5eefb8d5316c Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Tue, 2 Apr 2024 14:02:26 +0100 Subject: [PATCH 12/28] Succesful is not an extended state --- .../proxy/connection/backend/BackendPlaySessionHandler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java index 44a3839bc0..18f242fe3f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java @@ -214,10 +214,10 @@ public boolean handle(final ResourcePackRequestPacket packet) { serverConn.getConnection().write(new ResourcePackResponsePacket( packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.DOWNLOADED)); - serverConn.getConnection().write(new ResourcePackResponsePacket( - packet.getId(), packet.getHash(), - PlayerResourcePackStatusEvent.Status.SUCCESSFUL)); } + serverConn.getConnection().write(new ResourcePackResponsePacket( + packet.getId(), packet.getHash(), + PlayerResourcePackStatusEvent.Status.SUCCESSFUL)); } if (modifiedPack) { logger.warn("A plugin has tried to modify a ResourcePack provided by the backend server " From a72aef526b7980640565daabd1935332e74253e1 Mon Sep 17 00:00:00 2001 From: Limbo <35357032+limbo-app@users.noreply.github.com> Date: Sat, 6 Apr 2024 10:22:29 -0700 Subject: [PATCH 13/28] New Crowdin updates (#1275) --- .../velocitypowered/proxy/l10n/messages_bg_BG.properties | 8 ++++---- .../velocitypowered/proxy/l10n/messages_fr_FR.properties | 2 +- .../velocitypowered/proxy/l10n/messages_ko_KR.properties | 8 ++++---- .../velocitypowered/proxy/l10n/messages_pt_BR.properties | 8 ++++---- .../velocitypowered/proxy/l10n/messages_ru_RU.properties | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_bg_BG.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_bg_BG.properties index 013fd92c7f..c50dc10a99 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_bg_BG.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_bg_BG.properties @@ -29,13 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Този сървър е съ velocity.error.modern-forwarding-failed=Сървъра Ви не изпрати заявка за препращане на информация към проксито. Моля, убедете се, че сървъра Ви е настроен за работа с Velocity. velocity.error.moved-to-new-server=Ти беше изхвърлен от {0}\: {1} velocity.error.no-available-servers=Няма налични сървъри, км които да Ви свържем. Моля, опитайте по-късно, или се свържете с администратор. -velocity.error.illegal-chat-characters=Illegal characters in chat +velocity.error.illegal-chat-characters=Неодобрени символи в чата # Commands velocity.command.generic-error=Възникна грешка при изпълняването на командата. velocity.command.command-does-not-exist=Тази команда не съществува. velocity.command.players-only=Само играчи могат да изпълняват тази команда. velocity.command.server-does-not-exist=Сървър с името {0} не съществува. -velocity.command.player-not-found=The specified player {0} does not exist. +velocity.command.player-not-found=Този играч {0} не съществува. velocity.command.server-current-server=В момента сте свързан към {0}. velocity.command.server-too-many=Има прекалено много регистрирани сървъри. Използвайте TAB, за да видите всички налични сървъри. velocity.command.server-available=Налични сървъри\: @@ -48,7 +48,7 @@ velocity.command.glist-player-plural={0} играчи са свързани къ velocity.command.glist-view-all=За да видите всички играчи, разпределени по сървъри, използвайте /glist all. velocity.command.reload-success=Настройките на Velocity бяха презаредени успешно. velocity.command.reload-failure=Не успяхме да презаредим настройките на Velocity. Моля, проверете конзолата за повече информация. -velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} is licensed under the terms of the GNU General Public License v3. +velocity.command.version-copyright=Авторско право 2018-2023 {0}. {1} е лицензиран под условията на GNU General Public License v3. velocity.command.no-plugins=За момента няма инсталирани добавки. velocity.command.plugins-list=Добавки\: {0} velocity.command.plugin-tooltip-website=Уебсайт\: {0} @@ -60,6 +60,6 @@ velocity.command.dump-success=Създадохме анонимен доклад velocity.command.dump-will-expire=Този линк ще изтече след няколко дена. velocity.command.dump-server-error=Възникна грешка при сървърите на Velocity и доклада не може да бъде завършен. Моля, уведомете разработващия екип на Velocity относно този проблем и осигурете детайли за грешката от конзолата или логовете. velocity.command.dump-offline=Вероятна причина\: Невалидни системни DNS настройки или липса на Интернет връзка -velocity.command.send-usage=/send +velocity.command.send-usage=/изпрати <играч> <сървър> # Kick velocity.kick.shutdown=Проксито се изключва. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fr_FR.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fr_FR.properties index 024f37ad01..da99020907 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fr_FR.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_fr_FR.properties @@ -29,7 +29,7 @@ velocity.error.modern-forwarding-needs-new-client=Ce serveur est uniquement comp velocity.error.modern-forwarding-failed=Votre serveur n'a pas envoyé de requête de transfert vers le proxy. Assurez-vous que le serveur est configuré pour le transfert Velocity. velocity.error.moved-to-new-server=Vous avez été expulsé(e) de {0} \: {1} velocity.error.no-available-servers=Il n'y a pas de serveurs disponibles auxquels vous connecter. Réessayez ultérieurement ou contactez un administrateur. -velocity.error.illegal-chat-characters=Caractères interdits dans le chat +velocity.error.illegal-chat-characters=Caractères interdits dans le chat. # Commands velocity.command.generic-error=Une erreur est survenue lors de l'exécution de cette commande. velocity.command.command-does-not-exist=Cette commande n'existe pas. diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ko_KR.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ko_KR.properties index 6bb66d1ceb..b4bbf4c891 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ko_KR.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ko_KR.properties @@ -34,21 +34,21 @@ velocity.error.illegal-chat-characters=채팅에 올바르지 않은 문자가 velocity.command.generic-error=명령어를 실행하는 도중 오류가 발생했습니다. velocity.command.command-does-not-exist=존재하지 않는 명령어입니다. velocity.command.players-only=이 명령어는 플레이어만 사용할 수 있습니다. -velocity.command.server-does-not-exist=지정한 서버 {0} 이(가) 존재하지 않습니다. -velocity.command.player-not-found=지정한 플레이어 {0} 이(가) 존재하지 않습니다. +velocity.command.server-does-not-exist=지정한 서버 {0}이(가) 존재하지 않습니다. +velocity.command.player-not-found=지정한 플레이어 {0}이(가) 존재하지 않습니다. velocity.command.server-current-server=현재 {0}에 연결되어 있습니다. velocity.command.server-too-many=너무 많은 서버가 존재합니다. tab 자동완성으로 사용 가능한 모든 서버를 볼 수 있습니다. velocity.command.server-available=사용 가능한 서버\: velocity.command.server-tooltip-player-online=플레이어 {0}명 접속 중 velocity.command.server-tooltip-players-online=플레이어 {0}명 접속 중 velocity.command.server-tooltip-current-server=현재 이 서버에 연결되어 있습니다 -velocity.command.server-tooltip-offer-connect-server=이 서버에 연결하려면 클릭하세요 +velocity.command.server-tooltip-offer-connect-server=서버에 연결하려면 클릭 velocity.command.glist-player-singular=플레이어 {0}명이 현재 프록시에 연결되어 있습니다. velocity.command.glist-player-plural=플레이어 {0}명이 현재 프록시에 연결되어 있습니다. velocity.command.glist-view-all=서버에 있는 모든 플레이어를 보려면, /glist all을 사용하세요. velocity.command.reload-success=Velocity 설정을 성공적으로 다시 불러왔습니다. velocity.command.reload-failure=Velocity 설정을 다시 불러올 수 없습니다. 자세한 내용은 콘솔을 확인하세요. -velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} 는 GNU General Public License v3 라이센스의 약관을 따릅니다. +velocity.command.version-copyright=Copyright 2018-2023 {0}. {1}은(는) GNU General Public License v3 라이센스의 약관을 따릅니다. velocity.command.no-plugins=설치된 플러그인이 없습니다. velocity.command.plugins-list=플러그인\: {0} velocity.command.plugin-tooltip-website=웹사이트\: {0} diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pt_BR.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pt_BR.properties index 5fb79912b6..5a915a8dcb 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pt_BR.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_pt_BR.properties @@ -29,13 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Este servidor é compatível a velocity.error.modern-forwarding-failed=Seu servidor não enviou uma solicitação de encaminhamento para o proxy. Certifique-se de que o servidor está configurado para encaminhamento Velocity. velocity.error.moved-to-new-server=Você foi expulso de {0}\: {1} velocity.error.no-available-servers=Não há servidores disponíveis para conectá-lo. Tente novamente mais tarde ou contate um administrador. -velocity.error.illegal-chat-characters=Illegal characters in chat +velocity.error.illegal-chat-characters=Caracteres não permitidos no chat # Commands velocity.command.generic-error=Ocorreu um erro ao executar este comando. velocity.command.command-does-not-exist=Esse comando não existe. velocity.command.players-only=Apenas jogadores podem executar esse comando. velocity.command.server-does-not-exist=O servidor {0} não existe. -velocity.command.player-not-found=The specified player {0} does not exist. +velocity.command.player-not-found=O jogador {0} não existe. velocity.command.server-current-server=Você está atualmente conectado a {0}. velocity.command.server-too-many=Há muitos servidores configurados. Utilize o auto-preenchimento tab para ver todos os servidores disponíveis. velocity.command.server-available=Servidores disponíveis\: @@ -59,7 +59,7 @@ velocity.command.dump-send-error=Ocorreu um erro ao se comunicar com os servidor velocity.command.dump-success=Foi criado um relatório anônimo contendo informações úteis sobre este proxy. Se um desenvolvedor o solicitou, você pode compartilhar o seguinte link com eles\: velocity.command.dump-will-expire=Este link irá expirar em alguns dias. velocity.command.dump-server-error=Ocorreu um erro nos servidores Velocity e o dump não pôde ser concluído. Por favor, entre em contato com a staff do Velocity sobre este problema e forneça detalhes sobre esse erro a partir do log do console Velocity ou do servidor. -velocity.command.dump-offline=Causa provavel\: configurações de DNS do sistema inválidas ou sem conexão de internet +velocity.command.dump-offline=Causa provável\: configurações de DNS do sistema inválidas ou sem conexão de internet velocity.command.send-usage=/send # Kick -velocity.kick.shutdown=Proxy shutting down. \ No newline at end of file +velocity.kick.shutdown=Proxy desligando. \ No newline at end of file diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ru_RU.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ru_RU.properties index 14913c743f..a2a7afb9f6 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ru_RU.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages_ru_RU.properties @@ -29,13 +29,13 @@ velocity.error.modern-forwarding-needs-new-client=Этот сервер совм velocity.error.modern-forwarding-failed=Ваш сервер не посылал запрос на переадресацию на прокси-сервер. Убедитесь, что сервер настроен на переадресацию Velocity. velocity.error.moved-to-new-server=Вы были кикнуты с сервера {0}\: {1} velocity.error.no-available-servers=Нет серверов, доступных для подключения. Попробуйте позже или свяжитесь с администратором. -velocity.error.illegal-chat-characters=Illegal characters in chat +velocity.error.illegal-chat-characters=Недопустимые символы в чате # Commands velocity.command.generic-error=Во время выполнения этой команды произошла ошибка. velocity.command.command-does-not-exist=Этой команды не существует. velocity.command.players-only=Только игроки могут использовать эту команду. velocity.command.server-does-not-exist=Указанный сервер {0} не существует. -velocity.command.player-not-found=The specified player {0} does not exist. +velocity.command.player-not-found=Указанный игрок {0} не существует. velocity.command.server-current-server=На данный момент вы подключены к серверу {0}. velocity.command.server-too-many=Настроено слишком много серверов. Для просмотра всех доступных серверов, используйте автозаполнение клавишей Tab. velocity.command.server-available=Доступные серверы\: @@ -60,6 +60,6 @@ velocity.command.dump-success=Создан анонимный отчет, сод velocity.command.dump-will-expire=Срок действия этой ссылки истечёт через несколько дней. velocity.command.dump-server-error=Не удалось завершить дамп, так как на серверах Velocity произошла ошибка. Пожалуйста, свяжитесь с командой Velocity по поводу этой проблемы и сообщите подробности, а также предоставьте подробную информацию об этой ошибке из консоли Velocity или логов сервера. velocity.command.dump-offline=Вероятная причина\: Неверные настройки DNS или отсутствие подключения к интернету -velocity.command.send-usage=/send +velocity.command.send-usage=/send <никнейм> <сервер> # Kick velocity.kick.shutdown=Прокси-сервер выключается. \ No newline at end of file From 9e42049a67d90f3db846a2c0dba2538c15201629 Mon Sep 17 00:00:00 2001 From: Adrian <68704415+4drian3d@users.noreply.github.com> Date: Mon, 8 Apr 2024 12:24:20 -0500 Subject: [PATCH 14/28] Improved PluginMessaging API (#1254) * Improved PluginMessaging API by adding a method to easily encode the data to be sent * Added javadocs * Implement PluginMessageEncoder --- .../com/velocitypowered/api/proxy/Player.java | 35 ++++++++++++++++--- .../proxy/messages/ChannelMessageSink.java | 26 +++++++++++++- .../proxy/messages/PluginMessageEncoder.java | 29 +++++++++++++++ .../ComponentLoggerProviderImpl.java | 2 +- .../backend/VelocityServerConnection.java | 31 ++++++++++++++-- .../connection/client/ConnectedPlayer.java | 26 +++++++++++++- .../server/VelocityRegisteredServer.java | 34 +++++++++++++++--- 7 files changed, 168 insertions(+), 15 deletions(-) create mode 100644 api/src/main/java/com/velocitypowered/api/proxy/messages/PluginMessageEncoder.java rename proxy/src/main/java/com/velocitypowered/proxy/{provider => adventure}/ComponentLoggerProviderImpl.java (97%) diff --git a/api/src/main/java/com/velocitypowered/api/proxy/Player.java b/api/src/main/java/com/velocitypowered/api/proxy/Player.java index a73ff451b8..ae9a8006c6 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/Player.java @@ -13,6 +13,7 @@ import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.api.proxy.messages.ChannelMessageSink; import com.velocitypowered.api.proxy.messages.ChannelMessageSource; +import com.velocitypowered.api.proxy.messages.PluginMessageEncoder; import com.velocitypowered.api.proxy.player.PlayerSettings; import com.velocitypowered.api.proxy.player.ResourcePackInfo; import com.velocitypowered.api.proxy.player.TabList; @@ -282,16 +283,42 @@ default void clearHeaderAndFooter() { @NotNull Collection getPendingResourcePacks(); /** - * Note that this method does not send a plugin message to the server the player + * {@inheritDoc} + * + *

    Note that this method does not send a plugin message to the server the player * is connected to. You should only use this method if you are trying to communicate - * with a mod that is installed on the player's client. To send a plugin message to the server + * with a mod that is installed on the player's client.

    + * + *

    To send a plugin message to the server * from the player, you should use the equivalent method on the instance returned by * {@link #getCurrentServer()}. * - * @inheritDoc + *

    +   *    final ChannelIdentifier identifier;
    +   *    final Player player;
    +   *    player.getCurrentServer()
    +   *          .map(ServerConnection::getServer)
    +   *          .ifPresent((RegisteredServer server) -> {
    +   *            server.sendPluginMessage(identifier, data);
    +   *          });
    +   *  
    + * + */ + @Override + boolean sendPluginMessage(@NotNull ChannelIdentifier identifier, byte @NotNull [] data); + + /** + * {@inheritDoc} + *

    Note that this method does not send a plugin message to the server the player + * is connected to. You should only use this method if you are trying to communicate + * with a mod that is installed on the player's client.

    + * + *

    To send a plugin message to the server + * from the player, you should use the equivalent method on the instance returned by + * {@link #getCurrentServer()}. */ @Override - boolean sendPluginMessage(@NotNull ChannelIdentifier identifier, byte @NotNull[] data); + boolean sendPluginMessage(@NotNull ChannelIdentifier identifier, @NotNull PluginMessageEncoder dataEncoder); @Override default @NotNull Key key() { diff --git a/api/src/main/java/com/velocitypowered/api/proxy/messages/ChannelMessageSink.java b/api/src/main/java/com/velocitypowered/api/proxy/messages/ChannelMessageSink.java index b310f13bcb..3c1031f438 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/messages/ChannelMessageSink.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/messages/ChannelMessageSink.java @@ -7,6 +7,9 @@ package com.velocitypowered.api.proxy.messages; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + /** * Represents something that can be sent plugin messages. */ @@ -19,5 +22,26 @@ public interface ChannelMessageSink { * @param data the data to send * @return whether or not the message could be sent */ - boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data); + boolean sendPluginMessage(@NotNull ChannelIdentifier identifier, byte @NotNull[] data); + + /** + * Sends a plugin message to this target. + * + *

    +   *   final ChannelMessageSink target;
    +   *   final ChannelIdentifier identifier;
    +   *   final boolean result = target.sendPluginMessage(identifier, (output) -> {
    +   *     output.writeUTF("some input");
    +   *     output.writeInt(1);
    +   *   });
    +   * 
    + * + * @param identifier the channel identifier to send the message on + * @param dataEncoder the encoder of the data to be sent + * @return whether the message could be sent + */ + @ApiStatus.Experimental + boolean sendPluginMessage( + @NotNull ChannelIdentifier identifier, + @NotNull PluginMessageEncoder dataEncoder); } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/messages/PluginMessageEncoder.java b/api/src/main/java/com/velocitypowered/api/proxy/messages/PluginMessageEncoder.java new file mode 100644 index 0000000000..b4fcf91a3f --- /dev/null +++ b/api/src/main/java/com/velocitypowered/api/proxy/messages/PluginMessageEncoder.java @@ -0,0 +1,29 @@ +/* + * 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.proxy.messages; + +import com.google.common.io.ByteArrayDataOutput; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * A data encoder to be sent via a plugin message. + * + * @since 3.3.0 + */ +@FunctionalInterface +@ApiStatus.Experimental +public interface PluginMessageEncoder { + + /** + * Encodes data into a {@link ByteArrayDataOutput} to be transmitted by plugin messages. + * + * @param output the {@link ByteArrayDataOutput} provided + */ + void encode(@NotNull ByteArrayDataOutput output); +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/provider/ComponentLoggerProviderImpl.java b/proxy/src/main/java/com/velocitypowered/proxy/adventure/ComponentLoggerProviderImpl.java similarity index 97% rename from proxy/src/main/java/com/velocitypowered/proxy/provider/ComponentLoggerProviderImpl.java rename to proxy/src/main/java/com/velocitypowered/proxy/adventure/ComponentLoggerProviderImpl.java index 3cdb945a78..12b4aaf50e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/provider/ComponentLoggerProviderImpl.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/adventure/ComponentLoggerProviderImpl.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.velocitypowered.proxy.provider; +package com.velocitypowered.proxy.adventure; import com.google.auto.service.AutoService; import com.velocitypowered.proxy.util.TranslatableMapper; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java index e0b448bc8e..8c027546fb 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java @@ -19,11 +19,13 @@ import static com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants.HANDSHAKE_HOSTNAME_TOKEN; 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.ProtocolVersion; import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; +import com.velocitypowered.api.proxy.messages.PluginMessageEncoder; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.ServerInfo; import com.velocitypowered.proxy.VelocityServer; @@ -41,6 +43,7 @@ import com.velocitypowered.proxy.protocol.packet.JoinGamePacket; import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket; import com.velocitypowered.proxy.protocol.packet.ServerLoginPacket; +import com.velocitypowered.proxy.protocol.util.ByteBufDataOutput; import com.velocitypowered.proxy.server.VelocityRegisteredServer; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -52,6 +55,7 @@ import net.kyori.adventure.nbt.CompoundBinaryTag; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.jetbrains.annotations.NotNull; /** * Handles a connection from the proxy to some backend server. @@ -255,10 +259,31 @@ public String toString() { } @Override - public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) { + public boolean sendPluginMessage( + final @NotNull ChannelIdentifier identifier, + final byte @NotNull [] data + ) { return sendPluginMessage(identifier, Unpooled.wrappedBuffer(data)); } + @Override + public boolean sendPluginMessage( + final @NotNull ChannelIdentifier identifier, + final @NotNull PluginMessageEncoder dataEncoder + ) { + requireNonNull(identifier); + requireNonNull(dataEncoder); + final ByteBuf buf = Unpooled.buffer(); + final ByteBufDataOutput dataOutput = new ByteBufDataOutput(buf); + dataEncoder.encode(dataOutput); + if (buf.isReadable()) { + return sendPluginMessage(identifier, buf); + } else { + buf.release(); + return false; + } + } + /** * Sends a plugin message to the server through this connection. * @@ -270,9 +295,9 @@ public boolean sendPluginMessage(ChannelIdentifier identifier, ByteBuf data) { Preconditions.checkNotNull(identifier, "identifier"); Preconditions.checkNotNull(data, "data"); - MinecraftConnection mc = ensureConnected(); + final MinecraftConnection mc = ensureConnected(); - PluginMessagePacket message = new PluginMessagePacket(identifier.getId(), data); + final PluginMessagePacket message = new PluginMessagePacket(identifier.getId(), data); mc.write(message); return true; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 935a3c4817..16df7bb84d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -19,6 +19,7 @@ import static com.velocitypowered.api.proxy.ConnectionRequestBuilder.Status.ALREADY_CONNECTED; import static com.velocitypowered.proxy.connection.util.ConnectionRequestResults.plainResult; +import static java.util.Objects.requireNonNull; import static java.util.concurrent.CompletableFuture.completedFuture; import com.google.common.base.Preconditions; @@ -44,6 +45,7 @@ import com.velocitypowered.api.proxy.crypto.IdentifiedKey; import com.velocitypowered.api.proxy.crypto.KeyIdentifiable; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; +import com.velocitypowered.api.proxy.messages.PluginMessageEncoder; import com.velocitypowered.api.proxy.player.PlayerSettings; import com.velocitypowered.api.proxy.player.ResourcePackInfo; import com.velocitypowered.api.proxy.server.RegisteredServer; @@ -75,6 +77,7 @@ import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChatPacket; import com.velocitypowered.proxy.protocol.packet.config.StartUpdatePacket; import com.velocitypowered.proxy.protocol.packet.title.GenericTitlePacket; +import com.velocitypowered.proxy.protocol.util.ByteBufDataOutput; import com.velocitypowered.proxy.server.VelocityRegisteredServer; import com.velocitypowered.proxy.tablist.InternalTabList; import com.velocitypowered.proxy.tablist.KeyedVelocityTabList; @@ -83,6 +86,7 @@ import com.velocitypowered.proxy.util.ClosestLocaleMatcher; import com.velocitypowered.proxy.util.DurationUtils; import com.velocitypowered.proxy.util.TranslatableMapper; +import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import java.net.InetSocketAddress; import java.util.Collection; @@ -947,12 +951,32 @@ public Tristate getPermissionValue(String permission) { public boolean sendPluginMessage(@NotNull ChannelIdentifier identifier, byte @NotNull [] data) { Preconditions.checkNotNull(identifier, "identifier"); Preconditions.checkNotNull(data, "data"); - PluginMessagePacket message = new PluginMessagePacket(identifier.getId(), + final PluginMessagePacket message = new PluginMessagePacket(identifier.getId(), Unpooled.wrappedBuffer(data)); connection.write(message); return true; } + @Override + public boolean sendPluginMessage( + final @NotNull ChannelIdentifier identifier, + final @NotNull PluginMessageEncoder dataEncoder + ) { + requireNonNull(identifier); + requireNonNull(dataEncoder); + final ByteBuf buf = Unpooled.buffer(); + final ByteBufDataOutput dataOutput = new ByteBufDataOutput(buf); + dataEncoder.encode(dataOutput); + if (buf.isReadable()) { + final PluginMessagePacket message = new PluginMessagePacket(identifier.getId(), buf); + connection.write(message); + return true; + } else { + buf.release(); + return false; + } + } + @Override @Nullable public String getClientBrand() { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/server/VelocityRegisteredServer.java b/proxy/src/main/java/com/velocitypowered/proxy/server/VelocityRegisteredServer.java index 837c46a252..a3ddd71ca2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/server/VelocityRegisteredServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/server/VelocityRegisteredServer.java @@ -23,11 +23,13 @@ import static com.velocitypowered.proxy.network.Connections.MINECRAFT_DECODER; import static com.velocitypowered.proxy.network.Connections.MINECRAFT_ENCODER; import static com.velocitypowered.proxy.network.Connections.READ_TIMEOUT; +import static java.util.Objects.requireNonNull; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; +import com.velocitypowered.api.proxy.messages.PluginMessageEncoder; import com.velocitypowered.api.proxy.server.PingOptions; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.ServerInfo; @@ -42,6 +44,7 @@ import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder; import com.velocitypowered.proxy.protocol.netty.MinecraftVarintFrameDecoder; import com.velocitypowered.proxy.protocol.netty.MinecraftVarintLengthEncoder; +import com.velocitypowered.proxy.protocol.util.ByteBufDataOutput; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; @@ -59,6 +62,7 @@ import net.kyori.adventure.audience.ForwardingAudience; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.jetbrains.annotations.NotNull; /** * Represents a server registered on the proxy. @@ -107,9 +111,9 @@ public CompletableFuture ping(@Nullable EventLoop loop, PingOptions throw new IllegalStateException("No Velocity proxy instance available"); } CompletableFuture pingFuture = new CompletableFuture<>(); - server.createBootstrap(loop).handler(new ChannelInitializer() { + server.createBootstrap(loop).handler(new ChannelInitializer<>() { @Override - protected void initChannel(Channel ch) throws Exception { + protected void initChannel(Channel ch) { ch.pipeline().addLast(FRAME_DECODER, new MinecraftVarintFrameDecoder()) .addLast(READ_TIMEOUT, new ReadTimeoutHandler( pingOptions.getTimeout() == 0 @@ -143,10 +147,30 @@ public void removePlayer(ConnectedPlayer player) { } @Override - public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) { + public boolean sendPluginMessage(final @NotNull ChannelIdentifier identifier, final byte @NotNull [] data) { + requireNonNull(identifier); + requireNonNull(data); return sendPluginMessage(identifier, Unpooled.wrappedBuffer(data)); } + @Override + public boolean sendPluginMessage( + final @NotNull ChannelIdentifier identifier, + final @NotNull PluginMessageEncoder dataEncoder + ) { + requireNonNull(identifier); + requireNonNull(dataEncoder); + final ByteBuf buf = Unpooled.buffer(); + final ByteBufDataOutput dataInput = new ByteBufDataOutput(buf); + dataEncoder.encode(dataInput); + if (buf.isReadable()) { + return sendPluginMessage(identifier, buf); + } else { + buf.release(); + return false; + } + } + /** * Sends a plugin message to the server through this connection. The message will be released * afterwards. @@ -156,8 +180,8 @@ public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) { * @return whether or not the message was sent */ public boolean sendPluginMessage(ChannelIdentifier identifier, ByteBuf data) { - for (ConnectedPlayer player : players.values()) { - VelocityServerConnection serverConnection = player.getConnectedServer(); + for (final ConnectedPlayer player : players.values()) { + final VelocityServerConnection serverConnection = player.getConnectedServer(); if (serverConnection != null && serverConnection.getConnection() != null && serverConnection.getServer() == this) { return serverConnection.sendPluginMessage(identifier, data); From 3b6419997c4dba260096ed564085829c3825d387 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Sat, 20 Apr 2024 13:57:31 +0100 Subject: [PATCH 15/28] Align default prevent proxy connection settings with the default config file This option generally creates a bunch of oddities in many setups, defaulting to false as per the default toml config, is probably the better option here --- .../com/velocitypowered/proxy/config/VelocityConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java index f4a76919ee..0d5cc85677 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java @@ -503,7 +503,7 @@ public static VelocityConfiguration read(Path path) throws IOException { final boolean forceKeyAuthentication = config.getOrElse("force-key-authentication", true); final boolean announceForge = config.getOrElse("announce-forge", true); final boolean preventClientProxyConnections = config.getOrElse( - "prevent-client-proxy-connections", true); + "prevent-client-proxy-connections", false); final boolean kickExisting = config.getOrElse("kick-existing-players", false); final boolean enablePlayerAddressLogging = config.getOrElse( "enable-player-address-logging", true); From be678840de9c927c9e17bcea06ed7aedcea77d1e Mon Sep 17 00:00:00 2001 From: Adrian <68704415+4drian3d@users.noreply.github.com> Date: Sun, 21 Apr 2024 13:49:44 -0500 Subject: [PATCH 16/28] Added support for components when using CommandSyntaxException (#1295) --- .../proxy/command/VelocityCommandManager.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java index 80fef3d4e8..b92c4f5009 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.Message; import com.mojang.brigadier.ParseResults; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestion; @@ -33,6 +34,7 @@ import com.velocitypowered.api.command.CommandMeta; import com.velocitypowered.api.command.CommandResult; import com.velocitypowered.api.command.CommandSource; +import com.velocitypowered.api.command.VelocityBrigadierMessage; import com.velocitypowered.api.event.command.CommandExecuteEvent; import com.velocitypowered.api.event.command.PostCommandInvocationEvent; import com.velocitypowered.proxy.command.registrar.BrigadierCommandRegistrar; @@ -57,7 +59,7 @@ import org.jetbrains.annotations.VisibleForTesting; /** - * Impelements Velocity's command handler. + * Implements Velocity's command handler. */ public class VelocityCommandManager implements CommandManager { @@ -232,7 +234,12 @@ private boolean executeImmediately0(final CommandSource source, final String cmd boolean isSyntaxError = !e.getType().equals( CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand()); if (isSyntaxError) { - source.sendMessage(Component.text(e.getMessage(), NamedTextColor.RED)); + final Message message = e.getRawMessage(); + if (message instanceof VelocityBrigadierMessage velocityMessage) { + source.sendMessage(velocityMessage.asComponent().applyFallbackStyle(NamedTextColor.RED)); + } else { + source.sendMessage(Component.text(e.getMessage(), NamedTextColor.RED)); + } result = com.velocitypowered.api.command.CommandResult.SYNTAX_ERROR; // This is, of course, a lie, but the API will need to change... return true; From 8f4adb1cec79dbfcc60c4b893a9b59dbb6c6612a Mon Sep 17 00:00:00 2001 From: Adrian <68704415+4drian3d@users.noreply.github.com> Date: Mon, 22 Apr 2024 21:12:25 -0500 Subject: [PATCH 17/28] 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 --- .../connection/ConnectionHandshakeEvent.java | 21 +++ .../event/connection/PreTransferEvent.java | 100 +++++++++++++ .../api/network/HandshakeIntent.java | 42 ++++++ .../api/network/ProtocolState.java | 5 +- .../api/network/ProtocolVersion.java | 3 +- .../com/velocitypowered/api/proxy/Player.java | 10 ++ .../com/velocitypowered/proxy/Velocity.java | 5 +- .../proxy/config/VelocityConfiguration.java | 16 ++- .../migration/ConfigurationMigration.java | 5 +- .../TransferIntegrationMigration.java | 40 ++++++ .../connection/MinecraftSessionHandler.java | 5 + .../backend/BackendPlaySessionHandler.java | 27 ++++ .../backend/ConfigSessionHandler.java | 27 ++++ .../backend/VelocityServerConnection.java | 3 +- .../connection/client/ConnectedPlayer.java | 21 +++ .../client/HandshakeSessionHandler.java | 11 +- .../client/InitialLoginSessionHandler.java | 6 +- .../connection/registry/DimensionInfo.java | 11 +- .../proxy/protocol/StateRegistry.java | 136 ++++++++++++------ .../packet/EncryptionRequestPacket.java | 7 + .../protocol/packet/HandshakePacket.java | 14 +- .../proxy/protocol/packet/JoinGamePacket.java | 37 ++++- .../proxy/protocol/packet/RespawnPacket.java | 18 ++- .../protocol/packet/ServerDataPacket.java | 12 +- .../protocol/packet/ServerLoginPacket.java | 11 +- .../packet/ServerLoginSuccessPacket.java | 10 +- .../proxy/protocol/packet/TransferPacket.java | 64 +++++++++ .../brigadier/ArgumentPropertyRegistry.java | 78 +++++----- .../RegistryIdArgumentSerializer.java | 37 +++++ .../chat/session/SessionChatBuilder.java | 20 ++- .../chat/session/SessionCommandHandler.java | 2 +- .../session/SessionPlayerCommandPacket.java | 6 +- .../session/UnsignedPlayerCommandPacket.java | 46 ++++++ .../proxy/server/PingSessionHandler.java | 3 +- .../proxy/util/VelocityProperties.java | 59 ++++++++ .../src/main/resources/default-velocity.toml | 6 +- 36 files changed, 782 insertions(+), 142 deletions(-) create mode 100644 api/src/main/java/com/velocitypowered/api/event/connection/PreTransferEvent.java create mode 100644 api/src/main/java/com/velocitypowered/api/network/HandshakeIntent.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/config/migration/TransferIntegrationMigration.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryIdArgumentSerializer.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/util/VelocityProperties.java diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEvent.java b/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEvent.java index 14baac4130..e344b6c504 100644 --- a/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEvent.java @@ -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 @@ 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 + '}'; } } diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/PreTransferEvent.java b/api/src/main/java/com/velocitypowered/api/event/connection/PreTransferEvent.java new file mode 100644 index 0000000000..584ab0052d --- /dev/null +++ b/api/src/main/java/com/velocitypowered/api/event/connection/PreTransferEvent.java @@ -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 { + 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; + } + } +} diff --git a/api/src/main/java/com/velocitypowered/api/network/HandshakeIntent.java b/api/src/main/java/com/velocitypowered/api/network/HandshakeIntent.java new file mode 100644 index 0000000000..44aa4e689a --- /dev/null +++ b/api/src/main/java/com/velocitypowered/api/network/HandshakeIntent.java @@ -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; + }; + } +} diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolState.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolState.java index f5df6fa592..0ecc8287a6 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolState.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolState.java @@ -16,14 +16,15 @@ public enum ProtocolState { /** * Initial connection State. - *

    This status can be caused by a STATUS, LOGIN or TRANSFER intent.

    + *

    This status can be caused by a {@link HandshakeIntent#STATUS}, + * {@link HandshakeIntent#LOGIN} or {@link HandshakeIntent#TRANSFER} intent.

    * 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. - *

    Connections with the STATUS HandshakeIntent will pass through this state + *

    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.

    */ diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index e124245d56..ba69c6887e 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -85,7 +85,8 @@ public boolean isSupported() { 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; diff --git a/api/src/main/java/com/velocitypowered/api/proxy/Player.java b/api/src/main/java/com/velocitypowered/api/proxy/Player.java index ae9a8006c6..57b3075750 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/Player.java @@ -20,6 +20,7 @@ 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 @@ default void stopSound(@NotNull SoundStop stop) { @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); } \ No newline at end of file diff --git a/proxy/src/main/java/com/velocitypowered/proxy/Velocity.java b/proxy/src/main/java/com/velocitypowered/proxy/Velocity.java index cd4720cf5b..0ec8622ddb 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/Velocity.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/Velocity.java @@ -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); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java index 0d5cc85677..11c65d5270 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java @@ -30,6 +30,7 @@ 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 boolean isLogPlayerConnections() { return advanced.isLogPlayerConnections(); } + public boolean isAcceptTransfers() { + return this.advanced.isAcceptTransfers(); + } + public boolean isForceKeyAuthentication() { return forceKeyAuthentication; } @@ -456,7 +461,8 @@ public static VelocityConfiguration read(Path path) throws IOException { final ConfigurationMigration[] migrations = { new ForwardingMigration(), new KeyAuthenticationMigration(), - new MotdMigration() + new MotdMigration(), + new TransferIntegrationMigration() }; for (final ConfigurationMigration migration : migrations) { @@ -708,6 +714,8 @@ private static class Advanced { private boolean logCommandExecutions = false; @Expose private boolean logPlayerConnections = true; + @Expose + private boolean acceptTransfers = false; private Advanced() { } @@ -732,6 +740,7 @@ private Advanced(CommentedConfig config) { 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 boolean isLogPlayerConnections() { return logPlayerConnections; } + public boolean isAcceptTransfers() { + return this.acceptTransfers; + } + @Override public String toString() { return "Advanced{" @@ -807,6 +820,7 @@ public String toString() { + ", announceProxyCommands=" + announceProxyCommands + ", logCommandExecutions=" + logCommandExecutions + ", logPlayerConnections=" + logPlayerConnections + + ", acceptTransfers=" + acceptTransfers + '}'; } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/config/migration/ConfigurationMigration.java b/proxy/src/main/java/com/velocitypowered/proxy/config/migration/ConfigurationMigration.java index 2dc37cb446..a7fbb89fef 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/config/migration/ConfigurationMigration.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/config/migration/ConfigurationMigration.java @@ -25,7 +25,10 @@ * 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; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/config/migration/TransferIntegrationMigration.java b/proxy/src/main/java/com/velocitypowered/proxy/config/migration/TransferIntegrationMigration.java new file mode 100644 index 0000000000..26d89855ad --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/config/migration/TransferIntegrationMigration.java @@ -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 . + */ + +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"); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java index ad6b6db17d..fd9ddfc1bf 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java @@ -51,6 +51,7 @@ 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 @@ default boolean handle(ChatAcknowledgementPacket chatAcknowledgement) { default boolean handle(BundleDelimiterPacket bundleDelimiterPacket) { return false; } + + default boolean handle(TransferPacket transfer) { + return false; + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java index 18f242fe3f..c5d1aa108f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java @@ -25,6 +25,7 @@ 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.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.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 boolean handle(ServerDataPacket packet) { 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) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java index 32c07c042b..31d1dedb04 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/ConfigSessionHandler.java @@ -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.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 boolean handle(RegistrySyncPacket packet) { 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( diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java index 8c027546fb..edf3a9148c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java @@ -22,6 +22,7 @@ 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 @@ private void startHandshake() { .getHostString(); HandshakePacket handshake = new HandshakePacket(); - handshake.setNextStatus(StateRegistry.LOGIN_ID); + handshake.setIntent(HandshakeIntent.LOGIN); handshake.setProtocolVersion(protocolVersion); if (forwardingMode == PlayerInfoForwarding.LEGACY) { handshake.setServerAddress(createLegacyForwardingAddress()); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 16df7bb84d..edefbc2d8d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -26,6 +26,7 @@ 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.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 @@ void setClientBrand(final @Nullable String clientBrand) { 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 completions) { Preconditions.checkNotNull(completions, "completions"); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java index 5c5e928fe8..fae6533dba 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java @@ -20,6 +20,7 @@ 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 boolean handle(final HandshakePacket handshake) { } 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 boolean handle(final HandshakePacket handshake) { 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 @@ private void handleLogin(HandshakePacket handshake, InitialInboundConnection ic) } 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)); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialLoginSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialLoginSessionHandler.java index 5cc5371c02..00187d3470 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialLoginSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/InitialLoginSessionHandler.java @@ -40,6 +40,7 @@ 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 diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java index 6dec08eeb2..150c1f4570 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java @@ -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; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index f53604a5a3..e3cb2bc088 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -35,6 +35,7 @@ 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.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.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); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java index 98b644d0ae..422d5e117c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java @@ -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 void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi 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 void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi 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); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java index 107ea6f040..2edaed9ef2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java @@ -19,6 +19,7 @@ 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 void setPort(int port) { } 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 void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi this.serverAddress = ProtocolUtils.readString(buf, MAXIMUM_HOSTNAME_LENGTH); this.port = buf.readUnsignedShort(); this.nextStatus = ProtocolUtils.readVarInt(buf); + this.intent = HandshakeIntent.getById(nextStatus); } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java index aa5ccaf7a5..f1d2b6400e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java @@ -51,6 +51,7 @@ public class JoinGamePacket implements MinecraftPacket { private int simulationDistance; // 1.18+ private @Nullable Pair lastDeathPosition; // 1.19+ private int portalCooldown; // 1.20+ + private boolean enforcesSecureChat; // 1.20.5+ public int getEntityId() { return entityId; @@ -180,6 +181,14 @@ public void setPortalCooldown(int portalCooldown) { 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 @@ private void decode116Up(ByteBuf buf, ProtocolVersion version) { 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 @@ private void decode116Up(ByteBuf buf, ProtocolVersion version) { } } + @SuppressWarnings("checkstyle:VariableDeclarationUsageDistance") private void decode1202Up(ByteBuf buf, ProtocolVersion version) { this.entityId = buf.readInt(); this.isHardcore = buf.readBoolean(); @@ -311,7 +321,12 @@ private void decode1202Up(ByteBuf buf, ProtocolVersion version) { 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 @@ private void decode1202Up(ByteBuf buf, ProtocolVersion version) { 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 @@ private void decode1202Up(ByteBuf buf, ProtocolVersion version) { } this.portalCooldown = ProtocolUtils.readVarInt(buf); + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) { + this.enforcesSecureChat = buf.readBoolean(); + } } @Override @@ -391,8 +409,7 @@ private void encode116Up(ByteBuf buf, ProtocolVersion version) { 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 @@ private void encode1202Up(ByteBuf buf, ProtocolVersion version) { 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 @@ private void encode1202Up(ByteBuf buf, ProtocolVersion version) { } ProtocolUtils.writeVarInt(buf, portalCooldown); + + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) { + buf.writeBoolean(this.enforcesSecureChat); + } } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java index 7e9562c441..ceaee9fd24 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java @@ -160,15 +160,19 @@ public String toString() { @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 void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi 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 void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi 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 { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java index d92bf0c46f..610462a940 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java @@ -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 void decode(ByteBuf buf, ProtocolUtils.Direction direction, 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 void encode(ByteBuf buf, ProtocolUtils.Direction direction, 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 boolean handle(MinecraftSessionHandler handler) { public boolean isSecureChatEnforced() { return secureChatEnforced; } + + public void setSecureChatEnforced(boolean secureChatEnforced) { + this.secureChatEnforced = secureChatEnforced; + } } \ No newline at end of file diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java index 210447cc75..74eabb5c31 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java @@ -26,9 +26,8 @@ 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 void setPlayerKey(IdentifiedKey playerKey) { @Override public String toString() { return "ServerLogin{" - + "username='" + username + '\'' - + "uuid='" + holderUuid + '\'' - + "playerKey='" + playerKey + '\'' - + '}'; + + "username='" + username + '\'' + + "playerKey='" + playerKey + '\'' + + "holderUUID='" + holderUuid + '\'' + + '}'; } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java index fb7c087b4a..f4fa6bc309 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java @@ -23,8 +23,8 @@ 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 properties; + private static final boolean strictErrorHandling = VelocityProperties + .readBoolean("velocity.strictErrorHandling", true); public UUID getUuid() { if (uuid == null) { @@ -90,6 +92,9 @@ public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi 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 void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi ProtocolUtils.writeProperties(buf, properties); } } + if (version == ProtocolVersion.MINECRAFT_1_20_5) { + buf.writeBoolean(strictErrorHandling); + } } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java new file mode 100644 index 0000000000..b5a74e49f2 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java @@ -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 . + */ + +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); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java index 9eca02fbfb..17bdd976f2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java @@ -21,6 +21,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_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 void serialize(BoolArgumentType object, ByteBuf buf, }); 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 void serialize(BoolArgumentType object, ByteBuf buf, 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+ } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryIdArgumentSerializer.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryIdArgumentSerializer.java new file mode 100644 index 0000000000..5e8e1daf12 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryIdArgumentSerializer.java @@ -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 . + */ + +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 { + + 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); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatBuilder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatBuilder.java index 7f4df1be2c..9a4fdc7250 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatBuilder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatBuilder.java @@ -42,13 +42,19 @@ public MinecraftPacket toClient() { @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; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java index b9f2b238bb..5048294ca4 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java @@ -108,7 +108,7 @@ public void handlePlayerCommandInternal(SessionPlayerCommandPacket packet) { .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; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java index d4b3a3a958..c3b1ae3c06 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java @@ -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 void decode(ByteBuf buf, ProtocolUtils.Direction direction, } @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); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java new file mode 100644 index 0000000000..dd59e3ff20 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java @@ -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 . + */ + +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 + '\'' + + '}'; + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/server/PingSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/server/PingSessionHandler.java index c47d5d436c..89760344a8 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/server/PingSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/server/PingSessionHandler.java @@ -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); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/VelocityProperties.java b/proxy/src/main/java/com/velocitypowered/proxy/util/VelocityProperties.java new file mode 100644 index 0000000000..d2b304a869 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/VelocityProperties.java @@ -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 . + */ + +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; + } +} diff --git a/proxy/src/main/resources/default-velocity.toml b/proxy/src/main/resources/default-velocity.toml index 0f18208b55..3f4f6318c3 100644 --- a/proxy/src/main/resources/default-velocity.toml +++ b/proxy/src/main/resources/default-velocity.toml @@ -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 From bf507dc0b8d91bb24bddbc0a4dcbee89e60f6eeb Mon Sep 17 00:00:00 2001 From: Adrian <68704415+4drian3d@users.noreply.github.com> Date: Tue, 23 Apr 2024 10:07:39 -0500 Subject: [PATCH 18/28] Update snapshot protocol to 1.20.5 release (#1298) --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index ba69c6887e..9627b0e9ac 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -86,7 +86,7 @@ public boolean isSupported() { 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_5(-1, 191, "1.20.5"); // Future Minecraft 1.20.5 | Protocol 766 | Release Candidate 3 + MINECRAFT_1_20_5(766, "1.20.5"); private static final int SNAPSHOT_BIT = 30; From 3afd687bf1d2b4451b866bf1e21d71987b66b602 Mon Sep 17 00:00:00 2001 From: Jeroen B Date: Wed, 24 Apr 2024 07:55:21 +0200 Subject: [PATCH 19/28] Handle KnownPacks packet required for 1.20.5 vanilla connections (#1302) --- .../connection/MinecraftSessionHandler.java | 5 ++ .../client/ClientConfigSessionHandler.java | 10 +++ .../proxy/protocol/StateRegistry.java | 7 ++ .../packet/config/KnownPacksPacket.java | 69 +++++++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java index fd9ddfc1bf..67cd9d11b3 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java @@ -63,6 +63,7 @@ import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerCommandPacket; import com.velocitypowered.proxy.protocol.packet.config.ActiveFeaturesPacket; import com.velocitypowered.proxy.protocol.packet.config.FinishedUpdatePacket; +import com.velocitypowered.proxy.protocol.packet.config.KnownPacksPacket; import com.velocitypowered.proxy.protocol.packet.config.RegistrySyncPacket; import com.velocitypowered.proxy.protocol.packet.config.StartUpdatePacket; import com.velocitypowered.proxy.protocol.packet.config.TagsUpdatePacket; @@ -334,4 +335,8 @@ default boolean handle(BundleDelimiterPacket bundleDelimiterPacket) { default boolean handle(TransferPacket transfer) { return false; } + + default boolean handle(KnownPacksPacket packet) { + return false; + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConfigSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConfigSessionHandler.java index 667fe8d12a..c1ed4a87ae 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConfigSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConfigSessionHandler.java @@ -33,6 +33,7 @@ import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket; import com.velocitypowered.proxy.protocol.packet.ResourcePackResponsePacket; import com.velocitypowered.proxy.protocol.packet.config.FinishedUpdatePacket; +import com.velocitypowered.proxy.protocol.packet.config.KnownPacksPacket; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -131,6 +132,15 @@ public boolean handle(PingIdentifyPacket packet) { return true; } + @Override + public boolean handle(KnownPacksPacket packet) { + if (player.getConnectionInFlight() != null) { + player.getConnectionInFlight().ensureConnected().write(packet); + } + + return true; + } + @Override public void handleGeneric(MinecraftPacket packet) { VelocityServerConnection serverConnection = player.getConnectedServer(); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index e3cb2bc088..b0ee89f755 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -92,6 +92,7 @@ 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.KnownPacksPacket; import com.velocitypowered.proxy.protocol.packet.config.RegistrySyncPacket; import com.velocitypowered.proxy.protocol.packet.config.StartUpdatePacket; import com.velocitypowered.proxy.protocol.packet.config.TagsUpdatePacket; @@ -165,6 +166,10 @@ public enum StateRegistry { ResourcePackResponsePacket::new, map(0x05, MINECRAFT_1_20_2, false), map(0x06, MINECRAFT_1_20_5, false)); + serverbound.register( + KnownPacksPacket.class, + KnownPacksPacket::new, + map(0x07, MINECRAFT_1_20_5, false)); clientbound.register( PluginMessagePacket.class, PluginMessagePacket::new, @@ -207,6 +212,8 @@ public enum StateRegistry { map(0x08, MINECRAFT_1_20_2, false), map(0x09, MINECRAFT_1_20_3, false), map(0x0D, MINECRAFT_1_20_5, false)); + clientbound.register(KnownPacksPacket.class, KnownPacksPacket::new, + map(0x0E, MINECRAFT_1_20_5, false)); } }, PLAY { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java new file mode 100644 index 0000000000..db8bb1ec51 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java @@ -0,0 +1,69 @@ +/* + * 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 . + */ + +package com.velocitypowered.proxy.protocol.packet.config; + +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; + +public class KnownPacksPacket implements MinecraftPacket { + + private KnownPack[] packs; + + @Override + public void decode(ByteBuf buf, ProtocolUtils.Direction direction, + ProtocolVersion protocolVersion) { + final int packCount = ProtocolUtils.readVarInt(buf); + final KnownPack[] packs = new KnownPack[packCount]; + + for (int i = 0; i < packCount; i++) { + packs[i] = KnownPack.read(buf); + } + + this.packs = packs; + } + + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, + ProtocolVersion protocolVersion) { + ProtocolUtils.writeVarInt(buf, packs.length); + + for (KnownPack pack : packs) { + pack.write(buf); + } + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } + + public record KnownPack(String namespace, String id, String version) { + private static KnownPack read(ByteBuf buf) { + return new KnownPack(ProtocolUtils.readString(buf), ProtocolUtils.readString(buf), ProtocolUtils.readString(buf)); + } + + private void write(ByteBuf buf) { + ProtocolUtils.writeString(buf, namespace); + ProtocolUtils.writeString(buf, id); + ProtocolUtils.writeString(buf, version); + } + } +} From b50f9eceff4bd4e1fb7c9bf5beef8a0927efd851 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Wed, 24 Apr 2024 09:39:22 +0100 Subject: [PATCH 20/28] Fix command argument types for 1.20.5 --- proxy/build.gradle.kts | 1 + .../protocol/packet/brigadier/ArgumentPropertyRegistry.java | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/proxy/build.gradle.kts b/proxy/build.gradle.kts index 0edd10cce3..5e1387b06c 100644 --- a/proxy/build.gradle.kts +++ b/proxy/build.gradle.kts @@ -8,6 +8,7 @@ plugins { application { mainClass.set("com.velocitypowered.proxy.Velocity") + applicationDefaultJvmArgs += listOf("-Dvelocity.packet-decode-logging=true"); } tasks { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java index 17bdd976f2..7c04c97bc4 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java @@ -262,9 +262,9 @@ public void serialize(BoolArgumentType object, ByteBuf buf, 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); + empty(id("minecraft:loot_table", mapSet(MINECRAFT_1_20_5, 50))); + empty(id("minecraft:loot_predicate", mapSet(MINECRAFT_1_20_5, 51))); + empty(id("minecraft:loot_modifier", mapSet(MINECRAFT_1_20_5, 52))); // Crossstitch support register(id("crossstitch:mod_argument", mapSet(MINECRAFT_1_19, -256)), ModArgumentProperty.class, MOD); From 7e45c17b044592381910799d7db8e658339b1718 Mon Sep 17 00:00:00 2001 From: UserNugget <47762903+UserNugget@users.noreply.github.com> Date: Wed, 24 Apr 2024 12:50:33 +0300 Subject: [PATCH 21/28] Limit maximum amount of known packs by vanilla defaults (#1303) --- .../proxy/protocol/packet/config/KnownPacksPacket.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java index db8bb1ec51..3a7d60cba6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java @@ -21,16 +21,25 @@ import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; +import com.velocitypowered.proxy.util.except.QuietDecoderException; import io.netty.buffer.ByteBuf; public class KnownPacksPacket implements MinecraftPacket { + private static final int MAX_LENGTH_PACKS = Integer.getInteger("velocity.max-known-packs", 64); + private static final QuietDecoderException TOO_MANY_PACKS = + new QuietDecoderException("too many known packs"); + private KnownPack[] packs; @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { final int packCount = ProtocolUtils.readVarInt(buf); + if (packCount > MAX_LENGTH_PACKS) { + throw TOO_MANY_PACKS; + } + final KnownPack[] packs = new KnownPack[packCount]; for (int i = 0; i < packCount; i++) { From f98c522fa6570902bd121691b1329e11c521f5a8 Mon Sep 17 00:00:00 2001 From: powercas_gamer Date: Wed, 24 Apr 2024 22:12:59 +0200 Subject: [PATCH 22/28] Make copyright year a placeholder (#1305) * make copyright year a placeholder * review --- .../proxy/command/builtin/VelocityCommand.java | 4 +++- .../com/velocitypowered/proxy/l10n/messages.properties | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/VelocityCommand.java b/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/VelocityCommand.java index bd240804cf..26f99ecd22 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/VelocityCommand.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/command/builtin/VelocityCommand.java @@ -46,6 +46,7 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.text.SimpleDateFormat; +import java.time.LocalDate; import java.util.Collection; import java.util.Date; import java.util.List; @@ -165,7 +166,8 @@ public int run(final CommandContext context) { final Component copyright = Component .translatable("velocity.command.version-copyright", Component.text(version.getVendor()), - Component.text(version.getName())); + Component.text(version.getName()), + Component.text(LocalDate.now().getYear())); source.sendMessage(velocity); source.sendMessage(copyright); diff --git a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages.properties b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages.properties index f5b6ae9b4a..07aa348f31 100644 --- a/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages.properties +++ b/proxy/src/main/resources/com/velocitypowered/proxy/l10n/messages.properties @@ -48,7 +48,7 @@ velocity.command.glist-player-plural={0} players are currently connected to the velocity.command.glist-view-all=To view all players on servers, use /glist all. velocity.command.reload-success=Velocity configuration successfully reloaded. velocity.command.reload-failure=Unable to reload your Velocity configuration. Check the console for more details. -velocity.command.version-copyright=Copyright 2018-2023 {0}. {1} is licensed under the terms of the GNU General Public License v3. +velocity.command.version-copyright=Copyright 2018-{2} {0}. {1} is licensed under the terms of the GNU General Public License v3. velocity.command.no-plugins=There are no plugins currently installed. velocity.command.plugins-list=Plugins: {0} velocity.command.plugin-tooltip-website=Website: {0} From 2534412be45afe939c6dc10693d56fc9a0586956 Mon Sep 17 00:00:00 2001 From: powercas_gamer Date: Wed, 24 Apr 2024 22:13:09 +0200 Subject: [PATCH 23/28] remove access controller (#1306) --- .../com/velocitypowered/proxy/VelocityServer.java | 15 +++------------ .../plugin/loader/java/JavaPluginLoader.java | 5 +---- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java index 89f55064ed..1a9d71cb41 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java @@ -74,9 +74,7 @@ import java.net.http.HttpClient; import java.nio.file.Files; import java.nio.file.Path; -import java.security.AccessController; import java.security.KeyPair; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collection; import java.util.Locale; @@ -522,8 +520,8 @@ public void shutdown(boolean explicitExit, Component reason) { // makes sure that all the disconnect events are being fired CompletableFuture playersTeardownFuture = CompletableFuture.allOf(players.stream() - .map(ConnectedPlayer::getTeardownFuture) - .toArray((IntFunction[]>) CompletableFuture[]::new)); + .map(ConnectedPlayer::getTeardownFuture) + .toArray((IntFunction[]>) CompletableFuture[]::new)); playersTeardownFuture.get(10, TimeUnit.SECONDS); } catch (TimeoutException e) { @@ -552,14 +550,7 @@ public void shutdown(boolean explicitExit, Component reason) { shutdown = true; if (explicitExit) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - @SuppressFBWarnings("DM_EXIT") - public Void run() { - System.exit(0); - return null; - } - }); + System.exit(0); } }; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaPluginLoader.java b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaPluginLoader.java index 3795efd392..d1df777d35 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaPluginLoader.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/plugin/loader/java/JavaPluginLoader.java @@ -38,8 +38,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashSet; import java.util.Optional; import java.util.Set; @@ -92,8 +90,7 @@ public PluginDescription createPluginFromCandidate(PluginDescription candidate) URL pluginJarUrl = candidate.getSource().orElseThrow( () -> new InvalidPluginException("Description provided does not have a source path") ).toUri().toURL(); - PluginClassLoader loader = AccessController.doPrivileged( - (PrivilegedAction) () -> new PluginClassLoader(new URL[]{pluginJarUrl})); + PluginClassLoader loader = new PluginClassLoader(new URL[]{pluginJarUrl}); loader.addToClassloaders(); JavaVelocityPluginDescriptionCandidate candidateInst = From a9a31f69354249def1e2fc965e46e9a0887f4318 Mon Sep 17 00:00:00 2001 From: Kichura <68134602+Kichura@users.noreply.github.com> Date: Fri, 26 Apr 2024 07:05:23 +0200 Subject: [PATCH 24/28] Freeze ubuntu version, Update Gradle Wrapper. (#1292) --- .github/workflows/gradle.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index c3cce5bd1e..acec1f8502 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -2,15 +2,16 @@ # For more information see: https://docs.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle name: Java CI with Gradle - on: [push, pull_request] jobs: - build-17: - runs-on: ubuntu-latest + build: + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v2 + - name: Checkout Repository + uses: actions/checkout@v4 + - name: Validate Gradle Wrapper + uses: gradle/actions/wrapper-validation@v3 - name: Set up JDK 17 uses: actions/setup-java@v4 with: From 399bc2325f36165e1abc5470358ff3f9faaf3344 Mon Sep 17 00:00:00 2001 From: "Pantera (Mad_Daniel)" <89838384+Pantera07@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:13:08 +0900 Subject: [PATCH 25/28] Add version information for 1.20.6 (#1310) https://www.minecraft.net/en-us/article/minecraft-java-edition-1-20-6 --- .../java/com/velocitypowered/api/network/ProtocolVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 9627b0e9ac..8723d88840 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -86,7 +86,7 @@ public boolean isSupported() { 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_5(766, "1.20.5"); + MINECRAFT_1_20_5(766, "1.20.5", "1.20.6"); private static final int SNAPSHOT_BIT = 30; From 5cdcf86cf9fd7bd25c3c140435b9c63bc8f830fd Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Wed, 1 May 2024 17:22:18 +0100 Subject: [PATCH 26/28] Properly pass connection exceptions to the logger --- .../proxy/connection/MinecraftConnection.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java index 53d0a2364a..b1c91ebdb9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java @@ -195,8 +195,9 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E boolean isQuietDecoderException = cause instanceof QuietDecoderException; boolean willLog = !isQuietDecoderException && !frontlineHandler; if (willLog) { - logger.error("{}: exception encountered in {}", association, activeSessionHandler, - cause); + logger.atError().withThrowable(cause) + .log("{}: exception encountered in {}", association, + activeSessionHandler); } else { knownDisconnect = true; } @@ -226,7 +227,6 @@ public EventLoop eventLoop() { * Writes and immediately flushes a message to the connection. * * @param msg the message to write - * * @return A {@link ChannelFuture} that will complete when packet is successfully sent */ @Nullable @@ -370,12 +370,12 @@ public void setState(StateRegistry state) { this.state = state; // If the connection is LEGACY (<1.6), the decoder and encoder are not set. final MinecraftEncoder minecraftEncoder = this.channel.pipeline() - .get(MinecraftEncoder.class); + .get(MinecraftEncoder.class); if (minecraftEncoder != null) { minecraftEncoder.setState(state); } final MinecraftDecoder minecraftDecoder = this.channel.pipeline() - .get(MinecraftDecoder.class); + .get(MinecraftDecoder.class); if (minecraftDecoder != null) { minecraftDecoder.setState(state); } @@ -395,8 +395,8 @@ public void setState(StateRegistry state) { public void addPlayPacketQueueHandler() { if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE) == null) { this.channel.pipeline().addAfter(Connections.MINECRAFT_ENCODER, Connections.PLAY_PACKET_QUEUE, - new PlayPacketQueueHandler(this.protocolVersion, - channel.pipeline().get(MinecraftEncoder.class).getDirection())); + new PlayPacketQueueHandler(this.protocolVersion, + channel.pipeline().get(MinecraftEncoder.class).getDirection())); } } From 368d1a7c1250b4138f683e64ebb6aadfe7a4b1b3 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Wed, 1 May 2024 18:03:37 +0100 Subject: [PATCH 27/28] Do not send empty upsert player info packets There is no harm in this, but seemingly, some common mod blows up on this, and, well, why eat buffer? --- .../com/velocitypowered/proxy/tablist/VelocityTabList.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java index e18881b45a..d6b4143ce4 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java @@ -166,7 +166,9 @@ public void addEntry(TabListEntry entry1) { return entry; }); - this.connection.write(new UpsertPlayerInfoPacket(actions, List.of(playerInfoEntry))); + if (!actions.isEmpty()) { + this.connection.write(new UpsertPlayerInfoPacket(actions, List.of(playerInfoEntry))); + } } @Override From 1228f147423d14a6e0b0c940259aa59da90797b1 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Fri, 3 May 2024 19:20:12 +0100 Subject: [PATCH 28/28] Hotfix cancelling unsigned 1.20.6 commands --- .../protocol/packet/chat/session/SessionCommandHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java index 5048294ca4..6984970b3b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java @@ -55,7 +55,7 @@ public void handlePlayerCommandInternal(SessionPlayerCommandPacket packet) { + "Contact your network administrator.")); } // We seemingly can't actually do this if signed args exist, if not, we can probs keep stuff happy - if (player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_19_3)) { + if (player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_19_3) && packet.lastSeenMessages != null) { return CompletableFuture.completedFuture(new ChatAcknowledgementPacket(packet.lastSeenMessages.getOffset())); } return CompletableFuture.completedFuture(null);