From bf869010f05198a87301684d54b105b24696b679 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Sun, 29 Nov 2020 23:01:18 +0100 Subject: [PATCH] Minecart Purgatory - Further attempts at improving the coupling physics - Fixed reversed couplings losing their physics entry point - Fixed "angel block" placement through super glue --- .../glue/SuperGlueEntity.java | 53 ++++++++++------- .../train/CouplingPhysics.java | 57 +++++++++++++------ .../train/MinecartSim2020.java | 44 +++----------- .../train/capability/MinecartController.java | 2 +- .../ArmInteractionPointHandler.java | 5 +- .../create/foundation/utility/Couple.java | 16 ++++-- 6 files changed, 98 insertions(+), 79 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueEntity.java index d4a6f9b65..294a0582a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueEntity.java @@ -43,6 +43,7 @@ import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.RayTraceResult.Type; import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -256,26 +257,38 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat @OnlyIn(Dist.CLIENT) private void triggerPlaceBlock(PlayerEntity player, Hand hand) { - if (player instanceof ClientPlayerEntity && player.world instanceof ClientWorld) { - ClientPlayerEntity cPlayer = (ClientPlayerEntity) player; - Minecraft mc = Minecraft.getInstance(); - RayTraceResult ray = - cPlayer.pick(mc.playerController.getBlockReachDistance(), mc.getRenderPartialTicks(), false); - if (ray instanceof BlockRayTraceResult) { - for (Hand handIn : Hand.values()) { - ItemStack itemstack = cPlayer.getHeldItem(handIn); - int countBefore = itemstack.getCount(); - ActionResultType actionResultType = mc.playerController.func_217292_a(cPlayer, - (ClientWorld) cPlayer.world, handIn, (BlockRayTraceResult) ray); - if (actionResultType == ActionResultType.SUCCESS) { - cPlayer.swingArm(handIn); - if (!itemstack.isEmpty() - && (itemstack.getCount() != countBefore || mc.playerController.isInCreativeMode())) - mc.gameRenderer.itemRenderer.resetEquippedProgress(handIn); - return; - } - } - } + if (!(player instanceof ClientPlayerEntity)) + return; + if (!(player.world instanceof ClientWorld)) + return; + + ClientPlayerEntity cPlayer = (ClientPlayerEntity) player; + Minecraft mc = Minecraft.getInstance(); + RayTraceResult ray = + cPlayer.pick(mc.playerController.getBlockReachDistance(), mc.getRenderPartialTicks(), false); + + if (!(ray instanceof BlockRayTraceResult)) + return; + if (ray.getType() == Type.MISS) + return; + BlockRayTraceResult blockRay = (BlockRayTraceResult) ray; + if (!blockRay.getPos() + .offset(blockRay.getFace()) + .equals(getHangingPosition())) + return; + + for (Hand handIn : Hand.values()) { + ItemStack itemstack = cPlayer.getHeldItem(handIn); + int countBefore = itemstack.getCount(); + ActionResultType actionResultType = + mc.playerController.func_217292_a(cPlayer, (ClientWorld) cPlayer.world, handIn, blockRay); + if (actionResultType != ActionResultType.SUCCESS) + return; + + cPlayer.swingArm(handIn); + if (!itemstack.isEmpty() && (itemstack.getCount() != countBefore || mc.playerController.isInCreativeMode())) + mc.gameRenderer.itemRenderer.resetEquippedProgress(handIn); + return; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingPhysics.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingPhysics.java index 47ede3ff0..519a694b6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingPhysics.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingPhysics.java @@ -11,7 +11,9 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.MoverType; import net.minecraft.entity.item.minecart.AbstractMinecartEntity; import net.minecraft.state.properties.RailShape; +import net.minecraft.tags.BlockTags; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; @@ -23,12 +25,18 @@ public class CouplingPhysics { public static void tickCoupling(World world, Couple c) { Couple carts = c.map(MinecartController::cart); - float couplingLength = c.getFirst().getCouplingLength(true); + float couplingLength = c.getFirst() + .getCouplingLength(true); softCollisionStep(world, carts, couplingLength); + if (world.isRemote) + return; hardCollisionStep(world, carts, couplingLength); } public static void hardCollisionStep(World world, Couple carts, double couplingLength) { + if (!MinecartSim2020.canAddMotion(carts.get(false)) && MinecartSim2020.canAddMotion(carts.get(true))) + carts = carts.swap(); + Couple corrections = Couple.create(null, null); Couple maxSpeed = carts.map(AbstractMinecartEntity::getMaxCartSpeedOnRail); boolean firstLoop = true; @@ -39,6 +47,9 @@ public class CouplingPhysics { float stress = (float) (couplingLength - cart.getPositionVec() .distanceTo(otherCart.getPositionVec())); + if (Math.abs(stress) < 1 / 8f) + continue; + RailShape shape = null; BlockPos railPosition = cart.getCurrentRailPosition(); BlockState railState = world.getBlockState(railPosition.up()); @@ -53,7 +64,12 @@ public class CouplingPhysics { Vec3d link = otherCart.getPositionVec() .subtract(pos); float correctionMagnitude = firstLoop ? -stress / 2f : -stress; - correction = shape != null ? followLinkOnRail(link, pos, correctionMagnitude, shape).subtract(pos) + + if (!MinecartSim2020.canAddMotion(cart)) + correctionMagnitude /= 2; + + correction = shape != null + ? followLinkOnRail(link, pos, correctionMagnitude, MinecartSim2020.getRailVec(shape)).subtract(pos) : link.normalize() .scale(correctionMagnitude); @@ -75,27 +91,30 @@ public class CouplingPhysics { } public static void softCollisionStep(World world, Couple carts, double couplingLength) { - - Couple positions = carts.map(Entity::getPositionVector); Couple maxSpeed = carts.map(AbstractMinecartEntity::getMaxCartSpeedOnRail); Couple canAddmotion = carts.map(MinecartSim2020::canAddMotion); + Couple motions = carts.map(Entity::getMotion); + Couple nextPositions = carts.map(MinecartSim2020::predictNextPositionOf); - Couple shapes = carts.map(current -> { - BlockPos railPosition = current.getCurrentRailPosition(); + Couple shapes = carts.mapWithContext((cart, current) -> { + AbstractMinecartEntity minecart = cart.getMinecart(); + Vec3d vec = nextPositions.get(current); + int x = MathHelper.floor(vec.getX()); + int y = MathHelper.floor(vec.getY()); + int z = MathHelper.floor(vec.getZ()); + BlockPos pos = new BlockPos(x, y - 1, z); + if (minecart.world.getBlockState(pos).isIn(BlockTags.RAILS)) pos = pos.down(); + BlockPos railPosition = pos; BlockState railState = world.getBlockState(railPosition.up()); if (!(railState.getBlock() instanceof AbstractRailBlock)) return null; AbstractRailBlock block = (AbstractRailBlock) railState.getBlock(); - return block.getRailDirection(railState, world, railPosition, current); + return block.getRailDirection(railState, world, railPosition, cart); }); - Couple motions = carts.map(MinecartSim2020::predictMotionOf); - Couple nextPositions = positions.copy(); - nextPositions.replaceWithParams(Vec3d::add, motions); - float futureStress = (float) (couplingLength - nextPositions.getFirst() .distanceTo(nextPositions.getSecond())); - if (Math.abs(futureStress) < 1 / 128f) + if (MathHelper.epsilonEquals(futureStress, 0)) return; for (boolean current : Iterate.trueAndFalse) { @@ -107,12 +126,19 @@ public class CouplingPhysics { if (canAddmotion.get(current) != canAddmotion.get(!current)) correctionMagnitude = !canAddmotion.get(current) ? 0 : correctionMagnitude * 2; + if (!canAddmotion.get(current)) + continue; RailShape shape = shapes.get(current); - correction = shape != null ? followLinkOnRail(link, pos, correctionMagnitude, shape).subtract(pos) - : link.normalize() + if (shape != null) { + Vec3d railVec = MinecartSim2020.getRailVec(shape); + correction = followLinkOnRail(link, pos, correctionMagnitude, railVec).subtract(pos); + } else + correction = link.normalize() .scale(correctionMagnitude); + correction = VecHelper.clamp(correction, maxSpeed.get(current)); + motions.set(current, motions.get(current) .add(correction)); } @@ -121,8 +147,7 @@ public class CouplingPhysics { carts.forEachWithParams(Entity::setMotion, motions); } - public static Vec3d followLinkOnRail(Vec3d link, Vec3d cart, float diffToReduce, RailShape shape) { - Vec3d railAxis = MinecartSim2020.getRailVec(shape); + public static Vec3d followLinkOnRail(Vec3d link, Vec3d cart, float diffToReduce, Vec3d railAxis) { double dotProduct = railAxis.dotProduct(link); if (Double.isNaN(dotProduct) || dotProduct == 0 || diffToReduce == 0) return cart; 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 a01d3e6ff..a470a914d 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 @@ -46,33 +46,20 @@ public class MinecartSim2020 { map.put(RailShape.NORTH_EAST, Pair.of(north, east)); }); - public static Vec3d predictMotionOf(AbstractMinecartEntity cart) { -// if (cart instanceof FurnaceMinecartEntity) { -// return cart.getPositionVec() -// .subtract(cart.lastTickPosX, cart.lastTickPosY, cart.lastTickPosZ); -// } - return cart.getMotion().scale(1f); -// 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 Vec3d predictNextPositionOf(AbstractMinecartEntity cart) { + Vec3d position = cart.getPositionVec(); + Vec3d motion = cart.getMotion(); + return position.add(motion); } public static boolean canAddMotion(AbstractMinecartEntity c) { if (c instanceof FurnaceMinecartEntity) return MathHelper.epsilonEquals(((FurnaceMinecartEntity) c).pushX, 0) && MathHelper.epsilonEquals(((FurnaceMinecartEntity) c).pushZ, 0); - LazyOptional capability = c.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY); - if (capability.isPresent() && capability.orElse(null).isStalled()) + LazyOptional capability = + c.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY); + if (capability.isPresent() && capability.orElse(null) + .isStalled()) return false; return true; } @@ -196,21 +183,6 @@ public class MinecartSim2020 { } cart.setMotion(previousMotion); - - if (cart instanceof FurnaceMinecartEntity) { -// FurnaceMinecartEntity furnaceCart = (FurnaceMinecartEntity) cart; -// Vec3d vec3d = cart.getMotion(); -// double d2 = horizontalMag(vec3d); -// double d3 = furnaceCart.pushX * furnaceCart.pushX + furnaceCart.pushZ * furnaceCart.pushZ; -// if (d3 > 1.0E-4D && d2 > 0.001D) { -// double d40 = (double) MathHelper.sqrt(d2); -// double d50 = (double) MathHelper.sqrt(d3); -// furnaceCart.pushX = vec3d.x / d40 * d50; -// furnaceCart.pushZ = vec3d.z / d40 * d50; -// furnaceCart.setMotion(vec3d.mul(0.8D, 0.0D, 0.8D) -// .add(furnaceCart.pushX, 0.0D, furnaceCart.pushZ)); -// } - } } public static Vec3d getRailVec(RailShape shape) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartController.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartController.java index 121d1fa61..4b60990c1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartController.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartController.java @@ -187,9 +187,9 @@ public class MinecartController implements INBTSerializable { } })); mc.couplings = mc.couplings.swap(); + mc.needsEntryRefresh = true; if (mc == this) continue; - mc.needsEntryRefresh = true; mc.sendData(); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java index e461ed678..7cf1e883b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java @@ -114,8 +114,9 @@ public class ArmInteractionPointHandler { else inputs++; } - player.sendStatusMessage(Lang.createTranslationTextComponent("mechanical_arm.summary", inputs, outputs) - .applyTextStyle(TextFormatting.WHITE), true); + if (inputs + outputs > 0) + player.sendStatusMessage(Lang.createTranslationTextComponent("mechanical_arm.summary", inputs, outputs) + .applyTextStyle(TextFormatting.WHITE), true); } AllPackets.channel.sendToServer(new ArmPlacementPacket(currentSelection, pos)); diff --git a/src/main/java/com/simibubi/create/foundation/utility/Couple.java b/src/main/java/com/simibubi/create/foundation/utility/Couple.java index 0df6950b6..9c36c903f 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/Couple.java +++ b/src/main/java/com/simibubi/create/foundation/utility/Couple.java @@ -49,6 +49,14 @@ public class Couple extends Pair implements Iterable { return Couple.create(function.apply(first), function.apply(second)); } + public Couple mapWithContext(BiFunction function) { + return Couple.create(function.apply(first, true), function.apply(second, false)); + } + + public Couple mapWithParams(BiFunction function, Couple values) { + return Couple.create(function.apply(first, values.first), function.apply(second, values.second)); + } + public void replace(Function function) { setFirst(function.apply(getFirst())); setSecond(function.apply(getSecond())); @@ -95,17 +103,17 @@ public class Couple extends Pair implements Iterable { public Iterator iterator() { return new Couplerator<>(this); } - + private static class Couplerator implements Iterator { int state; private Couple couple; - + public Couplerator(Couple couple) { this.couple = couple; state = 0; } - + @Override public boolean hasNext() { return state != 2; @@ -120,7 +128,7 @@ public class Couple extends Pair implements Iterable { return couple.second; return null; } - + } }