diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementTraits.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementTraits.java index e5944e514..9a5d5da36 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementTraits.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementTraits.java @@ -13,6 +13,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.bea import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock; @@ -116,6 +117,8 @@ public class BlockMovementTraits { return true; if (block instanceof HorizontalFaceBlock) return true; + if (block instanceof CartAssemblerBlock) + return false; if (block instanceof AbstractRailBlock) return true; if (block instanceof RedstoneDiodeBlock) @@ -197,6 +200,8 @@ public class BlockMovementTraits { public static boolean notSupportive(BlockState state, Direction facing) { if (AllBlocks.MECHANICAL_DRILL.has(state)) return state.get(BlockStateProperties.FACING) == facing; + if (AllBlocks.CART_ASSEMBLER.has(state)) + return Direction.DOWN == facing; if (AllBlocks.MECHANICAL_SAW.has(state)) return state.get(BlockStateProperties.FACING) == facing; if (AllBlocks.PORTABLE_STORAGE_INTERFACE.has(state)) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntity.java index ff6f560eb..dfdfe4b6b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntity.java @@ -6,8 +6,11 @@ import static com.simibubi.create.foundation.utility.AngleHelper.getShortestAngl import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; +import java.util.Optional; import java.util.UUID; +import javax.annotation.Nullable; + import org.apache.commons.lang3.tuple.MutablePair; import com.simibubi.create.AllEntityTypes; @@ -72,7 +75,6 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD protected Vec3d motionBeforeStall; protected boolean stationary; protected boolean initialized; - protected boolean onCoupling; final List collidingEntities = new ArrayList<>(); private boolean isSerializingFurnaceCart; @@ -80,6 +82,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD private static final DataParameter STALLED = EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN); + private static final DataParameter> COUPLING = + EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.OPTIONAL_UNIQUE_ID); + private static final DataParameter> COUPLED_CART = + EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.OPTIONAL_UNIQUE_ID); + public float prevYaw; public float prevPitch; public float prevRoll; @@ -109,11 +116,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD } public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle, - Direction facing, boolean onCoupling) { + Direction facing) { ContraptionEntity entity = createMounted(world, contraption, initialAngle); entity.forcedAngle = facing.getHorizontalAngle(); entity.forceYaw(entity.forcedAngle); - entity.onCoupling = onCoupling; return entity; } @@ -312,27 +318,36 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD public void tickAsPassenger(Entity e) { boolean rotationLock = false; boolean pauseWhileRotating = false; + boolean rotating = false; Entity riding = e; while (riding.getRidingEntity() != null) riding = riding.getRidingEntity(); + boolean isOnCoupling = false; if (contraption instanceof MountedContraption) { MountedContraption mountedContraption = (MountedContraption) contraption; - if (onCoupling && riding instanceof AbstractMinecartEntity) { - MinecartCoupling coupling = MinecartCouplingHandler.getCoupling(world, riding.getUniqueID()); + UUID couplingId = getCouplingId(); + isOnCoupling = couplingId != null && riding instanceof AbstractMinecartEntity; + if (isOnCoupling) { + MinecartCoupling coupling = MinecartCouplingHandler.getCoupling(world, couplingId); if (coupling != null && coupling.areBothEndsPresent()) { + boolean notOnMainCart = !coupling.getId() + .equals(riding.getUniqueID()); Vec3d positionVec = coupling.asCouple() - .getSecond() + .get(notOnMainCart) .getPositionVec(); prevYaw = yaw; prevPitch = pitch; - double diffZ = positionVec.z - getZ(); - double diffX = positionVec.x - getX(); - yaw = 90 + (float) (MathHelper.atan2(diffZ, diffX) * 180 / Math.PI); + double diffZ = positionVec.z - riding.getZ(); + double diffX = positionVec.x - riding.getX(); + yaw = (float) (MathHelper.atan2(diffZ, diffX) * 180 / Math.PI); pitch = (float) (Math.atan2(positionVec.y - getY(), Math.sqrt(diffX * diffX + diffZ * diffZ)) * 180 / Math.PI); - return; + + if (notOnMainCart) { + yaw += 180; + } } } @@ -341,26 +356,27 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD } Vec3d movementVector = riding.getMotion(); - if (riding instanceof BoatEntity) - movementVector = getPositionVec().subtract(prevPosX, prevPosY, prevPosZ); - Vec3d motion = movementVector.normalize(); - boolean rotating = false; + if (!isOnCoupling) { + if (riding instanceof BoatEntity) + movementVector = getPositionVec().subtract(prevPosX, prevPosY, prevPosZ); + Vec3d motion = movementVector.normalize(); - if (!rotationLock) { - if (motion.length() > 0) { - targetYaw = yawFromVector(motion); - if (targetYaw < 0) - targetYaw += 360; - if (yaw < 0) - yaw += 360; + if (!rotationLock) { + if (motion.length() > 0) { + targetYaw = yawFromVector(motion); + if (targetYaw < 0) + targetYaw += 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); - if (Math.abs(AngleHelper.getShortestAngleDiff(yaw, targetYaw)) < 1f) - yaw = targetYaw; - else - rotating = true; } boolean wasStalled = isStalled(); @@ -579,12 +595,13 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD @Override protected void registerData() { this.dataManager.register(STALLED, false); + this.dataManager.register(COUPLING, null); + this.dataManager.register(COUPLED_CART, null); } @Override protected void readAdditional(CompoundNBT compound) { initialized = compound.getBoolean("Initialized"); - onCoupling = compound.getBoolean("OnCoupling"); contraption = Contraption.fromNBT(world, compound.getCompound("Contraption")); initialAngle = compound.getFloat("InitialAngle"); forceYaw(compound.contains("ForcedYaw") ? compound.getFloat("ForcedYaw") : initialAngle); @@ -598,6 +615,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD } if (compound.contains("Controller")) controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller")); + + if (compound.contains("OnCoupling")) { + setCouplingId(NBTUtil.readUniqueId(compound.getCompound("OnCoupling"))); + setCoupledCart(NBTUtil.readUniqueId(compound.getCompound("CoupledCart"))); + } else { + setCouplingId(null); + setCoupledCart(null); + } } public void forceYaw(float forcedYaw) { @@ -636,7 +661,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD compound.putFloat("InitialAngle", initialAngle); compound.putBoolean("Stalled", isStalled()); compound.putBoolean("Initialized", initialized); - compound.putBoolean("OnCoupling", onCoupling); + + if (getCouplingId() != null) { + compound.put("OnCoupling", NBTUtil.writeUniqueId(getCouplingId())); + compound.put("CoupledCart", NBTUtil.writeUniqueId(getCoupledCart())); + } } @Override @@ -849,4 +878,24 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD return e.getPushReaction() == PushReaction.NORMAL; } + @Nullable + public UUID getCouplingId() { + Optional uuid = dataManager.get(COUPLING); + return uuid == null ? null : uuid.isPresent() ? uuid.get() : null; + } + + public void setCouplingId(UUID id) { + dataManager.set(COUPLING, Optional.ofNullable(id)); + } + + @Nullable + public UUID getCoupledCart() { + Optional uuid = dataManager.get(COUPLED_CART); + return uuid.isPresent() ? uuid.get() : null; + } + + public void setCoupledCart(UUID id) { + dataManager.set(COUPLED_CART, Optional.ofNullable(id)); + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java index b23dba5e6..d222e0d5d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java @@ -46,6 +46,7 @@ import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; @@ -212,12 +213,24 @@ public class CartAssemblerBlock extends AbstractRailBlock float initialAngle = facing.getHorizontalAngle(); withTileEntityDo(world, pos, te -> contraption.rotationMode = CartMovementMode.values()[te.movementMode.value]); + boolean couplingFound = contraption.connectedCart != null; - if (couplingFound) + if (couplingFound) { MinecartCouplingHandler.connectCarts(null, world, cart.getEntityId(), contraption.connectedCart.getEntityId()); - ContraptionEntity entity = - ContraptionEntity.createMounted(world, contraption, initialAngle, facing, couplingFound); + Vec3d diff = contraption.connectedCart.getPositionVec() + .subtract(cart.getPositionVec()); + initialAngle = Direction.fromAngle(MathHelper.atan2(diff.z, diff.x) * 180 / Math.PI) + .getHorizontalAngle(); + } + + ContraptionEntity entity = ContraptionEntity.createMounted(world, contraption, initialAngle, facing); + + if (couplingFound) { + entity.setCouplingId(cart.getUniqueID()); + entity.setCoupledCart(contraption.connectedCart.getUniqueID()); + } + entity.setPosition(pos.getX(), pos.getY(), pos.getZ()); world.addEntity(entity); entity.startRiding(cart); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MinecartContraptionItem.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MinecartContraptionItem.java index e42b51b49..a0d3c23c2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MinecartContraptionItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MinecartContraptionItem.java @@ -159,8 +159,7 @@ public class MinecartContraptionItem extends Item { ContraptionEntity contraption; if (newFacing != null) - contraption = - ContraptionEntity.createMounted(world, mountedContraption, initialAngle, newFacing, false); + contraption = ContraptionEntity.createMounted(world, mountedContraption, initialAngle, newFacing); else contraption = ContraptionEntity.createMounted(world, mountedContraption, initialAngle); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MountedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MountedContraption.java index cae09b1ca..03383f747 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MountedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MountedContraption.java @@ -123,7 +123,7 @@ public class MountedContraption extends Contraption { @Override protected boolean customBlockRemoval(IWorld world, BlockPos pos, BlockState state) { - return pos.equals(anchor); + return AllBlocks.MINECART_ANCHOR.has(state); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartCouplingHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartCouplingHandler.java index da611d089..a55fea532 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartCouplingHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartCouplingHandler.java @@ -12,9 +12,11 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.Pair; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.train.MinecartCouplingSerializer.CouplingData; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.WorldAttached; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -217,13 +219,13 @@ public class MinecartCouplingHandler { @OnlyIn(Dist.CLIENT) public static void render(MatrixStack ms, IRenderTypeBuffer buffer) { ClientWorld world = Minecraft.getInstance().world; - if (world == null) + if (world == null) return; loadedCouplings.get(world) .values() .forEach(c -> MinecartCouplingRenderer.renderCoupling(ms, buffer, c)); } - + public static void tick(World world) { initQueuedCarts(world); removeUnloadedCouplings(world); @@ -367,7 +369,7 @@ public class MinecartCouplingHandler { train.flip(world); map.put(train.getId(), train); } - + public static MinecartCoupling getCoupling(World world, UUID id) { Map map = loadedCouplings.get(world); return map.get(id); @@ -376,6 +378,25 @@ public class MinecartCouplingHandler { public static void flipCoupling(World world, MinecartCoupling coupling) { Map map = loadedCouplings.get(world); map.remove(coupling.getId()); + + if (coupling.areBothEndsPresent()) { + Couple carts = coupling.asCouple(); + Couple ids = carts.map(Entity::getUniqueID); + carts.map(c -> c.isBeingRidden() ? c.getPassengers() + .get(0) : null) + .map(c -> c instanceof ContraptionEntity ? (ContraptionEntity) c : null) + .forEachWithContext((contraption, current) -> { + if (contraption == null || contraption.getCouplingId() == null) + return; + boolean switchTo = contraption.getCouplingId() + .equals(ids.get(current)) ? !current : current; + if (!carts.get(switchTo).getUniqueID().equals(contraption.getCoupledCart())) + return; + contraption.setCouplingId(ids.get(switchTo)); + contraption.setCoupledCart(ids.get(!switchTo)); + }); + } + coupling.flip(); map.put(coupling.getId(), coupling); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java index 6e6e083ac..b3f4d5b01 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java @@ -13,9 +13,7 @@ import net.minecraft.block.AbstractRailBlock; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.item.minecart.AbstractMinecartEntity; -import net.minecraft.entity.item.minecart.ContainerMinecartEntity; import net.minecraft.entity.item.minecart.FurnaceMinecartEntity; -import net.minecraft.inventory.container.Container; import net.minecraft.state.properties.RailShape; import net.minecraft.util.Direction; import net.minecraft.util.Util; @@ -49,24 +47,24 @@ public class MinecartSim2020 { }); public static Vec3d predictMotionOf(AbstractMinecartEntity cart) { - if (cart instanceof FurnaceMinecartEntity) { return cart.getPositionVec() .subtract(cart.lastTickPosX, cart.lastTickPosY, cart.lastTickPosZ); } - if (cart instanceof ContainerMinecartEntity) { - ContainerMinecartEntity containerCart = (ContainerMinecartEntity) cart; - float f = 0.98F; - if (containerCart.isEmpty()) - return cart.getMotion() - .mul(f, 0.0D, f); - int i = 15 - Container.calcRedstoneFromInventory(containerCart); - f += (float) i * 0.001F; - return cart.getMotion() - .mul(f, 0.0D, f); - } - return cart.getMotion() - .scale(cart.isBeingRidden() ? 0.997D : 0.96D); + return cart.getMotion().scale(1.03f); +// if (cart instanceof ContainerMinecartEntity) { +// ContainerMinecartEntity containerCart = (ContainerMinecartEntity) cart; +// float f = 0.98F; +// if (containerCart.isEmpty()) +// return cart.getMotion() +// .mul(f, 0.0D, f); +// int i = 15 - Container.calcRedstoneFromInventory(containerCart); +// f += (float) i * 0.001F; +// return cart.getMotion() +// .mul(f, 0.0D, f); +// } +// return cart.getMotion() +// .scale(cart.isBeingRidden() ? 0.997D : 0.96D); } public static boolean canAddMotion(AbstractMinecartEntity c) {