Block (horizontal) clipping exploit
This concerns two problems:
- Clipping exploit with player movement
- #1 but for ridden entities, as well as
MC-159615applying to ridden entities as the fix forMC-159615was only applied to player movement
Both problems are solved using the same fix, so only one issue needs to be opened.
To produce:
- Move right up to a block's face (no distance between entity and block)
- Move 2.0e-7 units (2 times the collision epsilon) into the block with a modified client. This movement must be less-than 1.0e-5 but greater-than the collision epsilon, so I picked 2.0e-7.
- The entity is now inside the block, so it can move straight through it now.
The problem is that the server is using an epsilon for detecting whether a player is inside new blocks. Specifically, it is using a value (approximately) 100 times larger than the collision epsilon: 1.0e-5 (casted to float for whatever reason)
I've written a fix here: https://github.com/Spottedleaf/Tuinity/commit/e14829ae71307ce0093ee786b5da9c2016d058d5#diff-1846af0e0fa2c5a684924993816ea334bd1f5c6d28db83319ca9a27b8269367c but this isn't portable to vanilla because it uses my system for collisions. I'll instead detail how this fix should look like in vanilla.
First, modify the method in PlayerConnection (spigot mappings) that returns whether the player is colliding with new VoxelShapes to not use the epsilon (let's call this method hasNewCollision). The reason is that the underlying collision methods (getCubes(), move(), both spigot mappings) already use an epsilon to account for floating point error, and using a bigger one here can let this function return false when we really need it to return true (specifically for small move vectors, like 2.0e-7).
Secondly, modify the algorithm (for both vehicle movement and player movement) to determine whether to block a move to these steps:
- If the player/entity violates the moved-wrongly threshold, block the movement.
- If the moved-wrongly limit isn't violated, then use the new hasNewCollision method to test whether the entity/player have entered new blocks. If they have, then block the movement.
This algorithm still allows the moved-wrongly limit to block clearly incorrect movements (i.e trying to move through a block in one movement) and for the hasNewCollision method to handle cases where players/vehicles try to move into a block. This covers all invalid movement cases, provided the moved-wrongly limit is no larger than any given block's width, height, or depth.
In my patch, you'll notice I try to avoid calling hasNewCollision for optimisation purposes. This can only be done if the old AABB and new AABB are the same (they can differ even if the new position is the exact same as the old) and the prior move() call places the player exactly where the move packet specified. This kind of optimisation is just an optimisation though, and is not required.
You'll also notice my patch doesn't use VoxelShapes for determining new collisions, but rather uses the bounding boxes themselves. With how VoxelShape movement is done, using the AABBs is actually the correct check, but using the AABBs isn't required unless you want to strictly check collisions within a block. So, using VoxelShapes will still prevent clipping through walls (which is what the issue here is).
I will again emphasize that this must be applied to both vehicle packet handling and player packet handling.
2021-01-18, 11:55 PM
2024-11-19, 02:10 PM
2024-11-19, 02:10 PM
1
1
-