#velocity
2096 messages · Page 3 of 3 (latest)
A client that stalls its FML/login handshake could enqueue plugin messages (each up to ~32 KiB serverbound) without bound in ClientPlaySessionHandler#loginPluginMessages, growing per-connection heap until an OOM kill. This PR caps the queue by both bytes (4 MiB) and count (1024), configurable via velocity.max-queued-login-plugin-message-bytes and velocity.max-queued-login-plugin-messages, and disconnects on overflow.
Building the project shows the following warning:
> Task :velocity-proxy:compileJava
warning: The `GraalVmProcessor` annotation processor is missing the recommended `log4j.graalvm.groupId` and `log4j.graalvm.artifactId` options.
To follow the GraalVM recommendations, please add the following options to your build tool:
-Alog4j.graalvm.groupId=<groupId>
-Alog4j.graalvm.artifactId=<artifactId>
This PR fixes this by adding the required options.
Depending on how long a client is actually able to stall the login phase for, this may be a scary OOM once again.
Without this fix, and at the default rate limit of 500 pps, a client would be able to fill this queue with 160MB of plugin messages every second (at 32kb/PM). That's 10GB within a minute, currently exploitable.
Of course this PR fixes that, and I'm sorry to keep bumping this but, #1786 would have greatly crippled this attack. At a limit of 5MB/s of decompressed packets per second, it would take around half an hour to fill the same 10GB in this queue. Still an OOM, if the client is actually able to stall the login phase for 30 minutes, but way less instant.
Now that we're using Java 21 throughout the project, I think we should take this opportunity to remove this try-catch block
I don't think that's likely to happen, but since it's good practice, I don't see a problem with it
I think this just hack the allowed range from -128 ~ 127 to -1~254 (255 is -1).
If modded servers register a dimension in -2 ~ -128, it may still broken.
And the second things, GTNH is not "hack this to an unsigned byte to allow dim IDs up to 255".
It hack to an int to completely fix this vanilla bug.
(https://github.com/GTNewHorizons/Hodgepodge/blob/master/src/main/java/com/mitchej123/hodgepodge/mixins/early/minecraft/packets/MixinS01PacketJoinGame_FixDimensionID.java)
If modded servers register a dimension in -2 ~ -128, it may still broken.
Not sure if this is possible, in older versions anyway. JoinGamePacket handles the dimension as a byte, regardless of its sign, it will always encode/decode as the same hex value. Though in vanilla minecraft this is definitely expected to be signed, because the nether is -1. RespawnPacket just encodes this as an integer instead, which is also expected to be signed, as the vanilla protocol expects the values -1, 0 and 1.
GTNH is not "hack this to an unsigned byte to allow dim IDs up to 255".
IMO it is a hack. The nether being -1 suggests that this value should be signed. Mods using a value over 127 would have needed to patch this bug also; RespawnPacket needs to return a signed -1 only ever for the nether, otherwise it should treat the byte as unsigned (and have a range from 0 - 255). This patch makes the range for the dimension value essentially be -1 - 254 (inclusive), as 255 is effectively mapped t...
Completely agree on both counts, this effectively won't ever happen, but it's an eye sore & bad practice in its current state.
38ff21a Fix theoretical IOOBE race (#1799) - WouterGritter
The proxy module doesn't need javadocs, and I'm generally not inclined to mix a set of dependency bumps which are fair, with a javadoc coverage thing which needs a lot of scrutinsation to deal with properly this time.
Correct me if I'm wrong, but it seems like SET_ACTION_BAR is the right action for the TitleActionbarPacket packet.
This bug doesn't surface when creating this class from the factory:
// GenericTitlePacket
public static GenericTitlePacket constructTitlePacket(ActionType type, ProtocolVersion version) {
GenericTitlePacket packet = null;
if (version.noLessThan(ProtocolVersion.MINECRAFT_1_17)) {
packet = switch (type) {
case SET_ACTION_BAR -> new TitleActionbarPacket();
case SET_SUBTITLE -> new TitleSubtitlePacket();
case SET_TIMES -> new TitleTimesPacket();
case SET_TITLE -> new TitleTextPacket();
case HIDE, RESET -> new TitleClearPacket();
default -> throw new IllegalArgumentException("Invalid ActionType");
};
} else {
packet = new LegacyTitlePacket();
}
packet.setAction(type);
return packet;
}
Namely through:
case SET_ACTION_BAR -> new TitleActionbarPacket();
packet.setAction(type); // overrides```...
We may even enforce this contract by adding this below the switch statement in the factory method:
if (packet.getAction() != type) {
throw new AssertionError("Title packet action type mismatch!");
}
But I don't think it's worth it to assert this at runtime (and this won't even work, TitleClearPacket can be created with both HIDE and RESET).
The enforcing of this is also quite inconsistent. TitleClearPacket throws when setting its action type to anything but HIDE and RESET, but the other packets let you set the action type to anything you want. Maybe it's worth expanding this PR to enforcing this for all other packet's setAction methods as well?
Fixes #1802, this PR builds on-top of the fix proposed and explained in that PR.
This PR drops the method visibility, enforces the action types (similar pattern to the already-existing enforcement in TitleClearPacket) and cleans up some whitespace formatting.
I don't like that this is null here, but this is exactly the old behavior. Previously this was less explicit as the setAction() setter just never got called.
On the topic of v4-vs-v7, if Mojang uses it to generate Entity UUIDs, then it's alright enough.
On the performance topic, are the gains actually significant?
I actually got curious and wrote a small benchmark for that and ran on my (admittedly ancient) desktop PC on both Windows (everyday usage) and Linux (installation ISO without background services):
> Windows
Benchmark Mode Cnt Score Error Units
UuidBenchmark.uuidInsecure thrpt 6 151409.421 ± 1504.844 ops/ms
UuidBenchmark.uuidSecure thrpt 6 698.752 ± 10.978 ops/ms
> Linux
Benchmark Mode Cnt Score Error Units
UuidBenchmark.uuidInsecure thrpt 6 156989.602 ± 593.248 ops/ms
UuidBenchmark.uuidSecure thrpt 6 2846.491 ± 35.525 ops/ms
So yeah, there are good magnitude-order speedups (less good on Linux, probably due to better reseeding from the kernel CSRNG). However, the baseline of 700 (or 2800) UUIDs/ms is not something that needs extreme urgent optimization.
This seems unnecessary vs. just clearing it below. when login is sent, the client has already sent its finish configuration packet and cannot change this counter anymore. same below
UUID.randomUUID() is known to scale rather bad with more threads (see https://github.com/openjdk/jdk/pull/14135), so this might make sense. If secure random should be used, an approach similar to that in the linked PR might be possible as well.
Fair point, I completely neglected the multithreaded-ness of Velocity and cas/mutex slowdown of Java rng/csrng implementations
The referenced library also provides benchmarks: https://github.com/f4b6a3/uuid-creator/wiki/5.0.-Benchmark
Is dropping this method intentional? KeyedVelocityTabList#buildEntry (which this was previously overriding) just delegated this to one of the other buildEntry()'s that is still overridden now, but this behavior might change in the future. If it does, a change in KeyedVelocityTabList may make VelocityTabListLegacy return the wrong entry here.
Could be overkill here, but we might consider "seeding" (xorring) the nextLong's with a value from SecureRandom, example & explanation from the referenced library: https://github.com/f4b6a3/uuid-creator/blob/master/src/main/java/com/github/f4b6a3/uuid/alt/GUID.java#L796
I think this is a bit overkill for this usecase. The uuid is only used for a "fake" mapping to the name, theres no real use besides it so it would never "cross" JVMs.
b72cf26 Cap pre-join plugin-message queue size (prevents a... - WouterGritter
25fbd83 Add decompressed-bytes-per-second rate limit, upda... - WouterGritter
Since Adventure's Facet platform is now deprecated, maybe it's worth considering an alternative, similar to: GemstoneGG#883, @4drian3d?
I'd rather this was included/PR'd into adventure-api. It serves literally zero point for an implementing platform to have a type pointer when you can just instanceof.
[PaperMC/Velocity] branch deleted: cat/pps
Expected Behavior
Hey, i'm trying to use Velocity for Modded Fabric on 26.1.2.
I had tried to join the Server without Velo, and it work right, but i had used now, the Automodpack plugin with the Mod from Automodpack. and this works fine :)
Without Velocity:
Client
https://mclo.gs/ojlvXCv
Server Log: https://mclo.gs/HIjrh9B
Actual Behavior
But when i try to join the server i got an issue and we had used -Dvelocity.max-known-packs= for more packets.
But, on joining it does not work and it throws this error:
[15:46:18] [Netty epoll Worker #4/ERROR] [com.velocitypowered.proxy.connection.MinecraftConnection]: [server connection] Suerion -> survival: exception encountered in com.velocitypowered.proxy.connection.backend.BackendPlaySessionHandler@2367b702
io.netty.handler.codec.CorruptedFrameException: Error decoding class com.velocitypowered.proxy.protocol.packet.AvailableCommandsPacket Direction CLIENTBOUND Protocol 26.1 State PLAY ID 0x10
at com.velocitypowered.proxy.p```...
@electronicboy Crossstich is not available for 26.1.2 thats why i had asked here.
The mod works fine on that version
@electronicboy Then the labels are not Correct on Modrinth and Curseforge...
Had added crossstich and it work, but i got this issues on Velo:
-> Caused by: java.lang.IllegalArgumentException: Argument type identifier 58 unknown.
Velocity log
https://mclo.gs/SmmCICQ
Server Log
https://mclo.gs/50YzUOq
Client Log:
https://mclo.gs/AzeEUNv
Network Protokol
https://mclo.gs/ppm8Y5j
Should i try to disable BadPackets and NetProdis?
[17:22:04] [main/WARN]: Error loading class: net/minecraft/class_2641$class_7232 (java.lang.ClassNotFoundException: net/minecraft/class_2641$class_7232)
[17:22:04] [main/WARN]: @Mixin target net/minecraft/class_2641$class_7232 was not found crossstitch.mixins.json:command.CommandTreeSerializationMixin from mod crossstitch
I don't really know anything about fabric/modded platforms, but this makes me guess that crossstitch is not yet compatible with 26.1, probably thanks to the removal of obfuscation. There is https://github.com/PaperMC/CrossStitch/pull/23 which looks to update it, but I'm not sure what the state of that is.
If you can, give that pr a try and let us know if that resolves your problem.
if it's not working then an issue should be opened against crossstitch, velocity can't parse data it doesn't understand, crossstich is the wrapper which mitigates that on the fabric side
[17:22:04] [main/WARN]: Error loading class: net/minecraft/class_2641$class_7232 (java.lang.ClassNotFoundException: net/minecraft/class_2641$class_7232) [17:22:04] [main/WARN]: @Mixin target net/minecraft/class_2641$class_7232 was not found crossstitch.mixins.json:command.CommandTreeSerializationMixin from mod crossstitchI don't really know anything about fabric/modded platforms, but this makes me guess that crossstitch is not yet compatible with 26.1, probably thanks to the removal of obfuscation. There is PaperMC/CrossStitch#23 which looks to update it, but I'm not sure what the state of that is.
If you can, give that pr a try and let us know if that resolves your problem.
@Emilxyz
With the pull, it workes! :) had build it and added it, now it work :), i could join :) it works fine, now i could test more
<img width="1920" height="1080" alt="Image" src="https://github.com/user-attachments/assets/1de33d97-50d7-4fcf-8230-5a5634fc8243" />
@electronicboy i had said, 26....
Filter the ServerboundChatSessionUpdatePacket when player info forwarding is disabled, since the client's profile key signature will not be valid for the player's offline UUID.
See comment in ClientPlaySessionHandler.java. This is marked as draft since it's in a "works for me" state, though I'm happy to address feedback and get this merged. I'm unsure whether this behavior belongs in a separate option or whether player-info-forwarding-mode = "NONE" is a good enough heuristic for when it's needed.
My use case is a public, Mojang-authenticated gateway to an online-mode=false Vanilla server (no Paper/Fabric) that unauthenticated bots can connect to over localhost.
[17:22:04] [main/WARN]: Error loading class: net/minecraft/class_2641$class_7232 (java.lang.ClassNotFoundException: net/minecraft/class_2641$class_7232) [17:22:04] [main/WARN]: @Mixin target net/minecraft/class_2641$class_7232 was not found crossstitch.mixins.json:command.CommandTreeSerializationMixin from mod crossstitchI don't really know anything about fabric/modded platforms, but this makes me guess that crossstitch is not yet compatible with 26.1, probably thanks to the removal of obfuscation. There is PaperMC/CrossStitch#23 which looks to update it, but I'm not sure what the state of that is.
If you can, give that pr a try and let us know if that resolves your problem.
It was ready but at the time I couldn't find any real mod with a custom argument for 26.1, so I wanted to wait for that.
No problem, I'll go ahead and refactor this PR and split them up as well when I have the time! Takes a bit to reapply these changes
@evan-goode, I'd probably mark this as ready so reviewers know it's time to suggest changes
Inspired by:
- https://github.com/GemstoneGG/Velocity-CTD/commit/137e6da1d218accdc6812f4900208c1494ed9459
- https://github.com/GemstoneGG/Velocity-CTD/commit/6b6345406ba90f3e32d12712a8271080d95c1142
With this PR, plugins may dynamically decide to add commands to the client's command tree by triggering Player#sendAvailableCommands and listening for the PlayerAvailableCommandsEvent that gets fired as a result of it.
How much memory does this PR consume per player?
Let's assume 1.000 commands per player. A conservative lower bound, and a complete but educated-ish guess, would be about ~64 bytes per command, giving 64kb per player (for 500 players, this is 32MB)
Take this with a giant grain of salt, but I had Claude Opus 4.7 have a go at estimating the memory footprint this PR brings with it.
Prompt: Investigate exactly how much memory 'RootCommandNode<CommandSource> backendCommandsNode' in 'BackendPlaySessionHandler' consumes per player for 1000 commands with typical str...
I'm not too sure if we need to return a CompletableFuture here. This doesn't get returned anywhere else in the Player interface, but at the same time, when this is completed it does guarantee that all PlayerAvailableCommandsEvents have been fired and the packet is on its way to the player.
Could this be useful for plugins? Or should we just return void and rely on plugins listening for this even to figure out that the packet is (about to be) on it's way?
Approving in its current state - changes may need to be made for other considerations by authors, of course
This targets the long-lost https://github.com/PaperMC/Velocity/issues/1369 issue.
This targets https://github.com/PaperMC/Velocity/pull/1791 but with fewer side effects.
My initial thought was to put this behind add a feature flag system, which would need to be enabled by plugins on init but...
Velocity didn't have these type pointers before so the deprecation of adventure platform has absolutely nothing to do with this.
What do you mean by this exactly? Velocity does currently resolve FacetPointers.TYPE to FacetPointers.Type.PLAYER and CONSOLE through pointers().
It seems strange that this was ever the case, as net.kyori.adventure.platform.facet is an unsupported API that really should never have been used in the first place.
This makes the deprecation of platform-facet and the likes put Velocity in quite a predicament... Removing the dependency could break plugins relying on it, but continuing to use a deprecated library/API also doesn't seem like the right solution.
I'd rather this was included/PR'd into adventure-api.
Getting net.kyori.adventure.platform.facet into adventure-api does seem like the proper solution, but I don't know if they'll want that. Another solution would be to provide these classes in proxy/deprecated/adventure-facet, similar to con...
My initial thought was to put this behind add a feature flag system, which would need to be enabled by plugins on init but...
I mean we could do this intuitively.
- get rid of
Player#sendAvailableCommands - introduce
Proxy#getAvailableCommandsService
interface AvailableCommandsService {
void sendAvailableCommands(Player player);
}
Plugins would need to obtain the AvailableCommandsService which would trigger the command tree to now be saved.
The issue is however that plugins really need to do this on startup, or they'll end up missing the backend command trees from players that are already connected.
Though I don't really like this. Seems complex and unnecessary to avoid a couple megabytes of ram, realistically.
Maybe an opt-out system flag would be better. Having memory issues? Know that no plugins make use of this feature? Disable it.
Wouldn't it need to be renamed from RootBeer?
As you've already mentioned, these pointers are marked as internal by adventure-platform. They're also not actually provided as a dependency by velocity-api and only required by velocity-proxy, which is not even published. So plugins using these is extremely unlikely and also unsupported anyways.
I'm also assuming that this pr will come with a velocity version bump, due to the other breaking changes in adventure 5. So I think just doing a clean cut and dropping adventure-platform-facet should be fine. Maybe mention it in an update announcement.
This would hold callbacks for packs that don't get a terminal client response for as long as the client is connected, right?
My initial thought was to put this behind add a feature flag system, which would need to be enabled by plugins on init but...
I mean we could do this intuitively.
- get rid of
Player#sendAvailableCommands- introduce
ProxyServer#getAvailableCommandsServiceinterface AvailableCommandsService { void sendAvailableCommands(Player player); }Plugins would need to obtain the
AvailableCommandsServicewhich would trigger the command tree to now be saved.The issue is however that plugins really need to do this on startup, or they'll end up missing the backend command trees from players that are already connected.
Though I don't really like this. Seems complex and unnecessary to avoid a couple megabytes of ram, realistically. Maybe an opt-out system flag would be better. Having memory issues? Know that no plugins make use of this feature? Disable it.
We could also just expose the AvailableCommandsService in the proxy init e...
Could also be an idea to add a status() method for the event to promote the adventure status.
I also thought about marking the Velocity one as obsolete but the Adventure one for example doesn't use the same enum order as Velocity & Minecraft, which would make handling the packet more annoying if we'd replace the Velocity one in the future.
This would hold callbacks for packs that don't get a terminal client response for as long as the client is connected, right?
Do you think it's better to add a timeout to this? What if the client is just really slow though, downloading a 50MB resource pack on a 1mbit/s connection
Alternatively we could keep the method as is and throw if it was not enabled by some feature system on init.
I don't think we have any feature that works like this right? If we are going to set a precedent for "resource intensive feature that must be opt-in in an elegant way" we need to think of a proper solution, one that would also work for future features like this.
An alternative for this specific PR could be to store the raw packet instead of the decoded command tree. Decode the packet only when sendAvailableCommands is called. Trade a bit of CPU time (only when this feature is used) for a lower memory footprint. I'm kinda leaning towards this; I might do some testing to see how much this would reduce memory usage in comparison.
This would hold callbacks for packs that don't get a terminal client response for as long as the client is connected, right?
Do you think it's better to add a timeout to this? What if the client is just really slow though, downloading a 50MB resource pack on a 1mbit/s connection
Yea I'm not sure, one of the maintainers might have an idea
Alternatively we could keep the method as is and throw if it was not enabled by some feature system on init.
I don't think we have any feature that works like this right? If we are going to set a precedent for "resource intensive feature that must be opt-in in an elegant way" we need to think of a proper solution, one that would also work for future features like this.
Sure, though we also should think about the users of this API and if it is hidden behind some 'obscure' mechanism they might not find it
Yea I'm not sure, one of the maintainers might have an idea
Are clients able to trigger this flow, of adding a resource pack & thus registering a callback? I don't think so but I might be wrong.
If we can only trigger a callback being registered through a plugin, I don't think this is really a cause for concern. The lifetime of the map (and its entries if the client never responds) is only as long as the client is connected, worst case we're storing a couple stale entries but that buys us having compatibility with slow clients.
Sure, though we also should think about the users of this API and if it is hidden behind some 'obscure' mechanism they might not find it
I mean, if we don't want to hide this API, we could keep Player#sendAvailableCommands and throw with an exception saying You must call ProxyInitializeEvent#enableFeature(FeatureFlags.SEND_AVAILABLE_COMMANDS) to make use of this feature!
This should never really produce an exception at runtime, because plugin developers will (should) catch this during development.
Alternatively we could log an error or warning and have it behave like a NOP instead of throwing.
An alternative for this specific PR could be to store the raw packet instead of the decoded command tree. Decode the packet only when sendAvailableCommands is called. Trade a bit of CPU time (only when this feature is used) for a lower memory footprint. I'm kinda leaning towards this; I might do some testing to see how much this would reduce memory usage in comparison.
This is really cursed. AvailableCommandsPacket needs to store a byte[] encoded and perform encoding during the constructor, decoding during the getRootNode getter. Reading/writing the bytes into this encoded field during encode() and decode(). IMO this isn't worth it, it deviates from how other packets do things so much, but it will reduce the memory footprint by a lot. Curious what other maintainers think of this approach.
Sure, though we also should think about the users of this API and if it is hidden behind some 'obscure' mechanism they might not find it
I mean, if we don't want to hide this API, we could keep
Player#sendAvailableCommandsand throw with an exception sayingYou must call ProxyInitializeEvent#enableFeature(FeatureFlags.SEND_AVAILABLE_COMMANDS) to make use of this feature!This should never really produce an exception at runtime, because plugin developers will (should) catch this during development.
Well this is what I meant.
Alternatively we could log an error or warning and have it behave like a NOP instead of throwing.
Well I think this could be annoying, and idk but I see no benefit with this option