Files
MiraiMC/patches/server/0071-lithium-block.moving_block_shapes.patch
etil2jz ac9967167c Update Upstream (Pufferfish)
Also drop merged PRs and patches replaced by the new chunk system
2022-10-13 12:48:37 +02:00

165 lines
8.6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 2No2Name <2No2Name@web.de>
Date: Fri, 21 Jan 2022 08:41:34 -0500
Subject: [PATCH] lithium: block.moving_block_shapes
Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0
You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings)
diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
index 7c59d44a3bafdc65f453d77ff3e25cffb742ad6c..636721a111cad13e7329f1157981ca03a8f339b3 100644
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
@@ -52,6 +52,74 @@ public class PistonMovingBlockEntity extends BlockEntity {
this.extending = extending;
this.isSourcePiston = source;
}
+ // JettPack start - lithium: block.moving_block_shapes
+ private static final VoxelShape[] PISTON_BASE_WITH_MOVING_HEAD_SHAPES = precomputePistonBaseWithMovingHeadShapes();
+
+ /**
+ * We cache the offset and simplified VoxelShapes that are otherwise constructed on every call of getCollisionShape.
+ * For each offset direction and distance (6 directions, 2 distances each, and no direction with 0 distance) we
+ * store the offset and simplified VoxelShapes in the original VoxelShape when they are accessed the first time.
+ * We use safe publication, because both the Render and Server thread are using the cache.
+ *
+ * @param blockShape the original shape, must not be modified after passing it as an argument to this method
+ * @param offset the offset distance
+ * @param direction the offset direction
+ * @return blockShape offset and simplified
+ */
+ private static VoxelShape getOffsetAndSimplified(VoxelShape blockShape, float offset, Direction direction) {
+ VoxelShape offsetSimplifiedShape = blockShape.getOffsetSimplifiedShape(offset, direction);
+ if (offsetSimplifiedShape == null) {
+ //create the offset shape and store it for later use
+ offsetSimplifiedShape = blockShape.move(direction.getStepX() * offset, direction.getStepY() * offset, direction.getStepZ() * offset).optimize();
+ blockShape.setShape(offset, direction, offsetSimplifiedShape);
+ }
+ return offsetSimplifiedShape;
+ }
+
+ /**
+ * Precompute all 18 possible configurations for the merged piston base and head shape.
+ *
+ * @return The array of the merged VoxelShapes, indexed by {@link PistonBlockEntityMixin#getIndexForMergedShape(float, Direction)}
+ */
+ private static VoxelShape[] precomputePistonBaseWithMovingHeadShapes() {
+ float[] offsets = {0f, 0.5f, 1f};
+ Direction[] directions = Direction.values();
+
+ VoxelShape[] mergedShapes = new VoxelShape[offsets.length * directions.length];
+
+ for (Direction facing : directions) {
+ VoxelShape baseShape = Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.EXTENDED, true)
+ .setValue(PistonBaseBlock.FACING, facing).getCollisionShape(null, null);
+ for (float offset : offsets) {
+ //this cache is only required for the merged piston head + base shape.
+ //this shape is only used when !this.extending
+ //here: isShort = this.extending != 1.0F - this.progress < 0.25F can be simplified to:
+ //isShort = f < 0.25F , because f = getAmountExtended(this.progress) can be simplified to f == 1.0F - this.progress
+ //therefore isShort is dependent on the offset:
+ boolean isShort = offset < 0.25f;
+
+ VoxelShape headShape = (Blocks.PISTON_HEAD.defaultBlockState().setValue(PistonHeadBlock.FACING, facing))
+ .setValue(PistonHeadBlock.SHORT, isShort).getCollisionShape(null, null);
+
+ VoxelShape offsetHead = headShape.move(facing.getStepX() * offset,
+ facing.getStepY() * offset,
+ facing.getStepZ() * offset);
+ mergedShapes[getIndexForMergedShape(offset, facing)] = Shapes.or(baseShape, offsetHead);
+ }
+
+ }
+
+ return mergedShapes;
+ }
+
+ private static int getIndexForMergedShape(float offset, Direction direction) {
+ if (offset != 0f && offset != 0.5f && offset != 1f) {
+ return -1;
+ }
+ //shape of offset 0 is still dependent on the direction, due to piston head and base being directional blocks
+ return (int) (2 * offset) + (3 * direction.get3DDataValue());
+ }
+ // JettPack end
@Override
public CompoundTag getUpdateTag() {
@@ -351,10 +419,27 @@ public class PistonMovingBlockEntity extends BlockEntity {
}
float f = this.getExtendedProgress(this.progress);
+ // JettPack start - lithium: block.moving_block_shapes
+ if (this.extending || !this.isSourcePiston || !(this.movedState.getBlock() instanceof PistonBaseBlock)) {
+ //here voxelShape2.isEmpty() is guaranteed, vanilla code would call union() which calls simplify()
+ VoxelShape blockShape = blockState.getCollisionShape(world, pos);
+
+ //we cache the simplified shapes, as the simplify() method costs a lot of CPU time and allocates several objects
+ VoxelShape offsetAndSimplified = getOffsetAndSimplified(blockShape, Math.abs(f), f < 0f ? this.direction.getOpposite() : this.direction);
+ return offsetAndSimplified;
+ } else {
+ //retracting piston heads have to act like their base as well, as the base block is replaced with the moving block
+ //f >= 0f is guaranteed (assuming no other mod interferes)
+ int index = getIndexForMergedShape(f, this.direction);
+ return PISTON_BASE_WITH_MOVING_HEAD_SHAPES[index];
+ }
+ /*
double d = (double)((float)this.direction.getStepX() * f);
double e = (double)((float)this.direction.getStepY() * f);
double g = (double)((float)this.direction.getStepZ() * f);
return Shapes.or(voxelShape, blockState.getCollisionShape(world, pos).move(d, e, g));
+ */
+ // JettPack end
}
}
diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java
index 2182afd1b95acf14c55bddfeec17dae0a63e1f00..461ac9a464c4a66e302798032c6019bb60f6862b 100644
--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java
+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java
@@ -26,6 +26,44 @@ public abstract class VoxelShape {
}
// Paper end
+ // JettPack start - lithium: block.moving_block_shapes
+ private volatile VoxelShape[] offsetAndSimplified;
+
+ public void setShape(float offset, Direction direction, VoxelShape offsetShape) {
+ if (offsetShape == null) {
+ throw new IllegalArgumentException("offsetShape must not be null!");
+ }
+ int index = getIndexForOffsetSimplifiedShapes(offset, direction);
+ VoxelShape[] offsetAndSimplifiedShapes = this.offsetAndSimplified;
+ if (offsetAndSimplifiedShapes == null) {
+ offsetAndSimplifiedShapes = new VoxelShape[1 + 2 * 6];
+ } else {
+ offsetAndSimplifiedShapes = offsetAndSimplifiedShapes.clone();
+ }
+ offsetAndSimplifiedShapes[index] = offsetShape;
+ this.offsetAndSimplified = offsetAndSimplifiedShapes;
+ }
+
+ public VoxelShape getOffsetSimplifiedShape(float offset, Direction direction) {
+ VoxelShape[] offsetAndSimplified = this.offsetAndSimplified;
+ if (offsetAndSimplified == null) {
+ return null;
+ }
+ int index = getIndexForOffsetSimplifiedShapes(offset, direction);
+ return offsetAndSimplified[index];
+ }
+
+ private static int getIndexForOffsetSimplifiedShapes(float offset, Direction direction) {
+ if (offset != 0f && offset != 0.5f && offset != 1f) {
+ throw new IllegalArgumentException("offset must be one of {0f, 0.5f, 1f}");
+ }
+ if (offset == 0f) {
+ return 0; //can treat offsetting by 0 in all directions the same
+ }
+ return (int) (2 * offset) + 2 * direction.get3DDataValue();
+ }
+ // JettPack end
+
protected VoxelShape(DiscreteVoxelShape voxels) { // Paper - protected
this.shape = voxels;
}