mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-05-19 20:13:53 +02:00
e5c6ca157c
commit 053dd09df6c426ab5e570f42a1edb5df3d0fbd01 Merge: 6d1e1c71decc645eba
Author: simibubi <31564874+simibubi@users.noreply.github.com> Date: Tue May 9 18:22:42 2023 +0200 Merge branch '1.18/api' of https://github.com/Layers-of-Railways/Create into pr/4692 commitecc645eba7
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Tue May 9 11:24:11 2023 +0100 Implemented support for creating and removing individual blockstate models commit 6d1e1c71de7ce20f6fd9fc8ed4ed9bdd1072829a Author: simibubi <31564874+simibubi@users.noreply.github.com> Date: Tue May 9 12:16:54 2023 +0200 Less error logging when migrating old worlds commit205e47352e
Author: techno-sam <linux.techno.sam@gmail.com> Date: Mon May 8 21:02:19 2023 -0700 Fix up ItemOutline commit6cf204f6af
Merge:fe049bc77
2e3c906ce
Author: techno-sam <linux.techno.sam@gmail.com> Date: Mon May 8 20:28:56 2023 -0700 Merge remote-tracking branch 'upstream/mc1.18/dev' into 1.18/api # Conflicts: # src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageCouplingRenderer.java commitfe049bc771
Author: techno-sam <linux.techno.sam@gmail.com> Date: Mon May 8 20:26:16 2023 -0700 Revert "Revert "Rewrite outline buffering"" This reverts commit726bfaf0
commit435b4c1c16
Author: techno-sam <linux.techno.sam@gmail.com> Date: Mon May 8 20:20:23 2023 -0700 Clean up last bits of upside down rendering commit662da6bab1
Merge:122fe77af
d83285e8a
Author: techno-sam <linux.techno.sam@gmail.com> Date: Mon May 8 20:16:32 2023 -0700 Merge remote-tracking branch 'origin/1.18/api' into 1.18/api # Conflicts: # src/main/java/com/simibubi/create/content/logistics/trains/StandardBogeyRenderer.java commit122fe77afa
Author: techno-sam <linux.techno.sam@gmail.com> Date: Mon May 8 20:15:46 2023 -0700 Fix up upside down rendering commitd83285e8a4
Merge:00e953a58
cdb0ad210
Author: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Sun May 7 07:02:18 2023 -0700 Merge pull request #3 from Layers-of-Railways/1.18/bogey-api Cleanup cycle groups and unused imports commitcdb0ad210b
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun May 7 10:15:47 2023 +0100 Fixed merge artifact commit457d5f33ed
Merge:4e4e227a3
00e953a58
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun May 7 10:14:07 2023 +0100 Merge remote-tracking branch 'origin/1.18/api' into 1.18/api commit00e953a585
Merge:1e4d5504e
a7a25896c
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com> Date: Sun May 7 10:13:49 2023 +0100 Merge pull request #2 from Rabbitminers/mc1.18/dev Added Return Values and Small Cleanup commita7a25896c1
Merge:7622128be
1e4d5504e
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com> Date: Sun May 7 10:13:40 2023 +0100 Merge branch '1.18/api' into mc1.18/dev commit4e4e227a35
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun May 7 10:10:30 2023 +0100 Cleanup to cycle groups commitaa94fc97d1
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun May 7 09:50:50 2023 +0100 Removed unused import of Railways commit7622128bec
Merge:81eeadb85
d52065808
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com> Date: Sun May 7 09:11:59 2023 +0100 Merge branch 'Layers-of-Railways:mc1.18/dev' into mc1.18/dev commit1e4d5504ee
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sat May 6 18:03:39 2023 -0700 Don't revert non-buggy changes commitb306cf2124
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sat May 6 18:00:59 2023 -0700 Take materials into consideration when trains pathfind commitfca02ae4bf
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sat May 6 10:25:51 2023 -0700 Add materials to track graph commit726bfaf0b5
Author: techno-sam <linux.techno.sam@gmail.com> Date: Fri May 5 21:16:49 2023 -0700 Revert "Rewrite outline buffering" This reverts commitd4106d545b
. commit171897bed2
Author: techno-sam <linux.techno.sam@gmail.com> Date: Fri May 5 20:55:25 2023 -0700 Fix up style cycling commitcbd0cf20da
Author: techno-sam <linux.techno.sam@gmail.com> Date: Fri May 5 07:32:06 2023 -0700 clean up nether portal carriage handling commitd556f08876
Author: techno-sam <linux.techno.sam@gmail.com> Date: Fri May 5 07:06:02 2023 -0700 upside down bogeys work in nether portals fixed coupling anchor offsets commitda26c0ccbf
Author: techno-sam <linux.techno.sam@gmail.com> Date: Thu May 4 09:32:53 2023 -0700 working on upside down bogeys in nether portals commit81eeadb853
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon May 1 16:15:28 2023 +0100 Small cleanup commitc7e9df973c
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon May 1 16:13:51 2023 +0100 Fixed issue raised in #1 commit2f285b6eb7
Author: techno-sam <linux.techno.sam@gmail.com> Date: Mon May 1 08:13:27 2023 -0700 add data gen commit206de01311
Merge:e91753a33
6564f4fa7
Author: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Mon May 1 06:49:21 2023 -0700 Merge pull request #1 from Rabbitminers/mc1.18/dev Bogey API commit6564f4fa73
Merge:e5d759582
e91753a33
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com> Date: Mon May 1 10:40:32 2023 +0100 Merge branch '1.18/api' into mc1.18/dev commite5d7595822
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon May 1 10:09:03 2023 +0100 Connected Custom Bogey Particle Types To CarriageParticles commite91753a33c
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sun Apr 30 19:51:26 2023 -0700 Fix up some problems commit9815f1490f
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 21:12:43 2023 +0100 Implemented default data when shifting styles commitda30e78815
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 21:12:14 2023 +0100 Added Particles To Bogey Style (And Respective Builder) commit08c000b8ba
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 21:01:19 2023 +0100 Added Backup Rendering If A Size Is Not Present commit2b76e8d7b3
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 21:00:40 2023 +0100 Added Common Renderer To Remove Function commit411ec36f57
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:59:50 2023 +0100 Added Display Name To Standard Bogey Style commit112306d5d4
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:59:30 2023 +0100 Displayed new style name when changing betweeen them commit5634670b27
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:06:00 2023 +0100 General Cleanup commit0f7a8b7b24
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:05:50 2023 +0100 Implemented Changes To Remaining Classes commit8aedc00f96
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:02:06 2023 +0100 Removed Bogey Style Handling From Registrate commitedf8079abf
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:01:40 2023 +0100 Removed Unused Registry Handling commit6a185c4e72
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:01:16 2023 +0100 Refactored Bogey Sizes commite10d07ddc3
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:01:00 2023 +0100 Overhauled Bogey Style commit74d98a2ad5
Merge:e629d02f5
4ebcf8201
Author: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Sun Apr 23 07:16:33 2023 -0700 Merge branch 'Creators-of-Create:mc1.18/dev' into 1.18/api commite629d02f50
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sun Apr 9 07:18:22 2023 -0700 Track API Clean up code a bit commitd9ce6ce995
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sun Apr 9 07:14:46 2023 -0700 Track API? Fix placement commit7fbf08ba54
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sat Apr 8 11:11:24 2023 -0700 Track API? Fix up some placement issues commit35644f1434
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sat Apr 8 08:11:13 2023 -0700 Track API maybe? Datagen Seems to be working commitf7c56b867a
Author: techno-sam <linux.techno.sam@gmail.com> Date: Thu Apr 6 21:24:31 2023 -0700 Track API maybe? Fix build - broken generic Not yet tested, but it is progress commit2a59fd7e8a
Author: techno-sam <linux.techno.sam@gmail.com> Date: Thu Apr 6 21:13:54 2023 -0700 Track API maybe? Not yet tested, but it is progress commit5ba30d6a85
Merge:e4e5ac1c4
c2977bbff
Author: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Thu Apr 6 17:10:39 2023 -0700 Merge branch 'Creators-of-Create:mc1.18/dev' into 1.18/api commitd52065808c
Merge:e4e5ac1c4
c2977bbff
Author: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Thu Apr 6 17:10:26 2023 -0700 Merge branch 'Creators-of-Create:mc1.18/dev' into mc1.18/dev commit53240bd42f
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 21:42:29 2023 +0100 Corrected Bogey InteractionResult To Pass commit69326e361a
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 21:30:28 2023 +0100 Fixed Default Values When Used Styles Are Removed commit4f176979de
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 19:33:17 2023 +0100 Fixed Carriage Sounds (Again) commit1e80af3303
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 19:27:58 2023 +0100 Refactored Bogey Sizes To Seperate Class commit129be61fee
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 17:20:17 2023 +0100 Fixed Bogey Sound Loading commit2543185a55
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 09:45:23 2023 +0100 Added Bogey Sound Customisation commit1ad5ae9514
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 00:44:53 2023 +0100 Added Size Transforms If Size Is Not Available For New Style commit96566b1614
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 2 23:02:02 2023 +0100 Moved Bogey Style Inside Of Bogey Data And Implemented Bogey Data Communication commiteedd984738
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 2 16:53:55 2023 +0100 Fixed Large Bogey Size commit68ca0974c6
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 2 16:47:58 2023 +0100 Implemented Style Cycling & Default Values commita55ba4267a
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 2 16:46:15 2023 +0100 Implemented renderer instance creator commit43523302c2
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 2 16:45:33 2023 +0100 Removed Unused Standard Bogey Instance commit773e084422
Merge:0c0b5a1ed
d1e1f7ec5
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sat Apr 1 18:50:15 2023 +0100 Merge remote-tracking branch 'origin/mc1.18/dev' into mc1.18/dev # Conflicts: # src/main/java/com/simibubi/create/AllBogeyStyles.java # src/main/java/com/simibubi/create/content/logistics/trains/BogeyTileEntityRenderer.java # src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyStyle.java # src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java # src/main/java/com/simibubi/create/content/logistics/trains/entity/StandardBogeyInstance.java # src/main/java/com/simibubi/create/foundation/data/BogeyStyleBuilder.java commit0c0b5a1ed6
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sat Apr 1 18:39:58 2023 +0100 Linked Style Registry To Bogey Blocks commit71f839ee51
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sat Apr 1 18:39:03 2023 +0100 Replaced size boolean with direct use of size enum commit50ff081704
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 30 18:47:13 2023 +0100 Added Resource Location To NBT helper methods commitd1e1f7ec5a
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 30 18:47:13 2023 +0100 Re-worked BogeyStyles commitda593fccb1
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 30 18:46:02 2023 +0100 Refactored IBogeyBlock to AbstractBogeyBlock and extracted relevant StandardBogeyBlock implementations commit17432c9113
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sat Mar 25 10:20:50 2023 +0000 Fixed Incorrect Registry Loading commitc7d899369a
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:44:03 2023 +0000 Registered Registers commit6d862290d7
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:43:23 2023 +0000 Added BogeyStyleBuilder To Registrate commit3dfb9e3b3b
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:43:08 2023 +0000 Implemented AllBogeyStyles commitc9e71b462d
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:42:56 2023 +0000 Created BogeyStyleBuilder commita90977d642
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:42:25 2023 +0000 Created AllRegistries and BogeyStyle Registry commit154d455f3f
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:41:56 2023 +0000 Added BogeyStyle Wrapper commitdfb7640bfc
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 18:50:41 2023 +0000 Removed left over logging statement commit9920536cc3
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 18:50:18 2023 +0000 Implemented Secondary Shaft To Large Renderer commit6cd40cc6f9
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 18:49:56 2023 +0000 Prevented Overwrite When Using Two BlockStates Of The Same Type With Different Properties commit06fb901144
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 18:39:11 2023 +0000 Implemented Common Rendering For StandardBogeyRenderer commit435b0f8266
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 18:38:40 2023 +0000 Added Common Renderer commit96a0623dab
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 18:38:29 2023 +0000 Implemented BlockState Models For Rendering commit469d9d592b
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 17:42:28 2023 +0000 Added Standard Bogey Instance (Might be redundant) commit2661d260d8
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 17:42:06 2023 +0000 Refactored Changes To Existing Methods commit9ded16fbab
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 17:41:15 2023 +0000 Integrated BogeyRenderer To BogeyInstance (Also Corrected Rendering In Contraption) commit4a82fcbca1
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 17:40:13 2023 +0000 Implemented Changes To StandardBogeyBlock commit7238fb93f3
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 17:39:51 2023 +0000 Added Renderer To IBogeyBlock commitded4c1f613
Merge:91727cc84
3c02fe6ec
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Wed Mar 22 17:03:37 2023 +0000 Merge remote-tracking branch 'origin/mc1.18/dev' into mc1.18/dev commit91727cc84a
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Wed Mar 22 17:03:28 2023 +0000 Implemented Model Data Initializer to StandardBogeyRenderer commit6d98a1f469
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Wed Mar 22 17:03:00 2023 +0000 Added Contraption Model Instance Initializer commit3c02fe6ecc
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com> Date: Tue Mar 21 22:45:34 2023 +0000 Added missing render type check commit6672c49649
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Tue Mar 21 22:37:36 2023 +0000 Re-created standard bogey with test api commita8a9491fa0
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Tue Mar 21 22:34:54 2023 +0000 Implemented Proof Of Concept Generic Bogey Renderer commite4e5ac1c40
Author: SpottyTheTurtle <69260662+SpottyTheTurtle@users.noreply.github.com> Date: Sat Mar 11 21:34:59 2023 +0000 init
771 lines
26 KiB
Java
771 lines
26 KiB
Java
package com.simibubi.create.content.logistics.trains.entity;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
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 com.simibubi.create.content.logistics.trains.TrackMaterial;
|
|
|
|
import org.apache.commons.lang3.mutable.MutableDouble;
|
|
import org.apache.commons.lang3.mutable.MutableObject;
|
|
|
|
import com.simibubi.create.Create;
|
|
import com.simibubi.create.content.logistics.trains.DimensionPalette;
|
|
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
|
import com.simibubi.create.content.logistics.trains.TrackNode;
|
|
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
|
|
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector;
|
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData;
|
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBlock.SignalType;
|
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary;
|
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup;
|
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint;
|
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
|
|
import com.simibubi.create.foundation.utility.Couple;
|
|
import com.simibubi.create.foundation.utility.Iterate;
|
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
|
import com.simibubi.create.foundation.utility.Pair;
|
|
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.nbt.Tag;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.phys.Vec3;
|
|
|
|
public class Navigation {
|
|
|
|
public Train train;
|
|
|
|
public GlobalStation destination;
|
|
public double distanceToDestination;
|
|
public double distanceStartedAt;
|
|
public boolean destinationBehindTrain;
|
|
public boolean announceArrival;
|
|
List<Couple<TrackNode>> currentPath;
|
|
|
|
private TravellingPoint signalScout;
|
|
public Pair<UUID, Boolean> waitingForSignal;
|
|
private Map<UUID, Pair<SignalBoundary, Boolean>> waitingForChainedGroups;
|
|
public double distanceToSignal;
|
|
public int ticksWaitingForSignal;
|
|
|
|
public Navigation(Train train) {
|
|
this.train = train;
|
|
currentPath = new ArrayList<>();
|
|
signalScout = new TravellingPoint();
|
|
waitingForChainedGroups = new HashMap<>();
|
|
}
|
|
|
|
public void tick(Level level) {
|
|
if (destination == null)
|
|
return;
|
|
|
|
if (!train.runtime.paused) {
|
|
boolean frontDriver = train.hasForwardConductor();
|
|
boolean backDriver = train.hasBackwardConductor();
|
|
if (destinationBehindTrain && !backDriver) {
|
|
if (frontDriver)
|
|
train.status.missingCorrectConductor();
|
|
else
|
|
train.status.missingConductor();
|
|
cancelNavigation();
|
|
return;
|
|
}
|
|
|
|
if (!destinationBehindTrain && !frontDriver) {
|
|
train.status.missingConductor();
|
|
cancelNavigation();
|
|
return;
|
|
}
|
|
|
|
train.status.foundConductor();
|
|
}
|
|
|
|
destination.reserveFor(train);
|
|
|
|
double acceleration = train.acceleration();
|
|
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) {
|
|
if (waitingForSignal != null && currentSignalResolved()) {
|
|
UUID signalId = waitingForSignal.getFirst();
|
|
SignalBoundary signal = train.graph.getPoint(EdgePointType.SIGNAL, signalId);
|
|
if (signal != null && signal.types.get(waitingForSignal.getSecond()) == SignalType.CROSS_SIGNAL)
|
|
waitingForChainedGroups.clear();
|
|
waitingForSignal = null;
|
|
}
|
|
|
|
TravellingPoint leadingPoint = !destinationBehindTrain ? train.carriages.get(0)
|
|
.getLeadingPoint()
|
|
: train.carriages.get(train.carriages.size() - 1)
|
|
.getTrailingPoint();
|
|
|
|
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;
|
|
signalScout.position = leadingPoint.position;
|
|
|
|
double brakingDistanceNoFlicker = brakingDistance + 3 - (brakingDistance % 3);
|
|
double scanDistance = Mth.clamp(brakingDistanceNoFlicker, preDepartureLookAhead, distanceToDestination);
|
|
|
|
MutableDouble crossSignalDistanceTracker = new MutableDouble(-1);
|
|
MutableObject<Pair<UUID, Boolean>> trackingCrossSignal = new MutableObject<>(null);
|
|
waitingForChainedGroups.clear();
|
|
|
|
// Adding 50 to the distance due to unresolved inaccuracies in
|
|
// TravellingPoint::travel
|
|
signalScout.travel(train.graph, (distanceToDestination + 50) * speedMod, controlSignalScout(),
|
|
(distance, couple) -> {
|
|
// > scanDistance and not following down a cross signal
|
|
boolean crossSignalTracked = trackingCrossSignal.getValue() != null;
|
|
if (!crossSignalTracked && distance > scanDistance)
|
|
return true;
|
|
|
|
Couple<TrackNode> nodes = couple.getSecond();
|
|
TrackEdgePoint boundary = couple.getFirst();
|
|
if (boundary == destination && ((GlobalStation) boundary).canApproachFrom(nodes.getSecond()))
|
|
return true;
|
|
if (!(boundary instanceof SignalBoundary signal))
|
|
return false;
|
|
|
|
UUID entering = signal.getGroup(nodes.getSecond());
|
|
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(entering);
|
|
if (signalEdgeGroup == null)
|
|
return false;
|
|
|
|
boolean primary = entering.equals(signal.groups.getFirst());
|
|
boolean crossSignal = signal.types.get(primary) == SignalType.CROSS_SIGNAL;
|
|
boolean occupied = !train.manualTick
|
|
&& (signal.isForcedRed(nodes.getSecond()) || signalEdgeGroup.isOccupiedUnless(train));
|
|
|
|
if (!crossSignalTracked) {
|
|
if (crossSignal) { // Now entering cross signal path
|
|
trackingCrossSignal.setValue(Pair.of(boundary.id, primary));
|
|
crossSignalDistanceTracker.setValue(distance);
|
|
waitingForChainedGroups.put(entering, Pair.of(signal, primary));
|
|
}
|
|
if (occupied) { // Section is occupied
|
|
waitingForSignal = Pair.of(boundary.id, primary);
|
|
distanceToSignal = distance;
|
|
if (!crossSignal)
|
|
return true; // Standard entry signal, do not collect any further segments
|
|
}
|
|
if (!occupied && !crossSignal && distance < distanceToSignal + .25
|
|
&& distance < brakingDistanceNoFlicker)
|
|
signalEdgeGroup.reserved = signal; // Reserve group for traversal
|
|
return false;
|
|
}
|
|
|
|
if (crossSignalTracked) {
|
|
waitingForChainedGroups.put(entering, Pair.of(signal, primary)); // Add group to chain
|
|
if (occupied) { // Section is occupied, but wait at the cross signal that started the chain
|
|
waitingForSignal = trackingCrossSignal.getValue();
|
|
distanceToSignal = crossSignalDistanceTracker.doubleValue();
|
|
if (!crossSignal)
|
|
return true; // Entry signals end a chain
|
|
}
|
|
if (!crossSignal) {
|
|
if (distance < distanceToSignal + .25) {
|
|
// Collect and reset the signal chain because none were blocked
|
|
trackingCrossSignal.setValue(null);
|
|
reserveChain();
|
|
return false;
|
|
} else
|
|
return true; // End of a blocked signal chain
|
|
}
|
|
}
|
|
|
|
return false;
|
|
|
|
}, (distance, edge) -> {
|
|
float current = curveDistanceTracker.floatValue();
|
|
if (current == -1 || distance < current)
|
|
curveDistanceTracker.setValue(distance);
|
|
});
|
|
|
|
if (trackingCrossSignal.getValue() != null && waitingForSignal == null)
|
|
reserveChain();
|
|
|
|
distanceToNextCurve = curveDistanceTracker.floatValue();
|
|
|
|
} else
|
|
ticksWaitingForSignal++;
|
|
}
|
|
|
|
double targetDistance = waitingForSignal != null ? distanceToSignal : distanceToDestination;
|
|
|
|
// always overshoot to ensure the travelling point crosses the target
|
|
targetDistance += 0.25d;
|
|
|
|
// dont leave until green light
|
|
if (targetDistance > 1 / 32f && train.getCurrentStation() != null) {
|
|
if (waitingForSignal != null && distanceToSignal < preDepartureLookAhead) {
|
|
ticksWaitingForSignal++;
|
|
return;
|
|
}
|
|
train.leaveStation();
|
|
}
|
|
|
|
train.currentlyBackwards = destinationBehindTrain;
|
|
|
|
if (targetDistance < -10) {
|
|
cancelNavigation();
|
|
return;
|
|
}
|
|
|
|
if (targetDistance - Math.abs(train.speed) < 1 / 32f) {
|
|
train.speed = Math.max(targetDistance, 1 / 32f) * speedMod;
|
|
return;
|
|
}
|
|
|
|
train.burnFuel();
|
|
|
|
double topSpeed = train.maxSpeed();
|
|
|
|
if (targetDistance < 10) {
|
|
double target = topSpeed * ((targetDistance) / 10);
|
|
if (target < Math.abs(train.speed)) {
|
|
train.speed += (target - Math.abs(train.speed)) * .5f * speedMod;
|
|
return;
|
|
}
|
|
}
|
|
|
|
topSpeed *= train.throttle;
|
|
double turnTopSpeed = Math.min(topSpeed, train.maxTurnSpeed());
|
|
|
|
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);
|
|
}
|
|
|
|
private void reserveChain() {
|
|
train.reservedSignalBlocks.addAll(waitingForChainedGroups.keySet());
|
|
waitingForChainedGroups.forEach((groupId, boundary) -> {
|
|
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(groupId);
|
|
if (signalEdgeGroup != null)
|
|
signalEdgeGroup.reserved = boundary.getFirst();
|
|
});
|
|
waitingForChainedGroups.clear();
|
|
}
|
|
|
|
private boolean currentSignalResolved() {
|
|
if (train.manualTick)
|
|
return true;
|
|
if (distanceToDestination < .5f)
|
|
return true;
|
|
SignalBoundary signal = train.graph.getPoint(EdgePointType.SIGNAL, waitingForSignal.getFirst());
|
|
if (signal == null)
|
|
return true;
|
|
|
|
// Cross Signal
|
|
if (signal.types.get(waitingForSignal.getSecond()) == SignalType.CROSS_SIGNAL) {
|
|
for (Entry<UUID, Pair<SignalBoundary, Boolean>> entry : waitingForChainedGroups.entrySet()) {
|
|
Pair<SignalBoundary, Boolean> boundary = entry.getValue();
|
|
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(entry.getKey());
|
|
if (signalEdgeGroup == null) { // Migration, re-initialize chain
|
|
waitingForSignal.setFirst(null);
|
|
return true;
|
|
}
|
|
if (boundary.getFirst()
|
|
.isForcedRed(boundary.getSecond())) {
|
|
train.reservedSignalBlocks.clear();
|
|
return false;
|
|
}
|
|
if (signalEdgeGroup.isOccupiedUnless(train))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Entry Signal
|
|
UUID groupId = signal.groups.get(waitingForSignal.getSecond());
|
|
if (groupId == null)
|
|
return true;
|
|
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(groupId);
|
|
if (signalEdgeGroup == null)
|
|
return true;
|
|
if (!signalEdgeGroup.isOccupiedUnless(train))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
public boolean isActive() {
|
|
return destination != null;
|
|
}
|
|
|
|
public ITrackSelector control(TravellingPoint mp) {
|
|
if (destination == null)
|
|
return mp.steer(train.manualSteer, new Vec3(0, 1, 0));
|
|
return (graph, pair) -> navigateOptions(currentPath, graph, pair.getSecond());
|
|
}
|
|
|
|
public ITrackSelector controlSignalScout() {
|
|
if (destination == null)
|
|
return signalScout.steer(train.manualSteer, new Vec3(0, 1, 0));
|
|
List<Couple<TrackNode>> pathCopy = new ArrayList<>(currentPath);
|
|
return (graph, pair) -> navigateOptions(pathCopy, graph, pair.getSecond());
|
|
}
|
|
|
|
private Entry<TrackNode, TrackEdge> navigateOptions(List<Couple<TrackNode>> path, TrackGraph graph,
|
|
List<Entry<TrackNode, TrackEdge>> options) {
|
|
if (path.isEmpty())
|
|
return options.get(0);
|
|
Couple<TrackNode> nodes = path.get(0);
|
|
TrackEdge targetEdge = graph.getConnection(nodes);
|
|
for (Entry<TrackNode, TrackEdge> entry : options) {
|
|
if (entry.getValue() != targetEdge)
|
|
continue;
|
|
path.remove(0);
|
|
return entry;
|
|
}
|
|
return options.get(0);
|
|
}
|
|
|
|
public void cancelNavigation() {
|
|
distanceToDestination = 0;
|
|
currentPath.clear();
|
|
if (destination == null)
|
|
return;
|
|
destination.cancelReservation(train);
|
|
destination = null;
|
|
train.runtime.transitInterrupted();
|
|
train.reservedSignalBlocks.clear();
|
|
}
|
|
|
|
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 cost;
|
|
|
|
distanceToDestination = distance;
|
|
|
|
if (noneFound) {
|
|
distanceToDestination = distanceStartedAt = 0;
|
|
currentPath = new ArrayList<>();
|
|
if (this.destination != null)
|
|
cancelNavigation();
|
|
return -1;
|
|
}
|
|
|
|
if (Math.abs(distanceToDestination) > 100)
|
|
announceArrival = true;
|
|
|
|
currentPath = pathTo.path;
|
|
destinationBehindTrain = pathTo.distance < 0;
|
|
train.reservedSignalBlocks.clear();
|
|
train.navigation.waitingForSignal = null;
|
|
|
|
if (this.destination == null && !simulate)
|
|
distanceStartedAt = distance;
|
|
|
|
if (this.destination == destination)
|
|
return 0;
|
|
|
|
if (!train.runtime.paused) {
|
|
boolean frontDriver = train.hasForwardConductor();
|
|
boolean backDriver = train.hasBackwardConductor();
|
|
if (destinationBehindTrain && !backDriver) {
|
|
if (frontDriver)
|
|
train.status.missingCorrectConductor();
|
|
else
|
|
train.status.missingConductor();
|
|
return -1;
|
|
}
|
|
|
|
if (!destinationBehindTrain && !frontDriver) {
|
|
if (backDriver)
|
|
train.status.missingCorrectConductor();
|
|
else
|
|
train.status.missingConductor();
|
|
return -1;
|
|
}
|
|
|
|
train.status.foundConductor();
|
|
}
|
|
|
|
this.destination = destination;
|
|
return cost;
|
|
}
|
|
|
|
@Nullable
|
|
private DiscoveredPath findPathTo(GlobalStation destination, double maxCost) {
|
|
TrackGraph graph = train.graph;
|
|
if (graph == null)
|
|
return null;
|
|
|
|
Couple<DiscoveredPath> results = Couple.create(null, null);
|
|
for (boolean forward : Iterate.trueAndFalse) {
|
|
|
|
// When updating destinations midtransit, avoid reversing out of path
|
|
if (this.destination != null && destinationBehindTrain == forward)
|
|
continue;
|
|
|
|
TravellingPoint initialPoint = forward ? train.carriages.get(0)
|
|
.getLeadingPoint()
|
|
: train.carriages.get(train.carriages.size() - 1)
|
|
.getTrailingPoint();
|
|
TrackEdge initialEdge = forward ? initialPoint.edge
|
|
: graph.getConnectionsFrom(initialPoint.node2)
|
|
.get(initialPoint.node1);
|
|
|
|
search(Double.MAX_VALUE, maxCost, forward, (distance, cost, reachedVia, currentEntry, globalStation) -> {
|
|
if (globalStation != destination)
|
|
return false;
|
|
|
|
TrackEdge edge = currentEntry.getSecond();
|
|
TrackNode node1 = currentEntry.getFirst()
|
|
.getFirst();
|
|
TrackNode node2 = currentEntry.getFirst()
|
|
.getSecond();
|
|
|
|
List<Couple<TrackNode>> currentPath = new ArrayList<>();
|
|
Pair<Boolean, Couple<TrackNode>> backTrack = reachedVia.get(edge);
|
|
Couple<TrackNode> toReach = Couple.create(node1, node2);
|
|
TrackEdge edgeReached = edge;
|
|
while (backTrack != null) {
|
|
if (edgeReached == initialEdge)
|
|
break;
|
|
if (backTrack.getFirst())
|
|
currentPath.add(0, toReach);
|
|
toReach = backTrack.getSecond();
|
|
edgeReached = graph.getConnection(toReach);
|
|
backTrack = reachedVia.get(edgeReached);
|
|
}
|
|
|
|
double position = edge.getLength() - destination.getLocationOn(edge);
|
|
double distanceToDestination = distance - position;
|
|
results.set(forward, new DiscoveredPath((forward ? 1 : -1) * distanceToDestination, cost, currentPath));
|
|
return true;
|
|
});
|
|
}
|
|
|
|
DiscoveredPath front = results.getFirst();
|
|
DiscoveredPath back = results.getSecond();
|
|
|
|
boolean frontEmpty = front == null;
|
|
boolean backEmpty = back == null;
|
|
boolean canDriveForward = train.hasForwardConductor() || train.runtime.paused;
|
|
boolean canDriveBackward = train.doubleEnded && train.hasBackwardConductor() || train.runtime.paused;
|
|
|
|
if (backEmpty || !canDriveBackward)
|
|
return canDriveForward ? front : null;
|
|
if (frontEmpty || !canDriveForward)
|
|
return canDriveBackward ? back : null;
|
|
|
|
boolean frontBetter = maxCost == -1 ? -back.distance > front.distance : back.cost > front.cost;
|
|
return frontBetter ? front : back;
|
|
}
|
|
|
|
public class DiscoveredPath {
|
|
List<Couple<TrackNode>> path;
|
|
double distance;
|
|
double cost;
|
|
|
|
public DiscoveredPath(double distance, double cost, List<Couple<TrackNode>> path) {
|
|
this.distance = distance;
|
|
this.cost = cost;
|
|
this.path = path;
|
|
}
|
|
}
|
|
|
|
public GlobalStation findNearestApproachable(boolean forward) {
|
|
TrackGraph graph = train.graph;
|
|
if (graph == null)
|
|
return null;
|
|
|
|
MutableObject<GlobalStation> result = new MutableObject<>(null);
|
|
double acceleration = train.acceleration();
|
|
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, cost, reachedVia, currentEntry, globalStation) -> {
|
|
if (distance < minDistance)
|
|
return false;
|
|
|
|
TrackEdge edge = currentEntry.getSecond();
|
|
double position = edge.getLength() - globalStation.getLocationOn(edge);
|
|
if (distance - position < minDistance)
|
|
return false;
|
|
Train presentTrain = globalStation.getPresentTrain();
|
|
if (presentTrain != null && presentTrain != train)
|
|
return false;
|
|
result.setValue(globalStation);
|
|
return true;
|
|
});
|
|
|
|
return result.getValue();
|
|
}
|
|
|
|
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;
|
|
|
|
// Cache the list of track types that the train can travel on
|
|
Set<TrackMaterial.TrackType> validTypes = new HashSet<>();
|
|
for (int i = 0; i < train.carriages.size(); i++) {
|
|
Carriage carriage = train.carriages.get(i);
|
|
if (i == 0) {
|
|
validTypes.addAll(carriage.leadingBogey().type.getValidPathfindingTypes(carriage.leadingBogey().getStyle()));
|
|
} else {
|
|
validTypes.retainAll(carriage.leadingBogey().type.getValidPathfindingTypes(carriage.leadingBogey().getStyle()));
|
|
}
|
|
if (carriage.isOnTwoBogeys())
|
|
validTypes.retainAll(carriage.trailingBogey().type.getValidPathfindingTypes(carriage.trailingBogey().getStyle()));
|
|
}
|
|
if (validTypes.isEmpty()) // if there are no valid track types, a route can't be found
|
|
return;
|
|
|
|
Map<TrackEdge, Integer> penalties = new IdentityHashMap<>();
|
|
boolean costRelevant = maxCost >= 0;
|
|
if (costRelevant) {
|
|
for (Train otherTrain : Create.RAILWAYS.trains.values()) {
|
|
if (otherTrain.graph != graph)
|
|
continue;
|
|
if (otherTrain == train)
|
|
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)
|
|
.getTrailingPoint();
|
|
|
|
Set<TrackEdge> visited = new HashSet<>();
|
|
Map<TrackEdge, Pair<Boolean, Couple<TrackNode>>> reachedVia = new IdentityHashMap<>();
|
|
PriorityQueue<FrontierEntry> frontier = new PriorityQueue<>();
|
|
|
|
TrackNode initialNode1 = forward ? startingPoint.node1 : startingPoint.node2;
|
|
TrackNode initialNode2 = forward ? startingPoint.node2 : startingPoint.node1;
|
|
TrackEdge initialEdge = graph.getConnectionsFrom(initialNode1)
|
|
.get(initialNode2);
|
|
if (initialEdge == null)
|
|
return;
|
|
|
|
double distanceToNode2 = forward ? initialEdge.getLength() - startingPoint.position : startingPoint.position;
|
|
|
|
frontier.add(new FrontierEntry(distanceToNode2, 0, initialNode1, initialNode2, initialEdge));
|
|
int signalWeight = Mth.clamp(ticksWaitingForSignal * 2, Train.Penalties.RED_SIGNAL, 200);
|
|
|
|
Search: while (!frontier.isEmpty()) {
|
|
FrontierEntry entry = frontier.poll();
|
|
if (!visited.add(entry.edge))
|
|
continue;
|
|
|
|
double distance = entry.distance;
|
|
int penalty = entry.penalty;
|
|
|
|
if (distance > maxDistance)
|
|
continue;
|
|
|
|
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()) {
|
|
for (TrackEdgePoint point : signalData.getPoints()) {
|
|
if (node1 == initialNode1 && point.getLocationOn(edge) < edge.getLength() - distanceToNode2)
|
|
continue;
|
|
if (costRelevant && distance + penalty > maxCost)
|
|
continue Search;
|
|
if (!point.canNavigateVia(node2))
|
|
continue Search;
|
|
if (point instanceof SignalBoundary signal) {
|
|
if (signal.isForcedRed(node2)) {
|
|
penalty += Train.Penalties.REDSTONE_RED_SIGNAL;
|
|
continue;
|
|
}
|
|
UUID group = signal.getGroup(node2);
|
|
if (group == null)
|
|
continue;
|
|
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(group);
|
|
if (signalEdgeGroup == null)
|
|
continue;
|
|
if (signalEdgeGroup.isOccupiedUnless(signal)) {
|
|
penalty += signalWeight;
|
|
signalWeight /= 2;
|
|
}
|
|
}
|
|
if (point instanceof GlobalStation station) {
|
|
Train presentTrain = station.getPresentTrain();
|
|
boolean isOwnStation = presentTrain == train;
|
|
if (presentTrain != null && !isOwnStation)
|
|
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;
|
|
if (!isOwnStation)
|
|
penalty += Train.Penalties.STATION;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (costRelevant && distance + penalty > maxCost)
|
|
continue;
|
|
|
|
List<Entry<TrackNode, TrackEdge>> validTargets = new ArrayList<>();
|
|
Map<TrackNode, TrackEdge> connectionsFrom = graph.getConnectionsFrom(node2);
|
|
for (Entry<TrackNode, TrackEdge> connection : connectionsFrom.entrySet()) {
|
|
TrackNode newNode = connection.getKey();
|
|
if (newNode == node1)
|
|
continue;
|
|
if (edge.canTravelTo(connection.getValue()))
|
|
validTargets.add(connection);
|
|
}
|
|
|
|
if (validTargets.isEmpty())
|
|
continue;
|
|
|
|
for (Entry<TrackNode, TrackEdge> target : validTargets) {
|
|
if (!validTypes.contains(target.getValue().getTrackMaterial().trackType))
|
|
continue;
|
|
TrackNode newNode = target.getKey();
|
|
TrackEdge newEdge = target.getValue();
|
|
double newDistance = newEdge.getLength() + distance;
|
|
int newPenalty = penalty;
|
|
reachedVia.putIfAbsent(newEdge, Pair.of(validTargets.size() > 1, Couple.create(node1, node2)));
|
|
frontier.add(new FrontierEntry(newDistance, newPenalty, node2, newNode, newEdge));
|
|
}
|
|
}
|
|
}
|
|
|
|
private class FrontierEntry implements Comparable<FrontierEntry> {
|
|
|
|
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, double cost, Map<TrackEdge, Pair<Boolean, Couple<TrackNode>>> reachedVia,
|
|
Pair<Couple<TrackNode>, TrackEdge> current, GlobalStation station);
|
|
}
|
|
|
|
public CompoundTag write(DimensionPalette dimensions) {
|
|
CompoundTag tag = new CompoundTag();
|
|
if (destination == null)
|
|
return tag;
|
|
tag.putUUID("Destination", destination.id);
|
|
tag.putDouble("DistanceToDestination", distanceToDestination);
|
|
tag.putDouble("DistanceStartedAt", distanceStartedAt);
|
|
tag.putBoolean("BehindTrain", destinationBehindTrain);
|
|
tag.putBoolean("AnnounceArrival", announceArrival);
|
|
tag.put("Path", NBTHelper.writeCompoundList(currentPath, c -> {
|
|
CompoundTag nbt = new CompoundTag();
|
|
nbt.put("Nodes", c.map(TrackNode::getLocation)
|
|
.serializeEach(loc -> loc.write(dimensions)));
|
|
return nbt;
|
|
}));
|
|
if (waitingForSignal == null)
|
|
return tag;
|
|
tag.putUUID("BlockingSignal", waitingForSignal.getFirst());
|
|
tag.putBoolean("BlockingSignalSide", waitingForSignal.getSecond());
|
|
tag.putDouble("DistanceToSignal", distanceToSignal);
|
|
tag.putInt("TicksWaitingForSignal", ticksWaitingForSignal);
|
|
return tag;
|
|
}
|
|
|
|
public void read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) {
|
|
destination = graph != null && tag.contains("Destination")
|
|
? graph.getPoint(EdgePointType.STATION, tag.getUUID("Destination"))
|
|
: null;
|
|
|
|
if (destination == null)
|
|
return;
|
|
|
|
distanceToDestination = tag.getDouble("DistanceToDestination");
|
|
distanceStartedAt = tag.getDouble("DistanceStartedAt");
|
|
destinationBehindTrain = tag.getBoolean("BehindTrain");
|
|
announceArrival = tag.getBoolean("AnnounceArrival");
|
|
currentPath.clear();
|
|
NBTHelper.iterateCompoundList(tag.getList("Path", Tag.TAG_COMPOUND),
|
|
c -> currentPath.add(Couple
|
|
.deserializeEach(c.getList("Nodes", Tag.TAG_COMPOUND), c2 -> TrackNodeLocation.read(c2, dimensions))
|
|
.map(graph::locateNode)));
|
|
waitingForSignal = tag.contains("BlockingSignal")
|
|
? Pair.of(tag.getUUID("BlockingSignal"), tag.getBoolean("BlockingSignalSide"))
|
|
: null;
|
|
if (waitingForSignal == null)
|
|
return;
|
|
distanceToSignal = tag.getDouble("DistanceToSignal");
|
|
ticksWaitingForSignal = tag.getInt("TicksWaitingForSignal");
|
|
}
|
|
|
|
}
|