mirror of
https://github.com/YatopiaMC/Yatopia.git
synced 2024-11-19 09:06:21 +01:00
233 lines
12 KiB
Diff
233 lines
12 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: JellySquid <jellysquid+atwork@protonmail.com>
|
|
Date: Sun, 24 Jan 2021 16:57:03 +0100
|
|
Subject: [PATCH] lithium block
|
|
|
|
Co-authored-by: Hugo Planque <hookwood01@gmail.com>
|
|
|
|
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/tuples/FinalObject.java b/src/main/java/me/jellysquid/mods/lithium/common/util/tuples/FinalObject.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..f78927e71258e859154cca8ba78d17130b0d82c1
|
|
--- /dev/null
|
|
+++ b/src/main/java/me/jellysquid/mods/lithium/common/util/tuples/FinalObject.java
|
|
@@ -0,0 +1,20 @@
|
|
+package me.jellysquid.mods.lithium.common.util.tuples;
|
|
+
|
|
+/**
|
|
+ * The purpose of this class is safe publication of the wrapped value. (JLS 17.5)
|
|
+ */
|
|
+public class FinalObject<T> {
|
|
+ private final T value;
|
|
+
|
|
+ public FinalObject(T value) {
|
|
+ this.value = value;
|
|
+ }
|
|
+
|
|
+ public FinalObject<T> of(T value) {
|
|
+ return new FinalObject<>(value);
|
|
+ }
|
|
+
|
|
+ public T getValue() {
|
|
+ return value;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/net/minecraft/core/EnumDirection.java b/src/main/java/net/minecraft/core/EnumDirection.java
|
|
index b8fe75b8c37ef1968519e69e078444b1a3c5c359..a825b17e454138e181926df3f2faa6d9d7af4055 100644
|
|
--- a/src/main/java/net/minecraft/core/EnumDirection.java
|
|
+++ b/src/main/java/net/minecraft/core/EnumDirection.java
|
|
@@ -100,6 +100,7 @@ public enum EnumDirection implements INamable {
|
|
return new EnumDirection[]{enumdirection, enumdirection1, enumdirection2, enumdirection2.opposite(), enumdirection1.opposite(), enumdirection.opposite()};
|
|
}
|
|
|
|
+ public int get3DDataValue(){ return c(); } // Yatopia - OBFHELPER
|
|
public int c() {
|
|
return this.g;
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java
|
|
index 58c7a52612fe0f5c1e4ddacc0bf93cd81f1286b8..af2a8fdcaf5962334dcc20717f3a1ad14aebcbcb 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java
|
|
@@ -29,9 +29,9 @@ import net.minecraft.world.phys.shapes.VoxelShapes;
|
|
public class TileEntityPiston extends TileEntity implements ITickable {
|
|
|
|
private IBlockData a;
|
|
- private EnumDirection b;
|
|
- private boolean c;
|
|
- private boolean g;
|
|
+ private EnumDirection b; public EnumDirection getFacing() { return b; } // Yatopia - OBFHELPER
|
|
+ private boolean c; public boolean isExtending() { return c; } // Yatopia - OBFHELPER
|
|
+ private boolean g; public boolean isSource() { return g; } // Yatopia - OBFHELPER
|
|
private static final ThreadLocal<EnumDirection> h = ThreadLocal.withInitial(() -> {
|
|
return null;
|
|
});
|
|
@@ -40,6 +40,74 @@ public class TileEntityPiston extends TileEntity implements ITickable {
|
|
private long k;
|
|
private int l;
|
|
|
|
+ // Yatopia start - Port Lithium
|
|
+ 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, EnumDirection direction) {
|
|
+ VoxelShape offsetSimplifiedShape = blockShape.getOffsetSimplifiedShape(offset, direction);
|
|
+ if (offsetSimplifiedShape == null) {
|
|
+ //create the offset shape and store it for later use
|
|
+ offsetSimplifiedShape = blockShape.offset(direction.getAdjacentX() * offset, direction.getAdjacentY() * offset, direction.getAdjacentZ() * offset).simplify();
|
|
+ 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 TileEntityPiston#getIndexForMergedShape(float, EnumDirection)}
|
|
+ */
|
|
+ private static VoxelShape[] precomputePistonBaseWithMovingHeadShapes() {
|
|
+ float[] offsets = {0f, 0.5f, 1f};
|
|
+ EnumDirection[] directions = EnumDirection.values();
|
|
+
|
|
+ VoxelShape[] mergedShapes = new VoxelShape[offsets.length * directions.length];
|
|
+
|
|
+ for (EnumDirection facing : directions) {
|
|
+ VoxelShape baseShape = Blocks.PISTON.getBlockData().set(BlockPiston.EXTENDED, true)
|
|
+ .set(BlockPiston.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.getBlockData().set(BlockPistonExtension.FACING, facing))
|
|
+ .set(BlockPistonExtension.SHORT, isShort).getCollisionShape(null, null);
|
|
+
|
|
+ VoxelShape offsetHead = headShape.offset(facing.getAdjacentX() * offset,
|
|
+ facing.getAdjacentY() * offset,
|
|
+ facing.getAdjacentZ() * offset);
|
|
+ mergedShapes[getIndexForMergedShape(offset, facing)] = VoxelShapes.union(baseShape, offsetHead);
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ return mergedShapes;
|
|
+ }
|
|
+
|
|
+ private static int getIndexForMergedShape(float offset, EnumDirection 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());
|
|
+ }
|
|
+ // Yatopia End
|
|
+
|
|
public TileEntityPiston() {
|
|
super(TileEntityTypes.PISTON);
|
|
}
|
|
@@ -350,13 +418,21 @@ public class TileEntityPiston extends TileEntity implements ITickable {
|
|
} else {
|
|
iblockdata = this.a;
|
|
}
|
|
+ float f = this.e(this.i); // Yatopia Start - Port Lithium
|
|
+ if (this.isExtending() || !this.isSource()) {
|
|
+ //here voxelShape2.isEmpty() is guaranteed, vanilla code would call union() which calls simplify()
|
|
+ VoxelShape blockShape = iblockdata.getCollisionShape(iblockaccess, blockposition);
|
|
+
|
|
+ //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.getFacing().opposite() : this.getFacing());
|
|
+ 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.getFacing());
|
|
+ return PISTON_BASE_WITH_MOVING_HEAD_SHAPES[index];
|
|
+ } // Yatopia End
|
|
|
|
- float f = this.e(this.i);
|
|
- double d0 = (double) ((float) this.b.getAdjacentX() * f);
|
|
- double d1 = (double) ((float) this.b.getAdjacentY() * f);
|
|
- double d2 = (double) ((float) this.b.getAdjacentZ() * f);
|
|
-
|
|
- return VoxelShapes.a(voxelshape, iblockdata.getCollisionShape(iblockaccess, blockposition).a(d0, d1, d2));
|
|
}
|
|
}
|
|
|
|
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 9567630593da7c77a0173b93c9a57ceb7887a59b..fbc5fab9946b6f9233f3014f0e69f2576b2138d7 100644
|
|
--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java
|
|
+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java
|
|
@@ -13,9 +13,50 @@ import net.minecraft.util.MathHelper;
|
|
import net.minecraft.world.phys.AxisAlignedBB;
|
|
import net.minecraft.world.phys.MovingObjectPositionBlock;
|
|
import net.minecraft.world.phys.Vec3D;
|
|
+import me.jellysquid.mods.lithium.common.util.tuples.FinalObject; // Yatopia
|
|
|
|
public abstract class VoxelShape {
|
|
|
|
+ // Yatopia - Port Lithium
|
|
+ private FinalObject<VoxelShape>[] offsetAndSimplified;
|
|
+
|
|
+ public void setShape(float offset, EnumDirection direction, VoxelShape offsetShape) {
|
|
+ if (offsetShape == null) {
|
|
+ throw new IllegalArgumentException("offsetShape must not be null!");
|
|
+ }
|
|
+ int index = getIndexForOffsetSimplifiedShapes(offset, direction);
|
|
+ FinalObject<VoxelShape>[] offsetAndSimplified = this.offsetAndSimplified;
|
|
+ if (offsetAndSimplified == null) {
|
|
+ //noinspection unchecked
|
|
+ this.offsetAndSimplified = (offsetAndSimplified = new FinalObject[1 + (2 * 6)]);
|
|
+ }
|
|
+ //using FinalObject as it stores the value in a final field, which guarantees safe publication
|
|
+ offsetAndSimplified[index] = new FinalObject<>(offsetShape);
|
|
+ }
|
|
+
|
|
+ public VoxelShape getOffsetSimplifiedShape(float offset, EnumDirection direction) {
|
|
+ FinalObject<VoxelShape>[] offsetAndSimplified = this.offsetAndSimplified;
|
|
+ if (offsetAndSimplified == null) {
|
|
+ return null;
|
|
+ }
|
|
+ int index = getIndexForOffsetSimplifiedShapes(offset, direction);
|
|
+ //usage of FinalObject guarantees that we are seeing a fully initialized VoxelShape here, even when it was created on a different thread
|
|
+ FinalObject<VoxelShape> wrappedShape = offsetAndSimplified[index];
|
|
+ //noinspection FinalObjectAssignedToNull,FinalObjectGetWithoutIsPresent
|
|
+ return wrappedShape == null ? null : wrappedShape.getValue();
|
|
+ }
|
|
+
|
|
+ private static int getIndexForOffsetSimplifiedShapes(float offset, EnumDirection 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();
|
|
+ }
|
|
+ // Yatopia End
|
|
+
|
|
protected final VoxelShapeDiscrete a; public final VoxelShapeDiscrete getShape() { return this.a; } // Tuinity - OBFHELPER
|
|
@Nullable
|
|
private VoxelShape[] b;
|
|
diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java
|
|
index 98e787e6383a39de1708428137fd7f9e057ff153..049aa5f51e7517744b25f8c2c4b5e7a7de24a73e 100644
|
|
--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java
|
|
+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java
|
|
@@ -187,6 +187,7 @@ public final class VoxelShapes {
|
|
return (long) i * (long) (j / IntMath.gcd(i, j));
|
|
}
|
|
|
|
+ public static VoxelShape union(VoxelShape voxelshape, VoxelShape voxelshape1) { return a(voxelshape, voxelshape1); } // Yatopia - OBFHELPER
|
|
public static VoxelShape a(VoxelShape voxelshape, VoxelShape voxelshape1) {
|
|
return a(voxelshape, voxelshape1, OperatorBoolean.OR);
|
|
}
|