#velocity

1 messages ยท Page 2 of 1

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

I did not implement the Player#playSound(Sound) method as adventure defines it like this:

Plays a sound at the location of the recipient of the sound.

Since we can't fulfill that, would it be fine to break that contract by replacing the javadoc?

https://github.com/KyoriPowered/adventure/blob/-/api/src/main/java/net/kyori/adventure/audience/Audience.java#L629C6-L631

I'll be honest, I tried this pull request for 30 minutes without knowing why the sound wasn't playing, since stopSound was working for me, until I saw that the #playSound(Sound) method wasn't implemented

From a plugin developer's perspective, this method should be implemented, but from a contract compliance perspective, it's okay not to implement it as required by the contract. With this in mind, good documentation at https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported would suffice, so I am now reverting my change

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

we are waiting for you

I'm not a team member, just sharing my thoughts, so my approval is not actually required. Also a friendly reminder that everyone is doing this on their free time, so it's not really needed to bump a review request after only a day.

I gave this another look and it basically lgtm other than these minor things in review comments.

Another thought I had (but I would wait with doing any changes) is that maybe we can just use ServerInfo for this instead of adding a new type, they basically share the same fields and probably will continue to do so in the future as well.

Also there is the issue of the planned config api switch which is holding up other things already that would make changes to the config, so be prepared for this pr to also be affected by this

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Should this work with RC1? I deployed velocity build 539 with Paper 1.21.9-RC1-30, and the client keeps saying Incompatible Client! Please use 1.7.2-1.21.9 Neither velocity nor MC show anything in the logs when I try to connect.

This pull request was merged to prepare support for Minecraft 1.21.9.
Since the release candidate has been published and a release date is approaching, we can be sure that there will be no changes that will break compatibility.
There are no plans to support snapshots in the main builds

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

On 1.20.2, the Minecraft client started clearing boss bars after the login packet, which meant that the ProxyServer#showBossbar API would result in the player getting kicked if the boss bar they were previously shown was updated after switching servers.

Therefore, I have added BossBarManager which drops boss bar packets once the client enters the configure phase to ensure that they do not disconnect, and then re-adds the boss bar once the client enters the login phase.

This ensures that clients do not receive boss bar updates for boss bars that they don't exist and causing them to disconnect. I have also taken care to ensure that this logic only applies on 1.20.2 and up, as it is not necessary for older clients.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

None

Actual Behavior

When I use a Chinese name and enter the /server command on the server for cross-server use, it prompts: Expected whitespace to end one argument, but found trailing data at position 7: server <--[HERE]

[servers]
"็™ปๅฝ•ๅคงๅŽ…" = "127.0.0.1:52020"
"ๅŽŸ็‰ˆ็”Ÿๅญ˜" = "127.0.0.1:52011"
"็ฉบๅฒ›็”Ÿๅญ˜" = "127.0.0.1:52022"
"่ฃ่€€็บชๅ…ƒ" = "127.0.0.1:52033"

try = [
"็™ปๅฝ•ๅคงๅŽ…"
]

[forced-hosts]
"lobby.sakura18.cn" = [
"็™ปๅฝ•ๅคงๅŽ…"
]
"factions.sakura18.cn" = [
"ๅŽŸ็‰ˆ็”Ÿๅญ˜"
]
"skyisland.sakura18.cn" = [
"็ฉบๅฒ›็”Ÿๅญ˜"
]
"mmorpg.sakura18.cn" = [
"่ฃ่€€็บชๅ…ƒ"
]

Steps to Reproduce

None

Plugin List

None

Velocity Version

velocity-3.4.0-SNAPSHOT-535

Additional Information

None

hexed flickerBOT
#

This is a duplicate of https://github.com/PaperMC/Velocity/issues/1362 and https://github.com/PaperMC/Velocity/issues/1220.

Velocity could address this by making their server command use StringArgumentType#string() rather than StringArgumentType#word(), which is implemented in this PR: https://github.com/PaperMC/Velocity/pull/1363.

With the string type, non "standard" characters would have to be enclosed in quote ". As an alternative, Velocity could use StringArgumentType#greedy since the server argument is at the end of the command.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

I see no need to replace the default ping value

If you want to use -1 for other things

If you are making a plugin that obtains the player's ping, it should be in your plugin where you have the logic for displaying the ping

The only reason I can see for actually changing this would be to modify the ping value that other plugins can obtain, such as placeholder or statistics plugins... Why would you want to do that?

hexed flickerBOT
#

Expected Behavior

Here is my (paper) brigadier command.

public LiteralCommandNode<CommandSource> create() {
    return literalArgumentBuilder("vtest")
            .then(requiredArgumentBuilder("message", StringArgumentType.greedyString())
                    .suggests((ctx, builder) -> {
                        String input = builder.getRemaining().toLowerCase();

                        int location = -1;
                        for (int i = 0; i < input.length(); i++) {
                            if (input.charAt(i) == ':') {
                                location = i;
                            }
                        }

                        return builder.createOffset(location + builder.getStart() + 1)
                                .suggest("This suggestion should move behind semicolons")
                                .buildFuture();
                    })
                    .executes(ctx -> 1)
            )
            .build();
}

it does the following:

h...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

