From d61e387916cb911ab1221936581ecd91ed6a7553 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Wed, 31 Mar 2021 14:27:27 +0200 Subject: [PATCH 1/3] The least performant option - Fixed slow merging of collision shapes - Improved async handling of the collision shape merger - BBs far away from an entity now get skipped in the collision cycle --- .../AbstractContraptionEntity.java | 2 ++ .../structureMovement/Contraption.java | 33 +++++++++++-------- .../ContraptionCollider.java | 13 ++++++-- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java index 867d8d685..d50d90658 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java @@ -461,6 +461,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit if (!ticking) contraption.stop(world); } + if (contraption != null) + contraption.onEntityRemoved(this); super.remove(keepData); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java index 249377298..659c2f591 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java @@ -137,7 +137,7 @@ public abstract class Contraption { private Map initialPassengers; private List pendingSubContraptions; - private CompletableFuture> simplifiedEntityColliderProvider; + private CompletableFuture simplifiedEntityColliderProvider; // Client public Map presentTileEntities; @@ -193,6 +193,7 @@ public abstract class Contraption { String type = nbt.getString("Type"); Contraption contraption = ContraptionType.fromType(type); contraption.readNBT(world, nbt, spawnData); + contraption.world = new ContraptionWorld(world, contraption); contraption.gatherBBsOffThread(); return contraption; } @@ -260,6 +261,13 @@ public abstract class Contraption { gatherBBsOffThread(); } + public void onEntityRemoved(AbstractContraptionEntity entity) { + if (simplifiedEntityColliderProvider != null) { + simplifiedEntityColliderProvider.cancel(false); + simplifiedEntityColliderProvider = null; + } + } + public void onEntityInitialize(World world, AbstractContraptionEntity contraptionEntity) { if (world.isRemote) return; @@ -282,15 +290,6 @@ public abstract class Contraption { } public void onEntityTick(World world) { - if (simplifiedEntityColliderProvider != null && simplifiedEntityColliderProvider.isDone()) { - try { - simplifiedEntityColliders = Optional.of(simplifiedEntityColliderProvider.join()); - } catch (Exception e) { - e.printStackTrace(); - } - simplifiedEntityColliderProvider = null; - } - fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, world.isRemote)); } @@ -1182,19 +1181,25 @@ public abstract class Contraption { } private void gatherBBsOffThread() { + getContraptionWorld(); simplifiedEntityColliderProvider = CompletableFuture.supplyAsync(() -> { VoxelShape combinedShape = VoxelShapes.empty(); for (Entry entry : blocks.entrySet()) { BlockInfo info = entry.getValue(); BlockPos localPos = entry.getKey(); - VoxelShape collisionShape = info.state.getCollisionShape(this.world, localPos); + VoxelShape collisionShape = info.state.getCollisionShape(world, localPos); if (collisionShape.isEmpty()) continue; - combinedShape = VoxelShapes.combineAndSimplify(combinedShape, + combinedShape = VoxelShapes.combine(combinedShape, collisionShape.withOffset(localPos.getX(), localPos.getY(), localPos.getZ()), IBooleanFunction.OR); } - return combinedShape.toBoundingBoxList(); - }); + return combinedShape.simplify() + .toBoundingBoxList(); + }) + .thenAccept(r -> { + simplifiedEntityColliders = Optional.of(r); + simplifiedEntityColliderProvider = null; + }); } public static float getRadius(Set blocks, Direction.Axis axis) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java index b95319e45..706805838 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java @@ -118,7 +118,6 @@ public class ContraptionCollider { motion = rotationMatrix.transform(motion); // Use simplified bbs when present - // TODO: is it worth filtering out far away bbs? final Vec3d motionCopy = motion; List collidableBBs = contraption.simplifiedEntityColliders.orElseGet(() -> { @@ -147,7 +146,17 @@ public class ContraptionCollider { for (AxisAlignedBB bb : collidableBBs) { Vec3d currentResponse = collisionResponse.getValue(); - obb.setCenter(obbCenter.add(currentResponse)); + Vec3d currentCenter = obbCenter.add(currentResponse); + + if (Math.abs(currentCenter.x - bb.getCenter().x) - entityBounds.getXSize() - 1 > bb.getXSize() / 2) + continue; + if (Math.abs((currentCenter.y + motion.y) - bb.getCenter().y) - entityBounds.getYSize() + - 1 > bb.getYSize() / 2) + continue; + if (Math.abs(currentCenter.z - bb.getCenter().z) - entityBounds.getZSize() - 1 > bb.getZSize() / 2) + continue; + + obb.setCenter(currentCenter); ContinuousSeparationManifold intersect = obb.intersect(bb, motion); if (intersect == null) From 5b63f30df390c045d5c0b8b07189ed229a50460f Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:22:41 +0200 Subject: [PATCH 2/3] Abort Mission - Drills and other block breakers on contraptions now give up trying to destroy a block when their movement direction is reversed --- .../components/actors/DrillMovementBehaviour.java | 5 ++--- .../bearing/MechanicalBearingTileEntity.java | 5 +++++ .../structureMovement/gantry/GantryContraptionEntity.java | 2 ++ .../piston/LinearActuatorTileEntity.java | 8 +++++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java index fd9a3959a..914ac161d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java @@ -1,10 +1,11 @@ package com.simibubi.create.content.contraptions.components.actors; +import javax.annotation.Nullable; + import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.VecHelper; @@ -17,8 +18,6 @@ import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import javax.annotation.Nullable; - public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java index e92e9ff22..4f3525ae6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java @@ -101,6 +101,11 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity public void onSpeedChanged(float prevSpeed) { super.onSpeedChanged(prevSpeed); assembleNextTick = true; + + if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) { + movedContraption.getContraption() + .stop(world); + } } public float getAngularSpeed() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java index c16b3d03d..003142dbf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java @@ -69,6 +69,8 @@ public class GantryContraptionEntity extends AbstractContraptionEntity { if (!isStalled() && ticksExisted > 2) move(movementVec.x, movementVec.y, movementVec.z); + if (Math.signum(prevAxisMotion) != Math.signum(axisMotion) && prevAxisMotion != 0) + contraption.stop(world); if (!world.isRemote && (prevAxisMotion != axisMotion || ticksExisted % 3 == 0)) sendPacket(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java index c958b6a92..4694bf984 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java @@ -20,7 +20,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; -public abstract class LinearActuatorTileEntity extends KineticTileEntity implements IControlContraption, IDisplayAssemblyExceptions { +public abstract class LinearActuatorTileEntity extends KineticTileEntity + implements IControlContraption, IDisplayAssemblyExceptions { public float offset; public boolean running; @@ -147,6 +148,11 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme super.onSpeedChanged(prevSpeed); assembleNextTick = true; waitingForSpeedChange = false; + + if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) { + movedContraption.getContraption() + .stop(world); + } } @Override From ba63cc3e7fe9fb78802fc632d0172925511c2202 Mon Sep 17 00:00:00 2001 From: Snownee Date: Thu, 1 Apr 2021 01:41:57 +0800 Subject: [PATCH 3/3] Fix tree fertilizer spreading podzol. Backport a440ab6 --- .../curiosities/TreeFertilizerItem.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java b/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java index 104095a74..c47b26f17 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java @@ -31,8 +31,8 @@ public class TreeFertilizerItem extends Item { return ActionResultType.SUCCESS; } - TreesDreamWorld world = new TreesDreamWorld((ServerWorld) context.getWorld()); BlockPos saplingPos = context.getPos(); + TreesDreamWorld world = new TreesDreamWorld((ServerWorld) context.getWorld(), saplingPos); for (BlockPos pos : BlockPos.getAllInBoxMutable(-1, 0, -1, 1, 0, 1)) { if (context.getWorld() @@ -45,8 +45,8 @@ public class TreeFertilizerItem extends Item { state.with(SaplingBlock.STAGE, 1)); for (BlockPos pos : world.blocksAdded.keySet()) { - BlockPos actualPos = pos.add(saplingPos) - .down(10); + BlockPos actualPos = pos.add(saplingPos).down(10); + BlockState newState = world.blocksAdded.get(pos); // Don't replace Bedrock if (context.getWorld() @@ -54,21 +54,15 @@ public class TreeFertilizerItem extends Item { .getBlockHardness(context.getWorld(), actualPos) == -1) continue; // Don't replace solid blocks with leaves - if (!world.getBlockState(pos) - .isNormalCube(world, pos) + if (!newState.isNormalCube(world, pos) && !context.getWorld() .getBlockState(actualPos) .getCollisionShape(context.getWorld(), actualPos) .isEmpty()) continue; - if (world.getBlockState(pos) - .getBlock() == Blocks.GRASS_BLOCK - || world.getBlockState(pos) - .getBlock() == Blocks.PODZOL) - continue; context.getWorld() - .setBlockState(actualPos, world.getBlockState(pos)); + .setBlockState(actualPos, newState); } if (context.getPlayer() != null && !context.getPlayer() @@ -83,18 +77,26 @@ public class TreeFertilizerItem extends Item { } private class TreesDreamWorld extends PlacementSimulationServerWorld { + private final BlockState soil; - protected TreesDreamWorld(ServerWorld wrapped) { + protected TreesDreamWorld(ServerWorld wrapped, BlockPos saplingPos) { super(wrapped); + soil = wrapped.getBlockState(saplingPos.down()); } @Override public BlockState getBlockState(BlockPos pos) { if (pos.getY() <= 9) - return Blocks.GRASS_BLOCK.getDefaultState(); + return soil; return super.getBlockState(pos); } + @Override + public boolean setBlockState(BlockPos pos, BlockState newState, int flags) { + if (newState.getBlock() == Blocks.PODZOL) + return true; + return super.setBlockState(pos, newState, flags); + } } }