From 547709c2e04cf89349193bf952603aea95efac73 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Tue, 21 Jan 2025 17:17:04 +0100 Subject: [PATCH] The last arrow bender - Factory gauges try to default to an arrow direction that doesn't clip into blocks --- gradle.properties | 2 +- .../factoryBoard/FactoryPanelBlock.java | 7 +- .../factoryBoard/FactoryPanelConnection.java | 119 +++++++++++------- .../factoryBoard/FactoryPanelRenderer.java | 2 +- 4 files changed, 84 insertions(+), 46 deletions(-) diff --git a/gradle.properties b/gradle.properties index 3ab81a692c..fd696388f0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,7 +27,7 @@ jei_minecraft_version = 1.20.1 jei_version = 15.10.0.39 curios_minecraft_version = 1.20.1 curios_version = 5.3.1 -ponder_version = 0.9.18 +ponder_version = 0.9.19 mixin_extras_version = 0.4.1 cc_tweaked_enable = true diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlock.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlock.java index 73efb3a4e3..7004556103 100644 --- a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlock.java @@ -15,8 +15,8 @@ import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.utility.CreateLang; -import net.createmod.catnip.math.VecHelper; import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -48,6 +48,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.EntityCollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.common.ForgeMod; @@ -147,7 +148,7 @@ public class FactoryPanelBlock extends FaceAttachedHorizontalDirectionalBlock Player player = context.getPlayer(); PanelSlot slot = getTargetedSlot(pos, state, context.getClickLocation()); - if (!(world instanceof ServerLevel serverLevel)) + if (!(world instanceof ServerLevel)) return InteractionResult.SUCCESS; return onBlockEntityUse(world, pos, be -> { @@ -294,6 +295,8 @@ public class FactoryPanelBlock extends FaceAttachedHorizontalDirectionalBlock @Override public VoxelShape getCollisionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + if (pContext instanceof EntityCollisionContext ecc && ecc.getEntity() == null) + return getShape(pState, pLevel, pPos, pContext); return Shapes.empty(); } diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnection.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnection.java index d90c375fa2..faf48616c9 100644 --- a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnection.java +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnection.java @@ -10,7 +10,9 @@ import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; public class FactoryPanelConnection { @@ -49,58 +51,91 @@ public class FactoryPanelConnection { return nbt; } - public List getPath(BlockState state, FactoryPanelPosition to) { + public List getPath(Level level, BlockState state, FactoryPanelPosition to) { if (!path.isEmpty() && arrowBendModeCurrentPathUses == arrowBendMode) return path; + boolean findSuitable = arrowBendMode == -1; arrowBendModeCurrentPathUses = arrowBendMode; - path.clear(); - Vec3 diff = calculatePathDiff(state, to); - BlockPos toTravelFirst = BlockPos.ZERO; - BlockPos toTravelLast = BlockPos.containing(diff.scale(2) - .add(0.1, 0.1, 0.1)); + FactoryPanelBehaviour fromBehaviour = FactoryPanelBehaviour.at(level, to); + final Vec3 diff = calculatePathDiff(state, to); + final Vec3 start = fromBehaviour != null ? fromBehaviour.getSlotPositioning() + .getLocalOffset(level, to.pos(), state) + .add(Vec3.atLowerCornerOf(to.pos())) : Vec3.ZERO; + final float xRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getXRot(state); + final float yRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getYRot(state); - if (arrowBendMode > 1) { - boolean flipX = diff.x > 0 ^ (arrowBendMode % 2 == 1); - boolean flipZ = diff.z > 0 ^ (arrowBendMode % 2 == 0); - int ceilX = Mth.positiveCeilDiv(toTravelLast.getX(), 2); - int ceilZ = Mth.positiveCeilDiv(toTravelLast.getZ(), 2); - int floorZ = Mth.floorDiv(toTravelLast.getZ(), 2); - int floorX = Mth.floorDiv(toTravelLast.getX(), 2); - toTravelFirst = new BlockPos(flipX ? floorX : ceilX, 0, flipZ ? floorZ : ceilZ); - toTravelLast = new BlockPos(!flipX ? floorX : ceilX, 0, !flipZ ? floorZ : ceilZ); - } + // When mode is not locked, find one that doesnt intersect with other gauges + ModeFinder: for (int actualMode = 0; actualMode <= 4; actualMode++) { + path.clear(); + if (!findSuitable && actualMode != arrowBendMode) + continue; + boolean desperateOption = actualMode == 4; - Direction lastDirection = null; - Direction currentDirection = null; + BlockPos toTravelFirst = BlockPos.ZERO; + BlockPos toTravelLast = BlockPos.containing(diff.scale(2) + .add(0.1, 0.1, 0.1)); - for (BlockPos toTravel : List.of(toTravelFirst, toTravelLast)) { - boolean zIsPreferred = - arrowBendMode == -1 ? (Math.abs(toTravel.getZ()) > Math.abs(toTravel.getX())) : arrowBendMode % 2 == 1; - List directionOrder = - zIsPreferred ? List.of(Direction.SOUTH, Direction.NORTH, Direction.WEST, Direction.EAST) - : List.of(Direction.WEST, Direction.EAST, Direction.SOUTH, Direction.NORTH); - - for (int i = 0; i < 100; i++) { - if (toTravel.equals(BlockPos.ZERO)) - break; - - for (Direction d : directionOrder) { - if (lastDirection != null && d == lastDirection.getOpposite()) - continue; - if (currentDirection == null || toTravel.relative(d) - .distManhattan(BlockPos.ZERO) < toTravel.relative(currentDirection) - .distManhattan(BlockPos.ZERO)) - currentDirection = d; - } - - lastDirection = currentDirection; - toTravel = toTravel.relative(currentDirection); - path.add(currentDirection); + if (actualMode > 1) { + boolean flipX = diff.x > 0 ^ (actualMode % 2 == 1); + boolean flipZ = diff.z > 0 ^ (actualMode % 2 == 0); + int ceilX = Mth.positiveCeilDiv(toTravelLast.getX(), 2); + int ceilZ = Mth.positiveCeilDiv(toTravelLast.getZ(), 2); + int floorZ = Mth.floorDiv(toTravelLast.getZ(), 2); + int floorX = Mth.floorDiv(toTravelLast.getX(), 2); + toTravelFirst = new BlockPos(flipX ? floorX : ceilX, 0, flipZ ? floorZ : ceilZ); + toTravelLast = new BlockPos(!flipX ? floorX : ceilX, 0, !flipZ ? floorZ : ceilZ); } - } + Direction lastDirection = null; + Direction currentDirection = null; + + for (BlockPos toTravel : List.of(toTravelFirst, toTravelLast)) { + boolean zIsFarther = Math.abs(toTravel.getZ()) > Math.abs(toTravel.getX()); + boolean zIsPreferred = desperateOption ? zIsFarther : actualMode % 2 == 1; + List directionOrder = + zIsPreferred ? List.of(Direction.SOUTH, Direction.NORTH, Direction.WEST, Direction.EAST) + : List.of(Direction.WEST, Direction.EAST, Direction.SOUTH, Direction.NORTH); + + for (int i = 0; i < 100; i++) { + if (toTravel.equals(BlockPos.ZERO)) + break; + + for (Direction d : directionOrder) { + if (lastDirection != null && d == lastDirection.getOpposite()) + continue; + if (currentDirection == null || toTravel.relative(d) + .distManhattan(BlockPos.ZERO) < toTravel.relative(currentDirection) + .distManhattan(BlockPos.ZERO)) + currentDirection = d; + } + + lastDirection = currentDirection; + toTravel = toTravel.relative(currentDirection); + path.add(currentDirection); + } + } + + if (findSuitable && !desperateOption) { + BlockPos travelled = BlockPos.ZERO; + for (int i = 0; i < path.size() - 1; i++) { + Direction d = path.get(i); + travelled = travelled.relative(d); + Vec3 testOffset = Vec3.atLowerCornerOf(travelled) + .scale(0.5); + testOffset = VecHelper.rotate(testOffset, 180, Axis.Y); + testOffset = VecHelper.rotate(testOffset, xRot + 90, Axis.X); + testOffset = VecHelper.rotate(testOffset, yRot, Axis.Y); + Vec3 v = start.add(testOffset); + if (!level.noCollision(new AABB(v, v).inflate(1 / 128f))) + continue ModeFinder; + } + } + + break; + } + return path; } diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelRenderer.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelRenderer.java index f9b109431f..951481cb88 100644 --- a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelRenderer.java @@ -86,7 +86,7 @@ public class FactoryPanelRenderer extends SmartBlockEntityRenderer path = connection.getPath(blockState, behaviour.getPanelPosition()); + List path = connection.getPath(behaviour.getWorld(), blockState, behaviour.getPanelPosition()); float xRot = FactoryPanelBlock.getXRot(blockState) + Mth.PI / 2; float yRot = FactoryPanelBlock.getYRot(blockState);