The last arrow bender

- Factory gauges try to default to an arrow direction that doesn't clip into blocks
This commit is contained in:
simibubi 2025-01-21 17:17:04 +01:00
parent 1b64d01010
commit 547709c2e0
4 changed files with 84 additions and 46 deletions

View file

@ -27,7 +27,7 @@ jei_minecraft_version = 1.20.1
jei_version = 15.10.0.39 jei_version = 15.10.0.39
curios_minecraft_version = 1.20.1 curios_minecraft_version = 1.20.1
curios_version = 5.3.1 curios_version = 5.3.1
ponder_version = 0.9.18 ponder_version = 0.9.19
mixin_extras_version = 0.4.1 mixin_extras_version = 0.4.1
cc_tweaked_enable = true cc_tweaked_enable = true

View file

@ -15,8 +15,8 @@ import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.CreateLang;
import net.createmod.catnip.math.VecHelper;
import net.createmod.catnip.math.AngleHelper; import net.createmod.catnip.math.AngleHelper;
import net.createmod.catnip.math.VecHelper;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis; 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.HitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext; 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.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.ForgeMod;
@ -147,7 +148,7 @@ public class FactoryPanelBlock extends FaceAttachedHorizontalDirectionalBlock
Player player = context.getPlayer(); Player player = context.getPlayer();
PanelSlot slot = getTargetedSlot(pos, state, context.getClickLocation()); PanelSlot slot = getTargetedSlot(pos, state, context.getClickLocation());
if (!(world instanceof ServerLevel serverLevel)) if (!(world instanceof ServerLevel))
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
return onBlockEntityUse(world, pos, be -> { return onBlockEntityUse(world, pos, be -> {
@ -294,6 +295,8 @@ public class FactoryPanelBlock extends FaceAttachedHorizontalDirectionalBlock
@Override @Override
public VoxelShape getCollisionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, public VoxelShape getCollisionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos,
CollisionContext pContext) { CollisionContext pContext) {
if (pContext instanceof EntityCollisionContext ecc && ecc.getEntity() == null)
return getShape(pState, pLevel, pPos, pContext);
return Shapes.empty(); return Shapes.empty();
} }

View file

@ -10,7 +10,9 @@ import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.Axis;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
public class FactoryPanelConnection { public class FactoryPanelConnection {
@ -49,21 +51,35 @@ public class FactoryPanelConnection {
return nbt; return nbt;
} }
public List<Direction> getPath(BlockState state, FactoryPanelPosition to) { public List<Direction> getPath(Level level, BlockState state, FactoryPanelPosition to) {
if (!path.isEmpty() && arrowBendModeCurrentPathUses == arrowBendMode) if (!path.isEmpty() && arrowBendModeCurrentPathUses == arrowBendMode)
return path; return path;
boolean findSuitable = arrowBendMode == -1;
arrowBendModeCurrentPathUses = arrowBendMode; arrowBendModeCurrentPathUses = arrowBendMode;
path.clear();
Vec3 diff = calculatePathDiff(state, to); 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);
// 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;
BlockPos toTravelFirst = BlockPos.ZERO; BlockPos toTravelFirst = BlockPos.ZERO;
BlockPos toTravelLast = BlockPos.containing(diff.scale(2) BlockPos toTravelLast = BlockPos.containing(diff.scale(2)
.add(0.1, 0.1, 0.1)); .add(0.1, 0.1, 0.1));
if (arrowBendMode > 1) { if (actualMode > 1) {
boolean flipX = diff.x > 0 ^ (arrowBendMode % 2 == 1); boolean flipX = diff.x > 0 ^ (actualMode % 2 == 1);
boolean flipZ = diff.z > 0 ^ (arrowBendMode % 2 == 0); boolean flipZ = diff.z > 0 ^ (actualMode % 2 == 0);
int ceilX = Mth.positiveCeilDiv(toTravelLast.getX(), 2); int ceilX = Mth.positiveCeilDiv(toTravelLast.getX(), 2);
int ceilZ = Mth.positiveCeilDiv(toTravelLast.getZ(), 2); int ceilZ = Mth.positiveCeilDiv(toTravelLast.getZ(), 2);
int floorZ = Mth.floorDiv(toTravelLast.getZ(), 2); int floorZ = Mth.floorDiv(toTravelLast.getZ(), 2);
@ -76,8 +92,8 @@ public class FactoryPanelConnection {
Direction currentDirection = null; Direction currentDirection = null;
for (BlockPos toTravel : List.of(toTravelFirst, toTravelLast)) { for (BlockPos toTravel : List.of(toTravelFirst, toTravelLast)) {
boolean zIsPreferred = boolean zIsFarther = Math.abs(toTravel.getZ()) > Math.abs(toTravel.getX());
arrowBendMode == -1 ? (Math.abs(toTravel.getZ()) > Math.abs(toTravel.getX())) : arrowBendMode % 2 == 1; boolean zIsPreferred = desperateOption ? zIsFarther : actualMode % 2 == 1;
List<Direction> directionOrder = List<Direction> directionOrder =
zIsPreferred ? List.of(Direction.SOUTH, Direction.NORTH, Direction.WEST, Direction.EAST) zIsPreferred ? List.of(Direction.SOUTH, Direction.NORTH, Direction.WEST, Direction.EAST)
: List.of(Direction.WEST, Direction.EAST, Direction.SOUTH, Direction.NORTH); : List.of(Direction.WEST, Direction.EAST, Direction.SOUTH, Direction.NORTH);
@ -101,6 +117,25 @@ public class FactoryPanelConnection {
} }
} }
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; return path;
} }

View file

@ -86,7 +86,7 @@ public class FactoryPanelRenderer extends SmartBlockEntityRenderer<FactoryPanelB
public static void renderPath(FactoryPanelBehaviour behaviour, FactoryPanelConnection connection, public static void renderPath(FactoryPanelBehaviour behaviour, FactoryPanelConnection connection,
float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) {
BlockState blockState = behaviour.blockEntity.getBlockState(); BlockState blockState = behaviour.blockEntity.getBlockState();
List<Direction> path = connection.getPath(blockState, behaviour.getPanelPosition()); List<Direction> path = connection.getPath(behaviour.getWorld(), blockState, behaviour.getPanelPosition());
float xRot = FactoryPanelBlock.getXRot(blockState) + Mth.PI / 2; float xRot = FactoryPanelBlock.getXRot(blockState) + Mth.PI / 2;
float yRot = FactoryPanelBlock.getYRot(blockState); float yRot = FactoryPanelBlock.getYRot(blockState);