Better bounding boxes for bearings.

- Fix bug causing entities to slip off the far corners of bearing contraptions.
 - This was already implemented for BearingLighter.java, now it's promoted to Contraption.java.
 - Promote anonymous WrappedWorld in Contraption.java to inner class.
This commit is contained in:
JozsefA 2021-03-10 17:08:20 -08:00
parent b7f0fe9b10
commit c54d80a161
4 changed files with 83 additions and 96 deletions

View file

@ -20,6 +20,9 @@ import java.util.stream.Collectors;
import javax.annotation.Nullable;
import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
import com.simibubi.create.foundation.render.backend.light.GridAlignedBB;
import com.simibubi.create.foundation.utility.*;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
@ -53,12 +56,6 @@ import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import com.simibubi.create.foundation.render.backend.light.EmptyLighter;
import com.simibubi.create.foundation.utility.BlockFace;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.NBTProcessors;
import com.simibubi.create.foundation.utility.UniqueLinkedList;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
import net.minecraft.block.AbstractButtonBlock;
@ -85,7 +82,6 @@ import net.minecraft.state.properties.PistonType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
@ -853,16 +849,7 @@ public abstract class Contraption {
TileEntity te = TileEntity.create(tag);
if (te == null)
return;
te.setLocation(new WrappedWorld(world) {
@Override
public BlockState getBlockState(BlockPos pos) {
if (!pos.equals(te.getPos()))
return Blocks.AIR.getDefaultState();
return info.state;
}
}, te.getPos());
te.setLocation(new ContraptionTileWorld(world, te, info), te.getPos());
if (te instanceof KineticTileEntity)
((KineticTileEntity) te).setSpeed(0);
te.getBlockState();
@ -1091,27 +1078,25 @@ public abstract class Contraption {
}
public void expandBoundsAroundAxis(Axis axis) {
AxisAlignedBB bb = bounds;
double maxXDiff = Math.max(bb.maxX - 1, -bb.minX);
double maxYDiff = Math.max(bb.maxY - 1, -bb.minY);
double maxZDiff = Math.max(bb.maxZ - 1, -bb.minZ);
double maxDiff = 0;
Set<BlockPos> blocks = getBlocks().keySet();
if (axis == Axis.X)
maxDiff = Math.max(maxZDiff, maxYDiff);
if (axis == Axis.Y)
maxDiff = Math.max(maxZDiff, maxXDiff);
if (axis == Axis.Z)
maxDiff = Math.max(maxXDiff, maxYDiff);
int radius = (int) (Math.ceil(Math.sqrt(getRadius(blocks, axis))));
Vec3d vec = new Vec3d(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis)
.getDirectionVec());
Vec3d planeByNormal = VecHelper.axisAlingedPlaneOf(vec);
Vec3d min = vec.mul(bb.minX, bb.minY, bb.minZ)
.add(planeByNormal.scale(-maxDiff));
Vec3d max = vec.mul(bb.maxX, bb.maxY, bb.maxZ)
.add(planeByNormal.scale(maxDiff + 1));
bounds = new AxisAlignedBB(min, max);
GridAlignedBB betterBounds = GridAlignedBB.ofRadius(radius);
GridAlignedBB contraptionBounds = GridAlignedBB.fromAABB(bounds);
if (axis == Direction.Axis.X) {
betterBounds.maxX = contraptionBounds.maxX;
betterBounds.minX = contraptionBounds.minX;
} else if (axis == Direction.Axis.Y) {
betterBounds.maxY = contraptionBounds.maxY;
betterBounds.minY = contraptionBounds.minY;
} else if (axis == Direction.Axis.Z) {
betterBounds.maxZ = contraptionBounds.maxZ;
betterBounds.minZ = contraptionBounds.minZ;
}
bounds = betterBounds.toAABB();
}
public void addExtraInventories(Entity entity) {}
@ -1163,4 +1148,51 @@ public abstract class Contraption {
return new EmptyLighter(this);
}
public static float getRadius(Set<BlockPos> blocks, Direction.Axis axis) {
switch (axis) {
case X:
return getMaxDistSqr(blocks, BlockPos::getY, BlockPos::getZ);
case Y:
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ);
case Z:
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY);
}
throw new IllegalStateException("Impossible axis");
}
public static float getMaxDistSqr(Set<BlockPos> blocks, Coordinate one, Coordinate other) {
float maxDistSq = -1;
for (BlockPos pos : blocks) {
float a = one.get(pos);
float b = other.get(pos);
float distSq = a * a + b * b;
if (distSq > maxDistSq) maxDistSq = distSq;
}
return maxDistSq;
}
private static class ContraptionTileWorld extends WrappedWorld implements IFlywheelWorld {
private final TileEntity te;
private final BlockInfo info;
public ContraptionTileWorld(World world, TileEntity te, BlockInfo info) {
super(world);
this.te = te;
this.info = info;
}
@Override
public BlockState getBlockState(BlockPos pos) {
if (!pos.equals(te.getPos()))
return Blocks.AIR.getDefaultState();
return info.state;
}
}
}

