Paper icon indicating copy to clipboard operation
Paper copied to clipboard

Soul sand does not clip minecart in 1.18.1 paper

Open Windmill1055 opened this issue 3 years ago • 3 comments

Expected behavior

months ago i opened an issue that soul sand does not clip minecart in 1.17.1 paper and it is fixed. But again i tested it in 1.18.1 paper and the problem occurs again.

Observed/Actual behavior

Soul sand can not clip minecart in 1.18.1 paper

Steps/models to reproduce

image build something like this.The simple machine is usually used to clip a minecart into soulsand. The minecart is on the slab so that when the lever is activated, the piston will get pushed out and the lever will be destroyed due to the piston movement, which will result in a 0t pulse to the piston. The soul sand will be instantly pushed out so that the minecart will stay in the soul sand rather than get pushed to the right. So if the soul sand can clip minecart like the vanilla gameplay, The minecart bottom will simply stay in the middle of soulsand. But in paper 1.18.1, the minecart will drop down.

Plugin and Datapack List

no plugin

Paper version

This server is running Paper version git-Paper-175 (MC: 1.18.1) (Implementing API version 1.18.1-R0.1-SNAPSHOT) (Git: 9490475) You are running the latest version

Other

No response

Windmill1055 avatar Jan 25 '22 07:01 Windmill1055

Confirmed in 1.18.1.

Machine-Maker avatar Feb 24 '22 23:02 Machine-Maker

still exists in 1.19

Windmill1055 avatar Aug 01 '22 05:08 Windmill1055

Here is previous discussion on the 1.17 issue, explaining the difficulty of a proper fix

I've published a hacky workaround here, in the form of a patch you can drop into patches/server before compiling Paper.

May be unstable!

Works on Paper commit 339e85d4915a7cfa0066e89c0ffa3ea7b983493d

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: lordpipe <[email protected]>
Date: Wed, 21 Sep 2022 20:59:29 -0600
Subject: [PATCH] Soul sand is freezy

Makes it possible to wedge a boat into soul sand without it falling.

diff --git a/src/main/java/io/papermc/paper/util/CollisionUtil.java b/src/main/java/io/papermc/paper/util/CollisionUtil.java
index a87f6380b2c387fb0cdd40d5087b5c93492e3c88..777a9bc2dda2f80a5dea8bfcce31a85b9af06cbf 100644
--- a/src/main/java/io/papermc/paper/util/CollisionUtil.java
+++ b/src/main/java/io/papermc/paper/util/CollisionUtil.java
@@ -38,6 +38,12 @@ public final class CollisionUtil {
     public static final long KNOWN_UNKNOWN_BLOCK = 0b10; // must read the actual block state for info
     public static final long KNOWN_SPECIAL_BLOCK = 0b11; // caller must check this block for special collisions
 
+    // this is ugly :D
+    // instead of doing multiple return values, we just stick this onto the static class object so that the results can
+    // propagate to net.minecraft.world.entity.Entity. this way, we don't have to change a bunch of function calls
+    // just to make soul sand a motion-freezing block
+    public static boolean lastBlockIsFreezy = false;
+
     public static boolean isSpecialCollidingBlock(final net.minecraft.world.level.block.state.BlockBehaviour.BlockStateBase block) {
         return block.shapeExceedsCube() || block.getBlock() == Blocks.MOVING_PISTON;
     }
@@ -407,6 +413,7 @@ public final class CollisionUtil {
                                                                   final List<AABB> into, final boolean loadChunks, final boolean collidesWithUnloaded,
                                                                   final boolean checkBorder, final boolean checkOnly, final BiPredicate<BlockState, BlockPos> predicate) {
         boolean ret = false;
+        lastBlockIsFreezy = false;
 
         if (checkBorder) {
             if (CollisionUtil.isAlmostCollidingOnBorder(getter.getWorldBorder(), aabb)) {
@@ -631,10 +638,12 @@ public final class CollisionUtil {
 
                                         if (checkOnly) {
                                             if (voxelshape3.intersects(aabb)) {
+                                                lastBlockIsFreezy = blockData.getBlock() instanceof net.minecraft.world.level.block.SoulSandBlock;
                                                 return true;
                                             }
                                         } else {
                                             ret |= addBoxesToIfIntersects(voxelshape3, aabb, into);
+                                            lastBlockIsFreezy |= blockData.getBlock() instanceof net.minecraft.world.level.block.SoulSandBlock;
                                         }
                                     }
                                 }
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index a3f1aef9d8f254747bd6580e8e3087a5c6829128..831d84322b688283d6c8860505ea3c2eab68083f 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -1383,6 +1383,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
             io.papermc.paper.util.CollisionUtil.getCollisions(world, this, collisionBox, potentialCollisions, false, this.level.paperConfig().chunks.preventMovingIntoUnloadedChunks,
                 false, false, null, null);
 
+
+            if (this instanceof net.minecraft.world.entity.vehicle.Boat
+                    && io.papermc.paper.util.CollisionUtil.lastBlockIsFreezy) {
+                // block is "freezy" - do not allow any motion changes while inside of it
+                return new Vec3(0.0, 0.0, 0.0);
+            }
+
             if (io.papermc.paper.util.CollisionUtil.isCollidingWithBorderEdge(world.getWorldBorder(), collisionBox)) {
                 io.papermc.paper.util.CollisionUtil.addBoxesToIfIntersects(world.getWorldBorder().getCollisionShape(), collisionBox, potentialCollisions);
             }

It basically works by making it so soul sand freezes any collision-originated motion of any boats or minecarts inside of it. It has caveats:

  • Only affects soul sand and soul soil, slab behavior is left alone
  • Doesn't exactly replicate the y levels that entities can settle inside of a soul sand block in the vanilla behavior
  • Makes it so boats dropped onto soul sand will hover over it, until the player attempts to ride the boat (probably fixable by making it so it only stops collision motion within the actual hitbox)

Let me know if you experience any issues with it.

lordofpipes avatar Aug 18 '22 18:08 lordofpipes

I have rewritten the collision patch locally to strictly adhere to Vanilla behavior, which fixes this issue, and will eventually push it once it's fully done.

Spottedleaf avatar Jul 25 '23 14:07 Spottedleaf

This includes the mentioned collision patch https://github.com/PaperMC/Folia/pull/153

Spottedleaf avatar Sep 12 '23 14:09 Spottedleaf

Resolved in Paper 1.20.2 https://github.com/PaperMC/Paper/commit/6af97e11b6a5c86dcbae29d554875ee271c5e51c

Spottedleaf avatar Sep 22 '23 23:09 Spottedleaf