CreateMod/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java
PepperCode1 1b2ca00c44 Minor fix-ups
- 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
2023-03-07 14:10:44 -08:00

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());
}
}