Transforming the bugs away
- Fix arm interaction point client-side deserialization and initialization issues - Fix sequenced gearshift structure rotation - Fix encased cogwheel rotation, mirroring, and structure transformation - Add ITransformableBlock to allow custom handling of StructureTransforms - Remove DirectionHelper - Add jarJarRelease Gradle task for building a jarJar without a classifier
This commit is contained in:
parent
82be76d893
commit
d9c6418fbf
15 changed files with 368 additions and 259 deletions
|
@ -209,6 +209,15 @@ jar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task jarJarRelease {
|
||||||
|
doLast {
|
||||||
|
tasks.jarJar {
|
||||||
|
classifier = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finalizedBy tasks.jarJar
|
||||||
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
withJavadocJar()
|
withJavadocJar()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.simibubi.create.api.behaviour;
|
package com.simibubi.create.api.behaviour;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
|
@ -14,7 +15,7 @@ import net.minecraftforge.fluids.FluidStack;
|
||||||
|
|
||||||
public abstract class BlockSpoutingBehaviour {
|
public abstract class BlockSpoutingBehaviour {
|
||||||
|
|
||||||
private static final HashMap<ResourceLocation, BlockSpoutingBehaviour> BLOCK_SPOUTING_BEHAVIOURS = new HashMap<>();
|
private static final Map<ResourceLocation, BlockSpoutingBehaviour> BLOCK_SPOUTING_BEHAVIOURS = new HashMap<>();
|
||||||
|
|
||||||
public static void addCustomSpoutInteraction(ResourceLocation resourceLocation,
|
public static void addCustomSpoutInteraction(ResourceLocation resourceLocation,
|
||||||
BlockSpoutingBehaviour movementBehaviour) {
|
BlockSpoutingBehaviour movementBehaviour) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.simibubi.create.content.contraptions.base;
|
package com.simibubi.create.content.contraptions.base;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.utility.DirectionHelper;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -15,7 +16,7 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
import net.minecraft.world.level.block.state.StateDefinition.Builder;
|
||||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||||
|
|
||||||
public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBlock {
|
public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBlock implements ITransformableBlock {
|
||||||
|
|
||||||
public static final BooleanProperty AXIS_ALONG_FIRST_COORDINATE = BooleanProperty.create("axis_along_first");
|
public static final BooleanProperty AXIS_ALONG_FIRST_COORDINATE = BooleanProperty.create("axis_along_first");
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBloc
|
||||||
|
|
||||||
if (faceAxis.isHorizontal()) {
|
if (faceAxis.isHorizontal()) {
|
||||||
alongFirst = faceAxis == Axis.Z;
|
alongFirst = faceAxis == Axis.Z;
|
||||||
Direction positivePerpendicular = DirectionHelper.getPositivePerpendicular(faceAxis);
|
Direction positivePerpendicular = faceAxis == Axis.X ? Direction.SOUTH : Direction.EAST;
|
||||||
|
|
||||||
boolean shaftAbove = prefersConnectionTo(world, pos, Direction.UP, true);
|
boolean shaftAbove = prefersConnectionTo(world, pos, Direction.UP, true);
|
||||||
boolean shaftBelow = prefersConnectionTo(world, pos, Direction.DOWN, true);
|
boolean shaftBelow = prefersConnectionTo(world, pos, Direction.DOWN, true);
|
||||||
|
@ -121,6 +122,23 @@ public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBloc
|
||||||
return super.rotate(state, rot);
|
return super.rotate(state, rot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState transform(BlockState state, StructureTransform transform) {
|
||||||
|
if (transform.mirror != null) {
|
||||||
|
state = mirror(state, transform.mirror);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transform.rotationAxis == Direction.Axis.Y) {
|
||||||
|
return rotate(state, transform.rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
Direction newFacing = transform.rotateFacing(state.getValue(FACING));
|
||||||
|
if (transform.rotationAxis == newFacing.getAxis() && transform.rotation.ordinal() % 2 == 1) {
|
||||||
|
state = state.cycle(AXIS_ALONG_FIRST_COORDINATE);
|
||||||
|
}
|
||||||
|
return state.setValue(FACING, newFacing);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
|
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
|
||||||
return face.getAxis() == getRotationAxis(state);
|
return face.getAxis() == getRotationAxis(state);
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
public interface ITransformableBlock {
|
||||||
|
BlockState transform(BlockState state, StructureTransform transform);
|
||||||
|
}
|
|
@ -4,13 +4,6 @@ import static net.minecraft.world.level.block.state.properties.BlockStatePropert
|
||||||
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING;
|
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING;
|
||||||
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING;
|
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
|
||||||
import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock;
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
|
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
|
|
||||||
import com.simibubi.create.foundation.utility.DirectionHelper;
|
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -30,7 +23,6 @@ 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.AttachFace;
|
||||||
import net.minecraft.world.level.block.state.properties.BellAttachType;
|
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.BlockStateProperties;
|
||||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
|
||||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
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.EnumProperty;
|
||||||
import net.minecraft.world.level.block.state.properties.Half;
|
import net.minecraft.world.level.block.state.properties.Half;
|
||||||
|
@ -124,16 +116,18 @@ public class StructureTransform {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minecraft does not support blockstate rotation around axes other than y. Add
|
* Vanilla does not support block state rotation around axes other than Y. Add
|
||||||
* specific cases here for blockstates, that should react to rotations around
|
* specific cases here for vanilla block states so that they can react to rotations
|
||||||
* horizontal axes
|
* around horizontal axes. For Create blocks, implement ITransformableBlock.
|
||||||
*/
|
*/
|
||||||
public BlockState apply(BlockState state) {
|
public BlockState apply(BlockState state) {
|
||||||
|
Block block = state.getBlock();
|
||||||
|
if (block instanceof ITransformableBlock transformable)
|
||||||
|
return transformable.transform(state, this);
|
||||||
|
|
||||||
if (mirror != null)
|
if (mirror != null)
|
||||||
state = state.mirror(mirror);
|
state = state.mirror(mirror);
|
||||||
|
|
||||||
Block block = state.getBlock();
|
|
||||||
|
|
||||||
if (rotationAxis == Axis.Y) {
|
if (rotationAxis == Axis.Y) {
|
||||||
if (block instanceof BellBlock) {
|
if (block instanceof BellBlock) {
|
||||||
if (state.getValue(BlockStateProperties.BELL_ATTACHMENT) == BellAttachType.DOUBLE_WALL)
|
if (state.getValue(BlockStateProperties.BELL_ATTACHMENT) == BellAttachType.DOUBLE_WALL)
|
||||||
|
@ -141,12 +135,10 @@ public class StructureTransform {
|
||||||
return state.setValue(BellBlock.FACING,
|
return state.setValue(BellBlock.FACING,
|
||||||
rotation.rotate(state.getValue(BellBlock.FACING)));
|
rotation.rotate(state.getValue(BellBlock.FACING)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return state.rotate(rotation);
|
return state.rotate(rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block instanceof AbstractChassisBlock)
|
|
||||||
return rotateChassis(state);
|
|
||||||
|
|
||||||
if (block instanceof FaceAttachedHorizontalDirectionalBlock) {
|
if (block instanceof FaceAttachedHorizontalDirectionalBlock) {
|
||||||
DirectionProperty facingProperty = FaceAttachedHorizontalDirectionalBlock.FACING;
|
DirectionProperty facingProperty = FaceAttachedHorizontalDirectionalBlock.FACING;
|
||||||
EnumProperty<AttachFace> faceProperty = FaceAttachedHorizontalDirectionalBlock.FACE;
|
EnumProperty<AttachFace> faceProperty = FaceAttachedHorizontalDirectionalBlock.FACE;
|
||||||
|
@ -185,30 +177,11 @@ public class StructureTransform {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AllBlocks.BELT.has(state)) {
|
|
||||||
state = transformBelt(state, halfTurn);
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.hasProperty(FACING)) {
|
if (state.hasProperty(FACING)) {
|
||||||
Direction newFacing = transformFacing(state.getValue(FACING));
|
state = state.setValue(FACING, rotateFacing(state.getValue(FACING)));
|
||||||
if (state.hasProperty(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE)) {
|
|
||||||
if (rotationAxis == newFacing.getAxis() && rotation.ordinal() % 2 == 1)
|
|
||||||
state = state.cycle(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE);
|
|
||||||
}
|
|
||||||
state = state.setValue(FACING, newFacing);
|
|
||||||
|
|
||||||
} else if (state.hasProperty(AXIS)) {
|
} else if (state.hasProperty(AXIS)) {
|
||||||
state = state.setValue(AXIS, transformAxis(state.getValue(AXIS)));
|
state = state.setValue(AXIS, rotateAxis(state.getValue(AXIS)));
|
||||||
|
|
||||||
} else if (halfTurn) {
|
} else if (halfTurn) {
|
||||||
|
|
||||||
if (state.hasProperty(FACING)) {
|
|
||||||
Direction stateFacing = state.getValue(FACING);
|
|
||||||
if (stateFacing.getAxis() == rotationAxis)
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.hasProperty(HORIZONTAL_FACING)) {
|
if (state.hasProperty(HORIZONTAL_FACING)) {
|
||||||
Direction stateFacing = state.getValue(HORIZONTAL_FACING);
|
Direction stateFacing = state.getValue(HORIZONTAL_FACING);
|
||||||
if (stateFacing.getAxis() == rotationAxis)
|
if (stateFacing.getAxis() == rotationAxis)
|
||||||
|
@ -216,6 +189,7 @@ public class StructureTransform {
|
||||||
}
|
}
|
||||||
|
|
||||||
state = state.rotate(rotation);
|
state = state.rotate(rotation);
|
||||||
|
|
||||||
if (state.hasProperty(SlabBlock.TYPE) && state.getValue(SlabBlock.TYPE) != SlabType.DOUBLE)
|
if (state.hasProperty(SlabBlock.TYPE) && state.getValue(SlabBlock.TYPE) != SlabType.DOUBLE)
|
||||||
state = state.setValue(SlabBlock.TYPE,
|
state = state.setValue(SlabBlock.TYPE,
|
||||||
state.getValue(SlabBlock.TYPE) == SlabType.BOTTOM ? SlabType.TOP : SlabType.BOTTOM);
|
state.getValue(SlabBlock.TYPE) == SlabType.BOTTOM ? SlabType.TOP : SlabType.BOTTOM);
|
||||||
|
@ -244,125 +218,21 @@ public class StructureTransform {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BlockState transformBelt(BlockState state, boolean halfTurn) {
|
public Direction mirrorFacing(Direction facing) {
|
||||||
Direction initialDirection = state.getValue(BeltBlock.HORIZONTAL_FACING);
|
|
||||||
boolean diagonal =
|
|
||||||
state.getValue(BeltBlock.SLOPE) == BeltSlope.DOWNWARD || state.getValue(BeltBlock.SLOPE) == BeltSlope.UPWARD;
|
|
||||||
|
|
||||||
if (!diagonal) {
|
|
||||||
for (int i = 0; i < rotation.ordinal(); i++) {
|
|
||||||
Direction direction = state.getValue(BeltBlock.HORIZONTAL_FACING);
|
|
||||||
BeltSlope slope = state.getValue(BeltBlock.SLOPE);
|
|
||||||
boolean vertical = slope == BeltSlope.VERTICAL;
|
|
||||||
boolean horizontal = slope == BeltSlope.HORIZONTAL;
|
|
||||||
boolean sideways = slope == BeltSlope.SIDEWAYS;
|
|
||||||
|
|
||||||
Direction newDirection = direction.getOpposite();
|
|
||||||
BeltSlope newSlope = BeltSlope.VERTICAL;
|
|
||||||
|
|
||||||
if (vertical) {
|
|
||||||
if (direction.getAxis() == rotationAxis) {
|
|
||||||
newDirection = direction.getCounterClockWise();
|
|
||||||
newSlope = BeltSlope.SIDEWAYS;
|
|
||||||
} else {
|
|
||||||
newSlope = BeltSlope.HORIZONTAL;
|
|
||||||
newDirection = direction;
|
|
||||||
if (direction.getAxis() == Axis.Z)
|
|
||||||
newDirection = direction.getOpposite();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sideways) {
|
|
||||||
newDirection = direction;
|
|
||||||
if (direction.getAxis() == rotationAxis)
|
|
||||||
newSlope = BeltSlope.HORIZONTAL;
|
|
||||||
else
|
|
||||||
newDirection = direction.getCounterClockWise();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (horizontal) {
|
|
||||||
newDirection = direction;
|
|
||||||
if (direction.getAxis() == rotationAxis)
|
|
||||||
newSlope = BeltSlope.SIDEWAYS;
|
|
||||||
else if (direction.getAxis() != Axis.Z)
|
|
||||||
newDirection = direction.getOpposite();
|
|
||||||
}
|
|
||||||
|
|
||||||
state = state.setValue(BeltBlock.HORIZONTAL_FACING, newDirection);
|
|
||||||
state = state.setValue(BeltBlock.SLOPE, newSlope);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (initialDirection.getAxis() != rotationAxis) {
|
|
||||||
for (int i = 0; i < rotation.ordinal(); i++) {
|
|
||||||
Direction direction = state.getValue(BeltBlock.HORIZONTAL_FACING);
|
|
||||||
Direction newDirection = direction.getOpposite();
|
|
||||||
BeltSlope slope = state.getValue(BeltBlock.SLOPE);
|
|
||||||
boolean upward = slope == BeltSlope.UPWARD;
|
|
||||||
boolean downward = slope == BeltSlope.DOWNWARD;
|
|
||||||
|
|
||||||
// Rotate diagonal
|
|
||||||
if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ downward ^ direction.getAxis() == Axis.Z) {
|
|
||||||
state = state.setValue(BeltBlock.SLOPE, upward ? BeltSlope.DOWNWARD : BeltSlope.UPWARD);
|
|
||||||
} else {
|
|
||||||
state = state.setValue(BeltBlock.HORIZONTAL_FACING, newDirection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (halfTurn) {
|
|
||||||
Direction direction = state.getValue(BeltBlock.HORIZONTAL_FACING);
|
|
||||||
Direction newDirection = direction.getOpposite();
|
|
||||||
BeltSlope slope = state.getValue(BeltBlock.SLOPE);
|
|
||||||
boolean vertical = slope == BeltSlope.VERTICAL;
|
|
||||||
|
|
||||||
if (diagonal) {
|
|
||||||
state = state.setValue(BeltBlock.SLOPE, slope == BeltSlope.UPWARD ? BeltSlope.DOWNWARD
|
|
||||||
: slope == BeltSlope.DOWNWARD ? BeltSlope.UPWARD : slope);
|
|
||||||
} else if (vertical) {
|
|
||||||
state = state.setValue(BeltBlock.HORIZONTAL_FACING, newDirection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Axis transformAxis(Axis axisIn) {
|
|
||||||
Direction facing = Direction.get(AxisDirection.POSITIVE, axisIn);
|
|
||||||
facing = transformFacing(facing);
|
|
||||||
Axis axis = facing.getAxis();
|
|
||||||
return axis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Direction transformFacing(Direction facing) {
|
|
||||||
if (mirror != null)
|
if (mirror != null)
|
||||||
facing = mirror.mirror(facing);
|
return mirror.mirror(facing);
|
||||||
for (int i = 0; i < rotation.ordinal(); i++)
|
|
||||||
facing = DirectionHelper.rotateAround(facing, rotationAxis);
|
|
||||||
return facing;
|
return facing;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockState rotateChassis(BlockState state) {
|
public Axis rotateAxis(Axis axis) {
|
||||||
if (rotation == Rotation.NONE)
|
Direction facing = Direction.get(AxisDirection.POSITIVE, axis);
|
||||||
return state;
|
return rotateFacing(facing).getAxis();
|
||||||
|
|
||||||
BlockState rotated = state.setValue(AXIS, transformAxis(state.getValue(AXIS)));
|
|
||||||
AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock();
|
|
||||||
|
|
||||||
for (Direction face : Iterate.directions) {
|
|
||||||
BooleanProperty glueableSide = block.getGlueableSide(rotated, face);
|
|
||||||
if (glueableSide != null)
|
|
||||||
rotated = rotated.setValue(glueableSide, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Direction face : Iterate.directions) {
|
public Direction rotateFacing(Direction facing) {
|
||||||
BooleanProperty glueableSide = block.getGlueableSide(state, face);
|
for (int i = 0; i < rotation.ordinal(); i++)
|
||||||
if (glueableSide == null || !state.getValue(glueableSide))
|
facing = facing.getClockWise(rotationAxis);
|
||||||
continue;
|
return facing;
|
||||||
Direction rotatedFacing = transformFacing(face);
|
|
||||||
BooleanProperty rotatedGlueableSide = block.getGlueableSide(rotated, rotatedFacing);
|
|
||||||
if (rotatedGlueableSide != null)
|
|
||||||
rotated = rotated.setValue(rotatedGlueableSide, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rotated;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StructureTransform fromBuffer(FriendlyByteBuf buffer) {
|
public static StructureTransform fromBuffer(FriendlyByteBuf buffer) {
|
||||||
|
|
|
@ -3,6 +3,8 @@ package com.simibubi.create.content.contraptions.components.structureMovement.ch
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.AllSoundEvents;
|
import com.simibubi.create.AllSoundEvents;
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock;
|
||||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||||
import com.simibubi.create.foundation.block.ITE;
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
@ -26,7 +28,7 @@ import net.minecraft.world.phys.BlockHitResult;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraftforge.common.Tags;
|
import net.minecraftforge.common.Tags;
|
||||||
|
|
||||||
public abstract class AbstractChassisBlock extends RotatedPillarBlock implements IWrenchable, ITE<ChassisTileEntity> {
|
public abstract class AbstractChassisBlock extends RotatedPillarBlock implements IWrenchable, ITE<ChassisTileEntity>, ITransformableBlock {
|
||||||
|
|
||||||
public AbstractChassisBlock(Properties properties) {
|
public AbstractChassisBlock(Properties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
|
@ -132,6 +134,44 @@ public abstract class AbstractChassisBlock extends RotatedPillarBlock implements
|
||||||
return mirrored;
|
return mirrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState transform(BlockState state, StructureTransform transform) {
|
||||||
|
if (transform.mirror != null) {
|
||||||
|
state = mirror(state, transform.mirror);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transform.rotationAxis == Direction.Axis.Y) {
|
||||||
|
return rotate(state, transform.rotation);
|
||||||
|
}
|
||||||
|
return transformInner(state, transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BlockState transformInner(BlockState state, StructureTransform transform) {
|
||||||
|
if (transform.rotation == Rotation.NONE)
|
||||||
|
return state;
|
||||||
|
|
||||||
|
BlockState rotated = state.setValue(AXIS, transform.rotateAxis(state.getValue(AXIS)));
|
||||||
|
AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock();
|
||||||
|
|
||||||
|
for (Direction face : Iterate.directions) {
|
||||||
|
BooleanProperty glueableSide = block.getGlueableSide(rotated, face);
|
||||||
|
if (glueableSide != null)
|
||||||
|
rotated = rotated.setValue(glueableSide, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Direction face : Iterate.directions) {
|
||||||
|
BooleanProperty glueableSide = block.getGlueableSide(state, face);
|
||||||
|
if (glueableSide == null || !state.getValue(glueableSide))
|
||||||
|
continue;
|
||||||
|
Direction rotatedFacing = transform.rotateFacing(face);
|
||||||
|
BooleanProperty rotatedGlueableSide = block.getGlueableSide(rotated, rotatedFacing);
|
||||||
|
if (rotatedGlueableSide != null)
|
||||||
|
rotated = rotated.setValue(rotatedGlueableSide, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rotated;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract BooleanProperty getGlueableSide(BlockState state, Direction face);
|
public abstract BooleanProperty getGlueableSide(BlockState state, Direction face);
|
||||||
|
|
||||||
protected boolean glueAllowedOnSide(BlockGetter world, BlockPos pos, BlockState state, Direction side) {
|
protected boolean glueAllowedOnSide(BlockGetter world, BlockPos pos, BlockState state, Direction side) {
|
||||||
|
|
|
@ -7,6 +7,8 @@ import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock;
|
import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticBlock;
|
import com.simibubi.create.content.contraptions.base.KineticBlock;
|
||||||
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
|
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||||
import com.simibubi.create.foundation.block.ITE;
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
import com.simibubi.create.foundation.gui.ScreenOpener;
|
import com.simibubi.create.foundation.gui.ScreenOpener;
|
||||||
|
|
||||||
|
@ -35,7 +37,7 @@ import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.fml.DistExecutor;
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
|
|
||||||
public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implements ITE<SequencedGearshiftTileEntity> {
|
public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implements ITE<SequencedGearshiftTileEntity>, ITransformableBlock {
|
||||||
|
|
||||||
public static final BooleanProperty VERTICAL = BooleanProperty.create("vertical");
|
public static final BooleanProperty VERTICAL = BooleanProperty.create("vertical");
|
||||||
public static final IntegerProperty STATE = IntegerProperty.create("state", 0, 5);
|
public static final IntegerProperty STATE = IntegerProperty.create("state", 0, 5);
|
||||||
|
@ -166,4 +168,24 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen
|
||||||
.intValue();
|
.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState transform(BlockState state, StructureTransform transform) {
|
||||||
|
if (transform.mirror != null) {
|
||||||
|
state = mirror(state, transform.mirror);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transform.rotationAxis == Direction.Axis.Y) {
|
||||||
|
return rotate(state, transform.rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transform.rotation.ordinal() % 2 == 1) {
|
||||||
|
if (transform.rotationAxis != state.getValue(HORIZONTAL_AXIS)) {
|
||||||
|
return state.cycle(VERTICAL);
|
||||||
|
} else if (state.getValue(VERTICAL)) {
|
||||||
|
return state.cycle(VERTICAL).cycle(HORIZONTAL_AXIS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
|
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||||
import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
|
import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltSlicer.Feedback;
|
import com.simibubi.create.content.contraptions.relays.belt.BeltSlicer.Feedback;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity.CasingType;
|
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity.CasingType;
|
||||||
|
@ -82,7 +84,7 @@ import net.minecraftforge.common.Tags;
|
||||||
import net.minecraftforge.items.CapabilityItemHandler;
|
import net.minecraftforge.items.CapabilityItemHandler;
|
||||||
import net.minecraftforge.items.IItemHandler;
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
|
||||||
public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEntity>, ISpecialBlockItemRequirement {
|
public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEntity>, ISpecialBlockItemRequirement, ITransformableBlock {
|
||||||
|
|
||||||
public static final Property<BeltSlope> SLOPE = EnumProperty.create("slope", BeltSlope.class);
|
public static final Property<BeltSlope> SLOPE = EnumProperty.create("slope", BeltSlope.class);
|
||||||
public static final Property<BeltPart> PART = EnumProperty.create("part", BeltPart.class);
|
public static final Property<BeltPart> PART = EnumProperty.create("part", BeltPart.class);
|
||||||
|
@ -594,6 +596,100 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
|
||||||
return rotate;
|
return rotate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockState transform(BlockState state, StructureTransform transform) {
|
||||||
|
if (transform.mirror != null) {
|
||||||
|
state = mirror(state, transform.mirror);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transform.rotationAxis == Direction.Axis.Y) {
|
||||||
|
return rotate(state, transform.rotation);
|
||||||
|
}
|
||||||
|
return transformInner(state, transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BlockState transformInner(BlockState state, StructureTransform transform) {
|
||||||
|
boolean halfTurn = transform.rotation == Rotation.CLOCKWISE_180;
|
||||||
|
|
||||||
|
Direction initialDirection = state.getValue(HORIZONTAL_FACING);
|
||||||
|
boolean diagonal =
|
||||||
|
state.getValue(SLOPE) == BeltSlope.DOWNWARD || state.getValue(SLOPE) == BeltSlope.UPWARD;
|
||||||
|
|
||||||
|
if (!diagonal) {
|
||||||
|
for (int i = 0; i < transform.rotation.ordinal(); i++) {
|
||||||
|
Direction direction = state.getValue(HORIZONTAL_FACING);
|
||||||
|
BeltSlope slope = state.getValue(SLOPE);
|
||||||
|
boolean vertical = slope == BeltSlope.VERTICAL;
|
||||||
|
boolean horizontal = slope == BeltSlope.HORIZONTAL;
|
||||||
|
boolean sideways = slope == BeltSlope.SIDEWAYS;
|
||||||
|
|
||||||
|
Direction newDirection = direction.getOpposite();
|
||||||
|
BeltSlope newSlope = BeltSlope.VERTICAL;
|
||||||
|
|
||||||
|
if (vertical) {
|
||||||
|
if (direction.getAxis() == transform.rotationAxis) {
|
||||||
|
newDirection = direction.getCounterClockWise();
|
||||||
|
newSlope = BeltSlope.SIDEWAYS;
|
||||||
|
} else {
|
||||||
|
newSlope = BeltSlope.HORIZONTAL;
|
||||||
|
newDirection = direction;
|
||||||
|
if (direction.getAxis() == Axis.Z)
|
||||||
|
newDirection = direction.getOpposite();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sideways) {
|
||||||
|
newDirection = direction;
|
||||||
|
if (direction.getAxis() == transform.rotationAxis)
|
||||||
|
newSlope = BeltSlope.HORIZONTAL;
|
||||||
|
else
|
||||||
|
newDirection = direction.getCounterClockWise();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (horizontal) {
|
||||||
|
newDirection = direction;
|
||||||
|
if (direction.getAxis() == transform.rotationAxis)
|
||||||
|
newSlope = BeltSlope.SIDEWAYS;
|
||||||
|
else if (direction.getAxis() != Axis.Z)
|
||||||
|
newDirection = direction.getOpposite();
|
||||||
|
}
|
||||||
|
|
||||||
|
state = state.setValue(HORIZONTAL_FACING, newDirection);
|
||||||
|
state = state.setValue(SLOPE, newSlope);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (initialDirection.getAxis() != transform.rotationAxis) {
|
||||||
|
for (int i = 0; i < transform.rotation.ordinal(); i++) {
|
||||||
|
Direction direction = state.getValue(HORIZONTAL_FACING);
|
||||||
|
Direction newDirection = direction.getOpposite();
|
||||||
|
BeltSlope slope = state.getValue(SLOPE);
|
||||||
|
boolean upward = slope == BeltSlope.UPWARD;
|
||||||
|
boolean downward = slope == BeltSlope.DOWNWARD;
|
||||||
|
|
||||||
|
// Rotate diagonal
|
||||||
|
if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ downward ^ direction.getAxis() == Axis.Z) {
|
||||||
|
state = state.setValue(SLOPE, upward ? BeltSlope.DOWNWARD : BeltSlope.UPWARD);
|
||||||
|
} else {
|
||||||
|
state = state.setValue(HORIZONTAL_FACING, newDirection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (halfTurn) {
|
||||||
|
Direction direction = state.getValue(HORIZONTAL_FACING);
|
||||||
|
Direction newDirection = direction.getOpposite();
|
||||||
|
BeltSlope slope = state.getValue(SLOPE);
|
||||||
|
boolean vertical = slope == BeltSlope.VERTICAL;
|
||||||
|
|
||||||
|
if (diagonal) {
|
||||||
|
state = state.setValue(SLOPE, slope == BeltSlope.UPWARD ? BeltSlope.DOWNWARD
|
||||||
|
: slope == BeltSlope.DOWNWARD ? BeltSlope.UPWARD : slope);
|
||||||
|
} else if (vertical) {
|
||||||
|
state = state.setValue(HORIZONTAL_FACING, newDirection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) {
|
public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -6,12 +6,15 @@ import com.simibubi.create.content.contraptions.base.CasingBlock;
|
||||||
import com.simibubi.create.content.contraptions.base.IRotate;
|
import com.simibubi.create.content.contraptions.base.IRotate;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
|
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||||
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
||||||
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
|
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
|
||||||
import com.simibubi.create.content.contraptions.relays.elementary.SimpleKineticTileEntity;
|
import com.simibubi.create.content.contraptions.relays.elementary.SimpleKineticTileEntity;
|
||||||
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
|
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
|
||||||
import com.simibubi.create.content.schematics.ItemRequirement;
|
import com.simibubi.create.content.schematics.ItemRequirement;
|
||||||
import com.simibubi.create.foundation.block.ITE;
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
|
import com.simibubi.create.foundation.utility.VoxelShaper;
|
||||||
import com.tterrag.registrate.util.entry.BlockEntry;
|
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -29,6 +32,8 @@ import net.minecraft.world.level.BlockGetter;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.LevelReader;
|
import net.minecraft.world.level.LevelReader;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Mirror;
|
||||||
|
import net.minecraft.world.level.block.Rotation;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
@ -38,7 +43,7 @@ import net.minecraft.world.phys.BlockHitResult;
|
||||||
import net.minecraft.world.phys.HitResult;
|
import net.minecraft.world.phys.HitResult;
|
||||||
|
|
||||||
public class EncasedCogwheelBlock extends RotatedPillarKineticBlock
|
public class EncasedCogwheelBlock extends RotatedPillarKineticBlock
|
||||||
implements ICogWheel, ITE<SimpleKineticTileEntity>, ISpecialBlockItemRequirement {
|
implements ICogWheel, ITE<SimpleKineticTileEntity>, ISpecialBlockItemRequirement, ITransformableBlock {
|
||||||
|
|
||||||
public static final BooleanProperty TOP_SHAFT = BooleanProperty.create("top_shaft");
|
public static final BooleanProperty TOP_SHAFT = BooleanProperty.create("top_shaft");
|
||||||
public static final BooleanProperty BOTTOM_SHAFT = BooleanProperty.create("bottom_shaft");
|
public static final BooleanProperty BOTTOM_SHAFT = BooleanProperty.create("bottom_shaft");
|
||||||
|
@ -120,6 +125,16 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock
|
||||||
return InteractionResult.SUCCESS;
|
return InteractionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) {
|
||||||
|
originalState = swapShaftsForRotation(originalState, Rotation.CLOCKWISE_90, targetedFace.getAxis());
|
||||||
|
return originalState.setValue(RotatedPillarKineticBlock.AXIS,
|
||||||
|
VoxelShaper
|
||||||
|
.axisAsFace(originalState.getValue(RotatedPillarKineticBlock.AXIS))
|
||||||
|
.getClockWise(targetedFace.getAxis())
|
||||||
|
.getAxis());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) {
|
public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) {
|
||||||
if (context.getLevel().isClientSide)
|
if (context.getLevel().isClientSide)
|
||||||
|
@ -170,6 +185,81 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock
|
||||||
return state.getValue(AXIS);
|
return state.getValue(AXIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockState swapShafts(BlockState state) {
|
||||||
|
boolean bottom = state.getValue(BOTTOM_SHAFT);
|
||||||
|
boolean top = state.getValue(TOP_SHAFT);
|
||||||
|
state = state.setValue(BOTTOM_SHAFT, top);
|
||||||
|
state = state.setValue(TOP_SHAFT, bottom);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockState swapShaftsForRotation(BlockState state, Rotation rotation, Direction.Axis rotationAxis) {
|
||||||
|
if (rotation == Rotation.NONE) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
Direction.Axis axis = state.getValue(AXIS);
|
||||||
|
if (axis == rotationAxis) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rotation == Rotation.CLOCKWISE_180) {
|
||||||
|
return swapShafts(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean clockwise = rotation == Rotation.CLOCKWISE_90;
|
||||||
|
|
||||||
|
if (rotationAxis == Direction.Axis.X) {
|
||||||
|
if ( axis == Direction.Axis.Z && !clockwise
|
||||||
|
|| axis == Direction.Axis.Y && clockwise) {
|
||||||
|
return swapShafts(state);
|
||||||
|
}
|
||||||
|
} else if (rotationAxis == Direction.Axis.Y) {
|
||||||
|
if ( axis == Direction.Axis.X && !clockwise
|
||||||
|
|| axis == Direction.Axis.Z && clockwise) {
|
||||||
|
return swapShafts(state);
|
||||||
|
}
|
||||||
|
} else if (rotationAxis == Direction.Axis.Z) {
|
||||||
|
if ( axis == Direction.Axis.Y && !clockwise
|
||||||
|
|| axis == Direction.Axis.X && clockwise) {
|
||||||
|
return swapShafts(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState mirror(BlockState state, Mirror mirror) {
|
||||||
|
Direction.Axis axis = state.getValue(AXIS);
|
||||||
|
if (axis == Direction.Axis.X && mirror == Mirror.FRONT_BACK
|
||||||
|
|| axis == Direction.Axis.Z && mirror == Mirror.LEFT_RIGHT) {
|
||||||
|
return swapShafts(state);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState rotate(BlockState state, Rotation rotation) {
|
||||||
|
state = swapShaftsForRotation(state, rotation, Direction.Axis.Y);
|
||||||
|
return super.rotate(state, rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState transform(BlockState state, StructureTransform transform) {
|
||||||
|
if (transform.mirror != null) {
|
||||||
|
state = mirror(state, transform.mirror);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transform.rotationAxis == Direction.Axis.Y) {
|
||||||
|
return rotate(state, transform.rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
state = swapShaftsForRotation(state, transform.rotation, transform.rotationAxis);
|
||||||
|
state = state.setValue(AXIS, transform.rotateAxis(state.getValue(AXIS)));
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) {
|
public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) {
|
||||||
return ItemRequirement
|
return ItemRequirement
|
||||||
|
|
|
@ -9,7 +9,6 @@ import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock;
|
||||||
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
|
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
|
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
|
||||||
import com.simibubi.create.foundation.utility.DirectionHelper;
|
|
||||||
import com.simibubi.create.foundation.utility.VoxelShaper;
|
import com.simibubi.create.foundation.utility.VoxelShaper;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -81,20 +80,20 @@ public interface IWrenchable {
|
||||||
|
|
||||||
if (targetedFace.getAxis() == Direction.Axis.Y) {
|
if (targetedFace.getAxis() == Direction.Axis.Y) {
|
||||||
if (originalState.hasProperty(HorizontalAxisKineticBlock.HORIZONTAL_AXIS))
|
if (originalState.hasProperty(HorizontalAxisKineticBlock.HORIZONTAL_AXIS))
|
||||||
return originalState.setValue(HorizontalAxisKineticBlock.HORIZONTAL_AXIS, DirectionHelper
|
return originalState.setValue(HorizontalAxisKineticBlock.HORIZONTAL_AXIS, VoxelShaper
|
||||||
.rotateAround(VoxelShaper.axisAsFace(originalState.getValue(HorizontalAxisKineticBlock.HORIZONTAL_AXIS)),
|
.axisAsFace(originalState.getValue(HorizontalAxisKineticBlock.HORIZONTAL_AXIS))
|
||||||
targetedFace.getAxis())
|
.getClockWise(targetedFace.getAxis())
|
||||||
.getAxis());
|
.getAxis());
|
||||||
if (originalState.hasProperty(HorizontalKineticBlock.HORIZONTAL_FACING))
|
if (originalState.hasProperty(HorizontalKineticBlock.HORIZONTAL_FACING))
|
||||||
return originalState.setValue(HorizontalKineticBlock.HORIZONTAL_FACING, DirectionHelper
|
return originalState.setValue(HorizontalKineticBlock.HORIZONTAL_FACING, originalState
|
||||||
.rotateAround(originalState.getValue(HorizontalKineticBlock.HORIZONTAL_FACING), targetedFace.getAxis()));
|
.getValue(HorizontalKineticBlock.HORIZONTAL_FACING).getClockWise(targetedFace.getAxis()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (originalState.hasProperty(RotatedPillarKineticBlock.AXIS))
|
if (originalState.hasProperty(RotatedPillarKineticBlock.AXIS))
|
||||||
return originalState.setValue(RotatedPillarKineticBlock.AXIS,
|
return originalState.setValue(RotatedPillarKineticBlock.AXIS,
|
||||||
DirectionHelper
|
VoxelShaper
|
||||||
.rotateAround(VoxelShaper.axisAsFace(originalState.getValue(RotatedPillarKineticBlock.AXIS)),
|
.axisAsFace(originalState.getValue(RotatedPillarKineticBlock.AXIS))
|
||||||
targetedFace.getAxis())
|
.getClockWise(targetedFace.getAxis())
|
||||||
.getAxis());
|
.getAxis());
|
||||||
|
|
||||||
if (!originalState.hasProperty(DirectionalKineticBlock.FACING))
|
if (!originalState.hasProperty(DirectionalKineticBlock.FACING))
|
||||||
|
@ -111,7 +110,7 @@ public interface IWrenchable {
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
newState = newState.setValue(DirectionalKineticBlock.FACING,
|
newState = newState.setValue(DirectionalKineticBlock.FACING,
|
||||||
DirectionHelper.rotateAround(newState.getValue(DirectionalKineticBlock.FACING), targetedFace.getAxis()));
|
newState.getValue(DirectionalKineticBlock.FACING).getClockWise(targetedFace.getAxis()));
|
||||||
if (targetedFace.getAxis() == Direction.Axis.Y
|
if (targetedFace.getAxis() == Direction.Axis.Y
|
||||||
&& newState.hasProperty(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE))
|
&& newState.hasProperty(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE))
|
||||||
newState = newState.cycle(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE);
|
newState = newState.cycle(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE);
|
||||||
|
|
|
@ -151,7 +151,10 @@ public class ArmInteractionPoint {
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return null;
|
return null;
|
||||||
BlockPos pos = NbtUtils.readBlockPos(nbt.getCompound("Pos")).offset(anchor);
|
BlockPos pos = NbtUtils.readBlockPos(nbt.getCompound("Pos")).offset(anchor);
|
||||||
ArmInteractionPoint point = type.createPoint(level, pos, level.getBlockState(pos));
|
BlockState state = level.getBlockState(pos);
|
||||||
|
if (!type.canCreatePoint(level, pos, state))
|
||||||
|
return null;
|
||||||
|
ArmInteractionPoint point = type.createPoint(level, pos, state);
|
||||||
if (point == null)
|
if (point == null)
|
||||||
return null;
|
return null;
|
||||||
point.deserialize(nbt, anchor);
|
point.deserialize(nbt, anchor);
|
||||||
|
|
|
@ -27,6 +27,7 @@ import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.ListTag;
|
import net.minecraft.nbt.ListTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
|
@ -39,6 +40,7 @@ import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.JukeboxBlock;
|
import net.minecraft.world.level.block.JukeboxBlock;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkSource;
|
||||||
import net.minecraft.world.phys.AABB;
|
import net.minecraft.world.phys.AABB;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
@ -410,10 +412,45 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
|
||||||
notifyUpdate();
|
notifyUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClientLevel#hasChunk (and consequently #isAreaLoaded) always returns true,
|
||||||
|
// so manually check the ChunkSource to avoid weird behavior on the client side
|
||||||
|
protected boolean isAreaActuallyLoaded(BlockPos center, int range) {
|
||||||
|
if (!level.isAreaLoaded(center, range)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (level.isClientSide) {
|
||||||
|
int minY = center.getY() - range;
|
||||||
|
int maxY = center.getY() + range;
|
||||||
|
if (maxY < level.getMinBuildHeight() || minY >= level.getMaxBuildHeight()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int minX = center.getX() - range;
|
||||||
|
int minZ = center.getZ() - range;
|
||||||
|
int maxX = center.getX() + range;
|
||||||
|
int maxZ = center.getZ() + range;
|
||||||
|
|
||||||
|
int minChunkX = SectionPos.blockToSectionCoord(minX);
|
||||||
|
int maxChunkX = SectionPos.blockToSectionCoord(maxX);
|
||||||
|
int minChunkZ = SectionPos.blockToSectionCoord(minZ);
|
||||||
|
int maxChunkZ = SectionPos.blockToSectionCoord(maxZ);
|
||||||
|
|
||||||
|
ChunkSource chunkSource = level.getChunkSource();
|
||||||
|
for (int chunkX = minChunkX; chunkX <= maxChunkX; ++chunkX) {
|
||||||
|
for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; ++chunkZ) {
|
||||||
|
if (!chunkSource.hasChunk(chunkX, chunkZ)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected void initInteractionPoints() {
|
protected void initInteractionPoints() {
|
||||||
if (!updateInteractionPoints || interactionPointTag == null)
|
if (!updateInteractionPoints || interactionPointTag == null)
|
||||||
return;
|
return;
|
||||||
if (!level.isAreaLoaded(worldPosition, getRange() + 1))
|
if (!isAreaActuallyLoaded(worldPosition, getRange() + 1))
|
||||||
return;
|
return;
|
||||||
inputs.clear();
|
inputs.clear();
|
||||||
outputs.clear();
|
outputs.clear();
|
||||||
|
@ -506,7 +543,7 @@ public class ArmTileEntity extends KineticTileEntity implements ITransformableTE
|
||||||
previousTarget = previousPoint == null ? ArmAngleTarget.NO_TARGET
|
previousTarget = previousPoint == null ? ArmAngleTarget.NO_TARGET
|
||||||
: previousPoint.getTargetAngles(worldPosition, ceiling);
|
: previousPoint.getTargetAngles(worldPosition, ceiling);
|
||||||
if (previousPoint != null)
|
if (previousPoint != null)
|
||||||
previousBaseAngle = previousPoint.getTargetAngles(worldPosition, ceiling).baseAngle;
|
previousBaseAngle = previousTarget.baseAngle;
|
||||||
|
|
||||||
ArmInteractionPoint targetedPoint = getTargetedInteractionPoint();
|
ArmInteractionPoint targetedPoint = getTargetedInteractionPoint();
|
||||||
if (targetedPoint != null)
|
if (targetedPoint != null)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.simibubi.create.foundation.block;
|
package com.simibubi.create.foundation.block;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||||
import com.simibubi.create.foundation.utility.DirectionHelper;
|
|
||||||
|
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||||
|
@ -31,7 +30,7 @@ public class WrenchableDirectionalBlock extends DirectionalBlock implements IWre
|
||||||
if (facing.getAxis() == targetedFace.getAxis())
|
if (facing.getAxis() == targetedFace.getAxis())
|
||||||
return originalState;
|
return originalState;
|
||||||
|
|
||||||
Direction newFacing = DirectionHelper.rotateAround(facing, targetedFace.getAxis());
|
Direction newFacing = facing.getClockWise(targetedFace.getAxis());
|
||||||
|
|
||||||
return originalState.setValue(FACING, newFacing);
|
return originalState.setValue(FACING, newFacing);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
package com.simibubi.create.foundation.utility;
|
|
||||||
|
|
||||||
import static net.minecraft.core.Direction.DOWN;
|
|
||||||
import static net.minecraft.core.Direction.EAST;
|
|
||||||
import static net.minecraft.core.Direction.NORTH;
|
|
||||||
import static net.minecraft.core.Direction.SOUTH;
|
|
||||||
import static net.minecraft.core.Direction.UP;
|
|
||||||
import static net.minecraft.core.Direction.WEST;
|
|
||||||
|
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.core.Direction.Axis;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A bunch of methods that got stripped out of Direction in 1.15
|
|
||||||
*
|
|
||||||
* @author Mojang
|
|
||||||
*/
|
|
||||||
public class DirectionHelper {
|
|
||||||
|
|
||||||
public static Direction rotateAround(Direction dir, Direction.Axis axis) {
|
|
||||||
switch (axis) {
|
|
||||||
case X:
|
|
||||||
if (dir != WEST && dir != EAST) {
|
|
||||||
return rotateX(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dir;
|
|
||||||
case Y:
|
|
||||||
if (dir != UP && dir != DOWN) {
|
|
||||||
return dir.getClockWise();
|
|
||||||
}
|
|
||||||
|
|
||||||
return dir;
|
|
||||||
case Z:
|
|
||||||
if (dir != NORTH && dir != SOUTH) {
|
|
||||||
return rotateZ(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dir;
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException("Unable to get CW facing for axis " + axis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Direction rotateX(Direction dir) {
|
|
||||||
switch (dir) {
|
|
||||||
case NORTH:
|
|
||||||
return DOWN;
|
|
||||||
case EAST:
|
|
||||||
case WEST:
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException("Unable to get X-rotated facing of " + dir);
|
|
||||||
case SOUTH:
|
|
||||||
return UP;
|
|
||||||
case UP:
|
|
||||||
return NORTH;
|
|
||||||
case DOWN:
|
|
||||||
return SOUTH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Direction rotateZ(Direction dir) {
|
|
||||||
switch (dir) {
|
|
||||||
case EAST:
|
|
||||||
return DOWN;
|
|
||||||
case SOUTH:
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException("Unable to get Z-rotated facing of " + dir);
|
|
||||||
case WEST:
|
|
||||||
return UP;
|
|
||||||
case UP:
|
|
||||||
return EAST;
|
|
||||||
case DOWN:
|
|
||||||
return WEST;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Direction getPositivePerpendicular(Axis horizontalAxis) {
|
|
||||||
return horizontalAxis == Axis.X ? SOUTH : EAST;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -28,7 +28,7 @@ public enum Pointing implements StringRepresentable {
|
||||||
Direction top = axis == Axis.Y ? Direction.SOUTH : Direction.UP;
|
Direction top = axis == Axis.Y ? Direction.SOUTH : Direction.UP;
|
||||||
int rotations = direction.getAxisDirection() == AxisDirection.NEGATIVE ? 4 - ordinal() : ordinal();
|
int rotations = direction.getAxisDirection() == AxisDirection.NEGATIVE ? 4 - ordinal() : ordinal();
|
||||||
for (int i = 0; i < rotations; i++)
|
for (int i = 0; i < rotations; i++)
|
||||||
top = DirectionHelper.rotateAround(top, axis);
|
top = top.getClockWise(axis);
|
||||||
return top;
|
return top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue