Contraption Bug-Fixes

- Fixed the generated rendering bounding box of rotating contraptions
- Fixed clockwork bearings moving their hands inconsistently in some cases
- Pistons, Pulleys and Bearings can now be kick-started with a right click
- Contacts no longer apply a pulse to the contact they were powering before movement
- Fixed deployers animating strangely when the contaption is stalled
- Fixed minecart contraptions not having the same orientation on server and client
- Fixed minecart contraptions not reacting to movement when the minecart is itself mounting another entity
- Fixed minecart contraptions not remembering their motion when unloaded while stalling
- Fixed minecart contraptions not being initialized with the correct angles
This commit is contained in:
simibubi 2020-03-07 19:08:16 +01:00
parent ea5c77b2b2
commit bea5d783ce
17 changed files with 243 additions and 79 deletions

View file

@ -19,6 +19,7 @@ import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.config.AllConfigs; import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity;
@ -34,6 +35,8 @@ import net.minecraft.nbt.NBTUtil;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -50,7 +53,7 @@ public abstract class Contraption {
public List<MutablePair<BlockInfo, MovementContext>> actors; public List<MutablePair<BlockInfo, MovementContext>> actors;
public CombinedInvWrapper inventory; public CombinedInvWrapper inventory;
public AxisAlignedBB constructCollisionBox; public AxisAlignedBB bounds;
public boolean stalled; public boolean stalled;
protected Set<BlockPos> cachedColliders; protected Set<BlockPos> cachedColliders;
@ -95,8 +98,8 @@ public abstract class Contraption {
Set<BlockPos> visited = new HashSet<>(); Set<BlockPos> visited = new HashSet<>();
anchor = pos; anchor = pos;
if (constructCollisionBox == null) if (bounds == null)
constructCollisionBox = new AxisAlignedBB(BlockPos.ZERO); bounds = new AxisAlignedBB(BlockPos.ZERO);
frontier.add(pos); frontier.add(pos);
if (!addToInitialFrontier(world, pos, forcedDirection, frontier)) if (!addToInitialFrontier(world, pos, forcedDirection, frontier))
@ -203,7 +206,7 @@ public abstract class Contraption {
if (blocks.put(localPos, blockInfo) != null) if (blocks.put(localPos, blockInfo) != null)
return; return;
constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(localPos)); bounds = bounds.union(new AxisAlignedBB(localPos));
TileEntity te = pair.getValue(); TileEntity te = pair.getValue();
if (te != null && MountedStorage.canUseAsStorage(te)) if (te != null && MountedStorage.canUseAsStorage(te))
@ -257,7 +260,7 @@ public abstract class Contraption {
inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
if (nbt.contains("BoundsFront")) if (nbt.contains("BoundsFront"))
constructCollisionBox = NBTHelper.readAABB(nbt.getList("BoundsFront", 5)); bounds = NBTHelper.readAABB(nbt.getList("BoundsFront", 5));
stalled = nbt.getBoolean("Stalled"); stalled = nbt.getBoolean("Stalled");
anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor")); anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor"));
@ -302,8 +305,8 @@ public abstract class Contraption {
nbt.put("Anchor", NBTUtil.writeBlockPos(anchor)); nbt.put("Anchor", NBTUtil.writeBlockPos(anchor));
nbt.putBoolean("Stalled", stalled); nbt.putBoolean("Stalled", stalled);
if (constructCollisionBox != null) { if (bounds != null) {
ListNBT bb = NBTHelper.writeAABB(constructCollisionBox); ListNBT bb = NBTHelper.writeAABB(bounds);
nbt.put("BoundsFront", bb); nbt.put("BoundsFront", bb);
} }
@ -387,8 +390,8 @@ public abstract class Contraption {
} }
} }
public AxisAlignedBB getCollisionBox() { public AxisAlignedBB getBoundingBox() {
return constructCollisionBox; return bounds;
} }
public List<MutablePair<BlockInfo, MovementContext>> getActors() { public List<MutablePair<BlockInfo, MovementContext>> getActors() {
@ -421,6 +424,27 @@ public abstract class Contraption {
return ((IPortableBlock) block).getMovementBehaviour(); return ((IPortableBlock) block).getMovementBehaviour();
} }
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;
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);
Vec3d vec = new Vec3d(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis).getDirectionVec());
Vec3d planeByNormal = VecHelper.planeByNormal(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);
}
protected abstract AllContraptionTypes getType(); protected abstract AllContraptionTypes getType();
} }

View file

@ -12,6 +12,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.item.BoatEntity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity; import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
@ -43,8 +44,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
protected Vec3d motionBeforeStall; protected Vec3d motionBeforeStall;
protected boolean stationary; protected boolean stationary;
private static final DataParameter<Boolean> STALLED = EntityDataManager.createKey(ContraptionEntity.class, private static final DataParameter<Boolean> STALLED =
DataSerializers.BOOLEAN); EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN);
public float prevYaw; public float prevYaw;
public float prevPitch; public float prevPitch;
@ -101,39 +102,41 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
Entity e = getRidingEntity(); Entity e = getRidingEntity();
if (e != null) { if (e != null) {
Vec3d movementVector = e.getMotion(); Entity riding = e;
while (riding.getRidingEntity() != null)
riding = riding.getRidingEntity();
Vec3d movementVector = riding.getMotion();
if (riding instanceof BoatEntity)
movementVector = new Vec3d(posX - prevPosX, posY - prevPosY, posZ - prevPosZ);
Vec3d motion = movementVector.normalize(); Vec3d motion = movementVector.normalize();
if (motion.length() > 0) { if (motion.length() > 0) {
targetYaw = yawFromVector(motion); targetYaw = yawFromVector(motion);
targetPitch = (float) ((Math.atan(motion.y) * 73.0D) / Math.PI * 180);
if (targetYaw < 0) if (targetYaw < 0)
targetYaw += 360; targetYaw += 360;
if (yaw < 0) if (yaw < 0)
yaw += 360; yaw += 360;
} }
if (Math.abs(getShortestAngleDiff(yaw, targetYaw)) >= 175) { // if (Math.abs(getShortestAngleDiff(yaw, targetYaw)) >= 175) {
initialAngle += 180; // initialAngle += 180;
yaw += 180; // yaw += 180;
prevYaw = yaw; // prevYaw = yaw;
} else { // } else {
float speed = 0.2f; float speed = 0.2f;
prevYaw = yaw; prevYaw = yaw;
yaw = angleLerp(speed, yaw, targetYaw); yaw = angleLerp(speed, yaw, targetYaw);
prevPitch = pitch; // }
pitch = angleLerp(speed, pitch, targetPitch);
}
boolean wasStalled = isStalled(); boolean wasStalled = isStalled();
tickActors(movementVector); tickActors(movementVector);
if (isStalled()) { if (isStalled()) {
if (!wasStalled) if (!wasStalled)
motionBeforeStall = e.getMotion(); motionBeforeStall = riding.getMotion();
e.setMotion(0, 0, 0); riding.setMotion(0, 0, 0);
} }
if (wasStalled && !isStalled()) { if (wasStalled && !isStalled()) {
e.setMotion(motionBeforeStall); riding.setMotion(motionBeforeStall);
motionBeforeStall = Vec3d.ZERO; motionBeforeStall = Vec3d.ZERO;
} }
@ -249,8 +252,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
public void setPosition(double x, double y, double z) { public void setPosition(double x, double y, double z) {
Entity e = getRidingEntity(); Entity e = getRidingEntity();
if (e != null && e instanceof AbstractMinecartEntity) { if (e != null && e instanceof AbstractMinecartEntity) {
x -= .5; Entity riding = e;
z -= .5; while (riding.getRidingEntity() != null)
riding = riding.getRidingEntity();
x = riding.posX - .5;
z = riding.posZ - .5;
} }
this.posX = x; this.posX = x;
@ -260,7 +266,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (this.isAddedToWorld() && !this.world.isRemote && world instanceof ServerWorld) if (this.isAddedToWorld() && !this.world.isRemote && world instanceof ServerWorld)
((ServerWorld) this.world).chunkCheck(this); // Forge - Process chunk registration after moving. ((ServerWorld) this.world).chunkCheck(this); // Forge - Process chunk registration after moving.
if (contraption != null) { if (contraption != null) {
AxisAlignedBB cbox = contraption.getCollisionBox(); AxisAlignedBB cbox = contraption.getBoundingBox();
if (cbox != null) if (cbox != null)
this.setBoundingBox(cbox.offset(x, y, z)); this.setBoundingBox(cbox.offset(x, y, z));
} }
@ -268,9 +274,9 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
@Override @Override
public void stopRiding() { public void stopRiding() {
super.stopRiding();
if (!world.isRemote) if (!world.isRemote)
disassemble(); disassemble();
super.stopRiding();
} }
public static float yawFromVector(Vec3d vec) { public static float yawFromVector(Vec3d vec) {
@ -309,14 +315,17 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
protected void readAdditional(CompoundNBT compound) { protected void readAdditional(CompoundNBT compound) {
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption")); contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
initialAngle = compound.getFloat("InitialAngle"); initialAngle = compound.getFloat("InitialAngle");
targetYaw = yaw = prevYaw = initialAngle;
dataManager.set(STALLED, compound.getBoolean("Stalled"));
ListNBT vecNBT = compound.getList("CachedMotion", 6); ListNBT vecNBT = compound.getList("CachedMotion", 6);
if (!vecNBT.isEmpty()) if (!vecNBT.isEmpty()) {
motionBeforeStall = new Vec3d(vecNBT.getDouble(0), vecNBT.getDouble(1), vecNBT.getDouble(2)); motionBeforeStall = new Vec3d(vecNBT.getDouble(0), vecNBT.getDouble(1), vecNBT.getDouble(2));
if (!motionBeforeStall.equals(Vec3d.ZERO))
targetYaw = prevYaw = yaw += yawFromVector(motionBeforeStall);
setMotion(Vec3d.ZERO);
}
if (compound.contains("Controller")) if (compound.contains("Controller"))
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller")); controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
prevYaw = initialAngle;
yaw = initialAngle;
targetYaw = initialAngle;
} }
public void attachToController() { public void attachToController() {
@ -341,7 +350,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
protected void writeAdditional(CompoundNBT compound) { protected void writeAdditional(CompoundNBT compound) {
compound.put("Contraption", getContraption().writeNBT()); compound.put("Contraption", getContraption().writeNBT());
compound.putFloat("InitialAngle", initialAngle); compound.putFloat("InitialAngle", initialAngle);
compound.put("CachedMotion", newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z)); if (!stationary)
compound.put("CachedMotion",
newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z));
compound.putBoolean("Stalled", isStalled());
if (controllerPos != null) if (controllerPos != null)
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos)); compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
} }
@ -364,9 +376,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
public void disassemble() { public void disassemble() {
if (getContraption() != null) if (getContraption() != null) {
float yaw = getYaw(1);
getContraption().disassemble(world, new BlockPos(getPositionVec().add(.5, .5, .5)), getContraption().disassemble(world, new BlockPos(getPositionVec().add(.5, .5, .5)),
new Vec3d(getRoll(1), getYaw(1), getPitch(1))); new Vec3d(getRoll(1), yaw, getPitch(1)));
}
remove(); remove();
} }

View file

@ -28,9 +28,11 @@ public class BearingContraption extends Contraption {
return null; return null;
BearingContraption construct = new BearingContraption(); BearingContraption construct = new BearingContraption();
construct.facing = direction; construct.facing = direction;
if (!construct.searchMovedStructure(world, pos.offset(direction), null)) BlockPos offset = pos.offset(direction);
if (!construct.searchMovedStructure(world, offset, null))
return null; return null;
construct.initActors(world); construct.initActors(world);
construct.expandBoundsAroundAxis(direction.getAxis());
return construct; return construct;
} }

View file

@ -1,14 +1,43 @@
package com.simibubi.create.modules.contraptions.components.contraptions.bearing; package com.simibubi.create.modules.contraptions.components.contraptions.bearing;
import net.minecraft.block.BlockState; import com.simibubi.create.foundation.block.IWithTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.IBlockReader;
public class ClockworkBearingBlock extends BearingBlock { import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public class ClockworkBearingBlock extends BearingBlock implements IWithTileEntity<ClockworkBearingTileEntity> {
@Override @Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) { public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new ClockworkBearingTileEntity(); return new ClockworkBearingTileEntity();
} }
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
if (!player.isAllowEdit())
return false;
if (player.isSneaking())
return false;
if (player.getHeldItem(handIn).isEmpty()) {
if (!worldIn.isRemote) {
withTileEntityDo(worldIn, pos, te -> {
if (te.running) {
te.disassembleConstruct();
return;
}
te.assembleNextTick = true;
});
}
return true;
}
return false;
}
} }

View file

@ -104,31 +104,41 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
} }
public float getHourArmSpeed() { public float getHourArmSpeed() {
float speed = getAngularSpeed() / 2f + clientHourAngleDiff / 3f; float speed = getAngularSpeed() / 2f;
if (speed != 0) { if (speed != 0) {
int dayTime = (int) (world.getDayTime() % 24000); int dayTime = (int) (world.getDayTime() % 24000);
int hours = (dayTime / 1000 + 6) % 24; int hours = (dayTime / 1000 + 6) % 24;
int offset = getBlockState().get(ClockworkBearingBlock.FACING).getAxisDirection().getOffset(); int offset = getBlockState().get(ClockworkBearingBlock.FACING).getAxisDirection().getOffset();
float hourTarget = (float) (offset * -360 / 12f * (hours % 12)); float hourTarget = (float) (offset * -360 / 12f * (hours % 12));
speed = Math.max(speed, AngleHelper.getShortestAngleDiff(hourAngle, hourTarget)); float shortestAngleDiff = AngleHelper.getShortestAngleDiff(hourAngle, hourTarget);
if (shortestAngleDiff < 0) {
speed = Math.max(speed, shortestAngleDiff);
} else {
speed = Math.min(-speed, shortestAngleDiff);
}
} }
return speed; return speed + clientHourAngleDiff / 3f;
} }
public float getMinuteArmSpeed() { public float getMinuteArmSpeed() {
float speed = getAngularSpeed() + clientMinuteAngleDiff / 3f; float speed = getAngularSpeed();
if (speed != 0) { if (speed != 0) {
int dayTime = (int) (world.getDayTime() % 24000); int dayTime = (int) (world.getDayTime() % 24000);
int minutes = (dayTime % 1000) * 60 / 1000; int minutes = (dayTime % 1000) * 60 / 1000;
int offset = getBlockState().get(ClockworkBearingBlock.FACING).getAxisDirection().getOffset(); int offset = getBlockState().get(ClockworkBearingBlock.FACING).getAxisDirection().getOffset();
float hourTarget = (float) (offset * -360 / 60f * (minutes)); float minuteTarget = (float) (offset * -360 / 60f * (minutes));
speed = Math.max(speed, AngleHelper.getShortestAngleDiff(minuteAngle, hourTarget)); float shortestAngleDiff = AngleHelper.getShortestAngleDiff(minuteAngle, minuteTarget);
if (shortestAngleDiff < 0) {
speed = Math.max(speed, shortestAngleDiff);
} else {
speed = Math.min(-speed, shortestAngleDiff);
}
} }
return speed; return speed + clientMinuteAngleDiff / 3f;
} }
public float getAngularSpeed() { public float getAngularSpeed() {
@ -175,16 +185,20 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
public void disassembleConstruct() { public void disassembleConstruct() {
if (!running) if (!running)
return; return;
if (hourHand != null)
hourAngle = 0;
minuteAngle = 0;
applyRotations();
if (hourHand != null) {
hourHand.disassemble(); hourHand.disassemble();
}
if (minuteHand != null) if (minuteHand != null)
minuteHand.disassemble(); minuteHand.disassemble();
hourHand = null; hourHand = null;
minuteHand = null; minuteHand = null;
running = false; running = false;
hourAngle = 0;
minuteAngle = 0;
sendData(); sendData();
} }

View file

@ -67,8 +67,11 @@ public class ClockworkContraption extends Contraption {
} }
hourArm.initActors(world); hourArm.initActors(world);
if (minuteArm != null) hourArm.expandBoundsAroundAxis(direction.getAxis());
if (minuteArm != null) {
minuteArm.initActors(world); minuteArm.initActors(world);
minuteArm.expandBoundsAroundAxis(direction.getAxis());
}
return Pair.of(hourArm, minuteArm); return Pair.of(hourArm, minuteArm);
} }

