Allow enabling sand duping (#10191)

Because this exploit has been widely known for years and has not been fixed by Mojang, we decided that it was worth allowing people to toggle it on/off due to how easy it is to make it configurable.

It should be noted that this decision does not promise all future exploits will be configurable.
This commit is contained in:
Owen 2024-03-03 17:05:34 -05:00 committed by GitHub
parent b21eb4d9a4
commit 89d51d5f29
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
673 changed files with 157 additions and 189 deletions

View file

@ -0,0 +1,116 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TonytheMacaroni <tonythemacaroni123@gmail.com>
Date: Wed, 6 Sep 2023 19:24:16 -0400
Subject: [PATCH] Add predicate for blocks when raytracing
diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java
index c978f3b2d42f512e982f289e76c2422e41b7eec6..bb8e962e63c7a2d931f9bd7f7c002aa35cfa5fd3 100644
--- a/src/main/java/net/minecraft/world/level/BlockGetter.java
+++ b/src/main/java/net/minecraft/world/level/BlockGetter.java
@@ -70,6 +70,12 @@ public interface BlockGetter extends LevelHeightAccessor {
// CraftBukkit start - moved block handling into separate method for use by Block#rayTrace
default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) {
+ // Paper start - Add predicate for blocks when raytracing
+ return clip(raytrace1, blockposition, null);
+ }
+
+ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {
+ // Paper end - Add predicate for blocks when raytracing
// Paper start - Prevent raytrace from loading chunks
BlockState iblockdata = this.getBlockStateIfLoaded(blockposition);
if (iblockdata == null) {
@@ -79,7 +85,7 @@ public interface BlockGetter extends LevelHeightAccessor {
return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo()));
}
// Paper end - Prevent raytrace from loading chunks
- if (iblockdata.isAir()) return null; // Paper - Perf: optimise air cases
+ if (iblockdata.isAir() || (canCollide != null && this instanceof LevelAccessor levelAccessor && !canCollide.test(org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, blockposition)))) return null; // Paper - Perf: optimise air cases & check canCollide predicate
FluidState fluid = iblockdata.getFluidState(); // Paper - Perf: don't need to go to world state again
Vec3 vec3d = raytrace1.getFrom();
Vec3 vec3d1 = raytrace1.getTo();
@@ -95,8 +101,14 @@ public interface BlockGetter extends LevelHeightAccessor {
// CraftBukkit end
default BlockHitResult clip(ClipContext context) {
+ // Paper start - Add predicate for blocks when raytracing
+ return clip(context, (java.util.function.Predicate<org.bukkit.block.Block>) null);
+ }
+
+ default BlockHitResult clip(ClipContext context, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {
+ // Paper end - Add predicate for blocks when raytracing
return (BlockHitResult) BlockGetter.traverseBlocks(context.getFrom(), context.getTo(), context, (raytrace1, blockposition) -> {
- return this.clip(raytrace1, blockposition); // CraftBukkit - moved into separate method
+ return this.clip(raytrace1, blockposition, canCollide); // CraftBukkit - moved into separate method // Paper - Add predicate for blocks when raytracing
}, (raytrace1) -> {
Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo());
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 457d5cdb510a11a069ac7f54a8ed95a74527bff3..be4fc09f9e30cb4bb5aaad49c23a19fd84f029bc 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1105,9 +1105,15 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize, Predicate<? super Entity> filter) {
+ // Paper start - Add predicate for blocks when raytracing
+ return rayTraceEntities((io.papermc.paper.math.Position) start, direction, maxDistance, raySize, filter);
+ }
+
+ public RayTraceResult rayTraceEntities(io.papermc.paper.math.Position start, Vector direction, double maxDistance, double raySize, Predicate<? super Entity> filter) {
Preconditions.checkArgument(start != null, "Location start cannot be null");
- Preconditions.checkArgument(this.equals(start.getWorld()), "Location start cannot be in a different world");
- start.checkFinite();
+ Preconditions.checkArgument(!(start instanceof Location location) || this.equals(location.getWorld()), "Location start cannot be in a different world");
+ Preconditions.checkArgument(start.isFinite(), "Location start is not finite");
+ // Paper end - Add predicate for blocks when raytracing
Preconditions.checkArgument(direction != null, "Vector direction cannot be null");
direction.checkFinite();
@@ -1157,9 +1163,16 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public RayTraceResult rayTraceBlocks(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks) {
+ // Paper start - Add predicate for blocks when raytracing
+ return this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, null);
+ }
+
+ @Override
+ public RayTraceResult rayTraceBlocks(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, Predicate<? super Block> canCollide) {
Preconditions.checkArgument(start != null, "Location start cannot be null");
- Preconditions.checkArgument(this.equals(start.getWorld()), "Location start cannot be in a different world");
- start.checkFinite();
+ Preconditions.checkArgument(!(start instanceof Location location) || this.equals(location.getWorld()), "Location start cannot be in a different world");
+ Preconditions.checkArgument(start.isFinite(), "Location start is not finite");
+ // Paper end - Add predicate for blocks when raytracing
Preconditions.checkArgument(direction != null, "Vector direction cannot be null");
direction.checkFinite();
@@ -1172,16 +1185,23 @@ public class CraftWorld extends CraftRegionAccessor implements World {
}
Vector dir = direction.clone().normalize().multiply(maxDistance);
- Vec3 startPos = CraftLocation.toVec3D(start);
+ Vec3 startPos = io.papermc.paper.util.MCUtil.toVec3(start); // Paper - Add predicate for blocks when raytracing
Vec3 endPos = startPos.add(dir.getX(), dir.getY(), dir.getZ());
- HitResult nmsHitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ignorePassableBlocks ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toNMS(fluidCollisionMode), CollisionContext.empty()));
+ HitResult nmsHitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ignorePassableBlocks ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toNMS(fluidCollisionMode), CollisionContext.empty()), canCollide); // Paper - Add predicate for blocks when raytracing
return CraftRayTraceResult.fromNMS(this, nmsHitResult);
}
@Override
public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate<? super Entity> filter) {
- RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks);
+ // Paper start - Add predicate for blocks when raytracing
+ return this.rayTrace(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, raySize, filter, null);
+ }
+
+ @Override
+ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate<? super Entity> filter, Predicate<? super Block> canCollide) {
+ RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, canCollide);
+ // Paper end - Add predicate for blocks when raytracing
Vector startVec = null;
double blockHitDistance = maxDistance;