From 64bc8a3499efcb7589d5bfd32d3adc1b6670f900 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Tue, 31 May 2022 02:01:32 +0200 Subject: [PATCH] Send nodes - Fixed incomplete track graph network packets at >1000 nodes - Fixed Metal girders having incorrect block properties - Trains getting abnormally high coupling stress now derail and stop moving - Fixed trains not always migrating graphs properly when track connections are severed - Motion applied to players run over by trains now caps at 60m/s - Fixed train relocation able to cause run-over damage - Fixed minecart contraption relocation sending nearby players to the moon - Fixed non-player entities not getting run over by trains - Trains can now reverse out of being stalled - Fixed train relocation not deactivating mounted actors - Fixed drill trains occasionally getting stuck breaking blocks at very low speeds --- .../java/com/simibubi/create/AllBlocks.java | 2 + .../BlockBreakingMovementBehaviour.java | 26 ++++++-- .../actors/PloughMovementBehaviour.java | 1 + .../PortableStorageInterfaceMovement.java | 5 ++ .../deployer/DeployerMovementBehaviour.java | 16 +++++ .../AbstractContraptionEntity.java | 10 +++ .../ContraptionCollider.java | 64 +++++++++++-------- .../structureMovement/MovementBehaviour.java | 4 ++ .../OrientedContraptionEntity.java | 5 ++ .../TrainCollisionPacket.java | 6 +- .../redstone/ContactMovementBehaviour.java | 6 ++ .../content/logistics/trains/TrackGraph.java | 24 +++---- .../logistics/trains/TrackGraphSync.java | 11 +++- .../logistics/trains/entity/Carriage.java | 9 ++- .../trains/entity/CarriageBogey.java | 2 + .../entity/CarriageContraptionEntity.java | 20 ++++++ .../logistics/trains/entity/Train.java | 41 +++++++++++- .../trains/entity/TrainRelocationPacket.java | 1 + .../trains/entity/TrainRelocator.java | 5 +- .../logistics/trains/entity/TrainStatus.java | 7 ++ .../trains/track/CurvedTrackInteraction.java | 4 +- 21 files changed, 215 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 7a9a910b9..f826b41d6 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -740,6 +740,7 @@ public class AllBlocks { .register(); public static final BlockEntry METAL_GIRDER = REGISTRATE.block("metal_girder", GirderBlock::new) + .initialProperties(SharedProperties::softMetal) .blockstate(GirderBlockStateGenerator::blockState) .properties(p -> p.color(MaterialColor.COLOR_GRAY)) .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) @@ -751,6 +752,7 @@ public class AllBlocks { public static final BlockEntry METAL_GIRDER_ENCASED_SHAFT = REGISTRATE.block("metal_girder_encased_shaft", GirderEncasedShaftBlock::new) + .initialProperties(SharedProperties::softMetal) .blockstate(GirderBlockStateGenerator::blockStateWithShaft) .properties(p -> p.color(MaterialColor.COLOR_GRAY)) .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java index 0b6c18dd5..2a8c478de 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java @@ -3,7 +3,9 @@ package com.simibubi.create.content.contraptions.components.actors; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.Debug; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; @@ -47,6 +49,8 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { } public void damageEntities(MovementContext context, BlockPos pos, Level world) { + if (context.contraption.entity instanceof OrientedContraptionEntity oce && oce.nonDamageTicks > 0) + return; DamageSource damageSource = getDamageSource(); if (damageSource == null && !throwsEntities()) return; @@ -58,7 +62,7 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { if (entity instanceof AbstractMinecart) for (Entity passenger : entity.getIndirectPassengers()) if (passenger instanceof AbstractContraptionEntity - && ((AbstractContraptionEntity) passenger).getContraption() == context.contraption) + && ((AbstractContraptionEntity) passenger).getContraption() == context.contraption) continue Entities; if (damageSource != null && !world.isClientSide) { @@ -69,9 +73,11 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { Vec3 motionBoost = context.motion.add(0, context.motion.length() / 4f, 0); int maxBoost = 4; if (motionBoost.length() > maxBoost) { - motionBoost = motionBoost.subtract(motionBoost.normalize().scale(motionBoost.length() - maxBoost)); + motionBoost = motionBoost.subtract(motionBoost.normalize() + .scale(motionBoost.length() - maxBoost)); } - entity.setDeltaMovement(entity.getDeltaMovement().add(motionBoost)); + entity.setDeltaMovement(entity.getDeltaMovement() + .add(motionBoost)); entity.hurtMarked = true; } } @@ -86,7 +92,7 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { } @Override - public void stopMoving(MovementContext context) { + public void cancelStall(MovementContext context) { CompoundTag data = context.data; if (context.world.isClientSide) return; @@ -101,10 +107,15 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { data.remove("TicksUntilNextProgress"); data.remove("BreakingPos"); - context.stall = false; + MovementBehaviour.super.cancelStall(context); world.destroyBlockProgress(id, breakingPos, -1); } + @Override + public void stopMoving(MovementContext context) { + cancelStall(context); + } + @Override public void tick(MovementContext context) { tickBreaker(context); @@ -165,7 +176,8 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { float breakSpeed = Mth.clamp(Math.abs(context.getAnimationSpeed()) / 500f, 1 / 128f, 16f); destroyProgress += Mth.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress); - world.playSound(null, breakingPos, stateToBreak.getSoundType().getHitSound(), SoundSource.NEUTRAL, .25f, 1); + world.playSound(null, breakingPos, stateToBreak.getSoundType() + .getHitSound(), SoundSource.NEUTRAL, .25f, 1); if (destroyProgress >= 10) { world.destroyBlockProgress(id, breakingPos, -1); @@ -181,7 +193,7 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { context.stall = false; if (shouldDestroyStartBlock(stateToBreak)) - BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack)); + BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack)); onBlockBroken(context, ogPos, stateToBreak); ticksUntilNextProgress = -1; data.remove("Progress"); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java index decdfab78..06fe4d036 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.actors; import com.simibubi.create.content.contraptions.components.actors.PloughBlock.PloughFakePlayer; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java index ca38086a5..bb1ac6c10 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java @@ -152,6 +152,11 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour { public void stopMoving(MovementContext context) { // reset(context); } + + @Override + public void cancelStall(MovementContext context) { + reset(context); + } public void reset(MovementContext context) { context.data.remove(_clientPrevPos_); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java index db2026c25..a67f352aa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java @@ -186,6 +186,21 @@ public class DeployerMovementBehaviour implements MovementBehaviour { context.stall = player.blockBreakingProgress != null; } + @Override + public void cancelStall(MovementContext context) { + if (context.world.isClientSide) + return; + + MovementBehaviour.super.cancelStall(context); + DeployerFakePlayer player = getPlayer(context); + if (player == null) + return; + if (player.blockBreakingProgress == null) + return; + context.world.destroyBlockProgress(player.getId(), player.blockBreakingProgress.getKey(), -1); + player.blockBreakingProgress = null; + } + @Override public void stopMoving(MovementContext context) { if (context.world.isClientSide) @@ -195,6 +210,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour { if (player == null) return; + cancelStall(context); context.tileData.put("Inventory", player.getInventory() .save(new ListTag())); player.discard(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java index 84feb17d9..228c37a87 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java @@ -29,6 +29,8 @@ import com.simibubi.create.content.contraptions.components.structureMovement.int import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption; import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket; import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; +import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.logistics.trains.entity.Train; import com.simibubi.create.foundation.collision.Matrix3d; import com.simibubi.create.foundation.mixin.accessor.ServerLevelAccessor; import com.simibubi.create.foundation.networking.AllPackets; @@ -440,6 +442,14 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return false; context.motion = actorPosition.subtract(previousPosition); + if (!level.isClientSide() && context.contraption.entity instanceof CarriageContraptionEntity cce + && cce.getCarriage() != null) { + Train train = cce.getCarriage().train; + double actualSpeed = train.speedBeforeStall != null ? train.speedBeforeStall : train.speed; + context.motion = context.motion.normalize() + .scale(actualSpeed); + } + Vec3 relativeMotion = context.motion; relativeMotion = reverseRotation(relativeMotion, 1); context.relativeMotion = relativeMotion; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java index 255f22459..63cff44ba 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java @@ -78,6 +78,8 @@ public class ContraptionCollider { List entitiesWithinAABB = world.getEntitiesOfClass(Entity.class, bounds.inflate(2) .expandTowards(0, 32, 0), contraptionEntity::canCollideWith); for (Entity entity : entitiesWithinAABB) { + if (!entity.isAlive()) + continue; PlayerType playerType = getPlayerType(entity); if (playerType == PlayerType.REMOTE) @@ -116,17 +118,18 @@ public class ContraptionCollider { // Use simplified bbs when present final Vec3 motionCopy = motion; - List collidableBBs = contraption.getSimplifiedEntityColliders().orElseGet(() -> { + List collidableBBs = contraption.getSimplifiedEntityColliders() + .orElseGet(() -> { - // Else find 'nearby' individual block shapes to collide with - List bbs = new ArrayList<>(); - List potentialHits = - getPotentiallyCollidedShapes(world, contraption, localBB.expandTowards(motionCopy)); - potentialHits.forEach(shape -> shape.toAabbs() - .forEach(bbs::add)); - return bbs; + // Else find 'nearby' individual block shapes to collide with + List bbs = new ArrayList<>(); + List potentialHits = + getPotentiallyCollidedShapes(world, contraption, localBB.expandTowards(motionCopy)); + potentialHits.forEach(shape -> shape.toAabbs() + .forEach(bbs::add)); + return bbs; - }); + }); MutableObject collisionResponse = new MutableObject<>(Vec3.ZERO); MutableObject normal = new MutableObject<>(Vec3.ZERO); @@ -308,25 +311,36 @@ public class ContraptionCollider { entityPosition.z + allowedMovement.z); entityPosition = entity.position(); - if (contraptionEntity instanceof CarriageContraptionEntity cce && entity.isOnGround()) { - if (AllConfigs.SERVER.trains.trainsCauseDamage.get()) { - Vec3 diffMotion = contraptionMotion.subtract(entity.getDeltaMovement()); - if (diffMotion.length() > 0.35f && contraptionMotion.length() > 0.35f) { - EntityDamageSource pSource = new EntityDamageSource("create.run_over", contraptionEntity); - double damage = diffMotion.length(); - if (playerType == PlayerType.CLIENT) + if (contraptionEntity instanceof CarriageContraptionEntity cce && entity.isOnGround() + && !(entity instanceof ItemEntity) && cce.nonDamageTicks == 0 + && AllConfigs.SERVER.trains.trainsCauseDamage.get()) { + + Vec3 diffMotion = contraptionMotion.subtract(entity.getDeltaMovement()); + if (diffMotion.length() > 0.35f && contraptionMotion.length() > 0.35f) { + + EntityDamageSource pSource = new EntityDamageSource("create.run_over", contraptionEntity); + double damage = diffMotion.length(); + + if (!(entity instanceof Player p) || !p.isCreative() && !p.isSpectator()) { + if (playerType == PlayerType.CLIENT) { AllPackets.channel .sendToServer(new TrainCollisionPacket((int) (damage * 16), contraptionEntity.getId())); - else + world.playSound((Player) entity, entity.blockPosition(), SoundEvents.PLAYER_ATTACK_CRIT, + SoundSource.NEUTRAL, 1, .75f); + } else { entity.hurt(pSource, (int) (damage * 16)); - if (!(entity instanceof Player p) || !p.isCreative() && !p.isSpectator()) - entityMotion = entityMotion.add(entity.position() - .subtract(contraptionPosition) - .multiply(1, 0, 1) - .normalize() - .add(0, .25, 0) - .scale(damage * 4)) - .add(diffMotion); + world.playSound(null, entity.blockPosition(), SoundEvents.PLAYER_ATTACK_CRIT, + SoundSource.NEUTRAL, 1, .75f); + } + + Vec3 added = entityMotion.add(entity.position() + .subtract(contraptionPosition) + .multiply(1, 0, 1) + .normalize() + .add(0, .25, 0) + .scale(damage * 4)) + .add(diffMotion); + entityMotion = VecHelper.clamp(added, 3); } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java index d5e58219a..642e7da4f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java @@ -52,6 +52,10 @@ public interface MovementBehaviour { default void onSpeedChanged(MovementContext context, Vec3 oldMotion, Vec3 motion) {} default void stopMoving(MovementContext context) {} + + default void cancelStall(MovementContext context) { + context.stall = false; + } default void writeExtraData(MovementContext context) {} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java index 286a6754e..5dca9a313 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java @@ -74,12 +74,15 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { public float prevPitch; public float pitch; + + public int nonDamageTicks; public OrientedContraptionEntity(EntityType type, Level world) { super(type, world); motionBeforeStall = Vec3.ZERO; attachedExtraInventories = false; isSerializingFurnaceCart = false; + nonDamageTicks = 10; } public static OrientedContraptionEntity create(Level world, Contraption contraption, Direction initialOrientation) { @@ -243,6 +246,8 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { @Override protected void tickContraption() { + if (nonDamageTicks > 0) + nonDamageTicks--; Entity e = getVehicle(); if (e == null) return; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TrainCollisionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TrainCollisionPacket.java index 29dda2427..f68876821 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TrainCollisionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TrainCollisionPacket.java @@ -7,6 +7,8 @@ import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; import net.minecraft.world.damagesource.EntityDamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; @@ -43,8 +45,10 @@ public class TrainCollisionPacket extends SimplePacketBase { Entity entity = level.getEntity(contraptionEntityId); if (!(entity instanceof CarriageContraptionEntity cce)) return; - + player.hurt(new EntityDamageSource("create.run_over", cce), (int) damage); + player.level.playSound(player, entity.blockPosition(), SoundEvents.PLAYER_ATTACK_CRIT, SoundSource.NEUTRAL, + 1, .75f); }); ctx.setPacketHandled(true); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContactMovementBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContactMovementBehaviour.java index 46cfd53ca..fe7539064 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContactMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContactMovementBehaviour.java @@ -49,6 +49,12 @@ public class ContactMovementBehaviour implements MovementBehaviour { public void stopMoving(MovementContext context) { deactivateLastVisitedContact(context); } + + @Override + public void cancelStall(MovementContext context) { + MovementBehaviour.super.cancelStall(context); + deactivateLastVisitedContact(context); + } public void deactivateLastVisitedContact(MovementContext context) { if (context.data.contains("lastContact")) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java index f472249d7..f97a3adad 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java @@ -294,9 +294,9 @@ public class TrackGraph { frontier.add(connected.getLocation()); if (target != null) { - transfer(level, currentNode, target); if (preAssignedIds != null && preAssignedIds.containsKey(currentNode.getNetId())) target.setId(preAssignedIds.get(currentNode.getNetId())); + transfer(level, currentNode, target); } } @@ -331,16 +331,18 @@ public class TrackGraph { } } - for (Iterator iterator = trains.keySet() - .iterator(); iterator.hasNext();) { - UUID uuid = iterator.next(); - Train train = trains.get(uuid); - if (train.graph != this) - continue; - if (!train.isTravellingOn(node)) - continue; - train.graph = target; - } + if (level != null) + for (Iterator iterator = trains.keySet() + .iterator(); iterator.hasNext();) { + UUID uuid = iterator.next(); + Train train = trains.get(uuid); + if (train.graph != this) + continue; + if (!train.isTravellingOn(node)) + continue; + train.graph = target; + train.syncTrackGraphChanges(); + } nodes.remove(nodeLoc); nodesById.remove(node.getNetId()); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java index 2b61e850a..a2fc36808 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java @@ -123,6 +123,15 @@ public class TrackGraphSync { for (TrackNode node : graph.nodes.values()) { TrackGraphSyncPacket currentPacket = packet; currentPacket.addedNodes.put(node.getNetId(), Pair.of(node.getLocation(), node.getNormal())); + if (sent++ < 1000) + continue; + + sent = 0; + packet = flushAndCreateNew(graph, player, packet); + } + + for (TrackNode node : graph.nodes.values()) { + TrackGraphSyncPacket currentPacket = packet; if (!graph.connectionsByNode.containsKey(node)) continue; graph.connectionsByNode.get(node) @@ -130,7 +139,7 @@ public class TrackGraphSync { Couple key = Couple.create(node.getNetId(), node2.getNetId()); currentPacket.addedEdges.add(Pair.of(key, edge.getTurn())); currentPacket.syncEdgeData(node, node2, edge); - });//FIXME these edges will have missing nodes + }); if (sent++ < 1000) continue; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java index 56d7332be..49af7c9d3 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java @@ -122,7 +122,7 @@ public class Carriage { Function forwardControl, Function backwardControl, int type) { boolean onTwoBogeys = isOnTwoBogeys(); - double stress = onTwoBogeys ? bogeySpacing - getAnchorDiff() : 0; + double stress = train.derailed ? 0 : onTwoBogeys ? bogeySpacing - getAnchorDiff() : 0; blocked = false; MutableDouble distanceMoved = new MutableDouble(distance); @@ -190,7 +190,7 @@ public class Carriage { return distanceMoved.getValue(); } - private double getAnchorDiff() { + public double getAnchorDiff() { double diff = 0; int entries = 0; @@ -753,7 +753,7 @@ public class Carriage { return; cc.portalCutoffMin = minAllowedLocalCoord(); cc.portalCutoffMax = maxAllowedLocalCoord(); - if (!entity.level.isClientSide()) + if (!entity.level.isClientSide()) return; DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> invalidate(cce)); } @@ -825,6 +825,9 @@ public class Carriage { double diffY = positionVec.y - coupledVec.y; double diffZ = positionVec.z - coupledVec.z; + if (!entity.level.isClientSide()) + entity.setServerSidePrevPosition(); + entity.setPos(positionAnchor); entity.prevYaw = entity.yaw; entity.prevPitch = entity.pitch; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageBogey.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageBogey.java index 381a800fc..be80158df 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageBogey.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageBogey.java @@ -109,6 +109,8 @@ public class CarriageBogey { public double getStress() { if (getDimension() == null) return 0; + if (carriage.train.derailed) + return 0; return type.getWheelPointSpacing() - leading().getPosition() .distanceTo(trailing().getPosition()); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java index 22016bb5e..d55c4ae3e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java @@ -76,6 +76,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { private boolean arrivalSoundReversed; private int arrivalSoundTicks; + private Vec3 serverPrevPos; + public CarriageContraptionEntity(EntityType type, Level world) { super(type, world); validForRender = false; @@ -133,6 +135,17 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { return entityData.get(SCHEDULED); } + public void setServerSidePrevPosition() { + serverPrevPos = position(); + } + + @Override + public Vec3 getPrevPositionVec() { + if (!level.isClientSide() && serverPrevPos != null) + return serverPrevPos; + return super.getPrevPositionVec(); + } + public boolean isLocalCoordWithin(BlockPos localPos, int min, int max) { if (!(getContraption() instanceof CarriageContraption cc)) return false; @@ -173,6 +186,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { @Override protected void tickContraption() { + if (nonDamageTicks > 0) + nonDamageTicks--; if (!(contraption instanceof CarriageContraption cc)) return; if (carriage == null) { @@ -511,6 +526,11 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { return true; } + if (carriage.train.speedBeforeStall != null && targetSpeed != 0 + && Math.signum(carriage.train.speedBeforeStall) != Math.signum(targetSpeed)) { + carriage.train.cancelStall(); + } + if (currentStation != null && targetSpeed != 0) { stationMessage = false; player.displayClientMessage(new TextComponent(" Departing from ").withStyle(ChatFormatting.YELLOW) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java index 59ff8b662..776394698 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java @@ -19,7 +19,9 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableObject; +import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.logistics.trains.DimensionPalette; import com.simibubi.create.content.logistics.trains.GraphLocation; import com.simibubi.create.content.logistics.trains.TrackEdge; @@ -91,7 +93,7 @@ public class Train { // considered for removal @Deprecated public boolean heldForAssembly; - + public boolean doubleEnded; public List carriages; public List carriageSpacing; @@ -173,7 +175,7 @@ public class Train { updateConductors(); return; } - + updateConductors(); runtime.tick(level); navigation.tick(level); @@ -186,6 +188,7 @@ public class Train { Carriage previousCarriage = null; int carriageCount = carriages.size(); boolean stalled = false; + double maxStress = 0; for (int i = 0; i < carriageCount; i++) { Carriage carriage = carriages.get(i); @@ -226,6 +229,7 @@ public class Train { actual = total / entries; stress[i - 1] = target - actual; + maxStress = Math.max(maxStress, Math.abs(target - actual)); } previousCarriage = carriage; @@ -275,7 +279,7 @@ public class Train { Function backwardControl = toFollowBackward == null ? navigation::control : mp -> mp.follow(toFollowBackward); - double totalStress = leadingStress + trailingStress; + double totalStress = derailed ? 0 : leadingStress + trailingStress; boolean first = i == 0; boolean last = i == carriageCount - 1; int carriageType = first ? last ? Carriage.BOTH : Carriage.FIRST : last ? Carriage.LAST : Carriage.MIDDLE; @@ -283,6 +287,14 @@ public class Train { carriage.travel(level, graph, distance + totalStress, forwardControl, backwardControl, carriageType); blocked |= carriage.blocked; + boolean onTwoBogeys = carriage.isOnTwoBogeys(); + maxStress = Math.max(maxStress, onTwoBogeys ? carriage.bogeySpacing - carriage.getAnchorDiff() : 0); + maxStress = Math.max(maxStress, carriage.leadingBogey() + .getStress()); + if (onTwoBogeys) + maxStress = Math.max(maxStress, carriage.trailingBogey() + .getStress()); + if (index == 0) { distance = actualDistance; collideWithOtherTrains(level, carriage); @@ -296,6 +308,15 @@ public class Train { navigation.cancelNavigation(); runtime.tick(level); status.endOfTrack(); + + } else if (maxStress > 2) { + speed = 0; + navigation.cancelNavigation(); + runtime.tick(level); + derailed = true; + syncTrackGraphChanges(); + status.highStress(); + } else if (speed != 0) status.trackOK(); @@ -338,6 +359,20 @@ public class Train { }; } + public void cancelStall() { + speedBeforeStall = null; + carriages.forEach(c -> { + c.stalled = false; + c.forEachPresentEntity(cce -> cce.getContraption() + .getActors() + .forEach(pair -> { + MovementBehaviour behaviour = AllMovementBehaviours.of(pair.getKey().state); + if (behaviour != null) + behaviour.cancelStall(pair.getValue()); + })); + }); + } + private boolean occupy(UUID groupId, @Nullable UUID boundaryId) { reservedSignalBlocks.remove(groupId); if (boundaryId != null && occupiedSignalBlocks.containsKey(groupId)) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocationPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocationPacket.java index 340aa830b..ccab1cc74 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocationPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocationPacket.java @@ -96,6 +96,7 @@ public class TrainRelocationPacket extends SimplePacketBase { sender.displayClientMessage(Lang.translate("train.relocate.success") .withStyle(ChatFormatting.GREEN), true); train.syncTrackGraphChanges(); + train.carriages.forEach(c -> c.forEachPresentEntity(e -> e.nonDamageTicks = 10)); return; } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java index 2859fc676..4bf644a29 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java @@ -147,9 +147,11 @@ public class TrainRelocator { Vec3 lookAngle = mc.player.getLookAngle(); boolean direction = bezierSelection != null && lookAngle.dot(bezierSelection.direction()) < 0; boolean result = relocate(relocating, mc.level, blockPos, hoveredBezier, direction, lookAngle, true); - if (!simulate && result) + if (!simulate && result) { + relocating.carriages.forEach(c -> c.forEachPresentEntity(e -> e.nonDamageTicks = 10)); AllPackets.channel.sendToServer(new TrainRelocationPacket(relocatingTrain, blockPos, hoveredBezier, direction, lookAngle, relocatingEntityId)); + } return lastHoveredResult = result; } @@ -238,6 +240,7 @@ public class TrainRelocator { train.graph = graph; train.speed = 0; train.migratingPoints.clear(); + train.cancelStall(); if (train.navigation.destination != null) train.navigation.cancelNavigation(); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainStatus.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainStatus.java index 116c8ed0b..478870df3 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainStatus.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainStatus.java @@ -69,6 +69,13 @@ public class TrainStatus { displayInformation("Tracks are missing beneath the Train", false); track = true; } + + public void highStress() { + if (track) + return; + displayInformation("Forced stop due to Stress on Couplings", false); + track = true; + } public void doublePortal() { if (track) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackInteraction.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackInteraction.java index ba39640d1..baac09364 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackInteraction.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackInteraction.java @@ -39,7 +39,7 @@ public class CurvedTrackInteraction { Minecraft mc = Minecraft.getInstance(); LocalPlayer player = mc.player; ClientLevel level = mc.level; - + if (!player.getAbilities().mayBuild) return; @@ -64,7 +64,7 @@ public class CurvedTrackInteraction { breakTicks++; breakTimeout = 2; - breakProgress += creative ? 0.25f : blockState.getDestroyProgress(player, level, breakPos); + breakProgress += creative ? 0.125f : blockState.getDestroyProgress(player, level, breakPos) / 8f; Vec3 vec = VecHelper.offsetRandomly(result.vec(), level.random, 0.25f); level.addParticle(new BlockParticleOption(ParticleTypes.BLOCK, blockState), vec.x, vec.y, vec.z, 0, 0, 0);