View file

@ -4,8 +4,11 @@ import com.simibubi.create.foundation.block.IWithTileEntity;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -16,6 +19,28 @@ public class MechanicalBearingBlock extends BearingBlock implements IWithTileEnt
return new MechanicalBearingTileEntity(); return new MechanicalBearingTileEntity();
} }
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
if (!player.isAllowEdit())
return false;
if (player.isSneaking())
return false;
if (player.getHeldItem(handIn).isEmpty()) {
if (!worldIn.isRemote) {
withTileEntityDo(worldIn, pos, te -> {
if (te.running) {
te.disassembleConstruct();
return;
}
te.assembleNextTick = true;
});
}
return true;
}
return false;
}
@Override @Override
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
withTileEntityDo(worldIn, pos, MechanicalBearingTileEntity::neighbourChanged); withTileEntityDo(worldIn, pos, MechanicalBearingTileEntity::neighbourChanged);

View file

@ -178,6 +178,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
running = false; running = false;
angle = 0; angle = 0;
updateGeneratedRotation(); updateGeneratedRotation();
assembleNextTick = false;
sendData(); sendData();
} }

View file

@ -22,6 +22,7 @@ import net.minecraft.state.properties.RailShape;
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;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.util.math.shapes.VoxelShapes;
@ -30,8 +31,8 @@ import net.minecraft.world.World;
public class CartAssemblerBlock extends AbstractRailBlock { public class CartAssemblerBlock extends AbstractRailBlock {
public static IProperty<RailShape> RAIL_SHAPE = EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST, public static IProperty<RailShape> RAIL_SHAPE =
RailShape.NORTH_SOUTH); EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST, RailShape.NORTH_SOUTH);
public static BooleanProperty POWERED = BlockStateProperties.POWERED; public static BooleanProperty POWERED = BlockStateProperties.POWERED;
public CartAssemblerBlock() { public CartAssemblerBlock() {
@ -62,6 +63,16 @@ public class CartAssemblerBlock extends AbstractRailBlock {
public void onMinecartPass(BlockState state, World world, BlockPos pos, AbstractMinecartEntity cart) { public void onMinecartPass(BlockState state, World world, BlockPos pos, AbstractMinecartEntity cart) {
if (!cart.canBeRidden()) if (!cart.canBeRidden())
return; return;
Vec3d p = cart.getPositionVec();
Vec3d m = cart.getMotion();
Vec3d p2 = p.add(m);
Direction facing = Direction.getFacingFromVector(m.x, m.y, m.z);
Axis axis = facing.getAxis();
double coord = axis.getCoordinate(pos.getX(), pos.getY(), pos.getZ()) + .5 + .25f * facing.getAxisDirection().getOffset();
if ((axis.getCoordinate(p.x, p.y, p.z) > coord) == (axis.getCoordinate(p2.x, p2.y, p2.z) % 1 > coord))
return;
if (state.get(POWERED)) if (state.get(POWERED))
disassemble(world, pos, cart); disassemble(world, pos, cart);
else else
@ -75,6 +86,8 @@ public class CartAssemblerBlock extends AbstractRailBlock {
Contraption contraption = MountedContraption.assembleMinecart(world, pos); Contraption contraption = MountedContraption.assembleMinecart(world, pos);
if (contraption == null) if (contraption == null)
return; return;
if (contraption.blocks.size() == 1)
return;
float initialAngle = ContraptionEntity.yawFromVector(cart.getMotion()); float initialAngle = ContraptionEntity.yawFromVector(cart.getMotion());
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());
@ -136,6 +149,11 @@ public class CartAssemblerBlock extends AbstractRailBlock {
super.fillStateContainer(builder); super.fillStateContainer(builder);
} }
@Override
public boolean isSolid(BlockState state) {
return false;
}
} }
public static BlockState createAnchor(BlockState state) { public static BlockState createAnchor(BlockState state) {

View file

@ -48,6 +48,7 @@ public class MountedContraption extends Contraption {
null), null)); null), null));
contraption.removeBlocksFromWorld(world, BlockPos.ZERO); contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
contraption.initActors(world); contraption.initActors(world);
contraption.expandBoundsAroundAxis(Axis.Y);
return contraption; return contraption;
} }

View file

@ -20,7 +20,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
public float offset; public float offset;
public boolean running; public boolean running;
protected boolean assembleNextTick; public boolean assembleNextTick;
public ContraptionEntity movedContraption; public ContraptionEntity movedContraption;
protected boolean forceMove; protected boolean forceMove;
protected ScrollOptionBehaviour<MovementMode> movementMode; protected ScrollOptionBehaviour<MovementMode> movementMode;

View file

@ -3,6 +3,7 @@ package com.simibubi.create.modules.contraptions.components.contraptions.piston;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.config.AllConfigs; import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock; import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock;
@ -32,7 +33,8 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.Tags; import net.minecraftforge.common.Tags;
public class MechanicalPistonBlock extends DirectionalAxisKineticBlock { public class MechanicalPistonBlock extends DirectionalAxisKineticBlock
implements IWithTileEntity<MechanicalPistonTileEntity> {
public static final EnumProperty<PistonState> STATE = EnumProperty.create("state", PistonState.class); public static final EnumProperty<PistonState> STATE = EnumProperty.create("state", PistonState.class);
protected boolean isSticky; protected boolean isSticky;
@ -52,11 +54,18 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock {
@Override @Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) { BlockRayTraceResult hit) {
if (state.get(STATE) != PistonState.RETRACTED)
return false;
if (!player.isAllowEdit()) if (!player.isAllowEdit())
return false; return false;
if (!player.getHeldItem(handIn).getItem().isIn(Tags.Items.SLIMEBALLS)) if (player.isSneaking())
return false;
if (!player.getHeldItem(handIn).getItem().isIn(Tags.Items.SLIMEBALLS)) {
if (player.getHeldItem(handIn).isEmpty()) {
withTileEntityDo(worldIn, pos, te -> te.assembleNextTick = true);
return true;
}
return false;
}
if (state.get(STATE) != PistonState.RETRACTED)
return false; return false;
Direction direction = state.get(FACING); Direction direction = state.get(FACING);
if (hit.getFace() != direction) if (hit.getFace() != direction)
@ -99,9 +108,7 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock {
} }
public enum PistonState implements IStringSerializable { public enum PistonState implements IStringSerializable {
RETRACTED, RETRACTED, MOVING, EXTENDED;
MOVING,
EXTENDED;
@Override @Override
public String getName() { public String getName() {

View file

@ -110,7 +110,7 @@ public class PistonContraption extends Contraption {
if (extensionLength == 0) if (extensionLength == 0)
return false; return false;
constructCollisionBox = new AxisAlignedBB(0, 0, 0, 0, 0, 0); bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
for (BlockInfo pole : poles) { for (BlockInfo pole : poles) {
BlockPos relPos = pole.pos.offset(direction, -extensionsInFront); BlockPos relPos = pole.pos.offset(direction, -extensionsInFront);
@ -213,7 +213,7 @@ public class PistonContraption extends Contraption {
} }
@Override @Override
public AxisAlignedBB getCollisionBox() { public AxisAlignedBB getBoundingBox() {
return super.getCollisionBox().union(pistonExtensionCollisionBox); return super.getBoundingBox().union(pistonExtensionCollisionBox);
} }
} }

View file

@ -2,24 +2,28 @@ package com.simibubi.create.modules.contraptions.components.contraptions.pulley;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IHaveNoBlockItem; import com.simibubi.create.foundation.block.IHaveNoBlockItem;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.base.HorizontalAxisKineticBlock; import com.simibubi.create.modules.contraptions.base.HorizontalAxisKineticBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.EnumProperty; import net.minecraft.state.EnumProperty;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class PulleyBlock extends HorizontalAxisKineticBlock { public class PulleyBlock extends HorizontalAxisKineticBlock implements IWithTileEntity<PulleyTileEntity> {
public static EnumProperty<Axis> HORIZONTAL_AXIS = BlockStateProperties.HORIZONTAL_AXIS; public static EnumProperty<Axis> HORIZONTAL_AXIS = BlockStateProperties.HORIZONTAL_AXIS;
@ -37,6 +41,20 @@ public class PulleyBlock extends HorizontalAxisKineticBlock {
return true; return true;
} }
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
if (!player.isAllowEdit())
return false;
if (player.isSneaking())
return false;
if (player.getHeldItem(handIn).isEmpty()) {
withTileEntityDo(worldIn, pos, te -> te.assembleNextTick = true);
return true;
}
return false;
}
@Override @Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.PULLEY.get(state.get(HORIZONTAL_AXIS)); return AllShapes.PULLEY.get(state.get(HORIZONTAL_AXIS));

View file

@ -52,7 +52,6 @@ public class DeployerMovementBehaviour extends MovementBehaviour {
Vec3d facingVec = new Vec3d(context.state.get(DeployerBlock.FACING).getDirectionVec()); Vec3d facingVec = new Vec3d(context.state.get(DeployerBlock.FACING).getDirectionVec());
facingVec = VecHelper.rotate(facingVec, context.rotation.x, context.rotation.y, context.rotation.z); facingVec = VecHelper.rotate(facingVec, context.rotation.x, context.rotation.y, context.rotation.z);
Vec3d vec = context.position.subtract(facingVec.scale(2)); Vec3d vec = context.position.subtract(facingVec.scale(2));
player.rotationYaw = ContraptionEntity.yawFromVector(facingVec); player.rotationYaw = ContraptionEntity.yawFromVector(facingVec);
player.rotationPitch = ContraptionEntity.pitchFromVector(facingVec) - 90; player.rotationPitch = ContraptionEntity.pitchFromVector(facingVec) - 90;

View file

@ -167,11 +167,18 @@ public class DeployerTileEntityRenderer extends SafeTileEntityRenderer<DeployerT
SuperByteBuffer pole = renderAndTransform(world, AllBlockPartials.DEPLOYER_POLE, blockState, pos, true); SuperByteBuffer pole = renderAndTransform(world, AllBlockPartials.DEPLOYER_POLE, blockState, pos, true);
SuperByteBuffer hand = renderAndTransform(world, handPose, blockState, pos, false); SuperByteBuffer hand = renderAndTransform(world, handPose, blockState, pos, false);
Vec3d center = VecHelper.getCenterOf(new BlockPos(context.position)); double factor;
double distance = context.position.distanceTo(center); if (context.contraption.stalled) {
double nextDistance = context.position.add(context.motion).distanceTo(center); factor = MathHelper.sin(AnimationTickHolder.getRenderTick() * .5f) * .25f + .25f;
} else {
Vec3d center = VecHelper.getCenterOf(new BlockPos(context.position));
double distance = context.position.distanceTo(center);
double nextDistance = context.position.add(context.motion).distanceTo(center);
factor = .5f - MathHelper.lerp(Minecraft.getInstance().getRenderPartialTicks(), distance, nextDistance);
}
Vec3d offset = new Vec3d(blockState.get(FACING).getDirectionVec()) Vec3d offset = new Vec3d(blockState.get(FACING).getDirectionVec())
.scale(.5f - MathHelper.lerp(Minecraft.getInstance().getRenderPartialTicks(), distance, nextDistance)); .scale(factor);
pole.translate(offset.x, offset.y, offset.z); pole.translate(offset.x, offset.y, offset.z);
hand.translate(offset.x, offset.y, offset.z); hand.translate(offset.x, offset.y, offset.z);

View file

@ -27,6 +27,8 @@ public class ContactMovementBehaviour extends MovementBehaviour {
if (world.isRemote) if (world.isRemote)
return; return;
if (context.firstMovement)
return;
deactivateLastVisitedContact(context); deactivateLastVisitedContact(context);
BlockState visitedState = world.getBlockState(pos); BlockState visitedState = world.getBlockState(pos);