diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 8c91c9cee..a96d2faa3 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -2143,7 +2143,7 @@ d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bear a80fb25a0b655e76be986b5b49fcb0f03461a1ab assets/create/models/item/zinc_nugget.json b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json 5049f72c327a88f175f6f9425909e098fc711100 assets/create/sounds.json -0f1b4b980afba9bf2caf583b88e261bba8b10313 data/create/advancements/aesthetics.json +5d0cc4c0255dc241e61c173b31ddca70c88d08e4 data/create/advancements/aesthetics.json 613e64b44bed959da899fdd54c1cacb227fb33f2 data/create/advancements/andesite_alloy.json 81885c6bfb85792c88aaa7c9b70f58832945d31f data/create/advancements/andesite_casing.json 83c046bd200623933545c9e4326f782fb02c87fa data/create/advancements/arm_blaze_burner.json diff --git a/src/generated/resources/data/create/advancements/aesthetics.json b/src/generated/resources/data/create/advancements/aesthetics.json index d723cbe38..59a86f429 100644 --- a/src/generated/resources/data/create/advancements/aesthetics.json +++ b/src/generated/resources/data/create/advancements/aesthetics.json @@ -28,8 +28,8 @@ "trigger": "create:bracket_apply", "conditions": { "accepted_entries": [ - "create:cogwheel", - "create:large_cogwheel" + "create:large_cogwheel", + "create:cogwheel" ] } }, diff --git a/src/main/java/com/simibubi/create/AllEntityTypes.java b/src/main/java/com/simibubi/create/AllEntityTypes.java index 9af30091d..05c266307 100644 --- a/src/main/java/com/simibubi/create/AllEntityTypes.java +++ b/src/main/java/com/simibubi/create/AllEntityTypes.java @@ -41,7 +41,7 @@ public class AllEntityTypes { GantryContraptionEntity::new, () -> ContraptionEntityRenderer::new, 10, 40, false); public static final EntityEntry CARRIAGE_CONTRAPTION = contraption("carriage_contraption", CarriageContraptionEntity::new, - () -> CarriageContraptionEntityRenderer::new, 5, 3, true); + () -> CarriageContraptionEntityRenderer::new, 15, 3, true); public static final EntityEntry SUPER_GLUE = register("super_glue", SuperGlueEntity::new, () -> SuperGlueRenderer::new, MobCategory.MISC, 10, diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java index 90f40f9ac..bdda992e7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java @@ -5,6 +5,9 @@ import java.util.Collection; import java.util.HashSet; import java.util.Vector; +import org.lwjgl.glfw.GLFW; + +import com.mojang.blaze3d.platform.InputConstants; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.ControlsUtil; @@ -13,6 +16,7 @@ import com.simibubi.create.foundation.utility.Lang; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelAccessor; public class ControlsHandler { @@ -24,6 +28,13 @@ public class ControlsHandler { static WeakReference entityRef = new WeakReference<>(null); static BlockPos controlsPos; + public static void levelUnloaded(LevelAccessor level) { + packetCooldown = 0; + entityRef = new WeakReference<>(null); + controlsPos = null; + currentlyPressed.clear(); + } + public static void startControlling(AbstractContraptionEntity entity, BlockPos controllerLocalPos) { entityRef = new WeakReference(entity); controlsPos = controllerLocalPos; @@ -36,10 +47,10 @@ public class ControlsHandler { ControlsUtil.getControls() .forEach(kb -> kb.setDown(ControlsUtil.isActuallyPressed(kb))); AbstractContraptionEntity abstractContraptionEntity = entityRef.get(); - + if (!currentlyPressed.isEmpty() && abstractContraptionEntity != null) - AllPackets.channel.sendToServer( - new ControlsInputPacket(currentlyPressed, false, abstractContraptionEntity.getId(), controlsPos)); + AllPackets.channel.sendToServer(new ControlsInputPacket(currentlyPressed, false, + abstractContraptionEntity.getId(), controlsPos, false)); packetCooldown = 0; entityRef = new WeakReference<>(null); @@ -57,6 +68,16 @@ public class ControlsHandler { if (packetCooldown > 0) packetCooldown--; + if (InputConstants.isKeyDown(Minecraft.getInstance() + .getWindow() + .getWindow(), GLFW.GLFW_KEY_ESCAPE)) { + BlockPos pos = controlsPos; + stopControlling(); + AllPackets.channel + .sendToServer(new ControlsInputPacket(currentlyPressed, false, entity.getId(), pos, true)); + return; + } + Vector controls = ControlsUtil.getControls(); Collection pressedKeys = new HashSet<>(); for (int i = 0; i < controls.size(); i++) { @@ -71,13 +92,14 @@ public class ControlsHandler { // Released Keys if (!releasedKeys.isEmpty()) { - AllPackets.channel.sendToServer(new ControlsInputPacket(releasedKeys, false, entity.getId(), controlsPos)); + AllPackets.channel + .sendToServer(new ControlsInputPacket(releasedKeys, false, entity.getId(), controlsPos, false)); // AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .5f, true); } // Newly Pressed Keys if (!newKeys.isEmpty()) { - AllPackets.channel.sendToServer(new ControlsInputPacket(newKeys, true, entity.getId(), controlsPos)); + AllPackets.channel.sendToServer(new ControlsInputPacket(newKeys, true, entity.getId(), controlsPos, false)); packetCooldown = PACKET_RATE; // AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .75f, true); } @@ -86,7 +108,7 @@ public class ControlsHandler { if (packetCooldown == 0) { if (!pressedKeys.isEmpty()) { AllPackets.channel - .sendToServer(new ControlsInputPacket(pressedKeys, true, entity.getId(), controlsPos)); + .sendToServer(new ControlsInputPacket(pressedKeys, true, entity.getId(), controlsPos, false)); packetCooldown = PACKET_RATE; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInputPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInputPacket.java index 6c4c95f4b..e1800777b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInputPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInputPacket.java @@ -22,13 +22,15 @@ public class ControlsInputPacket extends SimplePacketBase { private boolean press; private int contraptionEntityId; private BlockPos controlsPos; + private boolean stopControlling; public ControlsInputPacket(Collection activatedButtons, boolean press, int contraptionEntityId, - BlockPos controlsPos) { + BlockPos controlsPos, boolean stopControlling) { this.contraptionEntityId = contraptionEntityId; this.activatedButtons = activatedButtons; this.press = press; this.controlsPos = controlsPos; + this.stopControlling = stopControlling; } public ControlsInputPacket(FriendlyByteBuf buffer) { @@ -39,6 +41,7 @@ public class ControlsInputPacket extends SimplePacketBase { for (int i = 0; i < size; i++) activatedButtons.add(buffer.readVarInt()); controlsPos = buffer.readBlockPos(); + stopControlling = buffer.readBoolean(); } @Override @@ -48,6 +51,7 @@ public class ControlsInputPacket extends SimplePacketBase { buffer.writeVarInt(activatedButtons.size()); activatedButtons.forEach(buffer::writeVarInt); buffer.writeBlockPos(controlsPos); + buffer.writeBoolean(stopControlling); } @Override @@ -64,11 +68,14 @@ public class ControlsInputPacket extends SimplePacketBase { Entity entity = world.getEntity(contraptionEntityId); if (!(entity instanceof AbstractContraptionEntity ace)) return; - if (!ace.toGlobalVector(Vec3.atCenterOf(controlsPos), 0) - .closerThan(player.position(), 16)) + if (stopControlling) { + ace.stopControlling(controlsPos); return; + } - ControlsServerHandler.receivePressed(world, ace, controlsPos, uniqueID, activatedButtons, press); + if (ace.toGlobalVector(Vec3.atCenterOf(controlsPos), 0) + .closerThan(player.position(), 16)) + ControlsServerHandler.receivePressed(world, ace, controlsPos, uniqueID, activatedButtons, press); }); ctx.setPacketHandled(true); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeBlock.java index 44dfcc66a..715e12796 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeBlock.java @@ -49,7 +49,8 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock public NixieTubeBlock(Properties properties, DyeColor color) { super(properties); this.color = color; - registerDefaultState(defaultBlockState().setValue(FACE, DoubleAttachFace.FLOOR)); + registerDefaultState(defaultBlockState().setValue(FACE, DoubleAttachFace.FLOOR) + .setValue(WATERLOGGED, false)); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/BezierConnection.java b/src/main/java/com/simibubi/create/content/logistics/trains/BezierConnection.java index 52e2e91de..2e64212b7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/BezierConnection.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/BezierConnection.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.logistics.trains; import java.util.Iterator; -import com.jozufozu.flywheel.repack.joml.Math; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack.Pose; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java b/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java index fadb3d402..5062402cc 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java @@ -57,6 +57,8 @@ public class GlobalRailwayManager { } } + public void playerLogout(Player player) {} + public void levelLoaded(LevelAccessor level) { MinecraftServer server = level.getServer(); if (server == null || server.overworld() != level) @@ -75,13 +77,6 @@ public class GlobalRailwayManager { signalEdgeGroups = savedData.getSignalBlocks(); } - public void levelUnloaded(LevelAccessor level) { -// MinecraftServer server = level.getServer(); -// if (server == null || server.overworld() != level) -// return; -// cleanUp(); - } - public void cleanUp() { trackNetworks = new HashMap<>(); signalEdgeGroups = new HashMap<>(); 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 beacfc5de..509633476 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 @@ -136,9 +136,12 @@ public class Carriage { ISignalBoundaryListener passiveListener = point.ignoreSignals(); toMove += correction + bogeyCorrection; - double moved = point.travel(graph, toMove, toMove > 0 ? frontTrackSelector : backTrackSelector, - toMove > 0 ? atFront ? frontListener : atBack ? backListener : passiveListener - : atFront ? backListener : atBack ? frontListener : passiveListener); + double moved = + point + .travel(graph, toMove, toMove > 0 ? frontTrackSelector : backTrackSelector, + toMove > 0 ? atFront ? frontListener : atBack ? backListener : passiveListener + : atFront ? backListener : atBack ? frontListener : passiveListener, + point.ignoreTurns()); blocked |= point.blocked; distanceMoved.setValue(moved); @@ -227,8 +230,17 @@ public class Carriage { entity.setPos(positionAnchor); entity.prevYaw = entity.yaw; entity.prevPitch = entity.pitch; + entity.yaw = (float) (Mth.atan2(diffZ, diffX) * 180 / Math.PI) + 180; entity.pitch = (float) (Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)) * 180 / Math.PI) * -1; + + if (entity.firstPositionUpdate) { + entity.xo = entity.getX(); + entity.yo = entity.getY(); + entity.zo = entity.getZ(); + entity.prevYaw = entity.yaw; + entity.prevPitch = entity.pitch; + } } public TravellingPoint getLeadingPoint() { 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 b87d53720..10b5ab3f1 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 @@ -7,6 +7,7 @@ import com.simibubi.create.content.logistics.trains.IBogeyBlock; import com.simibubi.create.content.logistics.trains.TrackGraph; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.animation.LerpedFloat; @@ -62,9 +63,15 @@ public class CarriageBogey { xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ))); } - wheelAngle.setValue((wheelAngle.getValue() - angleDiff) % 360); - pitch.setValue(xRot); - yaw.setValue(-yRot); + double newWheelAngle = (wheelAngle.getValue() - angleDiff) % 360; + + for (boolean twice : Iterate.trueAndFalse) { + if (twice && !entity.firstPositionUpdate) + continue; + wheelAngle.setValue(newWheelAngle); + pitch.setValue(xRot); + yaw.setValue(-yRot); + } } public TravellingPoint leading() { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java index e151527ed..72617f239 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java @@ -32,6 +32,8 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; public class CarriageContraption extends Contraption { @@ -177,6 +179,7 @@ public class CarriageContraption extends Contraption { } @Override + @OnlyIn(Dist.CLIENT) public ContraptionLighter makeLighter() { return new NonStationaryLighter<>(this); } 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 0e39fcd91..9f205b634 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 @@ -61,10 +61,12 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { public boolean movingBackwards; public boolean leftTickingChunks; + public boolean firstPositionUpdate; public CarriageContraptionEntity(EntityType type, Level world) { super(type, world); validForRender = false; + firstPositionUpdate = true; } @Override @@ -172,12 +174,15 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { carriage.alignEntity(this); - Vec3 diff = position().subtract(xo, yo, zo); - Vec3 relativeDiff = VecHelper.rotate(diff, yaw, Axis.Y); - double signum = Math.signum(-relativeDiff.x); - double distanceTo = diff.length() * signum; + double distanceTo = 0; + if (!firstPositionUpdate) { + Vec3 diff = position().subtract(xo, yo, zo); + Vec3 relativeDiff = VecHelper.rotate(diff, yaw, Axis.Y); + double signum = Math.signum(-relativeDiff.x); + distanceTo = diff.length() * signum; + movingBackwards = signum < 0; + } - movingBackwards = signum < 0; carriage.bogeys.getFirst() .updateAngles(this, distanceTo); if (carriage.isOnTwoBogeys()) @@ -187,6 +192,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { if (carriage.train.derailed) spawnDerailParticles(carriage); + firstPositionUpdate = false; validForRender = true; } @@ -200,6 +206,18 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { } } + @Override + public void onClientRemoval() { + super.onClientRemoval(); + entityData.set(CARRIAGE_DATA, new CarriageSyncData()); + if (carriage != null) { + carriage.pointsInitialised = false; + carriage.leadingBogey().couplingAnchors = Couple.create(null, null); + carriage.trailingBogey().couplingAnchors = Couple.create(null, null); + } + firstPositionUpdate = true; + } + @Override protected void writeAdditional(CompoundTag compound, boolean spawnPacket) { super.writeAdditional(compound, spawnPacket); @@ -250,7 +268,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { return false; if (carriage.train.derailed) return false; - if (!level.isClientSide && carriage.train.heldForAssembly) { + if (carriage.train.heldForAssembly) { player.displayClientMessage(Lang.translate("schedule.train_still_assembling"), true); return false; } @@ -260,6 +278,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { train.status.manualControls(); train.navigation.cancelNavigation(); train.runtime.paused = true; + train.navigation.waitingForSignal = null; return true; } @@ -347,7 +366,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { if (lookAhead != null) { if (spaceDown) { - nav.startNavigation(lookAhead, false); + nav.startNavigation(lookAhead, -1, false); navDistanceTotal = nav.distanceToDestination; return true; } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java index 08898efe7..2c6d81801 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java @@ -25,7 +25,7 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer bogey.couplingAnchors.replace(v -> null); if (!super.shouldRender(entity, clippingHelper, cameraX, cameraY, cameraZ)) return false; - return entity.validForRender; + return entity.validForRender && !entity.firstPositionUpdate; } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSyncData.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSyncData.java index 6775165c3..ad9824632 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSyncData.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSyncData.java @@ -239,8 +239,8 @@ public class CarriageSyncData { TravellingPoint toApproach = pointsToApproach[index]; point.travel(graph, partial * f, - point.follow(toApproach, b -> success.setValue(success.booleanValue() && b)), - point.ignoreSignals()); + point.follow(toApproach, b -> success.setValue(success.booleanValue() && b)), point.ignoreSignals(), + point.ignoreTurns()); // could not pathfind to server location if (!success.booleanValue()) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java index 630456188..7af3adb53 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java @@ -6,10 +6,14 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.PriorityQueue; import java.util.Set; import java.util.UUID; +import javax.annotation.Nullable; + +import org.apache.commons.lang3.mutable.MutableDouble; import org.apache.commons.lang3.mutable.MutableObject; import com.simibubi.create.Create; @@ -49,6 +53,7 @@ public class Navigation { private TravellingPoint signalScout; public Pair waitingForSignal; public double distanceToSignal; + public int ticksWaitingForSignal; public Navigation(Train train) { this.train = train; @@ -84,9 +89,11 @@ public class Navigation { destination.reserveFor(train); double acceleration = AllConfigs.SERVER.trains.getAccelerationMPTT(); + double turnTopSpeed = AllConfigs.SERVER.trains.getTurningTopSpeedMPT(); double brakingDistance = (train.speed * train.speed) / (2 * acceleration); double speedMod = destinationBehindTrain ? -1 : 1; double preDepartureLookAhead = train.getCurrentStation() != null ? 4.5 : 0; + double distanceToNextCurve = -1; // Signals if (train.graph != null) { @@ -98,10 +105,14 @@ public class Navigation { : train.carriages.get(train.carriages.size() - 1) .getTrailingPoint(); - if (waitingForSignal == null) + if (waitingForSignal == null) { distanceToSignal = Double.MAX_VALUE; + ticksWaitingForSignal = 0; + } if (distanceToSignal > 1 / 16f) { + MutableDouble curveDistanceTracker = new MutableDouble(-1); + signalScout.node1 = leadingPoint.node1; signalScout.node2 = leadingPoint.node2; signalScout.edge = leadingPoint.edge; @@ -124,7 +135,15 @@ public class Navigation { return; } signalEdgeGroup.reserved = boundary; + }, (distance, edge) -> { + float current = curveDistanceTracker.floatValue(); + if (current == -1 || distance < current) + curveDistanceTracker.setValue(distance); }); + + distanceToNextCurve = curveDistanceTracker.floatValue(); + } else { + ticksWaitingForSignal++; } } @@ -165,7 +184,17 @@ public class Navigation { } } - train.targetSpeed = targetDistance > brakingDistance ? topSpeed * speedMod : 0; + double targetSpeed = targetDistance > brakingDistance ? topSpeed * speedMod : 0; + + if (distanceToNextCurve != -1) { + double slowingDistance = brakingDistance - (turnTopSpeed * turnTopSpeed) / (2 * acceleration); + double targetTurnSpeed = + distanceToNextCurve > slowingDistance ? topSpeed * speedMod : turnTopSpeed * speedMod; + if (Math.abs(targetTurnSpeed) < Math.abs(targetSpeed)) + targetSpeed = targetTurnSpeed; + } + + train.targetSpeed = targetSpeed; train.approachTargetSpeed(1); } @@ -228,16 +257,17 @@ public class Navigation { train.runtime.transitInterrupted(); } - public double startNavigation(GlobalStation destination, boolean simulate) { - Pair>> pathTo = findPathTo(destination); - boolean noneFound = pathTo.getFirst() == null; - double distance = noneFound ? -1 : Math.abs(pathTo.getFirst()); + public double startNavigation(GlobalStation destination, double maxCost, boolean simulate) { + DiscoveredPath pathTo = findPathTo(destination, maxCost); + boolean noneFound = pathTo == null; + double distance = noneFound ? -1 : Math.abs(pathTo.distance); + double cost = noneFound ? -1 : pathTo.cost; if (simulate) - return distance; + return cost; distanceToDestination = distance; - currentPath = pathTo.getSecond(); + currentPath = pathTo.path; if (noneFound) { distanceToDestination = 0; @@ -246,7 +276,7 @@ public class Navigation { return -1; } - destinationBehindTrain = pathTo.getFirst() < 0; + destinationBehindTrain = pathTo.distance < 0; if (this.destination == destination) return 0; @@ -274,24 +304,20 @@ public class Navigation { } this.destination = destination; - return distanceToDestination; + return cost; } - private Pair>> findPathTo(GlobalStation destination) { + @Nullable + private DiscoveredPath findPathTo(GlobalStation destination, double maxCost) { TrackGraph graph = train.graph; - List> path = new ArrayList<>(); - if (graph == null) - return Pair.of(null, path); - - MutableObject>>> frontResult = new MutableObject<>(Pair.of(null, path)); - MutableObject>>> backResult = new MutableObject<>(Pair.of(null, path)); + return null; + Couple results = Couple.create(null, null); for (boolean forward : Iterate.trueAndFalse) { if (this.destination == destination && destinationBehindTrain == forward) continue; - List> currentPath = new ArrayList<>(); TravellingPoint initialPoint = forward ? train.carriages.get(0) .getLeadingPoint() : train.carriages.get(train.carriages.size() - 1) @@ -300,7 +326,7 @@ public class Navigation { : graph.getConnectionsFrom(initialPoint.node2) .get(initialPoint.node1); - search(Double.MAX_VALUE, forward, (distance, reachedVia, currentEntry, globalStation) -> { + search(Double.MAX_VALUE, maxCost, forward, (distance, cost, reachedVia, currentEntry, globalStation) -> { if (globalStation != destination) return false; @@ -310,6 +336,7 @@ public class Navigation { TrackNode node2 = currentEntry.getFirst() .getSecond(); + List> currentPath = new ArrayList<>(); Pair> backTrack = reachedVia.get(edge); Couple toReach = Couple.create(node1, node2); TrackEdge edgeReached = edge; @@ -325,11 +352,7 @@ public class Navigation { double position = edge.getLength(node1, node2) - destination.getLocationOn(node1, node2, edge); double distanceToDestination = distance - position; - - if (forward) - frontResult.setValue(Pair.of(distanceToDestination, currentPath)); - else - backResult.setValue(Pair.of(-distanceToDestination, currentPath)); + results.set(forward, new DiscoveredPath((forward ? 1 : -1) * distanceToDestination, cost, currentPath)); return true; }); @@ -337,11 +360,11 @@ public class Navigation { break; } - Pair>> front = frontResult.getValue(); - Pair>> back = backResult.getValue(); + DiscoveredPath front = results.getFirst(); + DiscoveredPath back = results.getSecond(); - boolean frontEmpty = front.getFirst() == null; - boolean backEmpty = back.getFirst() == null; + boolean frontEmpty = front == null; + boolean backEmpty = back == null; if (backEmpty) return front; if (frontEmpty) @@ -354,10 +377,22 @@ public class Navigation { if (!canDriveForward) return back; - boolean frontBetter = -back.getFirst() > front.getFirst(); + boolean frontBetter = maxCost == -1 ? -back.distance > front.distance : back.cost > front.cost; return frontBetter ? front : back; } + public class DiscoveredPath { + List> path; + double distance; + double cost; + + public DiscoveredPath(double distance, double cost, List> path) { + this.distance = distance; + this.cost = cost; + this.path = path; + } + } + public GlobalStation findNearestApproachable(boolean forward) { TrackGraph graph = train.graph; if (graph == null) @@ -368,7 +403,7 @@ public class Navigation { double minDistance = .75f * (train.speed * train.speed) / (2 * acceleration); double maxDistance = Math.max(32, 1.5f * (train.speed * train.speed) / (2 * acceleration)); - search(maxDistance, forward, (distance, reachedVia, currentEntry, globalStation) -> { + search(maxDistance, forward, (distance, cost, reachedVia, currentEntry, globalStation) -> { if (distance < minDistance) return false; @@ -389,10 +424,36 @@ public class Navigation { } public void search(double maxDistance, boolean forward, StationTest stationTest) { + search(maxDistance, -1, forward, stationTest); + } + + public void search(double maxDistance, double maxCost, boolean forward, StationTest stationTest) { TrackGraph graph = train.graph; if (graph == null) return; + Map penalties = new IdentityHashMap<>(); + boolean costRelevant = maxCost >= 0; + if (costRelevant) { + for (Train otherTrain : Create.RAILWAYS.trains.values()) { + if (otherTrain.graph != graph) + continue; + int navigationPenalty = otherTrain.getNavigationPenalty(); + otherTrain.getEndpointEdges() + .forEach(nodes -> { + if (nodes.either(Objects::isNull)) + return; + for (boolean flip : Iterate.trueAndFalse) { + TrackEdge e = graph.getConnection(flip ? nodes.swap() : nodes); + if (e == null) + continue; + int existing = penalties.getOrDefault(e, 0); + penalties.put(e, existing + navigationPenalty / 2); + } + }); + } + } + TravellingPoint startingPoint = forward ? train.carriages.get(0) .getLeadingPoint() : train.carriages.get(train.carriages.size() - 1) @@ -400,8 +461,7 @@ public class Navigation { Set visited = new HashSet<>(); Map>> reachedVia = new IdentityHashMap<>(); - PriorityQueue, TrackEdge>>> frontier = - new PriorityQueue<>((p1, p2) -> Double.compare(p1.getFirst(), p2.getFirst())); + PriorityQueue frontier = new PriorityQueue<>(); TrackNode initialNode1 = forward ? startingPoint.node1 : startingPoint.node2; TrackNode initialNode2 = forward ? startingPoint.node2 : startingPoint.node1; @@ -410,20 +470,23 @@ public class Navigation { double distanceToNode2 = forward ? initialEdge.getLength(initialNode1, initialNode2) - startingPoint.position : startingPoint.position; - frontier.add(Pair.of(distanceToNode2, Pair.of(Couple.create(initialNode1, initialNode2), initialEdge))); + frontier.add(new FrontierEntry(distanceToNode2, 0, initialNode1, initialNode2, initialEdge)); Search: while (!frontier.isEmpty()) { - Pair, TrackEdge>> poll = frontier.poll(); - double distance = poll.getFirst(); + FrontierEntry entry = frontier.poll(); + + double distance = entry.distance; + int penalty = entry.penalty; + if (distance > maxDistance) continue; - Pair, TrackEdge> currentEntry = poll.getSecond(); - TrackEdge edge = currentEntry.getSecond(); - TrackNode node1 = currentEntry.getFirst() - .getFirst(); - TrackNode node2 = currentEntry.getFirst() - .getSecond(); + TrackEdge edge = entry.edge; + TrackNode node1 = entry.node1; + TrackNode node2 = entry.node2; + + if (costRelevant) + penalty += penalties.getOrDefault(edge, 0); EdgeData signalData = edge.getEdgeData(); if (signalData.hasPoints()) { @@ -431,44 +494,78 @@ public class Navigation { if (node1 == initialNode1 && point.getLocationOn(node1, node2, edge) < edge.getLength(node1, node2) - distanceToNode2) continue; + if (costRelevant && distance + penalty > maxCost) + continue Search; if (!point.canNavigateVia(node2)) continue Search; - if (point instanceof GlobalStation station && station.canApproachFrom(node2) - && stationTest.test(distance, reachedVia, currentEntry, station)) - return; + if (point instanceof GlobalStation station) { + if (station.getPresentTrain() != null) + penalty += Train.Penalties.STATION_WITH_TRAIN; + if (station.canApproachFrom(node2) && stationTest.test(distance, distance + penalty, reachedVia, + Pair.of(Couple.create(node1, node2), edge), station)) + return; + penalty += Train.Penalties.STATION; + } } } + if (costRelevant && distance + penalty > maxCost) + continue; + List> validTargets = new ArrayList<>(); Map connectionsFrom = graph.getConnectionsFrom(node2); - for (Entry entry : connectionsFrom.entrySet()) { - TrackNode newNode = entry.getKey(); - TrackEdge newEdge = entry.getValue(); + for (Entry connection : connectionsFrom.entrySet()) { + TrackNode newNode = connection.getKey(); + TrackEdge newEdge = connection.getValue(); Vec3 currentDirection = edge.getDirection(node1, node2, false); Vec3 newDirection = newEdge.getDirection(node2, newNode, true); if (currentDirection.dot(newDirection) < 3 / 4f) continue; - if (!visited.add(entry.getValue())) + if (!visited.add(connection.getValue())) continue; - validTargets.add(entry); + validTargets.add(connection); } if (validTargets.isEmpty()) continue; - for (Entry entry : validTargets) { - TrackNode newNode = entry.getKey(); - TrackEdge newEdge = entry.getValue(); + for (Entry target : validTargets) { + TrackNode newNode = target.getKey(); + TrackEdge newEdge = target.getValue(); + double newDistance = newEdge.getLength(node2, newNode) + distance; + int newPenalty = penalty; reachedVia.put(newEdge, Pair.of(validTargets.size() > 1, Couple.create(node1, node2))); - frontier.add(Pair.of(newEdge.getLength(node2, newNode) + distance, - Pair.of(Couple.create(node2, newNode), newEdge))); + frontier.add(new FrontierEntry(newDistance, newPenalty, node2, newNode, newEdge)); } } } + private class FrontierEntry implements Comparable { + + double distance; + int penalty; + TrackNode node1; + TrackNode node2; + TrackEdge edge; + + public FrontierEntry(double distance, int penalty, TrackNode node1, TrackNode node2, TrackEdge edge) { + this.distance = distance; + this.penalty = penalty; + this.node1 = node1; + this.node2 = node2; + this.edge = edge; + } + + @Override + public int compareTo(FrontierEntry o) { + return Double.compare(distance + penalty, o.distance + o.penalty); + } + + } + @FunctionalInterface public interface StationTest { - boolean test(double distance, Map>> reachedVia, + boolean test(double distance, double cost, Map>> reachedVia, Pair, TrackEdge> current, GlobalStation station); } @@ -491,6 +588,7 @@ public class Navigation { tag.putUUID("BlockingSignal", waitingForSignal.getFirst()); tag.putBoolean("BlockingSignalSide", waitingForSignal.getSecond()); tag.putDouble("DistanceToSignal", distanceToSignal); + tag.putInt("TicksWaitingForSignal", ticksWaitingForSignal); return tag; } @@ -513,6 +611,7 @@ public class Navigation { if (waitingForSignal == null) return; distanceToSignal = tag.getDouble("DistanceToSignal"); + ticksWaitingForSignal = tag.getInt("TicksWaitingForSignal"); } } 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 c46de93c9..5ba66432e 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 @@ -35,6 +35,7 @@ import com.simibubi.create.content.logistics.trains.management.schedule.Schedule import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime.State; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; @@ -246,24 +247,34 @@ public class Train { } private void updateNavigationTarget(double distance) { - if (navigation.destination != null) { - boolean recalculate = navigation.distanceToDestination % 100 > 20; - boolean imminentRecalculate = navigation.distanceToDestination > 5; - double toSubstract = navigation.destinationBehindTrain ? -distance : distance; - navigation.distanceToDestination -= toSubstract; - boolean signalMode = navigation.waitingForSignal != null; + if (navigation.destination == null) + return; + + boolean recalculate = navigation.distanceToDestination % 100 > 20; + boolean imminentRecalculate = navigation.distanceToDestination > 5; + double toSubstract = navigation.destinationBehindTrain ? -distance : distance; + navigation.distanceToDestination -= toSubstract; + boolean signalMode = navigation.waitingForSignal != null; + boolean navigatingManually = runtime.paused; + + if (signalMode) { + navigation.distanceToSignal -= toSubstract; + recalculate = navigation.distanceToSignal % 100 > 20; + } + + if (recalculate && (signalMode ? navigation.distanceToSignal : navigation.distanceToDestination) % 100 <= 20 + || imminentRecalculate && navigation.distanceToDestination <= 5) { if (signalMode) { - navigation.distanceToSignal -= toSubstract; - recalculate = navigation.distanceToSignal % 100 > 20; + navigation.waitingForSignal = null; + return; } - if (recalculate && (signalMode ? navigation.distanceToSignal : navigation.distanceToDestination) % 100 <= 20 - || imminentRecalculate && navigation.distanceToDestination <= 5) { - if (signalMode) { - navigation.waitingForSignal = null; - return; - } - navigation.startNavigation(navigation.destination, false); + GlobalStation destination = navigation.destination; + if (!navigatingManually) { + GlobalStation preferredDestination = runtime.findNextStation(); + if (preferredDestination != null) + destination = preferredDestination; } + navigation.startNavigation(destination, navigatingManually ? -1 : Double.MAX_VALUE, false); } } @@ -680,11 +691,36 @@ public class Train { return; occupiedSignalBlocks.add(id); prevGroup.setValue(id); - })); + }), signalScout.ignoreTurns()); }); } + public Couple> getEndpointEdges() { + return Couple.create(carriages.get(0) + .getLeadingPoint(), + carriages.get(carriages.size() - 1) + .getTrailingPoint()) + .map(tp -> Couple.create(tp.node1, tp.node2)); + } + + public static class Penalties { + static final int STATION = 200, STATION_WITH_TRAIN = 300; + static final int MANUAL_TRAIN = 200, IDLE_TRAIN = 700, ARRIVING_TRAIN = 50, WAITING_TRAIN = 50, ANY_TRAIN = 25; + } + + public int getNavigationPenalty() { + if (manualTick) + return Penalties.MANUAL_TRAIN; + if (runtime.getSchedule() == null || runtime.paused) + return Penalties.IDLE_TRAIN; + if (navigation.waitingForSignal != null && navigation.ticksWaitingForSignal > 0) + return Penalties.WAITING_TRAIN + Math.min(navigation.ticksWaitingForSignal / 20, 1000); + if (navigation.destination != null && navigation.distanceToDestination < 50 || navigation.distanceToSignal < 20) + return Penalties.ARRIVING_TRAIN; + return Penalties.ANY_TRAIN; + } + public CompoundTag write() { CompoundTag tag = new CompoundTag(); tag.putUUID("Id", id); 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 734b5d864..2fbfd881b 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 @@ -24,6 +24,7 @@ import com.simibubi.create.content.logistics.trains.TrackGraphHelper; import com.simibubi.create.content.logistics.trains.TrackNode; import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ISignalBoundaryListener; import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector; +import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITurnListener; import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection; import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.networking.AllPackets; @@ -63,7 +64,7 @@ public class TrainRelocator { public static boolean isRelocating() { return relocatingTrain != null; } - + @OnlyIn(Dist.CLIENT) public static void onClicked(ClickInputEvent event) { if (relocatingTrain == null) @@ -105,7 +106,7 @@ public class TrainRelocator { return null; BlockPos blockPos = blockhit.getBlockPos(); - if (simulate && toVisualise != null) { + if (simulate && toVisualise != null && lastHoveredResult != null) { for (int i = 0; i < toVisualise.size() - 1; i++) { Vec3 vec1 = toVisualise.get(i); Vec3 vec2 = toVisualise.get(i + 1); @@ -158,6 +159,7 @@ public class TrainRelocator { TravellingPoint probe = new TravellingPoint(node1, node2, edge, graphLocation.position); ISignalBoundaryListener ignoreSignals = probe.ignoreSignals(); + ITurnListener ignoreTurns = probe.ignoreTurns(); List, Double>> recordedLocations = new ArrayList<>(); List recordedVecs = new ArrayList<>(); Consumer recorder = tp -> { @@ -171,7 +173,7 @@ public class TrainRelocator { train.forEachTravellingPointBackwards((tp, d) -> { if (blocked.booleanValue()) return; - probe.travel(graph, d, steer, ignoreSignals); + probe.travel(graph, d, steer, ignoreSignals, ignoreTurns); recorder.accept(probe); if (probe.blocked) { blocked.setTrue(); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java index d72de14dc..6b8b2d307 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java @@ -56,6 +56,9 @@ public class TravellingPoint { public static interface ISignalBoundaryListener extends BiConsumer>> { }; + public static interface ITurnListener extends BiConsumer { + }; + public TravellingPoint() {} public TravellingPoint(TrackNode node1, TrackNode node2, TrackEdge edge, double position) { @@ -70,6 +73,11 @@ public class TravellingPoint { }; } + public ITurnListener ignoreTurns() { + return (d, c) -> { + }; + } + public ITrackSelector random() { return (graph, pair) -> pair.getSecond() .get(Create.RANDOM.nextInt(pair.getSecond() @@ -170,7 +178,7 @@ public class TravellingPoint { } public double travel(TrackGraph graph, double distance, ITrackSelector trackSelector, - ISignalBoundaryListener signalListener) { + ISignalBoundaryListener signalListener, ITurnListener turnListener) { blocked = false; double edgeLength = edge.getLength(node1, node2); if (distance == 0) @@ -185,7 +193,7 @@ public class TravellingPoint { boolean forward = distance > 0; double collectedDistance = forward ? -prevPos : -edgeLength + prevPos; - edgeTraversedFrom(graph, forward, signalListener, prevPos, collectedDistance); + edgeTraversedFrom(graph, forward, signalListener, turnListener, prevPos, collectedDistance); if (forward) { // Moving forward @@ -223,7 +231,9 @@ public class TravellingPoint { position -= edgeLength; collectedDistance += edgeLength; - edgeTraversedFrom(graph, forward, signalListener, 0, collectedDistance); + if (edge.isTurn()) + turnListener.accept(collectedDistance, edge); + edgeTraversedFrom(graph, forward, signalListener, turnListener, 0, collectedDistance); prevPos = 0; edgeLength = edge.getLength(node1, node2); @@ -268,7 +278,7 @@ public class TravellingPoint { edgeLength = edge.getLength(node1, node2); position += edgeLength; - edgeTraversedFrom(graph, forward, signalListener, edgeLength, collectedDistance); + edgeTraversedFrom(graph, forward, signalListener, turnListener, edgeLength, collectedDistance); } } @@ -277,7 +287,10 @@ public class TravellingPoint { } private void edgeTraversedFrom(TrackGraph graph, boolean forward, ISignalBoundaryListener signalListener, - double prevPos, double totalDistance) { + ITurnListener turnListener, double prevPos, double totalDistance) { + if (edge.isTurn()) + turnListener.accept(Math.max(0, totalDistance), edge); + EdgeData signalsOnEdge = edge.getEdgeData(); if (!signalsOnEdge.hasSignalBoundaries()) return; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java index 9462fad0d..bcde5a8d9 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java @@ -97,7 +97,7 @@ public class ScheduleRuntime { destinationReached(); return; } - if (train.navigation.startNavigation(nextStation, false) != -1) + if (train.navigation.startNavigation(nextStation, Double.MAX_VALUE, false) != -1) state = State.IN_TRANSIT; } @@ -134,7 +134,7 @@ public class ScheduleRuntime { if (!globalStation.name.matches(regex)) continue; boolean matchesCurrent = train.currentStation != null && train.currentStation.equals(globalStation.id); - double cost = matchesCurrent ? 0 : train.navigation.startNavigation(globalStation, true); + double cost = matchesCurrent ? 0 : train.navigation.startNavigation(globalStation, bestCost, true); if (cost < 0) continue; if (cost > bestCost) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockItem.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockItem.java index a3541e6ce..e256caa45 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockItem.java @@ -58,9 +58,10 @@ public class TrackBlockItem extends BlockItem { } boolean placing = !(state.getBlock() instanceof ITrackBlock); - if (placing && !state.getMaterial() - .isReplaceable()) { - pos = pos.relative(pContext.getClickedFace()); + if (placing) { + if (!state.getMaterial() + .isReplaceable()) + pos = pos.relative(pContext.getClickedFace()); state = getPlacementState(pContext); if (state == null) return InteractionResult.FAIL; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPaver.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPaver.java index 6c0bb604b..ae4cdfe0b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPaver.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPaver.java @@ -6,12 +6,11 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import org.apache.commons.lang3.tuple.Pair; - import com.simibubi.create.AllBlocks; import com.simibubi.create.content.curiosities.girder.GirderBlock; import com.simibubi.create.content.logistics.trains.BezierConnection; import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; @@ -33,7 +32,7 @@ public class TrackPaver { if (defaultBlockState.hasProperty(SlabBlock.TYPE)) defaultBlockState = defaultBlockState.setValue(SlabBlock.TYPE, SlabType.DOUBLE); boolean wallLike = isWallLike(defaultBlockState); - + if (defaultBlockState.getBlock() instanceof GirderBlock) for (Direction d : Iterate.horizontalDirections) if (Vec3.atLowerCornerOf(d.getNormal()) @@ -144,9 +143,9 @@ public class TrackPaver { int floor = Mth.floor(yValue); boolean placeSlab = slab && yValue - floor >= .5; BlockPos targetPos = new BlockPos(entry.getKey() - .getKey(), floor, + .getFirst(), floor, entry.getKey() - .getValue()); + .getSecond()); targetPos = targetPos.offset(tePosition) .above(placeSlab ? 1 : 0); BlockState stateToPlace = diff --git a/src/main/java/com/simibubi/create/events/ClientEvents.java b/src/main/java/com/simibubi/create/events/ClientEvents.java index ae01b58bf..845b548b0 100644 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/events/ClientEvents.java @@ -159,14 +159,13 @@ public class ClientEvents { } @SubscribeEvent - public static void onRenderSelection(DrawSelectionEvent event) { - } + public static void onRenderSelection(DrawSelectionEvent event) {} @SubscribeEvent public static void onJoin(ClientPlayerNetworkEvent.LoggedInEvent event) { CreateClient.checkGraphicsFanciness(); } - + @SubscribeEvent public static void onLeave(ClientPlayerNetworkEvent.LoggedOutEvent event) { CreateClient.RAILWAYS.cleanUp(); @@ -183,12 +182,13 @@ public class ClientEvents { @SubscribeEvent public static void onUnloadWorld(WorldEvent.Unload event) { - if (event.getWorld() - .isClientSide()) { - CreateClient.invalidateRenderers(); - CreateClient.SOUL_PULSE_EFFECT_HANDLER.refresh(); - AnimationTickHolder.reset(); - } + if (!event.getWorld() + .isClientSide()) + return; + CreateClient.invalidateRenderers(); + CreateClient.SOUL_PULSE_EFFECT_HANDLER.refresh(); + AnimationTickHolder.reset(); + ControlsHandler.levelUnloaded(event.getWorld()); } @SubscribeEvent @@ -281,13 +281,15 @@ public class ClientEvents { Fluid fluid = fluidstate.getType(); - if (AllFluids.CHOCOLATE.get().isSame(fluid)) { + if (AllFluids.CHOCOLATE.get() + .isSame(fluid)) { event.setDensity(5f); event.setCanceled(true); return; } - if (AllFluids.HONEY.get().isSame(fluid)) { + if (AllFluids.HONEY.get() + .isSame(fluid)) { event.setDensity(1.5f); event.setCanceled(true); return; @@ -307,18 +309,20 @@ public class ClientEvents { Level level = Minecraft.getInstance().level; BlockPos blockPos = info.getBlockPosition(); FluidState fluidstate = level.getFluidState(blockPos); - if (info.getPosition().y > blockPos.getY() + fluidstate.getHeight(level, blockPos)) - return; + if (info.getPosition().y > blockPos.getY() + fluidstate.getHeight(level, blockPos)) + return; Fluid fluid = fluidstate.getType(); - if (AllFluids.CHOCOLATE.get().isSame(fluid)) { + if (AllFluids.CHOCOLATE.get() + .isSame(fluid)) { event.setRed(98 / 256f); event.setGreen(32 / 256f); event.setBlue(32 / 256f); } - if (AllFluids.HONEY.get().isSame(fluid)) { + if (AllFluids.HONEY.get() + .isSame(fluid)) { event.setRed(234 / 256f); event.setGreen(174 / 256f); event.setBlue(47 / 256f); diff --git a/src/main/java/com/simibubi/create/events/CommonEvents.java b/src/main/java/com/simibubi/create/events/CommonEvents.java index 9d84d6518..8dfcc5aa4 100644 --- a/src/main/java/com/simibubi/create/events/CommonEvents.java +++ b/src/main/java/com/simibubi/create/events/CommonEvents.java @@ -49,6 +49,7 @@ import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; import net.minecraftforge.event.entity.player.AttackEntityEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent; +import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedOutEvent; import net.minecraftforge.event.server.ServerStoppingEvent; import net.minecraftforge.event.world.BiomeLoadingEvent; import net.minecraftforge.event.world.BlockEvent.FluidPlaceBlockEvent; @@ -82,6 +83,12 @@ public class CommonEvents { ToolboxHandler.playerLogin(player); Create.RAILWAYS.playerLogin(player); } + + @SubscribeEvent + public static void playerLoggedOut(PlayerLoggedOutEvent event) { + Player player = event.getPlayer(); + Create.RAILWAYS.playerLogout(player); + } @SubscribeEvent public static void whenFluidsMeet(FluidPlaceBlockEvent event) { @@ -188,7 +195,6 @@ public class CommonEvents { Create.REDSTONE_LINK_NETWORK_HANDLER.onUnloadWorld(world); Create.TORQUE_PROPAGATOR.onUnloadWorld(world); WorldAttached.invalidateWorld(world); - Create.RAILWAYS.levelUnloaded(world); } @SubscribeEvent diff --git a/src/main/java/com/simibubi/create/foundation/config/CTrains.java b/src/main/java/com/simibubi/create/foundation/config/CTrains.java index c476acc8a..921ef500f 100644 --- a/src/main/java/com/simibubi/create/foundation/config/CTrains.java +++ b/src/main/java/com/simibubi/create/foundation/config/CTrains.java @@ -2,19 +2,24 @@ package com.simibubi.create.foundation.config; public class CTrains extends ConfigBase { - public final ConfigFloat trainTopSpeed = f(40, 0, "trainTopSpeed", Comments.mps, Comments.trainTopSpeed); - public final ConfigFloat trainAcceleration = - f(6, 0, "trainAcceleration", Comments.acc, Comments.trainAcceleration); + public final ConfigFloat trainTopSpeed = f(36, 0, "trainTopSpeed", Comments.mps, Comments.trainTopSpeed); + public final ConfigFloat trainTurningTopSpeed = + f(18, 0, "trainTurningTopSpeed", Comments.mps, Comments.trainTurningTopSpeed); + public final ConfigFloat trainAcceleration = f(4, 0, "trainAcceleration", Comments.acc, Comments.trainAcceleration); @Override public String getName() { return "trains"; } - + public double getTopSpeedMPT() { return trainTopSpeed.getF() / 20; } - + + public double getTurningTopSpeedMPT() { + return trainTurningTopSpeed.getF() / 20; + } + public double getAccelerationMPTT() { return trainAcceleration.getF() / 400; } @@ -23,6 +28,7 @@ public class CTrains extends ConfigBase { static String mps = "[in Blocks/Second]"; static String acc = "[in Blocks/SecondĀ²]"; static String trainTopSpeed = "The top speed of any assembled Train."; + static String trainTurningTopSpeed = "The top speed of Trains during a turn."; static String trainAcceleration = "The acceleration of any assembled Train."; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java index 2370b8cee..4227a2b2b 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java @@ -4,7 +4,6 @@ import java.util.Random; import javax.annotation.Nullable; -import com.jozufozu.flywheel.repack.joml.Math; import com.mojang.math.Quaternion; import com.mojang.math.Vector3f;