1b2ca00c44
- Fix some contraption transforms (fix Fabricators-of-Create/Create#591) - Remove AllStitchedTextures - Organize imports - Swap jarjar versions and ranges to ensure more reliable version matching - Add the jarJarRelease task to the jarjar group
259 lines
8.8 KiB
Java
259 lines
8.8 KiB
Java
package com.simibubi.create.content.contraptions.components.structureMovement;
|
|
|
|
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.AXIS;
|
|
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING;
|
|
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING;
|
|
|
|
import com.simibubi.create.foundation.utility.VecHelper;
|
|
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.Direction.Axis;
|
|
import net.minecraft.core.Direction.AxisDirection;
|
|
import net.minecraft.network.FriendlyByteBuf;
|
|
import net.minecraft.world.level.block.BellBlock;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.FaceAttachedHorizontalDirectionalBlock;
|
|
import net.minecraft.world.level.block.Mirror;
|
|
import net.minecraft.world.level.block.Rotation;
|
|
import net.minecraft.world.level.block.SlabBlock;
|
|
import net.minecraft.world.level.block.StairBlock;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.properties.AttachFace;
|
|
import net.minecraft.world.level.block.state.properties.BellAttachType;
|
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
|
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
|
import net.minecraft.world.level.block.state.properties.Half;
|
|
import net.minecraft.world.level.block.state.properties.SlabType;
|
|
import net.minecraft.world.phys.Vec3;
|
|
|
|
public class StructureTransform {
|
|
|
|
// Assuming structures cannot be rotated around multiple axes at once
|
|
public Axis rotationAxis;
|
|
public BlockPos offset;
|
|
public int angle;
|
|
public Rotation rotation;
|
|
public Mirror mirror;
|
|
|
|
private StructureTransform(BlockPos offset, int angle, Axis axis, Rotation rotation, Mirror mirror) {
|
|
this.offset = offset;
|
|
this.angle = angle;
|
|
rotationAxis = axis;
|
|
this.rotation = rotation;
|
|
this.mirror = mirror;
|
|
}
|
|
|
|
public StructureTransform(BlockPos offset, Axis axis, Rotation rotation, Mirror mirror) {
|
|
this(offset, rotation == Rotation.NONE ? 0 : (4 - rotation.ordinal()) * 90, axis, rotation, mirror);
|
|
}
|
|
|
|
public StructureTransform(BlockPos offset, float xRotation, float yRotation, float zRotation) {
|
|
this.offset = offset;
|
|
if (xRotation != 0) {
|
|
rotationAxis = Axis.X;
|
|
angle = Math.round(xRotation / 90) * 90;
|
|
}
|
|
if (yRotation != 0) {
|
|
rotationAxis = Axis.Y;
|
|
angle = Math.round(yRotation / 90) * 90;
|
|
}
|
|
if (zRotation != 0) {
|
|
rotationAxis = Axis.Z;
|
|
angle = Math.round(zRotation / 90) * 90;
|
|
}
|
|
|
|
angle %= 360;
|
|
if (angle < -90)
|
|
angle += 360;
|
|
|
|
this.rotation = Rotation.NONE;
|
|
if (angle == -90 || angle == 270)
|
|
this.rotation = Rotation.CLOCKWISE_90;
|
|
if (angle == 90)
|
|
this.rotation = Rotation.COUNTERCLOCKWISE_90;
|
|
if (angle == 180)
|
|
this.rotation = Rotation.CLOCKWISE_180;
|
|
|
|
mirror = Mirror.NONE;
|
|
}
|
|
|
|
public Vec3 applyWithoutOffsetUncentered(Vec3 localVec) {
|
|
Vec3 vec = localVec;
|
|
if (mirror != null)
|
|
vec = VecHelper.mirror(vec, mirror);
|
|
if (rotationAxis != null)
|
|
vec = VecHelper.rotate(vec, angle, rotationAxis);
|
|
return vec;
|
|
}
|
|
|
|
public Vec3 applyWithoutOffset(Vec3 localVec) {
|
|
Vec3 vec = localVec;
|
|
if (mirror != null)
|
|
vec = VecHelper.mirrorCentered(vec, mirror);
|
|
if (rotationAxis != null)
|
|
vec = VecHelper.rotateCentered(vec, angle, rotationAxis);
|
|
return vec;
|
|
}
|
|
|
|
public Vec3 apply(Vec3 localVec) {
|
|
return applyWithoutOffset(localVec).add(Vec3.atLowerCornerOf(offset));
|
|
}
|
|
|
|
public BlockPos applyWithoutOffset(BlockPos localPos) {
|
|
return new BlockPos(applyWithoutOffset(VecHelper.getCenterOf(localPos)));
|
|
}
|
|
|
|
public BlockPos apply(BlockPos localPos) {
|
|
return applyWithoutOffset(localPos).offset(offset);
|
|
}
|
|
|
|
public void apply(BlockEntity te) {
|
|
if (te instanceof ITransformableTE)
|
|
((ITransformableTE) te).transform(this);
|
|
}
|
|
|
|
/**
|
|
* Vanilla does not support block state rotation around axes other than Y. Add
|
|
* specific cases here for vanilla block states so that they can react to rotations
|
|
* around horizontal axes. For Create blocks, implement ITransformableBlock.
|
|
*/
|
|
public BlockState apply(BlockState state) {
|
|
Block block = state.getBlock();
|
|
if (block instanceof ITransformableBlock transformable)
|
|
return transformable.transform(state, this);
|
|
|
|
if (mirror != null)
|
|
state = state.mirror(mirror);
|
|
|
|
if (rotationAxis == Axis.Y) {
|
|
if (block instanceof BellBlock) {
|
|
if (state.getValue(BlockStateProperties.BELL_ATTACHMENT) == BellAttachType.DOUBLE_WALL)
|
|
state = state.setValue(BlockStateProperties.BELL_ATTACHMENT, BellAttachType.SINGLE_WALL);
|
|
return state.setValue(BellBlock.FACING,
|
|
rotation.rotate(state.getValue(BellBlock.FACING)));
|
|
}
|
|
|
|
return state.rotate(rotation);
|
|
}
|
|
|
|
if (block instanceof FaceAttachedHorizontalDirectionalBlock) {
|
|
DirectionProperty facingProperty = FaceAttachedHorizontalDirectionalBlock.FACING;
|
|
EnumProperty<AttachFace> faceProperty = FaceAttachedHorizontalDirectionalBlock.FACE;
|
|
Direction stateFacing = state.getValue(facingProperty);
|
|
AttachFace stateFace = state.getValue(faceProperty);
|
|
boolean z = rotationAxis == Axis.Z;
|
|
Direction forcedAxis = z ? Direction.WEST : Direction.SOUTH;
|
|
|
|
if (stateFacing.getAxis() == rotationAxis && stateFace == AttachFace.WALL)
|
|
return state;
|
|
|
|
for (int i = 0; i < rotation.ordinal(); i++) {
|
|
stateFace = state.getValue(faceProperty);
|
|
stateFacing = state.getValue(facingProperty);
|
|
|
|
boolean b = state.getValue(faceProperty) == AttachFace.CEILING;
|
|
state = state.setValue(facingProperty, b ? forcedAxis : forcedAxis.getOpposite());
|
|
|
|
if (stateFace != AttachFace.WALL) {
|
|
state = state.setValue(faceProperty, AttachFace.WALL);
|
|
continue;
|
|
}
|
|
|
|
if (stateFacing.getAxisDirection() == (z ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE)) {
|
|
state = state.setValue(faceProperty, AttachFace.FLOOR);
|
|
continue;
|
|
}
|
|
state = state.setValue(faceProperty, AttachFace.CEILING);
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
boolean halfTurn = rotation == Rotation.CLOCKWISE_180;
|
|
if (block instanceof StairBlock) {
|
|
state = transformStairs(state, halfTurn);
|
|
return state;
|
|
}
|
|
|
|
if (state.hasProperty(FACING)) {
|
|
state = state.setValue(FACING, rotateFacing(state.getValue(FACING)));
|
|
} else if (state.hasProperty(AXIS)) {
|
|
state = state.setValue(AXIS, rotateAxis(state.getValue(AXIS)));
|
|
} else if (halfTurn) {
|
|
if (state.hasProperty(HORIZONTAL_FACING)) {
|
|
Direction stateFacing = state.getValue(HORIZONTAL_FACING);
|
|
if (stateFacing.getAxis() == rotationAxis)
|
|
return state;
|
|
}
|
|
|
|
state = state.rotate(rotation);
|
|
|
|
if (state.hasProperty(SlabBlock.TYPE) && state.getValue(SlabBlock.TYPE) != SlabType.DOUBLE)
|
|
state = state.setValue(SlabBlock.TYPE,
|
|
state.getValue(SlabBlock.TYPE) == SlabType.BOTTOM ? SlabType.TOP : SlabType.BOTTOM);
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
protected BlockState transformStairs(BlockState state, boolean halfTurn) {
|
|
if (state.getValue(StairBlock.FACING)
|
|
.getAxis() != rotationAxis) {
|
|
for (int i = 0; i < rotation.ordinal(); i++) {
|
|
Direction direction = state.getValue(StairBlock.FACING);
|
|
Half half = state.getValue(StairBlock.HALF);
|
|
if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ half == Half.BOTTOM
|
|
^ direction.getAxis() == Axis.Z)
|
|
state = state.cycle(StairBlock.HALF);
|
|
else
|
|
state = state.setValue(StairBlock.FACING, direction.getOpposite());
|
|
}
|
|
} else {
|
|
if (halfTurn) {
|
|
state = state.cycle(StairBlock.HALF);
|
|
}
|
|
}
|
|
return state;
|
|
}
|
|
|
|
public Direction mirrorFacing(Direction facing) {
|
|
if (mirror != null)
|
|
return mirror.mirror(facing);
|
|
return facing;
|
|
}
|
|
|
|
public Axis rotateAxis(Axis axis) {
|
|
Direction facing = Direction.get(AxisDirection.POSITIVE, axis);
|
|
return rotateFacing(facing).getAxis();
|
|
}
|
|
|
|
public Direction rotateFacing(Direction facing) {
|
|
for (int i = 0; i < rotation.ordinal(); i++)
|
|
facing = facing.getClockWise(rotationAxis);
|
|
return facing;
|
|
}
|
|
|
|
public static StructureTransform fromBuffer(FriendlyByteBuf buffer) {
|
|
BlockPos readBlockPos = buffer.readBlockPos();
|
|
int readAngle = buffer.readInt();
|
|
int axisIndex = buffer.readVarInt();
|
|
int rotationIndex = buffer.readVarInt();
|
|
int mirrorIndex = buffer.readVarInt();
|
|
return new StructureTransform(readBlockPos, readAngle, axisIndex == -1 ? null : Axis.values()[axisIndex],
|
|
rotationIndex == -1 ? null : Rotation.values()[rotationIndex],
|
|
mirrorIndex == -1 ? null : Mirror.values()[mirrorIndex]);
|
|
}
|
|
|
|
public void writeToBuffer(FriendlyByteBuf buffer) {
|
|
buffer.writeBlockPos(offset);
|
|
buffer.writeInt(angle);
|
|
buffer.writeVarInt(rotationAxis == null ? -1 : rotationAxis.ordinal());
|
|
buffer.writeVarInt(rotation == null ? -1 : rotation.ordinal());
|
|
buffer.writeVarInt(mirror == null ? - 1 : mirror.ordinal());
|
|
}
|
|
|
|
}
|