Reported by a user on the PaperMC discord [here](#velocity-dev message)

"Velocity commit (806b386) seems to have changed command suggestions. Tab completing a suggestion replaced the previous argument however. Is this an implementation bug that shifted towards plugins to adjust for this offset, or is this unexpected behaviour?"

https://github.com/user-attachments/assets/293a041f-9ee3-4843-bbce-7778bada1385

Actual Behavior

Steps to Reproduce

Plugin List

Velocity Version

Additional Information

hexed flickerBOT
#

Since 1.21.5 URIs without a http:// or https:// in a open_url click event are no longer silently ignored but fail parsing and disconnect. Paper mitigates this in their codec by prepending a https:// to URIs with no protocol.

This PR enables JSONOptions.EMIT_CLICK_URL_HTTPS on our component serializers, to match papers behavior. To "fix" the disconnect the option would technically only be needed for >= 1.21.5, but I think it is best to just enable it for every version to stay consistent.

Related #1630

hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

I want to be able to share libraries between my Velocity plugins. My current plugin setup is similar to this:

dependenciesec - contains Configurate
kingdoms - contains FileUtils, which loads configs with Configurate
gooeylibs - contains config base classes
eutils - contains config main classes

There are all velocity plugins.

Actual Behavior

I get this error whenever Configurate tries to load the class:

Unknown class of object ca.landonjw.gooeylibs2.api.configurable.button.BaseConfigButton

Steps to Reproduce

On proxy load, eutils calls FileUtils to load its configs. Configurate, then, calls Class.forName to load some gooeylibs class, but fails to do that.

This seems to be caused by Configurate calling Class.forName() and failing. I suspect there's some issues regarding classloading/PluginClassLoader preventing the classes from being found by Configurate, since I can do Class.forName from the other plugins and it works.

Plugin List

Plugins: v...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

That the command to be passed through

Actual Behavior

The player is kicked due to an outdated check in Velocity's unsigned command packet

Steps to Reproduce

  1. setup a paper 1.21.10 server behind velocity
  2. be op on that server
  3. run /fetchprofile name Timongcraft
  4. click on "give item" or "summon mannequin" (and run command in the dialog)

Plugin List

none

Velocity Version

Velocity 3.4.0-SNAPSHOT (git-4cd3b686-b546)

Additional Information

log.log - https://mclo.gs/Nm5WLe5

hexed flickerBOT
hexed flickerBOT
#
[PaperMC/Velocity] branch deleted: cat/increase-chat-string-limit
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#
[PaperMC/Velocity] New branch created: fix/reconfiguration-disconnect
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

If I delete the
forwarding.secret file, Velocity should restore it and generate a new key.

Actual Behavior

After deleting the file, Velocity simply crashes with an error.

[14:33:26 ERROR]: Unable to read/load/save your velocity.toml. The server will shut down.
java.lang.RuntimeException: The forwarding-secret-file does not exist.
at com.velocitypowered.proxy.config.VelocityConfiguration.read(VelocityConfiguration.java:531) ~[velocity-3.4.0-SNAPSHOT-551.jar:3.4.0-SNAPSHOT (git-67b988e6-b551)]
at com.velocitypowered.proxy.VelocityServer.doStartupConfigLoad(VelocityServer.java:405) ~[velocity-3.4.0-SNAPSHOT-551.jar:3.4.0-SNAPSHOT (git-67b988e6-b551)]
at com.velocitypowered.proxy.VelocityServer.start(VelocityServer.java:293) ~[velocity-3.4.0-SNAPSHOT-551.jar:3.4.0-SNAPSHOT (git-67b988e6-b551)]
at com.velocitypowered.proxy.Velocity.main(Velocity.java:71) ~[velocity-3.4.0-SNAPSHOT-551.jar:3.4.0-SNAPSHOT (git-67b988e6-b551)]

###...

hexed flickerBOT
#
[PaperMC/Velocity] New branch created: astei/packet-immutable
hexed flickerBOT
#
[PaperMC/Velocity] New branch created: fix/generate-deleted-forwarding-file
hexed flickerBOT
#

b1dd26f 1.21.10 (#1658) - RealBauHD
d266059 Update adventure to version 4.25.0 (#1660) - cedricmkl
806b386 Fix command suggestion offset (#1662) - Rossterd
5753548 Fix SimpleCommand suggestion offset (#1664) - Rossterd
1140fc6 fix: Enable EMIT_CLICK_URL_HTTPS on component serial... - Emilxyz
4cd3b68 Fix players disconnecting when updating boss bars... - okx-code
70c3eab Minor optimizations for MinecraftCompressorAndLeng... - astei
38a0a7e use correct string length for newer MC versions (F... - electronicboy
13a1c93 Bump Netty to 4.2.7.Final - astei
498a38c Re-enable adaptive allocator - astei...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#
[PaperMC/Velocity] New branch created: fix/null-ping-passthrough-description
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

Some players are getting this error when trying to join the network.

Actual Behavior

Some players are getting this error when trying to join the network.

Steps to Reproduce

Some players are getting this error when trying to join the network.

Plugin List

Velocity: velocity, luckperms, maintenance, advancedserverlist, botsentry, librelogin, mckotlin-velocity, packetevents, pl-hide-pro, skinsrestorer, vlobby
Backend1: no plugins
Backend2 (15):
Paper Plugins (2):

  • FancyHolograms, FancyNpcs
    Bukkit Plugins (13):
  • BetterGUI, ChatManager, DeluxeHub, LuckPerms, Multiverse-Core, packetevents, Pl-Hide-Pro, PlaceholderAPI, SkinsRestorer, TAB, ViaBackwards, ViaVersion, VoidGen

Velocity Version

Velocity 3.4.0-SNAPSHOT (git-02cf3490-b552)

Additional Information

unable to connect to server auth
java.io.IOException: Unexpectedly disconnected from remote server
at com.velocitypowered.proxy.connection.backend.TransitionSessionHandler....

#
[PaperMC/Velocity] branch deleted: fix/null-ping-passthrough-description
hexed flickerBOT
#

I was having a rough time narrowing down a mod that added some custom args under the minecraft: namespace, and found that the exception being thrown was always printing "null" and didn't provide any context as to what arg was causing the problem.

While poking around I noticed that 1.19.1+ had its exception in the right spot, so I've moved the other related exception from ArgumentPropertyRegistry#deserialize to ArgumentPropertyRegistry#readIdentifier.

hexed flickerBOT
#
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

In Velocity 3.4.0-SNAPSHOT (git-f75b5128-b554), the ProxyPingEvent occasionally provides
an InboundConnection where getRemoteAddress() returns null.

This causes NullPointerExceptions in plugins that expect a non-null remote address, such as AdvancedServerList.

Example error:
java.lang.NullPointerException: Cannot invoke "java.net.InetSocketAddress.getHostString()" because the return value of "InboundConnection.getRemoteAddress()" is null

Stacktrace:
at ch.andre601.advancedserverlist.velocity.listeners.VelocityEventWrapper.playerIP(VelocityEventWrapper.java:175)
at ch.andre601.advancedserverlist.core.events.PingEventHandler.handleEvent(PingEventHandler.java:63)
...

Steps to reproduce:

  1. Run Velocity 3.4.0-SNAPSHOT (git-f75b5128-b554)
  2. Install AdvancedServerList (or any plugin using ProxyPingEvent)
  3. Observe console when server list pings occur

Expected behavior:
getRemoteAddress() should never return null, or the API should document that this is pos...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

I'm getting this error when entering certain locations on my modded server.(lobby: farbic 1.21.1)

Actual Behavior

Velocity error:
[23:47:00 INFO]: [connected player] HuanMoLu (/221.200.159.10:60304) has connected
[23:47:00 INFO]: [server connection] HuanMoLu -> lobby has connected
[23:47:02 ERROR]: [server connection] HuanMoLu -> lobby: exception encountered in com.velocitypowered.proxy.connection.backend.BackendPlaySessionHandler@18bd7153
com.velocitypowered.proxy.util.except.QuietRuntimeException: A packet did not decode successfully (invalid data). For more information, launch Velocity with -Dvelocity.packet-decode-logging=true to see more.

lobby server error:
[23:47:02] [Server thread/INFO]: HuanMoLu[/221.200.159.10:56361] logged in with entity id 390 at (100001.22851206471, 80.0, -49999.76083794844)
[23:47:02] [Server thread/INFO]: [Essential Commands] Loading PlayerData for player with uuid '7f465ae6-0c31-33f3-b50d-053ffc618d8a'.
[23:47:02] [Serve...

hexed flickerBOT
hexed flickerBOT
#

Requested Feature

Add a function that could mask the IP of the internal server in logs and in the terminal.

Why is this needed?

The big problem is that players can be playing on different versions, whether 1.8 or 1.21.10, and you can't always use modern forwarding (as opposed to legacy/bungeeguard) to expand the list of available versions.

However, when a player fails to successfully connect to a server, the logs may show an error that shows the internal server's IP address. This isn't always safe, especially if you want to share plugin error logs or other information with others.

Alternative Solutions

Remove the IP address from the error yourself.

Additional Information

I don't think this should be the case. If there's a feature that allows you to hide players' IPs, why can't you hide servers' IPs? For example, I couldn't connect to a server and exposed my server's IP. If I provide the logs, I'll see.

[20:17:31 INFO]: [connected player] Asriel_NEO (/127.0.0.1...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

This change increases the TabComplete limit in order to fix the now broken pasting of larger commands into command blocks after Mojang's change to the way Tab Complete works. It has been increased to 32767 from 2048, and this increase has no negative impact on performance, stability, or protocol compliance.

Mojang clients and servers already allow command strings up to 32767 characters, and this update brings Velocity in line with the vanilla protocol. This prevents unnecessary disconnections when pasting valid command block contents while retaining full protection against malformed packets.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

We and paper intentionally limited this in the past in order to restrict ongoing DoS attacks, I do ponder if it makes any sense to move this restriction elsewhere, I guess some limited adventage with brig is that it might be able to deal with this stuff a bit smarter than the older bukkit command system so maybe this wasn't too much of a problem for us, outside of network buffers

hexed flickerBOT
#

I don't think this actually fixes the issue since we are already do this using our config library: https://github.com/PaperMC/Velocity/blob/b6b6b20fe97cd9cb0d6b4e817d3e7db72aca2d8d/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java#L495

The "real" issue is that the docker images used by those panels include those "broken" minimal configuration files and our config library lacks the functionality to populate missing fields. I think a switch to a different config library is planned in the future

hexed flickerBOT
#

I don't think this actually fixes the issue since we are already do this using our config library:

https://github.com/PaperMC/Velocity/blob/b6b6b20fe97cd9cb0d6b4e817d3e7db72aca2d8d/proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java#L495

To my understanding the "real" issue is that the docker images used by those panels include those "broken" minimal configuration files and our config library lacks the functionality to populate missing fields. I think a switch to a different config library is planned in the future

I worked with this fix with a person having the same issue, he said doing a explicit copy fixes it. He made a different patch for a different project but it worked. Today he is available again and I will ask him to test again. I will confirm soon.

hexed flickerBOT
hexed flickerBOT
#

Hey! Good news. This patch seems to completely patch the issue. I tested on a pterodactyl panel and now the file properly generates after applying this exact patch. You can safely merge. Thank you very much.

nightconfig automatically generates a new configuration file if one doesn't exist. I've personally never had any issues regarding this.
Are there any examples of when nightconfig's file creation might fail? Are there any open issues related to this PR?

#

The nature of the PR comment around aspects like a race condition make 0 sense here, the config file either exists or it doesn't unless there is some janky issue elsewhere, in which, I would rather deal with a solution for that rather than manually copying the configuration file to the disk to work around something which now sounds even more questionable than before.

Either way, given past interactions with this author, I do not feel comfortable merging code submitted by them into this repo due to the legal risks it could potentially entail.

hexed flickerBOT
#

This PR resolves issue #1637 by adding Javadocs to CommandExecuteEvent and PostCommandInvocationEvent.

As said in #1635, developers are not always aware that Velocity does command rate limiting. This can lead to confusion when not all rapidly executed commands (usually done with macros or mods) trigger the corresponding events, as they are forwarded directly to the backend server.

These small changes clarify the intended behavior directly within the event documentation, preventing further confusion.

#

Also amidst controversy around me, some people seem to be randomly banning me or targetting me with weird claims about my persona, I just want to get along with everybody and just make great software together. I might be a little stupid sometimes, but it's my first time working with other people and I really want to learn finally being in community with fellow developers and make friends ๐Ÿ‘

hexed flickerBOT
#

Still causing random OOM's.

[07:14:00 ERROR] [geyser]: Cannot reserve 8388608 bytes of direct buffer memory (allocated: 1067202503, limit: 1073741824)
[07:14:00 WARN] [geyser]: Downstream packet error! VarInt wider than 5 bytes
[07:14:00 WARN] [geyser]: Downstream packet error! Invalid packet id: 144867848
[07:14:00 WARN] [geyser]: Downstream packet error! readerIndex(36) + length(8) exceeds writerIndex(40): AdaptivePoolingAllocator$AdaptiveByteBuf(ridx: 36, widx: 40, cap: 40)
[07:14:00 WARN] [geyser]: Downstream packet error! (ClientboundContainerClosePacket) Packet "ClientboundContainerClosePacket" not fully read.

[07:14:00 WARN] [geyser]: Downstream packet error!
[07:14:00 WARN] [geyser]: Downstream packet error! Collection is empty

hexed flickerBOT
#
[PaperMC/Velocity] New branch created: shane/velocity-log-hack
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Because Scoreboard API hasn't been implemented in velocity, yet. I've just accepted that sorting by perm groups won't be a thing. Prefixes, however, works on my server network.

Velocity doesn't need a Scoreboard API for that to work though. It has no concept of 'permission groups' or any sort of grouping for that matter. So you would have to depend or a 3rd party to provide that or do it yourself, but a full-blown Scoreboard API is not needed for tablist sorting and formatting.

hexed flickerBOT
#

Seems like our server started to run into this too. Every once in a while velocity has a read timeout. We tried changing the network_compression_threshold to 64 and 128. We also attempted to change the connection-timeout value. Nothing seemed to fix it. Would be great if anyone has found a solution for this error. (We also tried it with no plugins at all besides Velocity and it was still occurring)

hexed flickerBOT
#

So why doesn't TAB show the prefixes or sort players based on their permission group?

Because Scoreboard API hasn't been implemented in velocity, yet. I've just accepted that sorting by perm groups won't be a thing. Prefixes, however, works on my server network.

I have a plugin installed on my proxy that adds support for scoreboards. Player prefixes and sorting shouldn't need the scoreboard API.

hexed flickerBOT
#

Seems like our server started to run into this too. Every once in a while velocity has a read timeout. We tried changing the network_compression_threshold to 64 and 128. We also attempted to change the connection-timeout value. Nothing seemed to fix it. Would be great if anyone has found a solution for this error. (We also tried it with no plugins at all besides Velocity and it was still occurring)

What Java GC engine you use?

#

Seems like our server started to run into this too. Every once in a while velocity has a read timeout. We tried changing the network_compression_threshold to 64 and 128. We also attempted to change the connection-timeout value. Nothing seemed to fix it. Would be great if anyone has found a solution for this error. (We also tried it with no plugins at all besides Velocity and it was still occurring)

What Java GC engine you use?

We're currently using G1GC

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

i try to join and it not works

Actual Behavior

i tried everything and i made everything with a yt tutorial and its not working i also tried to make everything offline and no secuiยดrity but it still not workd annd i need a fast fix then my minecraft server network ist down becaouse of this

Steps to Reproduce

i dont know

Plugin List

noone

Velocity Version

newest snapschot

Additional Information

please fix

hexed flickerBOT
#
[PaperMC/Velocity] New branch created: feat/mc-1.21.11
hexed flickerBOT
hexed flickerBOT
#

Requested Feature

I'd like to see the behavior of DisconnectEvent slightly changed for a more user-friendly (and less surprising) API.

Currently, DisconnectEvent is called when any player connection is closed for any reason at any point in the connection's lifecycle, this includes disconnects triggered by the user early in the login process, disconnects caused by the player already being on the server (with the kick option turned off), and disconnects caused by the pre-login events being cancelled. In all three of these cases, I think it's pointless to fire a DisconnectEvent when the corresponding LoginEvent has not been fired.

Furthermore, it'ss not immediately apparent (and not documented at all, actually) that DisconnectEvent covers so many cases, which means code like this is very common:

@Subscribe
public void onLogin(LoginEvent event) {
    // e.g. create player data and add it to a UUID -> Data map
    initialize(event.getPlayer().getUniqueId());
}

@Subscribe
public```...
hexed flickerBOT
hexed flickerBOT
#

Currently if you have the following command

var command = new BrigadierCommand(
        literalArgumentBuilder("vtestcommand")
                .then(literalArgumentBuilder("child")
                        .then(literalArgumentBuilder("grandchild")
                                .executes(ctx -> {
                                    ctx.getSource().sendMessage(text("grandchild response"));
                                    return 1;
                                })
                        )
                )
);

/root and /root child get forwarded to the backend and handled there, but /root nonexistant gets handled on the proxy. This is because the former cause "UnknownCommand" exception, and the later causes an "UnknownArgument" exception.

The first commit in this PR aligns that behaviour, however this causes breakages in Simple/Raw commands as those assume they get handled on the proxy even if the user doesn't have the requisite permission. Which isn't true...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

1.21.10 version:

io.netty.handler.codec.DecoderException: java.io.IOException: Packet play/clientbound/minecraft:set_border_warning_distance (afy) was larger than I expected, found 11 bytes extra whilst reading packet clientbound/minecraft:set_border_warning_distance
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:500)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.handler.flow.FlowControlHandler.dequeue(FlowControlHandler.java:202)
at io.netty.handler.flow.FlowControlHandler.channelRead(FlowControlHandler.java:164)
at io.netty.channel.AbstractChannelHan...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#
[PaperMC/Velocity] branch deleted: feat/mc-1.21.11
hexed flickerBOT
hexed flickerBOT
#

Requested Feature

Some clients and servers backport the 1.11+ 256 character chat length to 1.8, which had worked behind Velocity until https://github.com/PaperMC/Velocity/commit/371e68607695b48117e1cd57d19c67e40384c33a and https://github.com/PaperMC/Velocity/commit/91bdcebb1aefd7eb21ef88356e4dc88a3f697cb3. Clients sending these long messages now get kicked by the proxy. This could be fixed by either completely removing the condition to enforce only 100 character chat or adding a new config option to do so

Why is this needed?

Backporting increased chat length to 1.8 is well supported. On the client-side this includes Patcher for Forge and Apollo for Lunar Client, and on the server-side this includes Hypixel and forks such as SportPaper.

Alternative Solutions

This limit is imposed by the proxy and can only be changed there

Additional Information

No response

hexed flickerBOT
#

Expected Behavior

According to the JavaDocs comment for the LoginStatus enum:

The status of the connection when the player disconnected.

The result of DisconnectEvent#getLoginStatus() should be identical whether the client disconnects on its own or the backend disconnects the client: SUCCESSFUL_LOGIN

Actual Behavior

  • When disconnecting using the Minecraft client, the result of DisconnectEvent#getLoginStatus() is: SUCCESSFUL_LOGIN
  • When disconnecting using the backend console (Paper), the result of DisconnectEvent#getLoginStatus() is: PRE_SERVER_JOIN

Steps to Reproduce

  1. Listen to the DisconnectEvent event
@Subscribe
public void onDisconnected(DisconnectEvent event) {
    this.logger.info("Current Server: " + event.getPlayer().getCurrentServer());
    this.logger.info("Login Status: " + event.getLoginStatus());
}
  1. Log in to the server and disconnect using the Minecraft client (in-game).
  2. Log in to the server and disconnect the client via the backend with...
hexed flickerBOT
#

I almost feel like a config option for this is somewhat obsolete? Surely if someone doesn't want the feature they just wouldn't put the jars in the update folder?

I may be missing something obvious regarding this though.

I personally think a config option is good and that this functionality should be disabled by default, as plugins might download files into that update folder without user-consent. Sure they could also just download files directly if they are malicious but I'm thinking about cases where someone needs to use an older version for some reason (e.g. compatibility or bugs in a new version) but the plugin tries to always auto-update. (Ideally the config would even allow turning it off on a per-plugin basis)

hexed flickerBOT
hexed flickerBOT
#

This is not working properly. When sending update action during server switch caused by backend server shutdown, player is disconnected with Network Protocol Error. Works fine when switching server using /server.

Partially deobfuscated stack trace:

Description: Packet handling error

java.lang.NullPointerException: Cannot invoke "net.minecraft.client.gui.components.LerpingBossEvent.a(net.minecraft.world.BossEvent$BossBarColor)" because "$$3" is null
	at net.minecraft.client.gui.components.BossHealthOverlay$1.updateStyle(SourceFile:136)
	at net.minecraft.network.protocol.game.ClientboundBossEventPacket$UpdateStyleOperation.dispatch(SourceFile:267)
	at net.minecraft.network.protocol.game.ClientboundBossEventPacket.dispatch(SourceFile:91)
	at net.minecraft.client.gui.components.BossHealthOverlay.update(SourceFile:112)
	at net.minecraft.client.multiplayer.ClientPacketListener.handleBossUpdate(SourceFile:2067)
	at net.minecraft.network.protocol.game.ClientboundBossEventPacket.```...
hexed flickerBOT
hexed flickerBOT
#

This is still not working properly. When sending update action during server switch caused by backend server shutdown, player is disconnected with Network Protocol Error. Works fine when switching server using /server.

Partially deobfuscated stack trace:

Description: Packet handling error

java.lang.NullPointerException: Cannot invoke "net.minecraft.client.gui.components.LerpingBossEvent.a(net.minecraft.world.BossEvent$BossBarColor)" because "$$3" is null
	at net.minecraft.client.gui.components.BossHealthOverlay$1.updateStyle(SourceFile:136)
	at net.minecraft.network.protocol.game.ClientboundBossEventPacket$UpdateStyleOperation.dispatch(SourceFile:267)
	at net.minecraft.network.protocol.game.ClientboundBossEventPacket.dispatch(SourceFile:91)
	at net.minecraft.client.gui.components.BossHealthOverlay.update(SourceFile:112)
	at net.minecraft.client.multiplayer.ClientPacketListener.handleBossUpdate(SourceFile:2067)
	at net.minecraft.network.protocol.game.ClientboundBossEventPacket.handle```...
#

Expected Behavior

I set viaversions all purpur latest plugins.
The Velocity connect 1.21.11 and geyser

Actual Behavior

But below Error displeyed,and not nconnect.

[00:11:33 INFO]: [connected player] Fairy_Nakata (/192.168.11.22:49669) has connected
[00:11:34 INFO]: [server connection] Fairy_Nakata -> server1 has connected
[00:11:36 ERROR]: [server connection] Fairy_Nakata -> server1: exception encountered in com.velocitypowered.proxy.connection.backend.BackendPlaySessionHandler@49ac0fc1
com.velocitypowered.proxy.util.except.QuietRuntimeException: A packet did not decode successfully (invalid data). For more information, launch Velocity with -Dvelocity.packet-decode-logging=true to see more.
[00:11:36 INFO]: [connected player] Fairy_Nakata (/192.168.11.22:49669) has disconnected: server1 ใจใฎๆŽฅ็ถšใซๅ•้กŒใŒ็™บ็”Ÿใ—ใพใ—ใŸใ€‚

Steps to Reproduce

1.prepere purpur 1.21.10(latest)
2,set velocity
3.connect client by 1.21.11

Plugin List

Advanced-Portals-Spigot-2.5.0.jar
FoxCore
FoxGate
Geyse...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

Server should operate normally as excepted even with HAProxy enabled

Actual Behavior

With HAProxy enabled on Pterodactyl panel a server randomlly loops and takes up all the avaliable CPU (with PID limit disabled). If PID limit is enabled it gets hit and server is killed.

It loops with players online or with no players. Looping is random. Sometimes it takes a few days, sometimes just a few minutes.

Steps to Reproduce

Run Velocity server on Pterodactyl server
Enable HAproxy in the .toml configuration file
Wait

Plugin List

AutoUodateGeyser
CleanPing
Custom F3 Brand
FooodGate
ForceResourcePack
Geyser
JPremium
LuckPerms
mdMOTD
plan
SkinsRestorer
Sonar
Tebex
Velocity-hub
Voicechat
VotifierPlus

Velocity Version

[11:14:35 INFO]: Velocity 3.4.0-SNAPSHOT (git-8f65a814-b558)

Additional Information

No response

hexed flickerBOT
#

I found this slight redundancy while backporting modern forwarding to Forge 1.7.10-1.12.2, and have verified that Velocity rejects player connections if the backend server has not implemented the necessary player info forwarding flow (as it would with any modern server that doesn't have modern forwarding configured correctly).

The statement in the comment:

If the proxy is configured for modern forwarding, we must deny connections from 1.12.2 and lower, otherwise IP information will never get forwarded.

No longer seems to be true, considering Velocity's LoginSessionHandler will disconnect the player with the message velocity.error.modern-forwarding-failed if the proxy doesn't receive the velocity:player_info LoginPluginMessagePacket.

The velocity.error.modern-forwarding-needs-new-client disconnect message is also somewhat misleading, as it's on the backend server software to support modern forwarding/have modern forwarding configured correctly.
To elaborate: if you're using...

hexed flickerBOT
#

I mean, this is a weird are as protocol hacks are not something that we support; I'm dubious on the nature of removing a message which makes it fairly trivial to support a somewhat common misconfiguration that people have, protocol hacks don't tend to bump the protocol in a manner that velocity can even see it to attempt using a modern forwarding mechanism.

I am loosely open to not getting in the way of such hacks, but, it should be fairly opt in from servers doing stuff rather than removing the forward presentation which makes it clear why the connection can go on

hexed flickerBOT
#

That's quite fair, I was too deep on the topic and didn't think of things from that angle. I could see how removing that check would make things far more confusing to the average user.

Not at all married to the name, but would a config flag like this suffice?

advanced.modern-forwarding-allow-legacy-connections (defaulting to false)

Additionally, would it be acceptable to add an opt-in config flag that could move LoginPluginMessagePacket and LoginPluginResponsePackets registered version down to 1.7.2 to explicitly allow for back-ported solutions?
For example, something along the lines of:

advanced.modern-forwarding-register-legacy-login-packets (defaulting to false)

hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

For me to be able to connect every time

Actual Behavior

For a few joins in a row i get this error

[03:37:37 INFO]: [connected player] ImFascinated (/9.42.231.13:50645) has disconnected: An internal error occurred in your connection.
[03:37:37 ERROR]: [connected player] ImFascinated (/9.42.231.13:50645): exception encountered in com.velocitypowered.proxy.connection.client.ClientConfigSessionHandler@4d682691
io.netty.handler.codec.CorruptedFrameException: Error decoding class com.velocitypowered.proxy.protocol.packet.ClientSettingsPacket Direction SERVERBOUND Protocol 1.21.11 State CONFIG ID 0x0
        at com.velocitypowered.proxy.protocol.netty.MinecraftDecoder.handleDecodeFailure(MinecraftDecoder.java:130) ~[server.jar:3.4.0-SNAPSHOT (git-8f65a814-b558)]
        at com.velocitypowered.proxy.protocol.netty.MinecraftDecoder.tryDecode(MinecraftDecoder.java:85) ~[server.jar:3.4.0-SNAPSHOT (git-8f65a814-b558)]
        at com.velocitypowered.proxy.protocol.net```...
hexed flickerBOT
hexed flickerBOT
#

Ok.

The issue seems to be coming from "Enable-reuse-port" option. It seems like running pterodactyl with docker and this setting enabled, loops and overloads the CPU no matter that the system is powered by Linux OS. It does happen randomly though with no way to predict it. I narrowed it down that it can happen from anywhere as fast as 15 minutes to up to 24 hours.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

hey devlopers am tired out of this error

[08:09:58 INFO]: [connected player] Gamex_Bunny has disconnected: Your connection was corrupted by the anarchy system.
[08:09:58 ERROR]: [connected player] Gamex_Bunny : exception encountered in com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler@351aaad2
io.netty.handler.codec.EncoderException: java.lang.IllegalArgumentException: Invalid token
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:107) ~[server.jar:3.4.0-SNAPSHOT (git-372a3b28-b561)]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:827) ~[server.jar:3.4.0-SNAPSHOT (git-372a3b28-b561)]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:752) ~[server.jar:3.4.0-SNAPSHOT (git-372a3b28-b561)]
at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:113) ~[server.jar:3.4.0-SNAPSH...

hexed flickerBOT
#

In our plugin, I need to cancel a channel sent by Fabric's Particle API in order to prevent a confliction between Fabric API and our packet transformers. This patch allows me to intercept the register/unregister payloads and remove the channel.

I'm not familiar with the internals, so I wasn't sure where to put this best (as putting it into the registrar directly would probably introduce destructive API changes)

This patch is required for the top header commit on this tree: https://github.com/ViaVersion/ViaVersion/tree/next/fabric-particle-workaround

hexed flickerBOT
hexed flickerBOT
#

Requested Feature

Add a new config option to disable the error message when a connected player cannot connect.

https://github.com/PaperMC/Velocity/blob/372a3b28bd3bbaebf5934b4582dbb2feba70a93e/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java#L718

Why is this needed?

Especially on big servers, the red error messages can spam the console, even when player connection messages are disabled (there is already a setting for logging connection messages)

Alternative Solutions

  • donโ€™t add a new setting and only add the config check for the log-player-connections boolean
  • ignore these messages in console, wich can be very annoying or even confusing

Additional Information

The error is send here: https://github.com/PaperMC/Velocity/blob/372a3b28bd3bbaebf5934b4582dbb2feba70a93e/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java#L718

hexed flickerBOT
hexed flickerBOT
#

It's not handled in the configuration state at all, without my patch Velocity will just cancel/forward the packet to the server. I in general don't get the purpose of the protocol / why it still exists, as it makes things just more complicated and doesn't offer any benefits. Is there any other way I can edit the packet with internals/raw API?

hexed flickerBOT
#

Expected Behavior

No crash when using Java 25

Actual Behavior

Since I updated from Java 21 (amazon-corretto-21.0.5.11.1) to 25 (amazon-corretto-25.0.1.9.1-linux-x64), it seems that Velocity is crashing.
Here are attached the hs_err_pid and replay_pid if those help.

replay_pid3660711.log_

hs_err_pid3660711.log

Steps to Reproduce

I simply left the server open with players joining it.

Plugin List

Plugins: velocity, bungeeadmintools, floodgate, luckperms, mckotlin-velocity, minimotd-velocity, myserverproxy, pinglimiter, plan, signedvelocity, velocityfriends, velocityservertp

Velocity Version

Velocity 3.4.0-SNAPSHOT (git-372a3b28-b561)

Additional Information

Even though I am not an expert, i tried to read the last lines of the replay_pid file and it seems that the last action was a netty one. It is the case in all the previous crashes that I had since switching to Java 25.
As a result, it might be related in some way to https://github.com/PaperMC/Velocity/issu

#

The important part is where it crashes, which is the following part of the hs_err file:

---------------  T H R E A D  ---------------

Current thread (0x00007f878816dcc0):  JavaThread "C2 CompilerThread0" daemon [_thread_in_native, id=3660752, stack(0x00007f875e2e4000,0x00007f875e3e4000) (1024K)]


Current CompileTask:
C2:46721945 21650       4       io.netty.util.internal.ReferenceCountUpdater::retryRelease0 (70 bytes)

Stack: [0x00007f875e2e4000,0x00007f875e3e4000],  sp=0x00007f875e3df680,  free space=1005k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x717eb6]  Compile::final_graph_reshaping_walk(Node_Stack&, Node*, Final_Reshape_Counts&, Unique_Node_List&)+0x336
V  [libjvm.so+0x718d8c]  Compile::final_graph_reshaping()+0x23c
V  [libjvm.so+0x71c659]  Compile::Optimize()+0x999
V  [libjvm.so+0x72087c]  Compile::Compile(ciEnv*, ciMethod*, int, Options, DirectiveSet*)+0xf8c
V  [libjvm.so+0x63c969]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, boo```...
hexed flickerBOT
#

If those where to be handled it would be to fit it into the existing path that is used in play, rather than exposing the ability to cancel this stuff; it's generally an intentional design of velocity that plugins can't intercept arbitary stuff, if you want to intercept a channel you should register it yourself so that the standard event handling works, and then you can deal with controlling if it forwards or not

hexed flickerBOT
hexed flickerBOT
#

Requested Feature

When using Component.translatable(key, fallback), the expected behavior is that if the key is not found in the GlobalTranslator, the fallback string should be displayed. However, in Velocity, it currently displays the empty string instead of the provided fallback string.

The following is the test code.

import com.google.inject.Inject;
import com.velocitypowered.api.command.CommandManager;
import com.velocitypowered.api.command.SimpleCommand;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.proxy.ProxyServer;
import net.kyori.adventure.text.Component;
import org.slf4j.Logger;

@Plugin(
        id = "translatable-component-test",
        name = "TranslatableComponentTest",
        version = "0.0.1"
)
public class TestPlugin {
    @Inject
    private Logger logger;

    @Inject
    private ProxyServer server;

    @Subsc```...
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Requested Feature

add support for 1.7.2 to 1.12.2 modern forwarding with PCF

Why is this needed?

to allow the server to use a more secure modern forwarding from 1.7.2 to 1.12.2

Alternative Solutions

Ive had to compile custom code to allow the client from 1.7.2 to 1.12.2 to be able to use modern forwarding by setting locks of 1.13 to 1.7.2

https://github.com/p0t4t0sandwich/Velocity/tree/feat/modern-forwarding-legacy
edited this with more things changed

Additional Information

No response

hexed flickerBOT
#

Expected Behavior

When using a Fabric backend server behind a Velocity proxy, granting OP permissions
to a player causes the backend connection to fail.

Velocity throws a CorruptedFrameException while decoding the AvailableCommandsPacket.
This happens when the full Brigadier command tree is sent to the client after OP is granted.

The issue does not happen for non-OP players.


Steps to reproduce

  1. Set up a Velocity proxy
  2. Connect a Fabric server (Minecraft 1.21.x) as a backend
  3. Join the server through Velocity as a normal player
  4. Grant OP to the player (/op <player>)
  5. The player is disconnected and Velocity logs a decoding error

io.netty.handler.codec.CorruptedFrameException:
Error decoding class com.velocitypowered.proxy.protocol.packet.AvailableCommandsPacket
Direction CLIENTBOUND Protocol 1.21 State PLAY ID 0x11

Caused by: java.lang.IllegalArgumentException: Argument type identifier 57 unknown.
at com.velocitypowered.proxy.protocol.packet.brigadier.Argumen...

hexed flickerBOT
#

Reset buffer reader index on exception to prevent memory leaks when packet decoding fails.
Without this fix, if an exception is thrown during frame decoding, the buffer's reader index could be left in an inconsistent state, causing the ByteBuf to not be properly released.

This fix is designed to resolve an exploit recently being abused by a malicious actor with the intent of crashing Velocity servers for ransom.

The concerned lines were traced as being the cause of this issue by using Netty's leak detector while Velocity was being actively attacked.

This fix has been in use on Complex Gaming since January 7th with no adverse side effects.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#
[PaperMC/Velocity] New branch created: update-deps
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

On the ternaries, personal preference but that's an easy fix to make down the road. I don't think that should keep you from merging the pull request.
As for the difference in handling mod/description search: If you were to implement that in this code, you'd run the risk of, say, returning the player count from one server and the mod list from another, or returning the player count & mod list from a different server from the one the player is about to join, so unless someone jumps in here and says "hey I need that," I think it's fine the way it is.

#

057b0ef Fixed sending ServerData packets if the descriptio... - 4drian3d
eb7d7c2 Moved pre-1.19.1 command argument validation so it... - p0t4t0sandwich
333128c Generate a new forwarding secret file if the file... - 4drian3d
9942b67 feat: PlayerChannelUnregisterEvent (#1686) - SNWCreations
ef05f3a Fix exception message formatting in command invoca... - szymon-off
9362993 [ci skip] Replaced slf4j javadocs provider with ja... - 4drian3d
1e95491 Minecraft 1.21.11 (#1690) - 4drian3d
e258ea8 bump adventure to 4.26.1 (#1697) - RealBauHD
ad171e5 Restrict empty packet frames from clients - electronicboy...

#

7412aca Fixed sending ServerData packets if the descriptio... - 4drian3d
f75b512 Moved pre-1.19.1 command argument validation so it... - p0t4t0sandwich
b6b6b20 Generate a new forwarding secret file if the file... - 4drian3d
75d6811 feat: PlayerChannelUnregisterEvent (#1686) - SNWCreations
a046f70 Fix exception message formatting in command invoca... - szymon-off
6cc1be7 [ci skip] Replaced slf4j javadocs provider with ja... - 4drian3d
8f65a81 Minecraft 1.21.11 (#1690) - 4drian3d
4bc3f00 bump adventure to 4.26.1 (#1697) - RealBauHD
a03bd88 Restrict empty packet frames from clients - electronicboy...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#
[PaperMC/Velocity] branch deleted: update-deps
#
[PaperMC/Velocity] branch deleted: update/java/21
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

This PR covers the remaining outdated dependencies (and has been tested). It also reimplements the strictness of checkstyle not only in a general sense but also for packet-oriented classes. I simply believe that the packet-driven classes should be subject to checkstyle to ensure any future changes made or added to said classes donโ€™t fall behind in regards to codestyle, as some other classes have represented.

hexed flickerBOT
#

Thanks for bringing this upstream! This won't have any bearing on merging, but just curious if those docs are hand-written or generated ๐Ÿ‘€

Thanks for the comment! Iโ€™d say about 40% of them were generated; however, I spent a good sum of time ensuring they at least made sense but Iโ€™ll make sure to clean everything up when Iโ€™m awake again. Took me a good sum of hours to whip this all up haha. Appreciate the kindness here!

hexed flickerBOT
hexed flickerBOT
#

Pull request overview

This PR updates several core dependencies and tightens style enforcement, while adding extensive Javadoc and minor cleanups across proxy protocol packets and the public API. It also makes packet-oriented classes subject to Checkstyle by removing previous exclusions and documenting their behavior more thoroughly.

Changes:

  • Bump various libraries (Netty, fastutil, JUnit, Checkstyle, toml4j) and update Javadoc configuration to target Java 21.
  • Remove the Checkstyle exclusion for proxy protocol packets and reformat/annotate many packet, chat, and brigadier-related classes to satisfy stricter style rules.
  • Add and refine Javadoc for many API types (events, networking, player/server info, plugin metadata) to better document behavior and extension points.

Reviewed changes

Copilot reviewed 183 out of 185 changed files in this pull request and generated 4 comments.

Show a summary per file:
||| File | Description |
| ---- | ----------- |
| proxy/src/main/r...

#

In encode, the body that writes the sound source, entity id, volume, pitch, and seed is currently inside the if (fixedRange != null) block. This means that when fixedRange is null, the packet only writes the boolean flag and omits all the required fields, producing an invalid packet on the wire. To fix this, only the buf.writeFloat(fixedRange) call should be conditional, while the remaining writes (writeSoundSource, entity id, volume, pitch, seed) should execute regardless of whether fixedRange is present.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Implement adventure's SkinSource for Player and GameProfile to allow passing instances to ObjectContents.playerHead(SkinSource).

The GameProfile implementation creates a "static" player head if the profile has any properties. Otherwise, it creates a "dynamic" player head using the profile's UUID.

The Player implementation uses its current game profile and, if the player already sent its settings, includes whether the hat should be shown.

hexed flickerBOT
hexed flickerBOT
#

Requested Feature

i run in following issue, the proxie server don't recognize the deactivatet online mode from cardboard log:

io.netty.channel.ConnectTimeoutException: connection timed out after 5000 ms: /127.0.0.1:25566
at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe$1.run(AbstractEpollChannel.java:664) ~[velocity-3.5.0-SNAPSHOT-573.jar:3.5.0-SNAPSHOT (git-14160e19-b573)]
at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98) ~[velocity-3.5.0-SNAPSHOT-573.jar:3.5.0-SNAPSHOT (git-14160e19-b573)]
at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:160) ~[velocity-3.5.0-SNAPSHOT-573.jar:3.5.0-SNAPSHOT (git-14160e19-b573)]
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:148) ~[velocity-3.5.0-SNAPSHOT-573.jar:3.5.0-SNAPSHOT (git-14160e19-b573)]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:141) ~[velocity-3.5.0-SNAPSHOT-573.jar:3.5.0-SNAPSHOT...

hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

I expect the server to be able to send the client back to configuration and bring them back to play without issue.

Actual Behavior

The server recieves an invalid packet and disconnects the client.

Error message from an unmodified vanilla server

[13:50:31] [Server thread/INFO]: notmattw (9f36238e-bee0-3e4e-9404-44efe6986143) lost connection: Internal Exception: io.netty.handler.codec.DecoderException: Received unknown packet id 12

Also error message from a Minestom server

java.lang.IllegalStateException: Packet id 0x1d isn't registered!
	at net.minestom.server.network.packet.PacketRegistry$PacketRegistryTemplate.packetInfo(PacketRegistry.java:482)
	at net.minestom.server.network.packet.PacketReading.readPayload(PacketReading.java:210)
	at net.minestom.server.network.packet.PacketReading.readFramedPacket(PacketReading.java:187)

Steps to Reproduce

Start velocity pointing at a vanilla server with debug commands enabled, eg

java -DMC_DEBUG_ENABLED -D```...
hexed flickerBOT
hexed flickerBOT
#

For your interest, our fix for this was https://github.com/hollow-cube/Velocity/commit/11f99c5517c061f962502f852cd2d322a21d39cc

I found that, for our use case, it fully worked without the packet queue, but I thought making sure it queues packets on first run was more like the expected behaviour for this functionality. I can PR this upstream if this is a reasonable change, though it probably needs some more testing with some plugins and a vanilla server.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#
[PaperMC/Velocity] New branch created: l10n_dev/3.0.0
#
[PaperMC/Velocity] branch deleted: l10n_dev/3.0.0
hexed flickerBOT
#

Requested Feature

Add support for proxy_protocol to the speed configuration so that frp can obtain the real IP address.

Why is this needed?

This enables servers utilizing frp to retrieve the players' real IP addresses.

Alternative Solutions

NO

Additional Information

No response

#

ๅ› ไธบ็ฟป่ฏ‘็š„ๅŽŸๅ› ๏ผŒๆˆ‘ไธๅคชๆ˜Ž็™ฝโ€œfrpโ€ๆ˜ฏไป€ไนˆๆ„ๆ€๏ผŒไฝ†Velocityๅทฒ็ปๆœ‰haproxy-protocol้€‰้กนไบ†๏ผŒไฝ ๆ˜ฏ่ฟ™ไธชๆ„ๆ€ๅ—๏ผŸ

frp, which stands for Fast Reverse Proxy, is a technology used to expose public ports for devices without a public IP address.
URL: https://github.com/fatedier/frp/
I hope frp can natively support Paper's proxy_protocol, just like BungeeCord does.

hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

When a player logs in that is already logged in, the orginal connection should be disconnected correctly before connecting the player to the server again.

Actual Behavior

In rare cases with the duplicate_login event, if you time it correctly a second duplicate_login event is received from the server itself at the same time. This causes the original connection to be disconnected from the server but not from Velocity, and it's only 10-12 seconds later when the original connection times out in Velocity that the disconnect event is finally fired which then causes unexpected behavior with any plugin that does not expect this.

Steps to Reproduce

Players with high latency connections or otherwise poor connections have been the most impacted by this, as they're more likely to be disconnected and then try to reconnect before their previous connection has timed out.

I've been simulating that using a VPN to interrupt the client's connection to the server, disconn...

hexed flickerBOT
hexed flickerBOT
#

From my understanding, queue plugins have no way of knowing if a player got kicked from the backend. If this config option is turned on, plugins can still stop the proxy from disconnecting the player (and instead redirecting them) since such plugins already exist (KickRedirect). I'm just suggesting this because while redirect behavior plugins exist, there is no existing solution to disable the velocity redirect behavior for ALL kicks.

I think you can try to do something like this.

@Subscribe
    fun onPlayerKicked(event: KickedFromServerEvent) {
        val player = event.player
        val kickedFrom = event.server
        val current = player.currentServer.orElse(null)?.server
        if(current == null || current == kickedFrom) {
            val reason = event.serverKickReason.orElse(Component.text("ะžั‚ะบะปัŽั‡ะตะฝะธะต ะพั‚ ัะตั€ะฒะตั€ะฐ"))
            event.result = KickedFromServerEvent.DisconnectPlayer.create(reason)
        }
    }
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Description

This PR introduces a robust Server Health Checking system and an advanced IP Filtering framework (Maintenance, Blacklist, Whitelist) to Velocity. It also adds several administrative commands to manage these systems in real-time.

Key Features

1. Server Health Checker

  • Periodic Pings: Automatically monitors backend servers at a configurable interval.
  • Health States: Servers are categorized as HEALTHY, DEGRADED (high latency), or UNHEALTHY (timeout/offline).
  • Events: Fires a ServerHealthChangeEvent whenever a server's status changes, allowing plugins to react (e.g., for smart load balancing).
  • Configuration: Preserves defaults with a new [health-check] section in velocity.toml.

2. Advanced IP Filter Manager

  • Dynamic Blacklisting: Support for individual IPs and CIDR ranges with optional reasons and durations (temporary bans).
  • Whitelisting: Allows specific IPs/ranges to bypass maintenance mode.
  • Maintenance Mode: A global toggle to rest...
hexed flickerBOT
#

Adds an option for subdomain-matching to [forced-hosts] that falls back to suffix matching on domain boundaries when no exact match is found. This allows forced hosts to work when DNS services (e.g., Cloudflare proxied SRV records) prepend prefixes to the virtual hostname.

The problem is that Velocity does exact string matching on the virtual host for forced-hosts, so _dc-srv.xxxxx.play.example.com doesn't match play.example.com and forced host routing breaks.

This is a "rework" of this rejected PR: https://github.com/PaperMC/Velocity/pull/1497

I'd like to clear up that the use-case for this feature isn't "hiding a misconfiguration". When you proxy an SRV target's A record through Cloudflare, Cloudflare auto-unproxies it by rewriting the hostname to something like _dc-srv.xxxxx.play.example.com. This was intentional on my part since it causes casual DNS lookups on play.example.com return Cloudflare IPs, and the origin is only exposed if someone specifically queries the Minecra...

hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

Players should not be kicked at all

Actual Behavior

Players are kicked after a minutes of being on the Code of Conduct screen

Steps to Reproduce

  1. Enable Code of conduct on the first connect to server set in Velocity
  2. Join server
  3. Wait on Code of conduct screen for a minute
  4. Get click with Unable to connect you to server message

Plugin List

velocity, autoupdateplugins, floodgate, geyser, voicechat

Velocity Version

Velocity 3.5.0-SNAPSHOT (git-c2fd3c07-b576)

Additional Information

No response

hexed flickerBOT
#

Expected Behavior

Permission velocity.command.* set to false would no longer auto complete any of velocity's commands including the /velocity:callback command to the concerned players.

Actual Behavior

The /server command is fully hidden but /velocity:callback still auto complete in the chat.

Steps to Reproduce

Use a permission manager plugin such as LuckPerms and set the velocity.command.* to false for the default group.
Verify you are part of that group and not an Operator on the server (I've disabled default Operator system in LuckPerms config too).
Start typing /velocity:callback and see it auto complete.

Plugin List

LuckPerms

Velocity Version

Velocity 3.5.0-SNAPSHOT (git-c2fd3c07-b576)

Additional Information

Haven't checked much yet about what this command actualy do but since its only available with velocity: namespace it might be an internal command since its not available with just /callback

hexed flickerBOT
#

VelocityไธญJoinGamePacket.javaๅฏนไบŽ1.7.10็ปดๅบฆID็š„ไผ ้€’ๅชไฝฟ็”จ1ๅญ—่Š‚๏ผŒ่ฟ™ๅฏผ่‡ด้ƒจๅˆ†ๆจก็ป„็ปดๅบฆ็š„็ปดๅบฆIDไผ ้€’่ฟ‡็จ‹ไธญๅ‘็”Ÿๆ•ฐๆฎๆˆชๆ–ญ๏ผŒไผ ้€’ไบ†้žๆณ•ๆ•ฐๆฎ็ป™ๅฎขๆˆท็ซฏ๏ผŒๅฏผ่‡ดๅฎขๆˆท็ซฏๅดฉๆบƒใ€‚ไฝฟ็”จ4ๅญ—่Š‚ๅค„็†็ปดๅบฆIDๅฏไปฅ่งฃๅ†ณ่ฏฅ้—ฎ้ข˜ใ€‚ๆˆ‘ไฝฟ็”จไบ†Claudeๆฅๅˆ†ๆžๅ’Œไฟฎๆ”น๏ผˆๅ› ไธบๆˆ‘ไธไผš็ผ–็จ‹๏ผ‰๏ผŒๅ›พ็‰‡ไธบClaudeไฟฎๆ”นๅฎŒๆˆ็š„ๆ€ป็ป“ใ€‚

ๆˆ‘ๆ˜ฏๅœจๆธธ็ŽฉGTNH 2.8.0ๆ•ดๅˆๅŒ…ๆ—ถๅ‘็Žฐ็š„ๆญค้—ฎ้ข˜๏ผŒๅฝ“ๆ—ถๆˆ‘็š„ๆœๅŠกๅ™จไฝฟ็”จVelocity่ฝฌๅ‘๏ผŒ้€š่ฟ‡Velocityๅฎž็Žฐ็Žฉๅฎถ็™ปๅฝ•้ชŒ่ฏ๏ผŒๆˆ‘ๅœจๆธธ็Žฉ้€”ไธญๅ‘็Žฐๅœจ็งไบบ็ปดๅบฆ๏ผˆ็ปดๅบฆIDไธบ180๏ผ‰ไธญไธ‹็บฟๅ†ๅŠ ๅ…ฅๅฎขๆˆท็ซฏไผšๅดฉๆบƒ๏ผŒ่€Œ่ทณ่ฟ‡Velocity่ฝฌๅ‘ๅˆ™ไธไผš๏ผŒๆŠฅ้”™ๆ—ฅๅฟ—ๆ็คบ้žๆณ•็ปดๅบฆID-76ใ€‚


In Velocity, the JoinGamePacket.java uses only 1 byte to transmit the dimension ID for 1.7.10. This causes data truncation during the transmission of dimension IDs for some modded dimensions, sending illegal data to the client and causing the client to crash. Using 4 bytes to handle the dimension ID can resolve this issue. I used Claude to analyze and modify the code (since I don't know how to program), and the image shows the summary of the modifications completed by Claude.

I discovered this issue while playing the GTNH 2.8.0 modpack. At the time, my server used Velocity for forwarding and implemented player login authentication through Velocity. During gameplay, I found that log...

hexed flickerBOT
hexed flickerBOT
#

However, this logic seems to do functionally nothing as dimension is only ever written back to a ByteBuf using ByteBuf#writeByte, which will turn this (now signed) byte into an unsigned byte anyway.
See line 401 of this file https://github.com/xphorror/Velocity/blob/c7b83326182ed24c2edb462de04364f81ada5b0b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java#L401

Unless somehow the packet is read as a pre-1.9.1 packet and written as a post-1.9.1 packet? If this is the case please ignore this comment. Though that seems unlikely.

Are you sure this change solves your problem?

hexed flickerBOT
#

However, this logic seems to do functionally nothing as dimension is only ever written back to a ByteBuf using ByteBuf#writeByte, which will turn this (now signed) byte into an unsigned byte anyway.
See line 401 of this file https://github.com/xphorror/Velocity/blob/c7b83326182ed24c2edb462de04364f81ada5b0b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java#L401

Unless somehow the packet is read as a pre-1.9.1 packet and written as a post-1.9.1 packet? If this is the case please ignore this comment. Though that seems unlikely.

Are you sure this change solves your problem?


Yes,the problem fixed.Maybe I can record a video upload to youtube later.

hexed flickerBOT
#

The valuePattern indicates optional components with brackets "[port]:[forwardingmode]", but the conversion logic at line 109 splits on ":" with a limit of 4, expecting exactly 4 parts for the full format. The description says "Use <name>:<host>:[port]:[forwardingmode]" which suggests port and forwardingmode are optional, but the actual parsing logic requires that if you want to specify forwardingmode, you must include all 4 parts (name, host, port, forwardingmode). The pattern and error message should clarify this or the parsing should be made more flexible to handle name:host:forwardingmode without requiring the port.

#

The method has a potential NullPointerException at line 101. If serverInfo.getServerInfoForwardingMode() returns null (line 100 check), then server.getConfiguration() is called. However, the server field is annotated with @Nullable and could be null. When VelocityRegisteredServer is constructed with a null server (which is allowed by the constructor), calling getConfiguration() on it will throw a NullPointerException. Consider adding a null check for server or documenting that this method requires a non-null server to function properly.

      VelocityServer velocityServer = requireNonNull(server, "server");
      return velocityServer.getConfiguration().getPlayerInfoForwardingMode();
#

The change to include forwardingMode in equals() and hashCode() is a breaking change in the API. Previously, two ServerInfo objects with the same name and address but different (or null vs non-null) forwardingMode would be considered equal. Now they won't be. This could break existing code that relies on ServerInfo equality for lookups, comparisons, or use in collections. While this change makes logical sense for the new feature, it should be clearly documented as a breaking change or reconsidered to maintain backward compatibility. Consider whether forwardingMode should be part of the identity of a ServerInfo object or just a configuration detail.

#

The error message says "You don't have a forwarding secret set. This is required if you are using MODERN or BUNGEEGUARD forwarding modes." but it doesn't specify which server has the problematic configuration. Consider including the server name (entry.getKey()) in the error message to help administrators identify which specific server needs attention. For example: "Server 'servername' uses MODERN/BUNGEEGUARD forwarding mode but you don't have a forwarding secret set."

          logger.error("Server '{}' uses MODERN or BUNGEEGUARD forwarding mode but you "
                  + "don't have a forwarding secret set. This is required for security.",
              entry.getKey());
#

The example values in the default configuration show forwarding modes that may not align with a typical setup. Setting "factions" to MODERN and "minigames" to LEGACY seems arbitrary. Consider either using all three servers with null/INHERIT mode (demonstrating the default behavior), or adding comments to explain why different modes are shown. This will help users understand when and why they should set per-server forwarding modes rather than just copying these examples.

#

The comment on lines 78-79 doesn't explain the new per-server forwarding mode feature. Users seeing the new syntax for the first time won't understand what "forwarding-mode" means or when they should use it. Consider expanding the comment to briefly mention both syntaxes and that forwarding-mode is optional, with a reference to the documentation or a note that null/omitted values inherit from the global player-info-forwarding-mode setting.

# Configure your servers here. Each key represents the server's name.
# You can use the short form, where the value is the IP address and port to connect to:
#   lobby = "127.0.0.1:30066"
# or the object form:
#   factions = { address = "127.0.0.1:30067", forwarding-mode = "MODERN" }
# In the object form, address is the IP/port and forwarding-mode is optional; if it is
# omitted or set to null, the server inherits the global player-info-forwarding-mode
# setting defined above. See the Velocity documentation for more details.
#

Pull request overview

This PR introduces per-server player info forwarding mode configuration, allowing each backend server to use a different forwarding mode (MODERN, LEGACY, BUNGEEGUARD, or NONE) instead of inheriting the global proxy-wide setting. This enables mixed-version networks where some servers (e.g., 1.12) require LEGACY forwarding while others (e.g., Fabric 1.21) require MODERN forwarding.

Changes:

  • Added new ServerInfoForwardingMode enum and BackendServerConfig record to the API for per-server configuration
  • Extended configuration syntax to support both classic string format (server = "address:port") and new object format (server = {address = "...", forwarding-mode = "..."})
  • Modified ServerInfo to include an optional forwarding mode field, with corresponding updates to equals/hashCode/toString methods

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.

Show a summary per file:
||| File | Description |...

hexed flickerBOT
hexed flickerBOT
#

The goal of this PR was to make progress on a plugin update folder for Velocity.

Tasks:

  • [x] Initial implementation
  • [ ] Discuss nullability annotation for VelocityConfiguration#getUpdateFolderName
  • [ ] Discuss default config value
  • [ ] Discuss what the config value should be to entirely disable the update folder
  • [ ] Test implementation

closes https://github.com/PaperMC/Velocity/issues/809
based on https://github.com/PaperMC/Velocity/pull/842

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

I also noticed that in most places in the config object it seems like the nullable annotation is not used so I'll remove it unless suggested otherwise for VelocityConfiguration#getUpdateFolderName

technically the name is not nullable, as it is an empty string (and should be checked against being empty, not null) in the update-folder = "" syntax, so marking it as @Nullable would be wrong.

hexed flickerBOT
#

technically the name is not nullable, as it is an empty string (and should be checked against being empty, not null) in the update-folder = "" syntax, so marking it as @Nullable would be wrong.
That's true, currently it was requiring being set to null to disable it, I'll make these changes now. I am also going to opt for .update as default for now as that is my personal preference and what I think makes most sense.

hexed flickerBOT
#

Expected Behavior

Players connect to server through Velocity successfully.

Actual Behavior

Players can't connect to server with following errors in Velocity:

[16:24:56] [Netty epoll Worker #3/ERROR] [com.velocitypowered.proxy.connection.MinecraftConnection]: [server connection] Player-> server: exception encountered in com.velocitypowered.proxy.connection.backend.BackendPlaySessionHandler@2661ba29
io.netty.handler.codec.CorruptedFrameException: Error decoding class com.velocitypowered.proxy.protocol.packet.AvailableCommandsPacket Direction CLIENTBOUND Protocol 1.20 State PLAY ID 0x10
	at com.velocitypowered.proxy.protocol.netty.MinecraftDecoder.handleDecodeFailure(MinecraftDecoder.java:130)
	at com.velocitypowered.proxy.protocol.netty.MinecraftDecoder.tryDecode(MinecraftDecoder.java:85)
	at com.velocitypowered.proxy.protocol.netty.MinecraftDecoder.channelRead(MinecraftDecoder.java:60)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHand```...
hexed flickerBOT
#

This PR introduces PermissionFunction#getPermissionMap, and delegates like [Connected]Player#getPermissionMap.

I would like to see this be a feature of Velocity, because I'm currently trying to optimize a bit of code that uses the Velocity permission API:

private int getTimeoutInSeconds(Player player) {
  for (int i = 86400; i > 0; i--) {
    if (player.hasPermission("velocity.queue.timeout." + i)) {
      return i;
    }
  }
  return -1;
}

Of course having up to 86.400 permission checks is not good, even if it's just a one-off, and especially because we don't know how the permission provider implements this (each call might reach out to a redis/SQL db).

Unfortunately because lots of servers are already relying on being able to specify a permission like this, it's not trivial for me to fix this issue by reducing the amount of permission checks. Ideally I'd like to see Velocity and permission providers like LuckPerms expose the permission map, as I'm sure I'm no...

hexed flickerBOT
hexed flickerBOT
#

this is just abuse of permissions

I assume you're referring to the hasPermission call in a giant for loop, if so, I agree so this needs to be fixed.

It would be good to see what permission plugin devs have to say, but we can also look at the bukkit api which already contains a similar feature with PermissibleBase#getEffectivePermissions.

BungeeCord has CommandSender#getPermissions.

I'm not too familiar with fabric, and if this is a feature fabric explicitly supports or not, but LuckPerms also exposes similar functionality in their fabric implementation here. So I think there's president for permission plugins (at least LuckPerms) wanting/trying to expose this information....

#

using permissions themselves to define what is essentially a KV is the abuse

I know that several other implementations of permissions expose such a feature, and that is why plugins like LP generally have some means of trying to populate a list of those values to appease the fact that they're often hijacking an existing implementation; I want to see what plugin devs have to say moreso on the ABI rather than the existence of such a thing, I would ideally rather have some 3rd party vault replacement which can offer abstractions for what really should be the proper solution here, however

#

using permissions themselves to define what is essentially a KV is the abuse

I see. I've read through the LuckPerms docs, and it looks like for this usecase their meta system would be a perfect fit.

int timeout = user.getCachedData()
    .getMetaData(qo)
    .getMetaValue("queue.timeout", Integer::parseInt)
    .orElse(0);

Would be set with a command like
/lp user <name> meta set queue.timeout 120

I guess it would be out of the question to provide this functionality through a Velocity-native API. Something like what Vault accomplished would probably be the ideal solution here.

Though, that's for my specific use-case. I think it's still worth while to see if we can merge a feature similar to what I'm proposing here, exposing the permission map.

hexed flickerBOT
hexed flickerBOT
#

@4drian3d do you mind elaborating on your decision? Does anyone else still have a say in this? Another maintainer talked about getting the view of permission plugin maintainers, I've pinged the head maintainer of the largest permission plugin and we haven't even heard back yet.

It seems to me that what you want to do is add an API to Velocity so that you can use a LuckPerms feature without relying directly on LuckPerms. But you have to keep in mind that not everyone uses LuckPerms (even though it is one of the best and most popular permission plugins), and that there may be other permission plugins that do not necessarily use a simple key-value system for their permissions, but may declare other types of conditions to represent them.
Also, you are giving examples of platforms that are not known for having such good API infrastructure, placing many limitations on what developers can create.
For your specific use, it is best to create an abstraction in your project that can optimi...

hexed flickerBOT
#

My thoughts (for what they're worth):

  • Using permissions to represent a KV pair is not great, most permissions plugins have "metadata" or "options" concepts that are designed for this sort of data (in LP for example /lp user lucko meta set queue.timeout 100)
  • Meta/options probably do not belong in the Velocity PermissionFunction API, but not my call to make (obviously)
  • Exposing a Map<String, Boolean> goes against the original aims of Velocity's permissions API (https://github.com/PaperMC/Velocity/pull/41), which was to make as few assumptions as possible about how permission checks might be performed/evaluated by the implementation. The thinking was that this would allow permission plugins be creative and do useful things like wildcards, regex permissions, shorthand/glob syntax, etc without breaking any API contracts. That was my view ~8 years ago and it hasn't changed. ๐Ÿ˜› I took the same approach with fabric-permissions-api.
hexed flickerBOT
#

Thank you lucko, loud and clear.

Obviously introducing meta getters in the Velocity permission API is not a good idea. But I'm wondering how the Velocity team looks at exposing a separate, generic, meta api for players with a generic MetaHolder?

One of Velocity's strengths I think is that its stateless, at least between reboots. But obviously there's the need to keep some kind of state, hence the permission API. It might not be that far of a fetch to also include a meta system here? Again, leaving it up to plugins like LP to implement this.

hexed flickerBOT
#

I mean, the permission API inside of Velocity is pretty minimal, we didn't really want to impose any API decisions onto plugin devs and figured either everybody would just back something like LP or the community would re-vault; there was just a minimal acceptance of velocity itself needing to do permission lookups for the few builtins we provided, as well as plugins are going to need to do permission lookups too.

All of the methods you linked to from other systems having such methods aren't raw permission APIs by the platform, they're APIs for the platforms implementation of a permission system, and so LP has to implement that stuff as the platforms implementation dictated it; if any API expansion to velocities permission stuff came, it would need to be spearheaded by permission plugin devs for a reason (hence why I said that this really needs to be checked and back by permission plugin devs)

Velocity not dictating this kinda stuff, and being stateless in general, is part of our...

hexed flickerBOT
#

as well as basically being highly restricted in the type of information they return, which is generally just not API I really want to design

That would not necessarily have to be the case of course. Look at Paper's PersistentDataContainer, they solved it quite well by providing some primitive data types, whilst allowing plugin devs to map any type they'd like onto a String/int/long (array) which means basically everything can fit in there. And that's while Paper also had to solve the issue of storing this data. Velocity doesn't have this; it'd just need to pass custom types along to the underlying plugin so they can deal with it. But that's another question. Do we want to force plugin devs to have to worry about any generic type, or should we just limit it to the Java primitives.

I still think it's worth it to explore something like a MetaHolder API interface for Velocity. However as that's entirely different than what this PR is proposing I'm closing the PR for now.

hexed flickerBOT
#

I think Velocity's update folder should mirror the Paper update folder's name (update without a dot prefix).
Also why does this need config option? I don't see why the average admin would need to change this and for advanced setups a system property is better suited IMO.
I also don't get why we would create the update folder by default or why you don't utilize Java's Files class and instead use #toFile.

hexed flickerBOT
#

I think Velocity's update folder should mirror the Paper update folder's name (update without a dot prefix).

The dot prefix acts as a way of keeping the folder at the top of the directory list and separates it from being mixed in with the plugin folders. I personally think it makes the update folder much more accessible and easy to use, which is why I set it as the default. I would go as far to say that Paper could also benefit from changing the default to include the prefix.

Also why does this need config option? I don't see why the average admin would need to change this and for advanced setups a system property is better suited IMO.

I personally think a config option is nice to have for people who prefer different formats or languages. It could use a system properpty but I don't really think this being a config option has any drawbacks

I also don't get why we would create the update folder by default or why you don't utilize Java's Files class and instead use #toFile.

I...

hexed flickerBOT
#

The dot prefix acts as a way of keeping the folder at the top of the directory list and separates it from being mixed in with the plugin folders. I personally think it makes the update folder much more accessible and easy to use, which is why I set it as the default. I would go as far to say that Paper could also benefit from changing the default to include the prefix.

That makes sense, thank you for explaining.

I personally think a config option is nice to have for people who prefer different formats or languages. It could use a system properpty but I don't really think this being a config option has any drawbacks

I don't get how different languages/formats matter here. For the average admin it is that folder and the folder being standardized also simplifies debugging for other people.

I am happy to change this if needed

Ofc it is not needed, IMO it's better to use the NOI though, as that is the more modern and cleaner solution.

hexed flickerBOT
#

I don't get how different languages/formats matter here. For the average admin it is that folder and the folder being standardized also simplifies debugging for other people.

That's fair and very true. I guess it's almost like if Paper added a config option for .paper-remapped which would be unnecessary. With system properties the option would still be there. Would we stick to a single velocity.update-folder-name where an empty string disables the update folder or do you think a second velocity.disable-update-folder would be suitable?

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Well IMO we don't need to disable the update folder if we just don't auto create it, no?

I based the need to disable off of discussion in the other pr regarding this topic

Well then I think we might want a config section to disable it for individual plugins, but it also more seems like something for plugin authors to handle. If they are truly malicious they can do anything and if not then users should either raise an issue or search for an alternative. Also this should only become an issue after this feature is introduced, no?

hexed flickerBOT
#

Well then I think we might want a config section to disable it for individual plugins, but it also more seems like something for plugin authors to handle. If they are truly malicious they can do anything and if not then users should either raise an issue or search for an alternative. Also this should only become an issue after this feature is introduced, no?

In that case, I think sticking to just an empty string to disable is probably suitable enough as it doesn't require any extra options.

hexed flickerBOT
hexed flickerBOT
#

Should probably do a config migration to disable the update folder for older setups as there's the chance that some systems/forks implemented their own version which could break

How would we approach that for the system property route?

Although, any forks should be aware of what they are merging so I would personally say responsibility falls on them to make sure they aren't merging duplicate features/incompatibilities.

hexed flickerBOT
#

For anyone else that runs in to this and wants to work around the problem, lowering the velocity timeout to 18 seconds means that Velocity will always forcibly timeout and disconnect the orphaned connection prior to the very narrow window in the 19-20 seconds range where it's possible to trigger the out of sequence / misfiring duplicate_player login events issue.

hexed flickerBOT
#

Expected Behavior

This method should'nt be called.

Actual Behavior

This method does get called, possibly resulting in undesired VelocityBossBarImplementation#viewerDisconnected calls.
For reference, the entire ConnectedPlayer#disconnected method:

public void disconnected() {
  for (final VelocityBossBarImplementation bar : this.bossBars) {
    bar.viewerDisconnected(this);
  }
}

Steps to Reproduce

Add a printline/log statement in ConnectedPlayer#disconnected, join the proxy with minecraft account A, try to re-join the proxy with the same account.
The second connection will fail, and ConnectedPlayer#disconnected still gets called.

Plugin List

n/a

Velocity Version

Compiled from latest commit e0db25664fc82eabd9fde5aac22a2311a9765975 + the log statement in disconnected().

Additional Information

This currently isn't an issue, as bossbars won't be registered to the ConnectedPlayer. However if more logic ever gets added to this method this might be an...

hexed flickerBOT
#

Expected Behavior

Players should be able to switch servers without timing out

Actual Behavior

Sometimes players are randomly stuck inbetween the PlayerEnterConfigurationEvent and PlayerEnteredConfigurationEvent when switching between servers.

They do enter the "Reconfiguring"-phase clientwise, but Velocity seems to never actually put them into the reconfig phase, leading to them timing out. See below for what I tried for debugging.

Steps to Reproduce

This happens randomly for some (but not all) players, both vanilla users and people with mods. It doesn't happen everytime, just rarely.

For debugging, I have listened on Velocity to all the config events, and the PlayerEnterConfigurationEvent is fired. I then dug into client's NMS and added logging there too (primarily in (mojang mapped) ClientPacketListener#handleLogin and ClientPacketListener#handleConfigurationStart):

Client log when the timeout happened: https://mclo.gs/kU6CX7m
Proxy log when the timeout happened:...

hexed flickerBOT
#

We are experiencing the same issue on our network and can confirm the behavior described here.

Setup
Velocity 3.4.0
Backend servers: PaperMC 1.21.7
Minecraft client versions: mostly 1.21.7-1.21.10
Proxy network with multiple backend servers (lobby, gameplay servers)
Resource pack handled via server plugins (e.g. ItemsAdder)

Observed behavior
Players sometimes get stuck in the "Reconfiguring..." phase when switching between servers through the proxy. From the client perspective they clearly enter the configuration phase, but they never actually complete it and eventually time out.

More details:

  • This happens randomly and not for every player
  • Both vanilla clients and modded clients (e.g. LabyMod) are affected
  • For us it only happens during server switches, never during normal gameplay
  • Players can switch servers many times successfully and then suddenly hit this issue on the next switch
  • Other players may switch servers at the same time without any problem
  • When this happens, t...
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

(I'm not a team member too.) I was also experimenting with implementing a per-server forwarding configuration and came across this PR.

I noticed that there are still 3 calls to getPlayerInfoForwardingMode() which assume the forwarding mode is a global setting:

These calls are no longer valid after introducing per-server configuration and should instead use getConfiguredPlayerInfoForwarding(). (It might also require changes to MinecraftConnection,...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

as mentioned, there is already an issue open for this, issue si that I cannot reproduce it, generally need packet flow information from the proxy on what is being sent between the proxy and the server, and the proxy and the client; all I can guess at this point is that some communication is getting stuck somewhere, but it's hard to know where; knowing that some events do fire and some don't kinda helps, need to get back in tune with the logical flow here, however

hexed flickerBOT
#

as mentioned, there is already an issue open for this, issue si that I cannot reproduce it, generally need packet flow information from the proxy on what is being sent between the proxy and the server, and the proxy and the client; all I can guess at this point is that some communication is getting stuck somewhere, but it's hard to know where; knowing that some events do fire and some don't kinda helps, need to get back in tune with the logical flow here, however

Is there any setting we could enable to h elp with debugging? I have of course already tried to log packets but obviously it resulted in a gigabyte of "PlayerMovement" and "Particle" packets etc lol

hexed flickerBOT
#

There are no settings for diagnosing this. That's part of the headache, is that the only real thing that would be helpful at this point is packet logs to be able to validate what is/isn't being sent, PlayerEnteredConfigurationEvent is odd, because that is fired somewhat directly in response to the client sending a configuration_acknowledged packet

general flow here is that the target server sends the login success, we then start the jump over,

clear server state > PlayerEnterConfigurationEvent > send start_configuration; At this point the client should send us back a configuration_acknowledged which should trigger a few things, almost immediately, PlayerEnteredConfigurationEvent; what is the players active session handler at the point that the connection dies?

hexed flickerBOT
#

Expected Behavior

Proxies of a large network I'm working for were constantly being restarted due to OOM kills. I highly suspect this is due to a malicious decompression attack.

I had added the following logs in MinecraftCompressDecoder#decode:

if (claimedUncompressedSize > UNCOMPRESSED_CAP * 0.95) {
  LOGGER.warn("Received a packet with a large uncompressed size: {} bytes ({}% of the {} byte cap) from {}",
      claimedUncompressedSize,
      (int) (claimedUncompressedSize * 100.0 / UNCOMPRESSED_CAP),
      UNCOMPRESSED_CAP,
      ctx.channel().remoteAddress());
}

When we were under attack we got spammed by the following logs:

[17:36:45 WARN]: Received a packet with a large uncompressed size: 8380416 bytes (99% of the 8388608 byte cap) from /x.x.x.x:16643

All from the same IP address, all with the same packet size. Moments later the proxy got OOM killed.

When we blacklisted this IP at the firewall level the proxies stayed alive.

I've implemented the following fix on a...

hexed flickerBOT
#

probably some plugin message packets + plugin what process PluginMessageEvent async or abusing loginPluginMessages queue.

or you have compression disabled between proxy <--> backend, so these buffers are stored inside netty's internal write queue. Looks like configuration handlers do not have back pressure handling (writabilityChanged()), what propably should help to mitigate that type of attack.

hexed flickerBOT
hexed flickerBOT
#

velocity.log-server-backpressure already exists and was only checked by BackendPlaySessionHandler and used in BackendPlaySessionHandler#writabilityChanged, now every implementation of writabilityChanged() logs, and this PR adds the missing implementations for C[onfigSessionHandler and ClientConfigSessionHandler.

hexed flickerBOT
#

There are 12 classes that implement MinecraftSessionHandler. Should we implement writabilityChanged() in all 12 of them? Before this PR, only 2 classes implemented this, and after this PR only 4 classes implement the method. Was there any reason for omitting this method in some (most) session handlers?

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

I like the implementation The only issue I see is the folder name, since on some operating systems, putting a . at the beginning of a folder/file name hides it, so I'd prefer to keep a default similar to the one in Paper

Very good point, I hadn't considered that, I've just pushed that one.
Only other thing that I have just thought - could it be worth adding a getUpdateFolderName API method to VelocityServer?

hexed flickerBOT
#

This addresses the proxy side of #1723.

The issue report points at queued play traffic being replayed after the server sends the client back to configuration. On the connected PLAY -> CONFIG path, Velocity was still treating the transition too much like a normal play connection. That left two problems:

  • it could queue serverbound play traffic and replay it after the handoff
  • it could still forward generic/unknown client packets even when the backend was no longer actually in PLAY

these changes do three things:

  • use outbound only queueing for connected PLAY -> CONFIG reconfiguration
  • only forward generic/unknown client packets when the backend is open, phase complete, and actually in PLAY
  • only forward keepalives when client and backend states match, and only in CONFIG or PLAY

It should be noted that while testing this, I found a second bug on the backend side in Paper where the keepalive tracker survives listener handoff from PLAY to CONFIG, which can leave a stale...

#

Hello!
I took a peek into this and it turned out to be two separate problems.

The first one is on the Velocity side, which matches the original suspicion in this issue. On the connected PLAY -> CONFIG path, Velocity was still using full play queueing semantics and was too trusting about forwarding client traffic back to the backend. (serverbound play traffic could be replayed after the handoff, and generic packets could still be forwarded even when the backend was no longer actually in PLAY.)

See #1747- It switches this path to outbound only queueing, keeps generic/unknown forwarding gated on the backend actually being in PLAY, and only forwards keepalives when client and backend states match.

That being said, the patch fixed the proxy side issue, but it did not fully explain the timeout on its own. While testing it, I was able to locate a second bug in Paper- the keepalive tracker is carried across listener handoff from PLAY to CONFIG. Under latency, the configuration listener can...

hexed flickerBOT
#

small followup-
The timeout path ended up being even more specific than I thought from the earlier proxy debug logs:

On the failing repro, the backend sequence was:

  1. the PLAY listener issued keepalive A
  2. listener handoff moved the player into the CONFIG listener, but the old pending keepalive expectation was still carried over
  3. the CONFIG listener issued keepalive B
  4. the backend received reply B
  5. the backend rejected B as stale/out-of-order, because the inherited pending expectation was still A

See PaperMC/Paper#13712 for fixes + explaination.

With that Paper patch applied, I have not been able to reproduce the timeout anymore, including with added latency. Tested with 0ms, 50ms, 100ms, 500ms, 800ms.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

I don't like how a velocity.update-folder-name system property of "" needs to be set in order to disable this feature. That sounds to me like an empty folder name, which is more likely to refer to the "current directory" (whatever this might be, I would assume the plugins/ "root" folder with no prior knowledge), instead of "no directory" / "disable the feature", and would need to be documented elsewhere. Even still, it won't be clear to someone reading startup parameters what this feature does when set to an empty string, and that they should look up the docs.

I think Velocity's update folder should mirror the Paper update folder's name (update without a dot prefix).

See PluginInitializerManager.java#parse

Paper also uses the "update" (no dot) folder, but it gets it from the configuration. If we really want to mirror how Paper does things (which is not a bad thing, I think), we should also get this value from the config. An advantage of this is that we can add a comment expl...

hexed flickerBOT
#

I don't like how a velocity.update-folder-name system property of "" needs to be set in order to disable this feature. That sounds to me like an empty folder name, which is more likely to refer to the "current directory" (whatever this might be, I would assume the plugins/ "root" folder with no prior knowledge), instead of "no directory" / "disable the feature", and would need to be documented elsewhere. Even still, it won't be clear to someone reading startup parameters what this feature does when set to an empty string, and that they should look up the docs.

I think whether a second system property is added or not an empty string would have the same effect on the feature nonetheless. I personally am indifferent on whether a second system property is added or not. If someone wants to disable the feature they are likely to search the docs so will either find the system property and information regarding disabling it.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

I think this can be fixed even better by only ever instantiating ConnectedPlayer after VelocityServer#canRegisterConnection returns true. This avoid ever creating a BossBarManager/ChatQueue/whatever (this is done in ConnectedPlayer's constructor).

VelocityServer#canRegisterConnection currently consumes the ConnectedPlayer, but only ever checks its username and UUID. We can consume a com.velocitypowered.api.proxy.player.PlayerInfo instead, which is effectively a record of String username, UUID uuid, or just consume the username/UUID to perform the check.

hexed flickerBOT
#

I think this can be fixed even better by only ever instantiating ConnectedPlayer after VelocityServer#canRegisterConnection returns true. This avoid ever creating a BossBarManager/ChatQueue/whatever (this is done in ConnectedPlayer's constructor).

VelocityServer#canRegisterConnection currently consumes the ConnectedPlayer, but only ever checks its username and UUID. We can consume a com.velocitypowered.api.proxy.player.PlayerInfo instead, which is effectively a record of String username, UUID uuid, or just consume the username/UUID to perform the check.

Edit: The only issue is that we won't have access to ConnectedPlayer#disconnect0 then. This method only references the VelocityServer instance and the connection (mcConnection in AuthSessionHandler's context). Maybe we can pull this method into MinecraftConnection, and have ConnectedPlayer#disconnect0 just call this method on it's own connection to avoid duplicate code?

Edit # 2: The canonical solution is to use G...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

It should resolve the localhost into ::0 as the other program does.

Actual Behavior

It has an unresolved InetAddress now.

Steps to Reproduce

  1. Add exampleserver = 'some-machine-name:25565' in [servers] section of velocity.toml.
  2. Try to access the ServerInfo#getAddress() of exampleserver via any plugins in Velocity.
  3. We have an unresolved InetAddress.

Plugin List

Velocity Version

[15:55:57 INFO]: Velocity 3.5.0-SNAPSHOT (git-d11511c1-b584)
[15:55:57 INFO]: Copyright 2018-2026 Velocity Contributorsใ€‚Velocity ไปฅ GNU ้€š็”จๅ…ฌๅ…ฑ่ฎธๅฏ่ฏ็ฌฌไธ‰็‰ˆๆŽˆๆƒใ€‚
[15:55:57 INFO]: PaperMC - GitHub

Additional Information

Ref: https://github.com/PaperMC/Velocity/blob/d11511c18499497e7f7186211b109ef395b44acd/proxy/src/main/java/com/velocitypowered/proxy/util/AddressUtil.java#L44-L58
Why didn't we always resolve the hostname?

hexed flickerBOT
#

parseAndResolveAddress can throw IllegalArgumentException (e.g., from URI.create(...)), but this converter only catches IllegalStateException. Catch IllegalArgumentException as well (and ideally include the original exception as the cause) so invalid --add-server values are consistently reported as ValueConversionException.

      } catch (IllegalArgumentException | IllegalStateException e) {
        throw new ValueConversionException(
            "Invalid hostname for server flag with name: " + split[0], e);
#

Pull request overview

This PR addresses #1750 by ensuring server addresses defined via configuration/CLI are parsed using a resolving address parser so ServerInfo#getAddress() no longer returns an unresolved InetAddress when hostnames are used.

Changes:

  • Removed the non-resolving AddressUtil.parseAddress and switched call sites to AddressUtil.parseAndResolveAddress.
  • Updated config validation and server registration paths to use the resolving parser for both bind and [servers] entries.
  • Updated CLI --add-server parsing to use the resolving parser.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
proxy/src/main/java/com/velocitypowered/proxy/util/AddressUtil.java Removes parseAddress, leaving parseAndResolveAddress as the primary parser (and dropping Guava IP parsing).
proxy/src/main/java/com/velocitypowered/proxy/config/VelocityConfiguration.java Validates bin...
hexed flickerBOT
#

Expected Behavior

velocity works with 26.1 Release Candidate 2

Actual Behavior

<img width="1269" height="239" alt="Image" src="https://github.com/user-attachments/assets/99ca53f9-88a9-4cc0-8b95-c2b154663578" />
velocity has support for version 26.1, but version 26.1 has not been released
yet, I decided to try version 26.1 Release Candidate 2, but it did not work.

Steps to Reproduce

1.Run velocity server
2.Add that server to multiplayer on minecraft 26.1 Release Candidate 2
3. see's this won't work

Plugin List

velocity plugins
[20:00:52 INFO]: ะŸะปะฐะณะธะฝั‹: velocity

Velocity Version

[19:58:04 INFO]: Velocity 3.5.0-SNAPSHOT (git-d11511c1-b584)
[19:58:04 INFO]: Copyright 2018-2026 Velocity Contributors. Velocity ะปะธั†ะตะฝะทะธั€ะพะฒะฐะฝะฐ ะฝะฐ ัƒัะปะพะฒะธัั… GNU General Public License v3.
[19:58:04 INFO]: PaperMC - GitHub

Additional Information

No response

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

The problem with this is that disconnections caused by a duplicate login are represented in the API, specifically in the DisconnectEvent (https://jd.papermc.io/velocity/3.5.0/com/velocitypowered/api/event/connection/DisconnectEvent.LoginStatus.html#CONFLICTING_LOGIN), so by preventing the creation of the player object and its teardown, the event would not be triggered

The problem is now that we are already exposing the Player object to plugins through this event. Plugins can do whatever they want with the Player, including registering bossbars. Currently disconnected() only cleans up the bossbars, which could be omitted if we didn't ever expose the ConnectedPlayer object, but because we do we must consider a plugin registering bossbars on player disconnect. This sounds like weird behavior, but it's something that's possible nevertheless.

Also, it's interesting that a DisconnectEvent can be called on a player who was never connected, as far as the plugins go. Is this intentional...

hexed flickerBOT
#

There's no reason to delay setting up encryption to after we have fetched the GameProfile from Mojang.

Before this PR, this could result in a disconnect() call before we had set up encryption if Mojang's servers are down:

if (throwable != null) {
  logger.error("Unable to authenticate player", throwable);
  inbound.disconnect(Component.translatable("multiplayer.disconnect.authservers_down"));
  return;
}

// Only here we were setting up encryption

Simulating this with throwable != null || true, we get disconnected on the client with a garbled exception message complaining about packets instead of the proper disconnect message. This is because as far as the client is concerned, encryption should already be in place.

This PR moves enabling encryption on the connection right when we receive the packet and after we're done with setting up the crypto stuff.

This whole code block is already in a giant try/catch block:

try {
  // ...
} catch (GeneralSecurit```...
hexed flickerBOT
#

Expected Behavior

A clear single error-free port opening message should be displayed (just the fact that it is duplicated is wrong)

Actual Behavior

When the server starts, the output is:

[14:12:21 INFO]: Listening on /[0:0:0:0:0:0:0:0]:25565
[14:12:21 INFO]: Listening on /[0:0:0:0:0:0:0:0]:25565
[14:12:21 INFO]: Listening on /[0:0:0:0:0:0:0:0]:25565
[14:12:21 INFO]: Listening on /[0:0:0:0:0:0:0:0]:25565
[14:12:21 INFO]: Listening on /[0:0:0:0:0:0:0:0]:25565
[14:12:21 INFO]: Listening on /[0:0:0:0:0:0:0:0]:25565
[14:12:21 INFO]: Listening on /[0:0:0:0:0:0:0:0]:25565
[14:12:21 INFO]: Listening on /[0:0:0:0:0:0:0:0]:25565
[14:12:21 INFO]: Listening on /[0:0:0:0:0:0:0:0]:25565
[14:12:21 INFO]: Listening on /[0:0:0:0:0:0:0:0]:25565

When it stops, it is the same.

Steps to Reproduce

ะฃ ะผะตะฝั ัั‚ะพ ะฟะพัะฒะปัะตั‚ัั ะฟั€ะพัั‚ะพ ะฟั€ะธ ะทะฐะฟัƒัะบะต ัะตั€ะฒะตั€ะฐ.

Plugin List

It's not about plugins. I even tried deleting the cache, libraries, and plugins folder, but it doesn't help.

Velocity Ver...

hexed flickerBOT
hexed flickerBOT
#

For anybody still interested in this, I simply wrote a plugin that transported you using the new forwarding packets to do so.

So the proxy just forwarded you to the server essentially severing the connection with the proxy itself (yes a hack, and the serve had to be exposed also in teh docker not just the proxy). Took some unique pack via PacketEvents pertaining to the modpack and used it as a key to be able to differentiate between modded and unmodded clients. This allowed me to solve my problem without a lobby, essentially it automatically determines if you're supposed to be on the modded or the unmodded server when connecting. Anything else can be built on top of this (for example I later had 3 servers, two unmodded and one modded).

I wrote it some time ago so I don't remember all the details, however in all of the months of using it, I think it worked 99.7% of the time. There were a couple of strange problems when two players joined at the same time, I personally got timed out...

hexed flickerBOT
hexed flickerBOT
#

For consistency within this locale file, consider escaping the exclamation mark as \! (lines 18โ€“20 use escaped \!), or remove the exclamation entirely. While ! is valid in a .properties value, mixing escaped/unescaped punctuation makes the file harder to keep consistent across edits.

velocity.error.illegal-chat-characters=Illegรกlis karakterek a csevegรฉsben\!
#

Pull request overview

Updates the Hungarian (hu_HU) localization bundle to translate a few remaining English strings in Velocityโ€™s proxy user-facing messages.

Changes:

  • Translated velocity.error.illegal-chat-characters into Hungarian.
  • Localized the /send usage placeholders (<player> <server>) into Hungarian.
  • Translated the proxy shutdown kick message into Hungarian.

๐Ÿ’ก <a href="/PaperMC/Velocity/new/dev/3.0.0?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

An unintentional side effect introduced as a byproduct of the additional validation added in #1743 (in particular, the check added for packet direction and connection state) is that it breaks servers running a proxy-in-proxy configuration. Granted of course this is a known grey area and this is not officially supported, however we have had numerous complaints from users claiming that after updating to Velocity for Minecraft 26.1, their server no longer works.

The aim is to keep this validation optional via an added system property, retaining support for proxy-in-proxy, as it currently works fine otherwise, without any other changes on the user-end.

If there was any specific reasoning or justification for the validation being added that I'm unaware of, please let me know, but for the most part my understanding is that it was added as a generic safeguard because this is an uncommon packet state which doesn't normally occur for a single proxy to server.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

ConnectedPlayers DEFAULT_PERMISSIONS has always bothered me, because the field does not contain the default permissions of a player, it contains the default permission provider.

This PR fixes that ambiguous naming, and it also aligns VelocityConsole to a similar pattern: a single field defining the default, instead of hard-coding it multiple times in the constructor and the setupPermissions() method.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Ah, you're right. I have a misunderstanding.
The use case of mine is, I want to get the server ip address that the player really connected to in ServerConnection. (I can only get an unresolved one now; it may not be the connected ip if I resolve it.)
I want a feature, maybe. Something like make ServerConnection#getServerInfo() returns the actual backend ip address instead of callingRegisteredServer#getServerInfo().

hexed flickerBOT
#

This is an api enhancement of the use case mentioned in #1750. It adds a getConnectedServerInfo for getting the current connected IP and port.

If I have a backend server with some-dynamic-host-name:25565, it will be resolved in VelocityServerConnection#connect, but the resolution result (as the server player really connects to) cannot be gotten by the API; I got an unsolved InetSocketAddress instead.

It assumes future.channel().remoteAddress() will return an InetSocketAddress because it was up-cast from it in Bootstrap#connect(SocketAddress).

#

Pull request overview

Adds an API to expose the resolved (actually connected) backend server address (IP/port) for a ServerConnection, addressing cases where configured ServerInfo#getAddress() may remain unresolved when a hostname is used.

Changes:

  • Added ServerConnection#getConnectedServerInfo() to expose connected/resolved server address details.
  • Implemented tracking of the connected serverโ€™s resolved ServerInfo inside VelocityServerConnection during backend connect, and cleared it on disconnect.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
api/src/main/java/com/velocitypowered/api/proxy/ServerConnection.java Adds new API method getConnectedServerInfo() for exposing the resolved/connected server info.
proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java Stores connected server resolved address from Netty channel...
#

Javadoc grammar/capitalization needs correction: e.g., "currently connected to" (not "current connected to") and "resolved IP" (not "ip"). Also consider clarifying that the Optional may be empty when the connection is not yet established or has been closed.

   * Returns the server info that this connection is currently connected to.
   * Can be used for getting the resolved IP and port.
   *
   * @return the server info that this connection is currently connected to, if available;
   *         otherwise an empty {@link Optional} if the connection has not yet been established
   *         or has been closed
#

Adding a new abstract method to this public API interface is binary-incompatible for any external implementations (e.g., tests/mocks or downstream wrappers that implement ServerConnection). Consider making this a default method (e.g., returning Optional.empty()) to preserve binary compatibility, and override it in proxy implementations that can provide the resolved address.

  default Optional<ServerInfo> getConnectedServerInfo() {
    return Optional.empty();
  }
hexed flickerBOT
#

Expected Behavior

I encountered this issue while using the "The-Fool" modpack (forge 1.20.1)

Actual Behavior

My log:

[15:45:13 INFO]: [connected player] YGXB_net (/219.139.73.98:12335) has connected
[15:45:13 INFO]: [server connection] YGXB_net -> yz has connected
[15:45:18 ERROR]: [server connection] YGXB_net -> yz: exception encountered in com.velocitypowered.proxy.connection.backend.BackendPlaySessionHandler@7301bc5e
io.netty.handler.codec.CorruptedFrameException: Packet sent for class com.velocitypowered.proxy.protocol.packet.PluginMessagePacket was too big (expected 229378 bytes, got 432160 bytes)
        at com.velocitypowered.proxy.protocol.netty.MinecraftDecoder.handleOverflow(MinecraftDecoder.java:115) ~[velocity-3.5.0-SNAPSHOT-584.jar:3.5.0-SNAPSHOT (git-d11511c1-b584)]
        at com.velocitypowered.proxy.protocol.netty.MinecraftDecoder.doLengthSanityChecks(MinecraftDecoder.java:106) ~[velocity-3.5.0-SNAPSHOT-584.jar:3.5.0-SNAPSHOT (git-d11511c1-b584)]
        a```...
hexed flickerBOT
#

OK, it worked. Thank you

I hope this helps others

My shell:

java -Xms1G -Xmx1G -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:+UnlockExperimentalVMOptions -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch -XX:MaxInlineLevel=15 -Dvelocity.max-plugin-message-payload-size=50000 -jar velocity-3.5.0-SNAPSHOT-584.jar
hexed flickerBOT
#

Expected Behavior

Plugin messages sent on registered channels during the player join process should be forwarded to the backend server via getConnectionInFlight() when getConnectedServer() is null, the same way Forge Legacy handshake messages are. Messages should not be silently discarded.

Actual Behavior

ClientPlaySessionHandler.handle(PluginMessagePacket) at lines 303 to 310 only falls back to getConnectionInFlight() when the channel is LegacyForgeConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL. For all other channels, when getConnectedServer() returns null during the join window, serverConn is set to null and the handler silently skips the message. No warning, no error, no exception, etc.

VelocityServerConnection serverConn =
    (player.getConnectedServer() == null
        && packet.getChannel().equals(
        LegacyForgeConstants.FORGE_LEGACY_HANDSHAKE_CHANNEL))
        ? player.getConnectionInFlight() : player.getConnectedServer();

The null window exists between playe...

hexed flickerBOT
hexed flickerBOT
#

This is still happening.

Fixed on Velocity-CTD with https://github.com/GemstoneGG/Velocity-CTD/commit/f0bd9314fd46e860e0e3ce4daf46cb18761b41cf

The issue is that the decompression exploit happens before any packet ID + size checks down the line, because those can only be checked after the entire packet has been decompressed. Do that enough times and it's a DOS through OOM again.

#

Was kinda already working on compression limits due to it having been brought up elsewhere, looking at that patch looks somewhere between interesting/concerning, can't really take the code due to licensing issues, however

VeloFlame forks Velocity-CTD, which forks Velocity, every fork has the GNU GENERAL PUBLIC LICENSE just like Velocity so you should be all good. Regardless, the fix on CTD is a rewritten version on the VeloFlame fix (on their end its way more comprehensive and integrated with their already existing packet guard / "firewall" features). Feel free to do with it what you want.

The fix was applied in a rush as the exploit is currently being used in the wild, any improvements/suggestions welcome of course.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

When you open a shulker inside a menu or anywhere else, the shulker should open.

Actual Behavior

When you have a shulker full of stuff inside another menu (chest-like), the proxy cuts the connection.
Here's a clip of the actual behavior: https://medal.tv/it/games/minecraft/clips/mtxNyn27yJfNu57Uh?invite=cr-MSxES00sNDk0MjAyNjU3&v=40

Steps to Reproduce

1). Open a chest or a chest-like menu (pv plugin, ...)
2). Open open the sulker
3). Try to move the shulker

Plugin List

ViaVersion v5.8.1, LuckPerms v5.4.141, Vault v1.7.3-CMI, FastAsyncWorldEdit v2.15.1-SNAPSHOT-1290+886beb5, WorldGuard v7.0.9+5934e49, PlaceholderAPI v2.12.2, ViaBackwards v5.8.1, WorldGuardExtraFlags v4.2.4-SNAPSHOT, CoreProtect v23.1, CMILib v1.5.2.4, packetevents v2.11.2, nightcore v2.6.4, HeadDatabase v4.21.2, SSManager v1.0, aura-LuckPerms v1.0-SNAPSHOT, spark v1.10.156, AdvancedEnchantments v9.22.8, BottledExp v3.2.4.0, EliteLootbox v2.4.0, Pl-Hide-Pro v2.14.3, ItemEdit v3.7.8...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

@electronicboy
minecraft:black_shulker_box{BlockEntityTag:{Items:[{Count:1b,Slot:0b,id:"minecraft:leather_boots",tag:{Damage:0,Enchantments:[{id:"minecraft:protection",lvl:12s}],HideFlags:255,Unbreakable:1b,display:{Lore:['{"extra":[{"bold":false,"italic":false,"underlined":false,"strikethrough":false,"obfuscated":false,"color":"aqua","text":"โ›จ "},{"italic":false,"color":"white","text":"| "},{"italic":false,"color":"gray","text":"Protezione"},{"italic":false,"color":"white","text":": "},{"italic":false,"color":"aqua","text":"12"}],"text":""}'],Name:'{"text":"","extra":[{"text":"ั•","obfuscated":false,"italic":false,"underlined":false,"strikethrough":false,"color":"#3A2A1E","bold":true},{"text":"แด›","obfuscated":false,"italic":false,"underlined":false,"strikethrough":false,"color":"#392921","bold":true},{"text":"ษช","obfuscated":false,"italic":false,"underlined":false,"strikethrough":false,"color":"#382823","bold":true},{"text":"แด ","obfuscated":false,"italic":false,"underlined":false,"strike_...

hexed flickerBOT
hexed flickerBOT
#

These arbitrary limits really seem like a hack/plaster on the problem. There's bound to be way more issues like this, think mods sending really good compressible data. And how would the 1:64 ratio fare with a client sending a really long chat message consisting of one character?

My gut tells me theres a way better fix for these (de)compression attacks. Either detecting a client hammering hundreds of "weird"/big packets, or see if its possible to fix the actual problem where one client is allowed to generate gigabytes of decompressed packets that are queued to be processed. If we can solve that we dont need any arbitrary limits, which also deviates Velocity from the "Notchian" minecraft protocol, which mods and such are expecting.

Side note, how does vanilla MC / paper deal with this? It seems like these type of attacks are targeting Velocity itself, and the backends aren't really affected.

hexed flickerBOT
#

We have 0 context of "weird", that's the problem; the backends have less to worry about because they actually understand the context of the data and are able to apply natural limits to the data being passed as a result of that, your 8MB packet is seen as invalid and so you get booted from the network and your buffer cleaned out quickly

netty has a backpressure system, but it's not really good for the cases where the explosion happens in the pipeline rather than out of it, we could maybe emulate something like it to limit the damage done, however

#

We have 0 context of "weird", that's the problem; the backends have less to worry about because they actually understand the context of the data and are able to apply natural limits to the data being passed as a result of that, your 8MB packet is seen as invalid and so you get booted from the network and your buffer cleaned out quickly

netty has a backpressure system, but it's not really good for the cases where the explosion happens in the pipeline rather than out of it, we could maybe emulate something like it to limit the damage done, however

Something to think about. I have no doubt the limits in place will relieve most attacks, but as we've already seen a lot of people need to increase the limits. Especially modded networks, leaving them vulnerable in particular. Imo a fix that leaves a portion of the userbase vulnerable is not a fix at all, but I appreciate how quickly this was implemented and it patching probably >90% of Velocity instances.

Though I do wonder if a "wind...

hexed flickerBOT
#

Can someone explain why does this attack work in the first place?

I do not understand where leak happens.

In my head packet flow is this:

read():
  MinecraftCompressDecoder#decode
       creates new ByteBuf (8 mb) refCnt() == 1 ->
  MinecraftDecoder#channelRead: did nothing, refCnt() == 1 ->
  MinecraftConnection#channelRead
       BackendPlaySessionHandler#handleUnknown ->
             backendChannel.write(buf.retain()), refCnt() == 2 
                  //We still in same eventLoop(), context switch does not happen. ByteBuf immidialty goes throught Pipeline
                  MinecraftCompressorAndLengthEncoder(MessageToByteEncoder)#write -> buf.release(), refCnt == 1
       finally block:
              buf.release(), refCnt == 0
  refCnt reaches 0 -> netty should release memory, and next reads should reuse it

repeat read()
repeat read()
repeat read()

I dont see where memory leaking could happen.

  1. Does channel#write, somehow can still do context switch even we already ins...
hexed flickerBOT
#

UPD:
Looks like i found the issue:
MinecraftCompressorAndLengthEncoder allocates 8mb + some bytes for headers ByteBuf.
https://github.com/PaperMC/Velocity/blob/e834af9cf10d6c13703cb9ff6f349e196cb3d2bd/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftCompressorAndLengthEncoder.java#L92

then netty's ChannelOutboundBuffer will store that entire ByteBuf until flush() called.

And this is where leak happens.
https://github.com/PaperMC/Velocity/blob/dev/3.0.0/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java#L468

Probably you can manually calculate here how many bytes proximititly are gonna allocated by this write and do force flush if it more then XX mb are queues (one write will be always buf.readablyBytes() + some bytes)

#

I would note that "leak" generally has a pretty strong meaning, "memory sits around until flushed" is not a leak; But, that would in restospect explain some stuff, that isn't handled on the flush but on the channel readComplete, which apparently the newer adoptive allocator makes even worse?

I'm still somewhat inclined to keep some of the other checks just due to the nature, but can probably back off them; limiting how much can sit in the chain is something I was already trying to look into how to handle cleanly

#

limiting how much can sit in the chain is something I was already trying to look into how to handle cleanly

I think compression encoder can simply calculate how many bytes it allocated and if too many then do flush().

Something like this:

   private int threshold;
   private final VelocityCompressor compressor;
+  private long allocatedBytes = 0;
 
   public MinecraftCompressorAndLengthEncoder(int threshold, VelocityCompressor compressor) {
     this.threshold = threshold;
@@ -51,6 +52,16 @@
     } else {
       handleCompressed(ctx, msg, out);
     }
+    allocatedBytes += out.capacity();
+    if (allocatedBytes >= 64MB) {
+      ctx.channel().flush();
+    }
+  }
+
+  @Override
+  public void flush(ChannelHandlerContext ctx) throws Exception {
+    allocatedBytes = 0;
+    super.flush(ctx);
   }
 
   private void handleCompressed(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out)

If no compression, then backpressure should help to mitigate

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

am I wrong in thinking that this is backwards? The concern here is what clients are sending the server, not the inverse, but that's only dealing with S > C packets, and the batching there is generally fine, worse case I figure we can probably just do a force flush if we know the packet is is over some size
My understanding is that the exploits we're trying to patch is purely C > S, which is the other way around.

as an aside, with the new adoptive allocator, I wonder if it makes sense to get rid of the compression presizing, at least for natives, it seems that the thing already handles that just fine and worse case we'd see a single resize without any of the fuss, at least for the max cacacity, the java one is more of a concern but maybe worth just taking the hit, most packets compress down fairly well in the first place, so we're often in worse compression cases seeing 1/4 of the buffer be overheads, and that's without the pooling being accounted

hexed flickerBOT
#

proxy -> backend means this https://github.com/PaperMC/Velocity/blob/dev/3.0.0/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java#L468 where packet from client is forwarded to backend.

Client -> proxy -> backend
Backend -> proxy -> client

batching proxy to client is fine with current force flush limit, but proxy to backend force flush limit seems very high, client do not seens that many packets anyway. 15-20 packets before flush seems good value.

hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

player does not gets kicked

Actual Behavior

player gets kiked.

Steps to Reproduce

use axiom through a velocity proxy. Do a big change, player gets kiked.

Plugin List

none

Velocity Version

3.5.0-SNAPSHOT #590

currently latest

Additional Information

com.velocitypowered.proxy.protocol.packet.PluginMessagePacket was too big

[19:04:25 INFO]: [connected player] xXJuliGameXxf (/127.0.0.1:60903) has disconnected: An internal error occurred in your connection.
[19:04:25 INFO]: Exception while handling plugin message packet for [connected player] xXJuliGameXxf (/127.0.0.1:60903)
io.netty.handler.codec.CorruptedFrameException: Packet sent for class com.velocitypowered.proxy.protocol.packet.PluginMessagePacket was too big (expected 229378 bytes, got 488758 bytes)
        at com.velocitypowered.proxy.protocol.netty.MinecraftDecoder.handleOverflow(MinecraftDecoder.java:115) ~[server.jar:3.5.0-SNAPSHOT (git-1a41b77c-b590)]
        at com.velocit```...
hexed flickerBOT
hexed flickerBOT
#

This is not stale. It is a real issue that is hard to track down, and it has affected multiple users.

Over the course of 2 years or so, 6 users have reported this problem to me.

This is not a matter of plugins or no plugins. A plugin that merely registers a command shouldn't cause players to be disconnected.

A potential lead
I received the first report of this bug in July 2024. A user was having trouble on Velocity build #402.

They performed their own debugging, and as soon as they downgraded to build #400, the problems stopped.

The user concluded that code changes surrounding commands with signable component caused this error. Due to a lack of communication neither of us filed a bug report, but this bug surfaced rarely and has been a shadowy menace since. It seems to be the product of nondeterministic factors as I can never reproduce it, but it comes back repeatedly to haunt users of my plugin (LibertyBans) which registers the /ban command.

Logs
Today I obtained logs from a user...

hexed flickerBOT
#

Introduces CustomArgumentType interface which wraps native Brigadier argument types allowing for the creation of custom arguments.

Sends the native type to the client while parsing into the custom type.
Users create the argument node with the standard RequiredArgumentBuilder. Only when velocity wraps the arguments are they converted into the actual CustomArgumentCommandType.
Implemented nearly identically to Paper's CustomArgumentType.

hexed flickerBOT
#

We can't process cancelling signed chat messages and such on the proxy without entering illegal state territory in which your user would be disconnected the next time they send a signed chat/message to the server; This is generally not considered a bug and is sadly a limitation of the MC protocol, the only way to get around this right now would be using a plugin like signed velocity, otherwise, we would need some means of handshaking with the server to be able to aknowledge what has happened

hexed flickerBOT
#

Oh, I understand that. My question is though, why isn't it reproducible?

I suspect something more complicated is going on here. This is the error message; please take a look, as these are not signed chat messages we're talking about. I can't reproduce it, but other users have -- even with no other plugins installed.

[22:55:15 INFO]: [server connection] Blue_Gamer48 -> lobby has connected
[22:55:31 FATAL]: A plugin tried to deny a command with signable component(s). This is not supported. Disconnecting player Blue_Gamer48. Command packet: SessionPlayerCommand{command='ban Blue_Gamer48 Test', timeStamp=2026-04-11T20:55:31.326Z, salt=-1618365530119402377, argumentSignatures=ArgumentSignatures{entries=[ArgumentSignature{name='reason'}]}, lastSeenMessages=LastSeenMessages{offset=0, acknowledged={}, checksum=1}}
[22:55:31 INFO]: [connected player] Blue_Gamer48 (/188.108.208.192:60113) has disconnected: A proxy plugin caused an illegal protocol state. Contact your network administrator.
[22:```...
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#
[PaperMC/Velocity] New branch created: update/adventure/5.0.0
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

This PR introduces several high-performance features and security enhancements to Velocity, specifically optimized for high-traffic networks.

Key Enhancements:

  • Advanced Packet Limiter: Adds a type-aware packet rate limiter (Chat, TabComplete, PluginMessages) to prevent common exploits and CPU exhaustion.
  • MSPT-based Load Balancing: Introduces a ServerHealthTracker that monitors backend MSPT. Players are now dynamically routed to the healthiest server instead of simple round-robin.
  • Global Profile Cache: Integrated a Caffeine-based cache for GameProfiles to reduce Mojang API hits and decrease login times.
  • Performance First: All implementations follow Velocity's strict coding standards and utilize high-performance native-friendly logic.

These additions make this fork a powerhouse for networks requiring extreme stability and security.

hexed flickerBOT
hexed flickerBOT
#

Thanks for the feedback. The logic for reading MSPT data from the MOTD was initially added as a rapid prototype (PoC) solution for networks already utilizing specific telemetry plugins (like ServerListPlus, etc.). Naturally, in a production environment, synchronizing this data via an external telemetry layer like Plugin Messaging or Prometheus is much more robust. The codebase is designed to be modular enough to ingest this data from various sources. Rather than labeling a prototype feature as 'slop,' I would prefer to discuss the architectural merits. I've revised this section in the latest commit to be more modular.

#

This is a nightmare. Caching GameProfiles returned by Mojang's hasJoined URL removes any online-mode checks and lets any offline player join as an online mode player, as long as an online mode player had joined before (priming the cache).

AI Slop

It truely is, noone with proper knowledge would produce such a PR. This is not meant as an insult, but please do some actual learning in this field instead of PR-farming with slop if you're interested in this!

#

Velocity already has a partial packet limiter and these sensitive matters are mostly handled by maintainers or long time contributors for various reasons.
Also adding modules that depend on things outside the Vanilla protocol are AFAIK not really wanted.

And sorry but it doesn't look like "you" revised anything here. And even then most features are questionable at best and for example caching the game profiles like this is dangerous.

#

This is not an issue with this PR per-se, but there are no migrations in place for messages.properties or any similar file for a different languages. Updating velocity without removing messages.properties or manually adding this key will make the hover text show up as the translation key. Is this something that should be considered in the future? Message files migrations for adding keys, just like there's a migration system in-place for velocity.toml?

#

Why does Set<BossBar> bossBars need to be monotonically non-null? Seems like no real performance gain for less readability.

What are you talking about? For me at least it is Nullable: https://github.com/PaperMC/Velocity/pull/1756/changes#diff-1cd097c1de92fff8c43bc33eb4f52405eb5396f9e8cc922a4502e4cad12e1f88R189

yes but you're treating it as a monotonically non-null value. we can just leave it as a

private final Set<BossBar> bossBars = new HashSet<>();

and omit any null checks down the line. keeping this value null until it's used doesn't seem like it'll affect performance at all, and it makes the code that's using this field less readable (null -> either instantiate this set when modifying it, or assuming an empty set when querying it)

#

They don't though (https://github.com/PaperMC/Velocity/pull/1756/changes#diff-1cd097c1de92fff8c43bc33eb4f52405eb5396f9e8cc922a4502e4cad12e1f88R613), or am I missing something?

oh yes my bad, its not monotonically non-null, but my point still holds. this can be a HashSet that's initiated once (at construct time of the object) and only updated/queried without null-checks. that'd get rid of null-checks in every method that's using this field

hexed flickerBOT
#

This is not an issue with this PR per-se, but there are no migrations in place for messages.properties or any similar file for a different languages. Updating velocity without removing messages.properties or manually adding this key will make the hover text show up as the translation key. Is this something that should be considered in the future? Message files migrations for adding keys, just like there's a migration system in-place for velocity.toml?

This problem also came to my attention when working on this pr. However, solving it is way out of scope of this pr and should be discussed in a separate issue.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

In the same VelocityCommand.Info record, right above or below run().

As to why this should (could) be a separate helper method, it's not run()'s responsibility to format this string. Having it be a separate method is clearer and easier to find/modify at a later date.

Though that makes me think, maybe this better as a translatable message in messages.properties? That way this would be a Component.translatable() call with two arguments (name + version) and it's the translatable component responsibility to format this properly.

hexed flickerBOT
#

Expected Behavior

I have a server bundle on the ArcLight core. When I add the Create Aeronautics and Sable mod, I can't connect. Everything works without the mod.

Actual Behavior

[12:57:52 INFO]: Booting up Velocity 3.5.0-SNAPSHOT (git-f712997d-b593)...
[12:57:52 INFO]: Connections will use NIO channels, Java compression, Java ciphers
[12:57:52 WARN]: The proxy is running in offline mode! This is a security risk and you will NOT receive any support!
[12:57:52 INFO]: Loading localizations...
[12:57:52 INFO]: Loading plugins...
[12:57:52 INFO]: Loaded plugin cmiv 1.0.1.2 by Zrips
[12:57:52 INFO]: Loaded plugin minimotd-velocity 2.1.3 by jmp
[12:57:52 INFO]: Loaded 3 plugins
[12:57:52 INFO] [cmiv]: Registering event listeners
[12:57:52 INFO]: Listening on /[0:0:0:0:0:0:0:0]:38745
[12:57:52 INFO]: Done (0,75s)!
[12:57:53 INFO] [minimotd-velocity]: There is an update available for MiniMOTD!
[12:57:53 INFO] [minimotd-velocity]: This server is running version v2.1.3, which is 9 ver...

hexed flickerBOT
#

When reuse-port is enabled in the config, the listening on and closing endpoint messages are logged for every endpoint that is opened/closed, even when as far as I can tell, the address being logged is always the same

Fixes #1755

I remember creating a similar issue report and assume this might actually be intentional when digging deeper into logs: https://github.com/PaperMC/Velocity/pull/1535#issuecomment-2753979167

Maybe this should be reapproached?

hexed flickerBOT
#

As to why this should (could) be a separate helper method, it's not run()'s responsibility to format this string. Having it be a separate method is clearer and easier to find/modify at a later date.

Thanks for your input, however, I don't think this really matters that much, so I'm gonna leave this as-is for now.

Though that makes me think, maybe this better as a translatable message in messages.properties?

As to making this message translatable, this doesn't make a lot of sense in my opinion. The translation string would essentially be `{0} {1}, so I think this is also fine as-is.

hexed flickerBOT
#
#

Have you measured the performance of java's random UUID generation and this proprietary implementation? Is it even worth it to roll our own, aside from possible security/duplicate UUID concerns?
Yes at higher player counts there is thread congestion on netty threads (this worsens with the higher the threads and all players getting the same player info packets at the same time)

The security UUID concern should not be applicable here as they are only used as identifiers internally.
I kept the UUID.randomUUID() in click callbacks to ensure the security.

#

Also, how "unique" do the UUIDs have to be in the tablist? Could we increment the lower or higher long to keep the UUIDs "locally" unique per session or per tablist? That would speed this up a lot. Kind of similar how anonymous player entries in the server player list packets are expected to have a uuid of new UUID(0, 0). Though that does abuse the hell out of the universally unique IDs here.

This should technically also work for the legacy tablist implementations. The uuid is used to have a unique id for a player name as UUIDs aren't send in legacy with the tablist packets.

hexed flickerBOT
hexed flickerBOT
#

I think relying on an external library for this rather than manually fiddling with bits in our own FastRandomUuid is favorable. Its current name also suggests its perfectly safe to use in other cases where a random uuid is needed, which its really not due to relying on a non-secure random generator.

I think a better solution would be to get rid of this class and move it to VelocityTabListLegacy as a private static method (does the bossbar class actually re-generate the random uuids a bunch of time?)

#

I think relying on an external library for this rather than manually fiddling with bits in our own FastRandomUuid is favorable. Its current name also suggests its perfectly safe to use in other cases where a random uuid is needed, which its really not due to relying on a non-secure random generator.

I think a better solution would be to get rid of this class and move it to VelocityTabListLegacy as a private static method (does the bossbar class actually re-generate the random uuids a bunch of time?)

The method is now only present in VelocityTabListLegacy. I don't think an additional library is really needed, the collision chances are basically zero and the uuid is structurally valid. It's also not a usable "uuid" as it's used to spoof a tablist entry for temporary binding to a tab name.

hexed flickerBOT
#

The bug is still occurring in version 26.1.2
We get the error: โ€˜keepalive: time out (out of order!)โ€™
Several disconnections a day for various players.

I'm not entirely sure whether it's an โ€˜out of orderโ€™ error with keepalive packets or with the chat specifically. The strange thing is that you don't even need to type commands or send messages in the chat; just exploring the world for a few minutes is enough to trigger this โ€˜timeoutโ€™ error.

hexed flickerBOT
#

The bug is still occurring in version 26.1.2 We get the error: โ€˜keepalive: time out (out of order!)โ€™ Several disconnections a day for various players.

I'm not entirely sure whether it's an โ€˜out of orderโ€™ error with keepalive packets or with the chat specifically. The strange thing is that you don't even need to type commands or send messages in the chat; just exploring the world for a few minutes is enough to trigger this โ€˜timeoutโ€™ error.

Can you send a screenshot of this error?

hexed flickerBOT
#

Fix chat race conditions not addressed by #1042.

Despite #1042 serializing chat/command processing through ChatQueue, two issues allowed out-of-order packets to reach the backend:

  1. Rate-limited commands bypassed ChatQueue entirely

RateLimitedCommandHandler returned false when a command was rate-limited and forward-commands-if-rate-limited was enabled (the default). This caused the Netty dispatch path to write the packet directly to the backend via handleGeneric, racing ahead of any earlier commands still waiting in the queue for their CommandExecuteEvent to complete. Under rapid command bursts (e.g. litematica's schematic paste), this produced the exact out_of_order_chat kick described in #1042.

Fix: route rate-limited commands through ChatQueue via a new forwardRateLimited path, skipping plugin event firing but preserving write order.

  1. ChatQueue.writePacket blocked the Netty event loop

writePacket submitted a runnable to the event loop that called awaitUninterrupti...

hexed flickerBOT
hexed flickerBOT
#

VelocityRegisteredServer line 103-109 seems very fishy. It's converting one enum class to another, both with exactly the same value set.

I would consider moving the PlayerInfoForwarding class to the api module instead and use that everywhere instead.

There is a PR to expose the forwarding mode that wasn't merged since it's deemed more of an internal property

Though when making the decision that exposing this through the api module is undesired, I think it would be better to make ServerInfo an interface and implement it in the proxy module with the additional PlayerInfoForwarding field. I'm pretty sure that would break binary compatibility with plugins though... If that's something that we should be concerned about, extending this class as class VelocityServerInfo extends ServerInfo with the additional property would probably be best here. I just really dislike having two identical enums, one in the implementation module and one in the api module, and converting between the t...

hexed flickerBOT
#

The bug is still occurring in version 26.1.2 We get the error: โ€˜keepalive: time out (out of order!)โ€™ Several disconnections a day for various players.
I'm not entirely sure whether it's an โ€˜out of orderโ€™ error with keepalive packets or with the chat specifically. The strange thing is that you don't even need to type commands or send messages in the chat; just exploring the world for a few minutes is enough to trigger this โ€˜timeoutโ€™ error.

Can you send a screenshot of this error?

<img width="1458" height="183" alt="Captura de pantalla (8136)" src="https://github.com/user-attachments/assets/bd32f6a7-f6f7-43c6-bdad-798b41c8fc77" />

This usually happens with entity ID number 1, as it doesnโ€™t happen as often with subsequent entities ID, but it still disconnects the user.

I investigated the code and the line causing the disconnection is in: net.minecraft.server.network.ServerCommonPacketListenerImpl

            LOGGER.info("Disconnecting {} for sending keepali...
hexed flickerBOT
#
  • Remove restrictive handshake hostname length limit: The 261-character MAXIMUM_HOSTNAME_LENGTH in HandshakePacket.decode() silently disconnects clients when enough plugins inject forwarding data into the hostname field that the combined length exceeds the limit. readString(buf) now uses the default 65536 limit, matching every other string field and aligning with Paper/Spigot's equivalent fix (readUtf(255) to readUtf(Short.MAX_VALUE) in ClientIntentionPacket).

  • Fix plugin messages silently dropped during player join: Fixes #1766

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

While working through implementing Legacy+BungeeGuard forwarding for ProxyCompatibleForge, I realized that #1176 never implemented a way for Velocity to forward the modern FORGE[#] hostname token when legacy forwarding types were in use.
Additionally, while testing I found that the existing token forwarding for 1.8 - 1.12.2 didn't work with BungeeGuard forwarding.

The latter was a simple one-line fix, but I'd like some feedback regarding forwarding the modern FORGE[#] token, or if there are any other sections that need a tidy.

Somewhat in-line with Waterfall's "forgeClient" and "extraData" properties, I've added a new "modernForgeClient" property to account for backend implementations that always associate "forgeClient" with the older FML token, or backend implementations built with respect to Waterfall assuming the forwarded token is in the form of FML[#]. Any implementation that appends the "extraData" verbatim to the hostname (and replaces \1 with \0) should continue to funct...

hexed flickerBOT
#

Here's the current state of things:
Config setting: advanced.modern-forwarding-allow-legacy-connections
System Property: velocity.register-login-plugin-messages-for-legacy-versions

Given the two will most often be used in tandem I wonder if it'll be better to have them both as system properties, as that would also cut down on the chances of a casual user accidentally enabling the advanced setting and getting an odd connection error.

I'm also open to new name ideas, as that property name is abysmally long.

hexed flickerBOT
hexed flickerBOT
#

The packets-per-second limit was introduced to mitigate compression bomb attacks, where an attacker floods the proxy with small packets that decompress to the maximum allowed size. It's the wrong metric for this, though: 500 packets/s at 2 MiB each is 1 GiB/s of decompressed data, which kills the proxy just as effectively. At the same time, legitimate clients with chatty mods (e.g. heavy plugin-message traffic) were getting disconnected despite consuming far less than any attacker would.

This PR adds a decompressed-bytes-per-second limit to [packet-limiter], applied after decompression in MinecraftCompressDecoder. This directly measures what was causing OOM issues, rather than using a proxy metric. With a default of 5 MiB/s over a 7-second window (35 MiB of headroom per window), legitimate clients should never get close to this limit, while any compression bomb is caught well before it causes memory pressure.

Default changes (config version 2.7 -> 2.8):

  • packets-per-second: 500...
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

I wonder what your usecase for this feature is? I think the 'modern' go-to solution for a sort of 'anonymous'/intermediate proxy not exposed to the world would be to use Docker and Docker's networking.

I think most people would use this for better performance when having multiple servers on the same machine. As you said there are different (or even better) alternatives for networking security.

hexed flickerBOT
#
[PaperMC/Velocity] New branch created: cat/initial-choose-server-resulted
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

readByteArray already takes a cap and rejects oversized counts, but readKeyArray, readIntegerArray, readStringArray and readVarIntArray only check that the count fits in the remaining buffer bytes. Since each entry is 4 to 8 bytes (a primitive int or an Object reference) but the buffer check is in bytes, a single varint count of around the frame size lets a peer push us into a 4x to 8x larger heap allocation than the wire bytes.

For example readIntegerArray was reachable from AvailableCommandsPacket (clientbound). Setting the array length to ~2M passes the isReadable(length) check and we then new int[~2M], an 8 MiB allocation per packet. Similar story for the other three.

Adds a cap parameter to each of the four readers, defaults to DEFAULT_MAX_STRING_SIZE (the same constant readByteArray uses) and rejects with the existing checkFrame if the count exceeds it. Tests for the cap path are added.

./gradlew :velocity-proxy:test :velocity-proxy:checkstyleMain clean.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

it must start!!

Actual Behavior

Latest version replaces .jar file with new version and can then not access that file itself. It worked until I replaced the docker image today.

Here the log messages:

2026/05/11 14:12:08,stdout,Error: Unable to access jarfile ./velocity-3.5.0-SNAPSHOT-595.jar
2026/05/11 14:12:08,stdout,[init] Setting initial memory to 2048m and max to 2048m
2026/05/11 14:12:07,stdout,[init] Replacing env variables in configs that match the prefix CFG_...
2026/05/11 14:12:07,stdout,[init] /server/forwarding.secret already exists
2026/05/11 14:12:07,stdout,[mc-image-helper] 12:12:07.019 INFO : The file /server/velocity.toml already exists
2026/05/11 14:12:04,stdout,"[init] Downloading default top-level configs, if needed
"
2026/05/11 14:12:04,stdout,[mc-image-helper] 12:12:04.231 INFO : Removing old file velocity-3.5.0-SNAPSHOT-594.jar
2026/05/11 14:12:04,stdout,[mc-image-helper] 12:12:04.221 INFO : Do...

hexed flickerBOT
hexed flickerBOT
#

I think returning -1 in HandshakePacket#decodeExpectedMaxLength isn't desirable. No authentication is required to send this packet, anyone can open TCP connections & spam this packet possibly opening up DOS attacks again that were mitigated by some recent commits.

Good point. I was assuming the VarInt limit handled it, but 2MB is obviously still an exploitable size. The hostname is now capped at Short.MAX_VALUE characters, which matches Paper's readUtf(Short.MAX_VALUE) in ClientIntentionPacket.

hexed flickerBOT
#

I mean, this looks like two distinct set of changes

  1. The plugin message thing, this would be a bug
  2. the hostname length limit, this isn't a bug fix, at least not as we consider it given that we cater to the vanilla protocol, increasing it beyond the vanilla length limit on the incoming side is pretty breaky behaviorally

Regarding the hostname limit: Paper/Spigot made the equivalent change years ago (readUtf(255) to readUtf(Short.MAX_VALUE) in ClientIntentionPacket) for the same reason - plugins inject forwarding data into the hostname field, which is standard practice in the BungeeCord forwarding model. Velocity's own encode() already writes hostnames with no length cap, so the decode side is just being made consistent. The limit is now Short.MAX_VALUE to match Paper, and decodeExpectedMaxLength is kept in place for DoS protection on the unauthenticated packet.

#

Spigot made that change year ago purely for their forwarding mechanism and nothing else, it breaks compatability with the vanilla protocol in a way which prevents the proxy from being able to connect to vanilla servers entirely. The decode/encode inconsistency here is just a sad reality of how that mechanism is intended to work to keep compat with legacy forwarding.

That data inside of that packet is somewhat trusted due to the vanilla protocol limit on the decode side usually getting in the way of doing anything fancy there, effectively removing that limit stands out as a potential security risk at the very least; it's definetly not something I feel should just be changed overnight

#

There are a couple issues with this PR:

  • This vulnerability can be exploited by a DoS attack and this fix will improve code robustness

    This path is not exploitable client-side. Both cases where the exceptions are caught are clientbound-only. This could only be exploited by a malicious backend server.

  • readBinaryTag() can throw way more than just the NegativeArraySizeException (most obvious example is a bad array index in ProtocolUtils#readBinaryTag line 506; BINARY_TAG_TYPES[buf.readByte()])

  • The server won't crash anyways as the uncaught exceptions will be caught upstream (MinecraftDecoder#tryDecode)

#

The incoming decode limit doesn't affect vanilla backend compatibility. Velocity controls what it sends to backends based on forwarding mode, and the encode side already has no length cap, so anything that would break from a longer incoming hostname is already breakable through Velocity's own outgoing path. The decode/encode inconsistency doesn't protect anything if the encode side is already uncapped.

The security concern is fair, which is why the limit is Short.MAX_VALUE with decodeExpectedMaxLength kept in place, not removed entirely.

#

In my opinion it does not need to matter if upping the limit breaks vanilla backend compatibility if we put this limit behind a system property.

It's already possible to completely break vanilla (or any) connections with system properties by lowering packet size limits. Adding another system property that's a NOP by default, but allows a server admin to break vanilla connections (and fix support for EduGeyser) by increasing this limit isn't something new in that regard.

#

A system property that defaults to the broken behavior means every affected server admin has to independently diagnose a silent disconnect with no error output and somehow discover the flag. That's the same problem as the current bug, just with an extra step. The default should handle legitimate use cases without manual intervention. And to be clear, this has nothing to do with EduGeyser support. EduGeyser typically works fine without this change. These are general Velocity bugs that any plugin setup can hit under the right conditions.

hexed flickerBOT
#

I'm not understanding how allowing clients to send arbitary data inside of the handshake packet is

  1. for plugins
  2. a legitimate usecase

Mojang already offers a supported mechanism for plugins to sync arbitary data during early connections to the client, API here is lacking but I would much rather discuss proper solutions to that rather than having to maintain spec violations

hexed flickerBOT
#

The change isn't about allowing external clients to send arbitrary data. The longer hostnames come from plugins running inside Velocity, sending through internal channels like LocalChannel. External clients still send normal short hostnames.

Some plugins use the hostname field to forward data before authentication. This is the same BungeeCord forwarding pattern that Velocity explicitly supports, the limit was just set for DNS + Forge markers without accounting for forwarding payloads.
It's obviously not the intended use of the field, but I'm not the one introducing or picking that pattern.

hexed flickerBOT
#

Summary

Restore the full play-packet queue when a player connection reenters configuration state from play state.

This keeps the existing serverbound forwarding guards from the previous reconfiguration change, but avoids switching the client-side connection to outbound-only queueing during reconfiguration. Reentering configuration is a transitional protocol state, so both inbound and outbound play packets should be handled consistently until the configuration acknowledgement completes.

Root cause

The current code installs only PlayPacketQueueOutboundHandler when a play-state client is moved back into configuration. That protects clientbound play packets, but leaves the inbound side without the normal configuration-state queueing used elsewhere. In nested or rapid server-switch flows, this can leave the switch stuck waiting for reconfiguration to complete.

Validation

  • git diff --check
  • JAVA_HOME=/home/alex/.gradle/jdks/eclipse_adoptium-21-amd64-linux.2 ./gradlew check --c...
hexed flickerBOT
hexed flickerBOT
#

Expected Behavior

No CorruptedFrameException thrown

Actual Behavior

io.netty.handler.codec.CorruptedFrameException: Uncompressed size 12451 exceeds ratio threshold of 8448.0 for compressed sized 132 thrown

Steps to Reproduce

With a vanilla or paper backend, get a book & quill and write 30 pages with the following string on each page (copy/paste 30 times)

abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789

Plugin List

n/a

Velocity Version

Built from latest commit (9c0c9b02187c20bb767ce16ac7685580430d9b10)

Additional Information

This exception should not occur during vanilla gameplay (no mods, client or server-side).

This bug has been introduced since 9890c429, which tried to resolve decompression attacks. Apparently book contents sent from the client t...

#

I think this flag is fundamentally flawed, if we want to have zero impact on the vanilla protocol and what's expected with no modded or malicious clients. Increasing velocity.max-compression-ratio from the default 10 to 100 generates the same exception after creating a book with 100 pages (the maximum) of the long string in the description, this time with a decompressed size of 25404 and a compressed size of 183 (ratio of 138.8).

I mean, highly repeating patterns compress very well, only real fix to this would be to remove the compression threshold restriction

Yeah I agree. I assume this commit was another one to try to resolve the decompression attacks, right? I think we should take a look at merging #1786 soon. This PR resolves the actual underlying issue, rapid expansion of large packets in a short amount of time. The cause (9890c42) only looks at any individual packet, which may seem malicious but really isn't in this case. Again decompressed this is way less than 100kb for a s...

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

For context, https://github.com/PaperMC/Velocity/pull/1088 is the PR that originally introduced the packet queue here, e.g.

if (state == StateRegistry.CONFIG) {
  // Activate the play packet queue
  addPlayPacketQueueHandler();
} else if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE) != null) {
  // Remove the queue
  this.channel.pipeline().remove(Connections.PLAY_PACKET_QUEUE);
}

in MinecraftConnection#setState.

hexed flickerBOT
#

I realized what we were doing was unidiomatic and did a big refactor internally now to use Velocity more idiomatically, so this isn't needed for me anymore, so will close. We were chaining velocity but after some consideration, it's not worth the trouble of patching velocity to make it work. We not just use one velocity + a plugin, which is way simpler and better.

hexed flickerBOT
#

Might still be worth looking into - chaining Velocity instances might not be explicitly supported but adding Velocity into the chain should not break the vanilla MC protocol.

Client - > Velocity_1 -> Velocity_2 -> Backend breaking suggests something is going wrong, either Velocity_1 breaks the vanilla protocol with the packets its sending serverbound, or Velocity_2 does not understand the vanilla protocol Velocity_1 is speaking clientbound.

hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
hexed flickerBOT
#

I don't like this. But it works. RespawnPacket encodes the dimension as an int instead of a byte, which is where the actual bug occurs.

Reading this as an unsigned byte, then just writing it back as a byte in JoinGamePacket is a NOP. When switching servers, due to some weirdness with old clients we need to send a RespawnPacket that's generated off of this JoinGamePacket. That's when we write this previously signed byte as an int, resulting in a different value than the client expects.

This is a huge hack because we still need -1 to work for the nether.
I suggest changing the comment for why exactly this is needed, for future readers:

// Vanilla 1.7.10 uses a signed byte for dimension (-1 Nether, 0 Overworld, 1 End).
// Modded servers hack this to an unsigned byte to allow dim IDs up to 255.
// We must store the canonical int here because RespawnPacket.fromJoinGame copies this
// value into a packet that encodes dimension as a 4-byte int (RespawnPacket.encode,
// pre-1```...