Cart Rotation Lock

- Minecart assemblers can now be configured to 3 different rotation modes
This commit is contained in:
simibubi 2020-04-29 23:32:17 +02:00
parent 45897e4c18
commit 885791f878
9 changed files with 154 additions and 25 deletions

View file

@ -15,6 +15,7 @@ import com.simibubi.create.modules.contraptions.components.contraptions.bearing.
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.ClockworkBearingTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.bearing.ClockworkBearingTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.MechanicalBearingTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.bearing.MechanicalBearingTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.CartAssemblerTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonTileEntityRenderer; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyRenderer; import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyRenderer;
@ -146,6 +147,7 @@ public enum AllTileEntities {
SPEED_GAUGE(SpeedGaugeTileEntity::new, AllBlocks.SPEED_GAUGE), SPEED_GAUGE(SpeedGaugeTileEntity::new, AllBlocks.SPEED_GAUGE),
STRESS_GAUGE(StressGaugeTileEntity::new, AllBlocks.STRESS_GAUGE), STRESS_GAUGE(StressGaugeTileEntity::new, AllBlocks.STRESS_GAUGE),
ANALOG_LEVER(AnalogLeverTileEntity::new, AllBlocks.ANALOG_LEVER), ANALOG_LEVER(AnalogLeverTileEntity::new, AllBlocks.ANALOG_LEVER),
CART_ASSEMBLER(CartAssemblerTileEntity::new, AllBlocks.CART_ASSEMBLER),
// Logistics // Logistics
REDSTONE_BRIDGE(RedstoneLinkTileEntity::new, AllBlocks.REDSTONE_BRIDGE), REDSTONE_BRIDGE(RedstoneLinkTileEntity::new, AllBlocks.REDSTONE_BRIDGE),

View file

@ -133,6 +133,9 @@ public enum ScreenResources {
I_MOVE_PLACE(9, 1), I_MOVE_PLACE(9, 1),
I_MOVE_PLACE_RETURNED(10, 1), I_MOVE_PLACE_RETURNED(10, 1),
I_MOVE_NEVER_PLACE(11, 1), I_MOVE_NEVER_PLACE(11, 1),
I_CART_ROTATE(12, 1),
I_CART_ROTATE_PAUSED(13, 1),
I_CART_ROTATE_LOCKED(14, 1),
I_DONT_REPLACE(0, 2), I_DONT_REPLACE(0, 2),
I_REPLACE_SOLID(1, 2), I_REPLACE_SOLID(1, 2),

View file

@ -19,16 +19,16 @@ public class AngleHelper {
public static float rad(float angle) { public static float rad(float angle) {
return (float) (angle / 180 * Math.PI); return (float) (angle / 180 * Math.PI);
} }
public static float deg(float angle) { public static float deg(float angle) {
return (float) (angle * 180 / Math.PI); return (float) (angle * 180 / Math.PI);
} }
public static float angleLerp(float pct, float current, float target) { public static float angleLerp(float pct, float current, float target) {
return current + getShortestAngleDiff(current, target) * pct; return current + getShortestAngleDiff(current, target) * pct;
} }
public static float getShortestAngleDiff(double current, double target) { public static float getShortestAngleDiff(double current, double target) {
current = current % 360; current = current % 360;
target = target % 360; target = target % 360;
return (float) (((((target - current) % 360) + 540) % 360) - 180); return (float) (((((target - current) % 360) + 540) % 360) - 180);

View file

@ -12,8 +12,11 @@ import org.apache.commons.lang3.tuple.MutablePair;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.simibubi.create.AllEntities; import com.simibubi.create.AllEntities;
import com.simibubi.create.AllPackets; import com.simibubi.create.AllPackets;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.BearingContraption; import com.simibubi.create.modules.contraptions.components.contraptions.bearing.BearingContraption;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.CartAssemblerTileEntity.CartMovementMode;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.MountedContraption;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.LinearActuatorTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.piston.LinearActuatorTileEntity;
import net.minecraft.block.material.PushReaction; import net.minecraft.block.material.PushReaction;
@ -156,6 +159,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
public void tickAsPassenger(Entity e) { public void tickAsPassenger(Entity e) {
boolean rotationLock = false;
boolean pauseWhileRotating = false;
if (contraption instanceof MountedContraption) {
rotationLock = ((MountedContraption) contraption).rotationMode == CartMovementMode.ROTATION_LOCKED;
pauseWhileRotating = ((MountedContraption) contraption).rotationMode == CartMovementMode.ROTATE_PAUSED;
}
Entity riding = e; Entity riding = e;
while (riding.getRidingEntity() != null) while (riding.getRidingEntity() != null)
riding = riding.getRidingEntity(); riding = riding.getRidingEntity();
@ -163,20 +174,28 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (riding instanceof BoatEntity) if (riding instanceof BoatEntity)
movementVector = new Vec3d(posX - prevPosX, posY - prevPosY, posZ - prevPosZ); movementVector = new Vec3d(posX - prevPosX, posY - prevPosY, posZ - prevPosZ);
Vec3d motion = movementVector.normalize(); Vec3d motion = movementVector.normalize();
boolean rotating = false;
if (motion.length() > 0) { if (!rotationLock) {
targetYaw = yawFromVector(motion); if (motion.length() > 0) {
if (targetYaw < 0) targetYaw = yawFromVector(motion);
targetYaw += 360; if (targetYaw < 0)
if (yaw < 0) targetYaw += 360;
yaw += 360; if (yaw < 0)
yaw += 360;
}
prevYaw = yaw;
yaw = angleLerp(0.4f, yaw, targetYaw);
if (Math.abs(AngleHelper.getShortestAngleDiff(yaw, targetYaw)) < 1f)
yaw = targetYaw;
else
rotating = true;
} }
prevYaw = yaw;
yaw = angleLerp(0.4f, yaw, targetYaw);
boolean wasStalled = isStalled(); boolean wasStalled = isStalled();
tickActors(movementVector); if (!rotating || !pauseWhileRotating)
tickActors(movementVector);
if (isStalled()) { if (isStalled()) {
if (!wasStalled) if (!wasStalled)
motionBeforeStall = riding.getMotion(); motionBeforeStall = riding.getMotion();
@ -434,8 +453,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
@Override @Override
protected void doWaterSplashEffect() { protected void doWaterSplashEffect() {}
}
public void preventMovedEntitiesFromGettingStuck() { public void preventMovedEntitiesFromGettingStuck() {
Vec3d stuckTest = new Vec3d(0, -2, 0); Vec3d stuckTest = new Vec3d(0, -2, 0);
@ -524,8 +542,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
@Override @Override
// Make sure nothing can move contraptions out of the way // Make sure nothing can move contraptions out of the way
public void setMotion(Vec3d motionIn) { public void setMotion(Vec3d motionIn) {}
}
@Override @Override
public PushReaction getPushReaction() { public PushReaction getPushReaction() {

View file

@ -1,10 +1,11 @@
package com.simibubi.create.modules.contraptions.components.contraptions.mounted; package com.simibubi.create.modules.contraptions.components.contraptions.mounted;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.block.RenderUtilityBlock; import com.simibubi.create.foundation.block.RenderUtilityBlock;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity; import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.CartAssemblerTileEntity.CartMovementMode;
import net.minecraft.block.AbstractRailBlock; import net.minecraft.block.AbstractRailBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -19,6 +20,7 @@ import net.minecraft.state.IProperty;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.RailShape; import net.minecraft.state.properties.RailShape;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -28,7 +30,7 @@ import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class CartAssemblerBlock extends AbstractRailBlock { public class CartAssemblerBlock extends AbstractRailBlock implements ITE<CartAssemblerTileEntity> {
public static IProperty<RailShape> RAIL_SHAPE = public static IProperty<RailShape> RAIL_SHAPE =
EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST, RailShape.NORTH_SOUTH); EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST, RailShape.NORTH_SOUTH);
@ -45,6 +47,16 @@ public class CartAssemblerBlock extends AbstractRailBlock {
super.fillStateContainer(builder); super.fillStateContainer(builder);
} }
@Override
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new CartAssemblerTileEntity();
}
@Override @Override
public BlockState getStateForPlacement(BlockItemUseContext context) { public BlockState getStateForPlacement(BlockItemUseContext context) {
boolean alongX = context.getPlacementHorizontalFacing().getAxis() == Axis.X; boolean alongX = context.getPlacementHorizontalFacing().getAxis() == Axis.X;
@ -72,12 +84,15 @@ public class CartAssemblerBlock extends AbstractRailBlock {
if (!cart.getPassengers().isEmpty()) if (!cart.getPassengers().isEmpty())
return; return;
Contraption contraption = MountedContraption.assembleMinecart(world, pos); MountedContraption contraption = MountedContraption.assembleMinecart(world, pos);
if (contraption == null) if (contraption == null)
return; return;
if (contraption.blocks.size() == 1) if (contraption.blocks.size() == 1)
return; return;
float initialAngle = ContraptionEntity.yawFromVector(cart.getMotion()); float initialAngle = ContraptionEntity.yawFromVector(cart.getMotion());
withTileEntityDo(world, pos, te -> contraption.rotationMode = CartMovementMode.values()[te.movementMode.value]);
ContraptionEntity entity = ContraptionEntity.createMounted(world, contraption, initialAngle); ContraptionEntity entity = ContraptionEntity.createMounted(world, contraption, initialAngle);
entity.setPosition(pos.getX(), pos.getY(), pos.getZ()); entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
world.addEntity(entity); world.addEntity(entity);
@ -129,7 +144,7 @@ public class CartAssemblerBlock extends AbstractRailBlock {
public PushReaction getPushReaction(BlockState state) { public PushReaction getPushReaction(BlockState state) {
return PushReaction.BLOCK; return PushReaction.BLOCK;
} }
@Override @Override
public boolean isNormalCube(BlockState state, IBlockReader worldIn, BlockPos pos) { public boolean isNormalCube(BlockState state, IBlockReader worldIn, BlockPos pos) {
return false; return false;
@ -142,7 +157,7 @@ public class CartAssemblerBlock extends AbstractRailBlock {
builder.add(BlockStateProperties.HORIZONTAL_AXIS); builder.add(BlockStateProperties.HORIZONTAL_AXIS);
super.fillStateContainer(builder); super.fillStateContainer(builder);
} }
@Override @Override
public boolean isSolid(BlockState state) { public boolean isSolid(BlockState state) {
return false; return false;
@ -155,4 +170,9 @@ public class CartAssemblerBlock extends AbstractRailBlock {
return AllBlocks.MINECART_ANCHOR.get().getDefaultState().with(BlockStateProperties.HORIZONTAL_AXIS, axis); return AllBlocks.MINECART_ANCHOR.get().getDefaultState().with(BlockStateProperties.HORIZONTAL_AXIS, axis);
} }
@Override
public Class<CartAssemblerTileEntity> getTileEntityClass() {
return CartAssemblerTileEntity.class;
}
} }

View file

@ -0,0 +1,65 @@
package com.simibubi.create.modules.contraptions.components.contraptions.mounted;
import java.util.List;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.ScreenResources;
import com.simibubi.create.foundation.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.scrollvalue.INamedIconOptions;
import com.simibubi.create.foundation.behaviour.scrollvalue.ScrollOptionBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.util.Direction;
public class CartAssemblerTileEntity extends SmartTileEntity {
protected ScrollOptionBehaviour<CartMovementMode> movementMode;
public CartAssemblerTileEntity() {
super(AllTileEntities.CART_ASSEMBLER.type);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
movementMode = new ScrollOptionBehaviour<>(CartMovementMode.class,
Lang.translate("contraptions.cart_movement_mode"), this, getMovementModeSlot());
movementMode.requiresWrench();
behaviours.add(movementMode);
}
protected ValueBoxTransform getMovementModeSlot() {
return new CenteredSideValueBoxTransform((state, d) -> d == Direction.UP);
}
public static enum CartMovementMode implements INamedIconOptions {
ROTATE(ScreenResources.I_CART_ROTATE),
ROTATE_PAUSED(ScreenResources.I_CART_ROTATE_PAUSED),
ROTATION_LOCKED(ScreenResources.I_CART_ROTATE_LOCKED),
;
private String translationKey;
private ScreenResources icon;
private CartMovementMode(ScreenResources icon) {
this.icon = icon;
translationKey = "contraptions.cart_movement_mode." + Lang.asId(name());
}
@Override
public ScreenResources getIcon() {
return icon;
}
@Override
public String getTranslationKey() {
return translationKey;
}
}
}

View file

@ -7,11 +7,14 @@ import java.util.List;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.AllContraptionTypes; import com.simibubi.create.modules.contraptions.components.contraptions.AllContraptionTypes;
import com.simibubi.create.modules.contraptions.components.contraptions.BlockMovementTraits; import com.simibubi.create.modules.contraptions.components.contraptions.BlockMovementTraits;
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption; import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.CartAssemblerTileEntity.CartMovementMode;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.RailShape; import net.minecraft.state.properties.RailShape;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -26,12 +29,14 @@ import net.minecraft.world.gen.feature.template.Template.BlockInfo;
public class MountedContraption extends Contraption { public class MountedContraption extends Contraption {
public CartMovementMode rotationMode;
@Override @Override
protected AllContraptionTypes getType() { protected AllContraptionTypes getType() {
return AllContraptionTypes.MOUNTED; return AllContraptionTypes.MOUNTED;
} }
public static Contraption assembleMinecart(World world, BlockPos pos) { public static MountedContraption assembleMinecart(World world, BlockPos pos) {
if (isFrozen()) if (isFrozen())
return null; return null;
@ -39,7 +44,7 @@ public class MountedContraption extends Contraption {
if (!state.has(RAIL_SHAPE)) if (!state.has(RAIL_SHAPE))
return null; return null;
Contraption contraption = new MountedContraption(); MountedContraption contraption = new MountedContraption();
if (!contraption.searchMovedStructure(world, pos, null)) if (!contraption.searchMovedStructure(world, pos, null))
return null; return null;
@ -83,6 +88,19 @@ public class MountedContraption extends Contraption {
return pair; return pair;
} }
@Override
public CompoundNBT writeNBT() {
CompoundNBT writeNBT = super.writeNBT();
writeNBT.putString("RotationMode", NBTHelper.writeEnum(rotationMode));
return writeNBT;
}
@Override
public void readNBT(World world, CompoundNBT nbt) {
rotationMode = NBTHelper.readEnum(nbt.getString("RotationMode"), CartMovementMode.class);
super.readNBT(world, nbt);
}
@Override @Override
public void removeBlocksFromWorld(IWorld world, BlockPos offset) { public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
super.removeBlocksFromWorld(world, offset, (pos, state) -> pos.equals(anchor)); super.removeBlocksFromWorld(world, offset, (pos, state) -> pos.equals(anchor));

View file

@ -391,6 +391,10 @@
"create.contraptions.movement_mode.rotate_place": "Always Place when Stopped", "create.contraptions.movement_mode.rotate_place": "Always Place when Stopped",
"create.contraptions.movement_mode.rotate_place_returned": "Only Place near Initial Angle", "create.contraptions.movement_mode.rotate_place_returned": "Only Place near Initial Angle",
"create.contraptions.movement_mode.rotate_never_place": "Only Place when Anchor Destroyed", "create.contraptions.movement_mode.rotate_never_place": "Only Place when Anchor Destroyed",
"create.contraptions.cart_movement_mode": "Cart Movement Mode",
"create.contraptions.cart_movement_mode.rotate": "Always face toward motion",
"create.contraptions.cart_movement_mode.rotate_paused": "Pause actors while rotating",
"create.contraptions.cart_movement_mode.rotation_locked": "Lock rotation",
"create.logistics.filter": "Filter", "create.logistics.filter": "Filter",
"create.logistics.firstFrequency": "Freq. #1", "create.logistics.firstFrequency": "Freq. #1",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB