mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-02-05 09:54:59 +01:00
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
This commit is contained in:
parent
224c5d0426
commit
64bc8a3499
21 changed files with 215 additions and 54 deletions
|
@ -740,6 +740,7 @@ public class AllBlocks {
|
|||
.register();
|
||||
|
||||
public static final BlockEntry<GirderBlock> 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<GirderEncasedShaftBlock> 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))
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -78,6 +78,8 @@ public class ContraptionCollider {
|
|||
List<Entity> 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<AABB> collidableBBs = contraption.getSimplifiedEntityColliders().orElseGet(() -> {
|
||||
List<AABB> collidableBBs = contraption.getSimplifiedEntityColliders()
|
||||
.orElseGet(() -> {
|
||||
|
||||
// Else find 'nearby' individual block shapes to collide with
|
||||
List<AABB> bbs = new ArrayList<>();
|
||||
List<VoxelShape> 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<AABB> bbs = new ArrayList<>();
|
||||
List<VoxelShape> potentialHits =
|
||||
getPotentiallyCollidedShapes(world, contraption, localBB.expandTowards(motionCopy));
|
||||
potentialHits.forEach(shape -> shape.toAabbs()
|
||||
.forEach(bbs::add));
|
||||
return bbs;
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
MutableObject<Vec3> collisionResponse = new MutableObject<>(Vec3.ZERO);
|
||||
MutableObject<Vec3> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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<UUID> 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<UUID> 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());
|
||||
|
|
|
@ -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<Integer> 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;
|
||||
|
|
|
@ -122,7 +122,7 @@ public class Carriage {
|
|||
Function<TravellingPoint, ITrackSelector> forwardControl,
|
||||
Function<TravellingPoint, ITrackSelector> 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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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("<i> Departing from ").withStyle(ChatFormatting.YELLOW)
|
||||
|
|
|
@ -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<Carriage> carriages;
|
||||
public List<Integer> 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<TravellingPoint, ITrackSelector> 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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue