mirror of
https://github.com/YatopiaMC/Yatopia.git
synced 2024-11-26 04:25:39 +01:00
Fix oversized block collisions
We went thru a bunch of effort for this fix, but its finally been patched. In the meantime I ported jellysquid's latest changes to entity collisions which also work completely fine. Thanks to Simon ( @smonnnn ) who is also going to be the co-author of this commit cuz he was the one to properly implement the problematic patch . These changes should lower your mspt. Fixes #165 Fixes #178 Co-authored-by: Simon L <slooij1@gmail.com>
This commit is contained in:
parent
71c51a9aa2
commit
339da44a99
@ -178,10 +178,10 @@ index 0000000000000000000000000000000000000000..20f80ae80de91615ea02f0771f7c020c
|
||||
+}
|
||||
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/entity/LithiumEntityCollisions.java b/src/main/java/me/jellysquid/mods/lithium/common/entity/LithiumEntityCollisions.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7ef9775d351446637dd70e79497164913845c729
|
||||
index 0000000000000000000000000000000000000000..a009068a2ac9c1671978cfd942b83c5b414b3c7a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/me/jellysquid/mods/lithium/common/entity/LithiumEntityCollisions.java
|
||||
@@ -0,0 +1,193 @@
|
||||
@@ -0,0 +1,179 @@
|
||||
+package me.jellysquid.mods.lithium.common.entity;
|
||||
+
|
||||
+import dev.tr7zw.yatopia.EntityFilter;
|
||||
@ -228,27 +228,13 @@ index 0000000000000000000000000000000000000000..7ef9775d351446637dd70e7949716491
|
||||
+ public static Producer<AxisAlignedBB> getBlockCollisionProducerAABB(ICollisionAccess world, Entity entity, AxisAlignedBB box) {
|
||||
+ final ChunkAwareBlockCollisionSweeper sweeper = new ChunkAwareBlockCollisionSweeper(world, entity, box);
|
||||
+
|
||||
+ return new Producer<AxisAlignedBB>() {
|
||||
+ private boolean skipWorldBorderCheck = entity == null;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean computeNext(Consumer<? super AxisAlignedBB> consumer) {
|
||||
+ if (!this.skipWorldBorderCheck) {
|
||||
+ this.skipWorldBorderCheck = true;
|
||||
+
|
||||
+ if (canEntityCollideWithWorldBorder(world, entity)) {
|
||||
+ consumer.accept(world.getWorldBorder().asVoxelShape().getBoundingBox());
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ VoxelShape shape = sweeper.step();
|
||||
+ if (shape != null) {
|
||||
+ consumer.accept(shape.getBoundingBox());
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ return consumer -> {
|
||||
+ VoxelShape shape = sweeper.getNextCollidedShape();
|
||||
+ if (shape != null) {
|
||||
+ consumer.accept(shape.getBoundingBox());
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
@ -264,7 +250,7 @@ index 0000000000000000000000000000000000000000..7ef9775d351446637dd70e7949716491
|
||||
+
|
||||
+ final ChunkAwareBlockCollisionSweeper sweeper = new ChunkAwareBlockCollisionSweeper(world, entity, box);
|
||||
+
|
||||
+ VoxelShape shape = sweeper.step();
|
||||
+ VoxelShape shape = sweeper.getNextCollidedShape();
|
||||
+ return shape != null;
|
||||
+ }
|
||||
+
|
||||
@ -351,7 +337,7 @@ index 0000000000000000000000000000000000000000..7ef9775d351446637dd70e7949716491
|
||||
+ *
|
||||
+ * @return True if the {@param box} is fully within the {@param border}, otherwise false.
|
||||
+ */
|
||||
+ public static boolean isBoxFullyWithinWorldBorder(WorldBorder border, AxisAlignedBB box) {
|
||||
+ public static boolean isWithinWorldBorder(WorldBorder border, AxisAlignedBB box) {
|
||||
+ double wboxMinX = Math.floor(border.getMinX());
|
||||
+ double wboxMinZ = Math.floor(border.getMinZ());
|
||||
+
|
||||
@ -362,11 +348,11 @@ index 0000000000000000000000000000000000000000..7ef9775d351446637dd70e7949716491
|
||||
+ box.maxX >= wboxMinX && box.maxX < wboxMaxX && box.maxZ >= wboxMinZ && box.maxZ < wboxMaxZ;
|
||||
+ }
|
||||
+
|
||||
+ private static boolean canEntityCollideWithWorldBorder(ICollisionAccess world, Entity entity) {
|
||||
+ public static boolean canEntityCollideWithWorldBorder(ICollisionAccess world, Entity entity) {
|
||||
+ WorldBorder border = world.getWorldBorder();
|
||||
+
|
||||
+ boolean isInsideBorder = isBoxFullyWithinWorldBorder(border, entity.getBoundingBox().shrink(EPSILON));
|
||||
+ boolean isCrossingBorder = isBoxFullyWithinWorldBorder(border, entity.getBoundingBox().grow(EPSILON));
|
||||
+ boolean isInsideBorder = isWithinWorldBorder(border, entity.getBoundingBox().shrink(EPSILON));
|
||||
+ boolean isCrossingBorder = isWithinWorldBorder(border, entity.getBoundingBox().grow(EPSILON));
|
||||
+
|
||||
+ return !isInsideBorder && isCrossingBorder;
|
||||
+ }
|
||||
@ -377,12 +363,13 @@ index 0000000000000000000000000000000000000000..7ef9775d351446637dd70e7949716491
|
||||
+}
|
||||
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/entity/movement/ChunkAwareBlockCollisionSweeper.java b/src/main/java/me/jellysquid/mods/lithium/common/entity/movement/ChunkAwareBlockCollisionSweeper.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b9d279d1a9703c17221d4219b86b8f31bdcc2895
|
||||
index 0000000000000000000000000000000000000000..508fe7cf5281cff7528b90e584c17e73fc5a2388
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/me/jellysquid/mods/lithium/common/entity/movement/ChunkAwareBlockCollisionSweeper.java
|
||||
@@ -0,0 +1,247 @@
|
||||
@@ -0,0 +1,279 @@
|
||||
+package me.jellysquid.mods.lithium.common.entity.movement;
|
||||
+
|
||||
+import me.jellysquid.mods.lithium.common.entity.LithiumEntityCollisions;
|
||||
+import net.minecraft.server.AxisAlignedBB;
|
||||
+import net.minecraft.server.BlockPosition;
|
||||
+import net.minecraft.server.Blocks;
|
||||
@ -422,6 +409,8 @@ index 0000000000000000000000000000000000000000..b9d279d1a9703c17221d4219b86b8f31
|
||||
+ private final ICollisionAccess view;
|
||||
+ private final VoxelShapeCollision context;
|
||||
+
|
||||
+ private final Entity entity;
|
||||
+
|
||||
+ //limits of the area without extension for oversized blocks
|
||||
+ private final int minX, minY, minZ, maxX, maxY, maxZ;
|
||||
+
|
||||
@ -437,6 +426,7 @@ index 0000000000000000000000000000000000000000..b9d279d1a9703c17221d4219b86b8f31
|
||||
+ private boolean sectionOversizedBlocks;
|
||||
+ private IChunkAccess cachedChunk;
|
||||
+ private ChunkSection cachedChunkSection;
|
||||
+ private boolean needEntityCollisionCheck;
|
||||
+
|
||||
+ public ChunkAwareBlockCollisionSweeper(ICollisionAccess view, Entity entity, AxisAlignedBB box) {
|
||||
+ this.box = box;
|
||||
@ -444,6 +434,8 @@ index 0000000000000000000000000000000000000000..b9d279d1a9703c17221d4219b86b8f31
|
||||
+ // todo: ivan, make obfhelpers
|
||||
+ this.context = entity == null ? VoxelShapeCollision.a() : VoxelShapeCollision.a(entity);
|
||||
+ this.view = view;
|
||||
+ this.entity = entity;
|
||||
+ this.needEntityCollisionCheck = entity != null;
|
||||
+
|
||||
+ this.minX = MathHelper.floor(box.minX - EPSILON);
|
||||
+ this.maxX = MathHelper.floor(box.maxX + EPSILON);
|
||||
@ -517,17 +509,33 @@ index 0000000000000000000000000000000000000000..b9d279d1a9703c17221d4219b86b8f31
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ public VoxelShape getNextCollidedShape() {
|
||||
+ VoxelShape shape = null;
|
||||
+
|
||||
+ if (this.needEntityCollisionCheck) {
|
||||
+ shape = this.getNextEntityCollision();
|
||||
+
|
||||
+ this.needEntityCollisionCheck = false;
|
||||
+ }
|
||||
+
|
||||
+ if (shape == null) {
|
||||
+ shape = this.getNextBlockCollision();
|
||||
+ }
|
||||
+
|
||||
+ return shape;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /**
|
||||
+ * Advances the sweep forward until finding a block with a box-colliding VoxelShape
|
||||
+ *
|
||||
+ * @return null if no VoxelShape is left in the area, otherwise the next VoxelShape
|
||||
+ */
|
||||
+ public VoxelShape step() {
|
||||
+ private VoxelShape getNextBlockCollision() {
|
||||
+ while (true) {
|
||||
+ if (this.cIterated >= this.cTotalSize) {
|
||||
+ if (!this.nextSection()) {
|
||||
+ return null;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ this.cIterated++;
|
||||
@ -578,6 +586,16 @@ index 0000000000000000000000000000000000000000..b9d279d1a9703c17221d4219b86b8f31
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ private VoxelShape getNextEntityCollision() {
|
||||
+ if (LithiumEntityCollisions.canEntityCollideWithWorldBorder(this.view, this.entity)) {
|
||||
+ return this.view.getWorldBorder().asVoxelShape();
|
||||
+ }
|
||||
+
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
|
@ -7,61 +7,20 @@ Original code by JellySquid, licensed under LGPLv3
|
||||
you can find the original code on https://github.com/jellysquid3/lithium-fabric/ (Yarn mappings)
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockBase.java b/src/main/java/net/minecraft/server/BlockBase.java
|
||||
index 1d02880e5818d22c13d67d3f44844a2cca51c164..4ece27e3e6885246bc8b54b9277e01211db4f989 100644
|
||||
index 1d02880e5818d22c13d67d3f44844a2cca51c164..13f541390040d07229de0fbb1cfa4bcfe7d0794f 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockBase.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockBase.java
|
||||
@@ -339,10 +339,11 @@ public abstract class BlockBase {
|
||||
// Paper end
|
||||
|
||||
// Tuinity start - micro the hell out of this call
|
||||
- protected boolean shapeExceedsCube = true;
|
||||
+ protected boolean shapeExceedsCube = this.shapeExceedsCube(); // Yatopia start - re add this function or collisions break
|
||||
public final boolean shapeExceedsCube() {
|
||||
- return this.shapeExceedsCube;
|
||||
+ return this.a == null || this.a.c;
|
||||
@@ -345,6 +345,8 @@ public abstract class BlockBase {
|
||||
}
|
||||
+ // Yatiopia end
|
||||
// Tuinity end
|
||||
|
||||
+ public final boolean shapeExceedsCubeUncached() { return this.a == null || this.a.c; } // Yatopia - uncached shapeExceedsCube due to collisions stuff
|
||||
+
|
||||
// Tuinity start
|
||||
@@ -356,8 +357,6 @@ public abstract class BlockBase {
|
||||
if (!this.getBlock().o()) {
|
||||
this.a = new BlockBase.BlockData.Cache(this.p());
|
||||
}
|
||||
- this.shapeExceedsCube = this.a == null || this.a.c; // Tuinity - moved from actual method to here
|
||||
-
|
||||
}
|
||||
|
||||
public Block getBlock() {
|
||||
@@ -607,7 +606,25 @@ public abstract class BlockBase {
|
||||
}
|
||||
|
||||
public IBlockData updateState(EnumDirection enumdirection, IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) {
|
||||
- return this.getBlock().updateState(this.p(), enumdirection, iblockdata, generatoraccess, blockposition, blockposition1);
|
||||
+ // Yatopia start
|
||||
+ IBlockData updated = this.getBlock().updateState(this.p(), enumdirection, iblockdata, generatoraccess, blockposition, blockposition1);
|
||||
+ if (updated.shapeExceedsCube()) {
|
||||
+ IChunkAccess chunk = generatoraccess.getChunkIfLoadedImmediately(blockposition1.getX() >> 4, blockposition1.getZ() >> 4);
|
||||
+ if (chunk != null) {
|
||||
+ ChunkSection section = chunk.getSections()[blockposition1.getY() >> 4];
|
||||
+ if (section != null) section.oversizedBlockCount++;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (iblockdata.shapeExceedsCube()) {
|
||||
+ IChunkAccess chunk = generatoraccess.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
+ if (chunk != null) {
|
||||
+ ChunkSection section = chunk.getSections()[blockposition.getY() >> 4];
|
||||
+ if (section != null) section.oversizedBlockCount--;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return updated;
|
||||
+ // Yatopia end
|
||||
}
|
||||
|
||||
public boolean a(IBlockAccess iblockaccess, BlockPosition blockposition, PathMode pathmode) {
|
||||
protected boolean isTicking;
|
||||
protected Fluid fluid;
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkSection.java b/src/main/java/net/minecraft/server/ChunkSection.java
|
||||
index cebd808e273dbdb88feb16920dd7a2f60390b34f..478af91f52272424da61d626534298290d6385f5 100644
|
||||
index cebd808e273dbdb88feb16920dd7a2f60390b34f..d210ac3d5775491e9beb885dde608f5e8fda8eb2 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkSection.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkSection.java
|
||||
@@ -4,7 +4,7 @@ import java.util.function.Predicate;
|
||||
@ -77,31 +36,27 @@ index cebd808e273dbdb88feb16920dd7a2f60390b34f..478af91f52272424da61d62653429829
|
||||
short tickingBlockCount; // Paper - private -> package-private
|
||||
private short e;
|
||||
final DataPaletteBlock<IBlockData> blockIds; // Paper - package-private
|
||||
+ short oversizedBlockCount = 0; // Yatopia
|
||||
+ private short oversizedBlockCount = 0; // Yatopia
|
||||
|
||||
final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper
|
||||
|
||||
@@ -67,6 +68,9 @@ public class ChunkSection {
|
||||
@@ -67,6 +68,7 @@ public class ChunkSection {
|
||||
|
||||
if (!iblockdata1.isAir()) {
|
||||
--this.nonEmptyBlockCount;
|
||||
+ if(iblockdata1.shapeExceedsCube()){ //Yatopia - lithium oversized blocks count
|
||||
+ --this.oversizedBlockCount;
|
||||
+ } // Yatopia end
|
||||
+ if (iblockdata1.shapeExceedsCubeUncached()) this.oversizedBlockCount--; // Yatopia
|
||||
if (iblockdata1.isTicking()) {
|
||||
--this.tickingBlockCount;
|
||||
// Paper start
|
||||
@@ -81,6 +85,9 @@ public class ChunkSection {
|
||||
@@ -81,6 +83,7 @@ public class ChunkSection {
|
||||
|
||||
if (!iblockdata.isAir()) {
|
||||
++this.nonEmptyBlockCount;
|
||||
+ if(iblockdata.shapeExceedsCube()){ //Yatopia - lithium oversized blocks count
|
||||
+ ++this.oversizedBlockCount;
|
||||
+ } // Yatopia end
|
||||
+ if (iblockdata.shapeExceedsCubeUncached()) this.oversizedBlockCount++; // Yatopia
|
||||
if (iblockdata.isTicking()) {
|
||||
++this.tickingBlockCount;
|
||||
// Paper start
|
||||
@@ -126,10 +133,12 @@ public class ChunkSection {
|
||||
@@ -126,10 +129,12 @@ public class ChunkSection {
|
||||
// Paper start
|
||||
this.tickingList.clear();
|
||||
// Paper end
|
||||
@ -110,11 +65,11 @@ index cebd808e273dbdb88feb16920dd7a2f60390b34f..478af91f52272424da61d62653429829
|
||||
this.tickingBlockCount = 0;
|
||||
this.e = 0;
|
||||
this.blockIds.forEachLocation((iblockdata, location) -> { // Paper
|
||||
+ if (iblockdata.shapeExceedsCube()) this.oversizedBlockCount += location; // Yatopia
|
||||
+ if (iblockdata.shapeExceedsCubeUncached()) this.oversizedBlockCount += location; // Yatopia
|
||||
Fluid fluid = iblockdata.getFluid();
|
||||
|
||||
if (!iblockdata.isAir()) {
|
||||
@@ -173,4 +182,11 @@ public class ChunkSection {
|
||||
@@ -173,4 +178,11 @@ public class ChunkSection {
|
||||
public boolean a(Predicate<IBlockData> predicate) {
|
||||
return this.blockIds.contains(predicate);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user