View file

@ -1,13 +1,8 @@
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
import java.util.Set;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter;
import com.simibubi.create.foundation.render.backend.light.GridAlignedBB;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
public class BearingLighter extends ContraptionLighter<BearingContraption> {
public BearingLighter(BearingContraption contraption) {
@ -16,60 +11,8 @@ public class BearingLighter extends ContraptionLighter<BearingContraption> {
@Override
public GridAlignedBB getContraptionBounds() {
Set<BlockPos> blocks = contraption.getBlocks().keySet();
Direction orientation = contraption.facing;
Direction.Axis axis = orientation.getAxis();
int radius = (int) (Math.ceil(Math.sqrt(getRadius(blocks, axis))));
GridAlignedBB betterBounds = GridAlignedBB.ofRadius(radius);
GridAlignedBB contraptionBounds = GridAlignedBB.fromAABB(contraption.bounds);
if (axis == Direction.Axis.X) {
betterBounds.maxX = contraptionBounds.maxX;
betterBounds.minX = contraptionBounds.minX;
} else if (axis == Direction.Axis.Y) {
betterBounds.maxY = contraptionBounds.maxY;
betterBounds.minY = contraptionBounds.minY;
} else if (axis == Direction.Axis.Z) {
betterBounds.maxZ = contraptionBounds.maxZ;
betterBounds.minZ = contraptionBounds.minZ;
}
betterBounds.translate(contraption.anchor);
return betterBounds;
}
private static float getRadius(Set<BlockPos> blocks, Direction.Axis axis) {
switch (axis) {
case X:
return getMaxDistSqr(blocks, BlockPos::getY, BlockPos::getZ);
case Y:
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ);
case Z:
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY);
}
throw new IllegalStateException("Impossible axis");
}
private static float getMaxDistSqr(Set<BlockPos> blocks, Coordinate one, Coordinate other) {
float maxDistSq = -1;
for (BlockPos pos : blocks) {
float a = one.get(pos);
float b = other.get(pos);
float distSq = a * a + b * b;
if (distSq > maxDistSq) maxDistSq = distSq;
}
return maxDistSq;
}
private interface Coordinate {
float get(BlockPos from);
GridAlignedBB bb = GridAlignedBB.fromAABB(contraption.bounds);
bb.translate(contraption.anchor);
return bb;
}
}

View file

@ -269,6 +269,10 @@ public class GridAlignedBB {
}
}
public AxisAlignedBB toAABB() {
return toAABB(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View file

@ -0,0 +1,8 @@
package com.simibubi.create.foundation.utility;
import net.minecraft.util.math.BlockPos;
@FunctionalInterface
public interface Coordinate {
float get(BlockPos from);
}