Couple things, Part II

- Fixed a few major issues with dual cart assembly
- Attempted to fight the heavy loss of momentum in coupling physics
This commit is contained in:
simibubi 2020-08-06 16:29:40 +02:00
parent 7e167f3b29
commit bb5a6c45f6
7 changed files with 140 additions and 55 deletions

View File

@ -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.MechanicalBearingBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity; 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.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;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock;
@ -116,6 +117,8 @@ public class BlockMovementTraits {
return true; return true;
if (block instanceof HorizontalFaceBlock) if (block instanceof HorizontalFaceBlock)
return true; return true;
if (block instanceof CartAssemblerBlock)
return false;
if (block instanceof AbstractRailBlock) if (block instanceof AbstractRailBlock)
return true; return true;
if (block instanceof RedstoneDiodeBlock) if (block instanceof RedstoneDiodeBlock)
@ -197,6 +200,8 @@ public class BlockMovementTraits {
public static boolean notSupportive(BlockState state, Direction facing) { public static boolean notSupportive(BlockState state, Direction facing) {
if (AllBlocks.MECHANICAL_DRILL.has(state)) if (AllBlocks.MECHANICAL_DRILL.has(state))
return state.get(BlockStateProperties.FACING) == facing; return state.get(BlockStateProperties.FACING) == facing;
if (AllBlocks.CART_ASSEMBLER.has(state))
return Direction.DOWN == facing;
if (AllBlocks.MECHANICAL_SAW.has(state)) if (AllBlocks.MECHANICAL_SAW.has(state))
return state.get(BlockStateProperties.FACING) == facing; return state.get(BlockStateProperties.FACING) == facing;
if (AllBlocks.PORTABLE_STORAGE_INTERFACE.has(state)) if (AllBlocks.PORTABLE_STORAGE_INTERFACE.has(state))

View File

@ -6,8 +6,11 @@ import static com.simibubi.create.foundation.utility.AngleHelper.getShortestAngl
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.MutablePair;
import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllEntityTypes;
@ -72,7 +75,6 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
protected Vec3d motionBeforeStall; protected Vec3d motionBeforeStall;
protected boolean stationary; protected boolean stationary;
protected boolean initialized; protected boolean initialized;
protected boolean onCoupling;
final List<Entity> collidingEntities = new ArrayList<>(); final List<Entity> collidingEntities = new ArrayList<>();
private boolean isSerializingFurnaceCart; private boolean isSerializingFurnaceCart;
@ -80,6 +82,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
private static final DataParameter<Boolean> STALLED = private static final DataParameter<Boolean> STALLED =
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN); EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN);
private static final DataParameter<Optional<UUID>> COUPLING =
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.OPTIONAL_UNIQUE_ID);
private static final DataParameter<Optional<UUID>> COUPLED_CART =
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.OPTIONAL_UNIQUE_ID);
public float prevYaw; public float prevYaw;
public float prevPitch; public float prevPitch;
public float prevRoll; public float prevRoll;
@ -109,11 +116,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle, public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle,
Direction facing, boolean onCoupling) { Direction facing) {
ContraptionEntity entity = createMounted(world, contraption, initialAngle); ContraptionEntity entity = createMounted(world, contraption, initialAngle);
entity.forcedAngle = facing.getHorizontalAngle(); entity.forcedAngle = facing.getHorizontalAngle();
entity.forceYaw(entity.forcedAngle); entity.forceYaw(entity.forcedAngle);
entity.onCoupling = onCoupling;
return entity; return entity;
} }
@ -312,27 +318,36 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
public void tickAsPassenger(Entity e) { public void tickAsPassenger(Entity e) {
boolean rotationLock = false; boolean rotationLock = false;
boolean pauseWhileRotating = false; boolean pauseWhileRotating = false;
boolean rotating = false;
Entity riding = e; Entity riding = e;
while (riding.getRidingEntity() != null) while (riding.getRidingEntity() != null)
riding = riding.getRidingEntity(); riding = riding.getRidingEntity();
boolean isOnCoupling = false;
if (contraption instanceof MountedContraption) { if (contraption instanceof MountedContraption) {
MountedContraption mountedContraption = (MountedContraption) contraption; MountedContraption mountedContraption = (MountedContraption) contraption;
if (onCoupling && riding instanceof AbstractMinecartEntity) { UUID couplingId = getCouplingId();
MinecartCoupling coupling = MinecartCouplingHandler.getCoupling(world, riding.getUniqueID()); isOnCoupling = couplingId != null && riding instanceof AbstractMinecartEntity;
if (isOnCoupling) {
MinecartCoupling coupling = MinecartCouplingHandler.getCoupling(world, couplingId);
if (coupling != null && coupling.areBothEndsPresent()) { if (coupling != null && coupling.areBothEndsPresent()) {
boolean notOnMainCart = !coupling.getId()
.equals(riding.getUniqueID());
Vec3d positionVec = coupling.asCouple() Vec3d positionVec = coupling.asCouple()
.getSecond() .get(notOnMainCart)
.getPositionVec(); .getPositionVec();
prevYaw = yaw; prevYaw = yaw;
prevPitch = pitch; prevPitch = pitch;
double diffZ = positionVec.z - getZ(); double diffZ = positionVec.z - riding.getZ();
double diffX = positionVec.x - getX(); double diffX = positionVec.x - riding.getX();
yaw = 90 + (float) (MathHelper.atan2(diffZ, diffX) * 180 / Math.PI); yaw = (float) (MathHelper.atan2(diffZ, diffX) * 180 / Math.PI);
pitch = (float) (Math.atan2(positionVec.y - getY(), Math.sqrt(diffX * diffX + diffZ * diffZ)) * 180 pitch = (float) (Math.atan2(positionVec.y - getY(), Math.sqrt(diffX * diffX + diffZ * diffZ)) * 180
/ Math.PI); / Math.PI);
return;
if (notOnMainCart) {
yaw += 180;
}
} }
} }
@ -341,10 +356,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
Vec3d movementVector = riding.getMotion(); Vec3d movementVector = riding.getMotion();
if (!isOnCoupling) {
if (riding instanceof BoatEntity) if (riding instanceof BoatEntity)
movementVector = getPositionVec().subtract(prevPosX, prevPosY, prevPosZ); movementVector = getPositionVec().subtract(prevPosX, prevPosY, prevPosZ);
Vec3d motion = movementVector.normalize(); Vec3d motion = movementVector.normalize();
boolean rotating = false;
if (!rotationLock) { if (!rotationLock) {
if (motion.length() > 0) { if (motion.length() > 0) {
@ -362,6 +377,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
else else
rotating = true; rotating = true;
} }
}
boolean wasStalled = isStalled(); boolean wasStalled = isStalled();
if (!rotating || !pauseWhileRotating) if (!rotating || !pauseWhileRotating)
@ -579,12 +595,13 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
@Override @Override
protected void registerData() { protected void registerData() {
this.dataManager.register(STALLED, false); this.dataManager.register(STALLED, false);
this.dataManager.register(COUPLING, null);
this.dataManager.register(COUPLED_CART, null);
} }
@Override @Override
protected void readAdditional(CompoundNBT compound) { protected void readAdditional(CompoundNBT compound) {
initialized = compound.getBoolean("Initialized"); initialized = compound.getBoolean("Initialized");
onCoupling = compound.getBoolean("OnCoupling");
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption")); contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
initialAngle = compound.getFloat("InitialAngle"); initialAngle = compound.getFloat("InitialAngle");
forceYaw(compound.contains("ForcedYaw") ? compound.getFloat("ForcedYaw") : initialAngle); forceYaw(compound.contains("ForcedYaw") ? compound.getFloat("ForcedYaw") : initialAngle);
@ -598,6 +615,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
if (compound.contains("Controller")) if (compound.contains("Controller"))
controllerPos = NBTUtil.readBlockPos(compound.getCompound("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) { public void forceYaw(float forcedYaw) {
@ -636,7 +661,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
compound.putFloat("InitialAngle", initialAngle); compound.putFloat("InitialAngle", initialAngle);
compound.putBoolean("Stalled", isStalled()); compound.putBoolean("Stalled", isStalled());
compound.putBoolean("Initialized", initialized); compound.putBoolean("Initialized", initialized);
compound.putBoolean("OnCoupling", onCoupling);
if (getCouplingId() != null) {
compound.put("OnCoupling", NBTUtil.writeUniqueId(getCouplingId()));
compound.put("CoupledCart", NBTUtil.writeUniqueId(getCoupledCart()));
}
} }
@Override @Override
@ -849,4 +878,24 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
return e.getPushReaction() == PushReaction.NORMAL; return e.getPushReaction() == PushReaction.NORMAL;
} }
@Nullable
public UUID getCouplingId() {
Optional<UUID> 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> uuid = dataManager.get(COUPLED_CART);
return uuid.isPresent() ? uuid.get() : null;
}
public void setCoupledCart(UUID id) {
dataManager.set(COUPLED_CART, Optional.ofNullable(id));
}
} }

View File

@ -46,6 +46,7 @@ import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents; import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; 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;
@ -212,12 +213,24 @@ public class CartAssemblerBlock extends AbstractRailBlock
float initialAngle = facing.getHorizontalAngle(); float initialAngle = facing.getHorizontalAngle();
withTileEntityDo(world, pos, te -> contraption.rotationMode = CartMovementMode.values()[te.movementMode.value]); withTileEntityDo(world, pos, te -> contraption.rotationMode = CartMovementMode.values()[te.movementMode.value]);
boolean couplingFound = contraption.connectedCart != null; boolean couplingFound = contraption.connectedCart != null;
if (couplingFound) if (couplingFound) {
MinecartCouplingHandler.connectCarts(null, world, cart.getEntityId(), MinecartCouplingHandler.connectCarts(null, world, cart.getEntityId(),
contraption.connectedCart.getEntityId()); contraption.connectedCart.getEntityId());
ContraptionEntity entity = Vec3d diff = contraption.connectedCart.getPositionVec()
ContraptionEntity.createMounted(world, contraption, initialAngle, facing, couplingFound); .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()); entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
world.addEntity(entity); world.addEntity(entity);
entity.startRiding(cart); entity.startRiding(cart);

View File

@ -159,8 +159,7 @@ public class MinecartContraptionItem extends Item {
ContraptionEntity contraption; ContraptionEntity contraption;
if (newFacing != null) if (newFacing != null)
contraption = contraption = ContraptionEntity.createMounted(world, mountedContraption, initialAngle, newFacing);
ContraptionEntity.createMounted(world, mountedContraption, initialAngle, newFacing, false);
else else
contraption = ContraptionEntity.createMounted(world, mountedContraption, initialAngle); contraption = ContraptionEntity.createMounted(world, mountedContraption, initialAngle);

View File

@ -123,7 +123,7 @@ public class MountedContraption extends Contraption {
@Override @Override
protected boolean customBlockRemoval(IWorld world, BlockPos pos, BlockState state) { protected boolean customBlockRemoval(IWorld world, BlockPos pos, BlockState state) {
return pos.equals(anchor); return AllBlocks.MINECART_ANCHOR.has(state);
} }
} }

View File

@ -12,9 +12,11 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.mojang.blaze3d.matrix.MatrixStack; 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.content.contraptions.components.structureMovement.train.MinecartCouplingSerializer.CouplingData;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.WorldAttached; import com.simibubi.create.foundation.utility.WorldAttached;
import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectArrayList;
@ -376,6 +378,25 @@ public class MinecartCouplingHandler {
public static void flipCoupling(World world, MinecartCoupling coupling) { public static void flipCoupling(World world, MinecartCoupling coupling) {
Map<UUID, MinecartCoupling> map = loadedCouplings.get(world); Map<UUID, MinecartCoupling> map = loadedCouplings.get(world);
map.remove(coupling.getId()); map.remove(coupling.getId());
if (coupling.areBothEndsPresent()) {
Couple<AbstractMinecartEntity> carts = coupling.asCouple();
Couple<UUID> 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(); coupling.flip();
map.put(coupling.getId(), coupling); map.put(coupling.getId(), coupling);
} }

View File

@ -13,9 +13,7 @@ import net.minecraft.block.AbstractRailBlock;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity; import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.entity.item.minecart.ContainerMinecartEntity;
import net.minecraft.entity.item.minecart.FurnaceMinecartEntity; import net.minecraft.entity.item.minecart.FurnaceMinecartEntity;
import net.minecraft.inventory.container.Container;
import net.minecraft.state.properties.RailShape; import net.minecraft.state.properties.RailShape;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Util; import net.minecraft.util.Util;
@ -49,24 +47,24 @@ public class MinecartSim2020 {
}); });
public static Vec3d predictMotionOf(AbstractMinecartEntity cart) { public static Vec3d predictMotionOf(AbstractMinecartEntity cart) {
if (cart instanceof FurnaceMinecartEntity) { if (cart instanceof FurnaceMinecartEntity) {
return cart.getPositionVec() return cart.getPositionVec()
.subtract(cart.lastTickPosX, cart.lastTickPosY, cart.lastTickPosZ); .subtract(cart.lastTickPosX, cart.lastTickPosY, cart.lastTickPosZ);
} }
if (cart instanceof ContainerMinecartEntity) { return cart.getMotion().scale(1.03f);
ContainerMinecartEntity containerCart = (ContainerMinecartEntity) cart; // if (cart instanceof ContainerMinecartEntity) {
float f = 0.98F; // ContainerMinecartEntity containerCart = (ContainerMinecartEntity) cart;
if (containerCart.isEmpty()) // float f = 0.98F;
return cart.getMotion() // if (containerCart.isEmpty())
.mul(f, 0.0D, f); // return cart.getMotion()
int i = 15 - Container.calcRedstoneFromInventory(containerCart); // .mul(f, 0.0D, f);
f += (float) i * 0.001F; // int i = 15 - Container.calcRedstoneFromInventory(containerCart);
return cart.getMotion() // f += (float) i * 0.001F;
.mul(f, 0.0D, f); // return cart.getMotion()
} // .mul(f, 0.0D, f);
return cart.getMotion() // }
.scale(cart.isBeingRidden() ? 0.997D : 0.96D); // return cart.getMotion()
// .scale(cart.isBeingRidden() ? 0.997D : 0.96D);
} }
public static boolean canAddMotion(AbstractMinecartEntity c) { public static boolean canAddMotion(AbstractMinecartEntity c) {