CreateMod/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java
simibubi e5c6ca157c Squashed commit of the following:
commit 053dd09df6c426ab5e570f42a1edb5df3d0fbd01
Merge: 6d1e1c71d ecc645eba
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

commit ecc645eba7
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

commit 205e47352e
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Mon May 8 21:02:19 2023 -0700

    Fix up ItemOutline

commit 6cf204f6af
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

commit fe049bc771
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Mon May 8 20:26:16 2023 -0700

    Revert "Revert "Rewrite outline buffering""

    This reverts commit 726bfaf0

commit 435b4c1c16
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

commit 662da6bab1
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

commit 122fe77afa
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Mon May 8 20:15:46 2023 -0700

    Fix up upside down rendering

commit d83285e8a4
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

commit cdb0ad210b
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun May 7 10:15:47 2023 +0100

    Fixed merge artifact

commit 457d5f33ed
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

commit 00e953a585
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

commit a7a25896c1
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

commit 4e4e227a35
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun May 7 10:10:30 2023 +0100

    Cleanup to cycle groups

commit aa94fc97d1
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun May 7 09:50:50 2023 +0100

    Removed unused import of Railways

commit 7622128bec
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

commit 1e4d5504ee
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sat May 6 18:03:39 2023 -0700

    Don't revert non-buggy changes

commit b306cf2124
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sat May 6 18:00:59 2023 -0700

    Take materials into consideration when trains pathfind

commit fca02ae4bf
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sat May 6 10:25:51 2023 -0700

    Add materials to track graph

commit 726bfaf0b5
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Fri May 5 21:16:49 2023 -0700

    Revert "Rewrite outline buffering"

    This reverts commit d4106d545b.

commit 171897bed2
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Fri May 5 20:55:25 2023 -0700

    Fix up style cycling

commit cbd0cf20da
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Fri May 5 07:32:06 2023 -0700

    clean up nether portal carriage handling

commit d556f08876
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

commit da26c0ccbf
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

commit 81eeadb853
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon May 1 16:15:28 2023 +0100

    Small cleanup

commit c7e9df973c
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon May 1 16:13:51 2023 +0100

    Fixed issue raised in #1

commit 2f285b6eb7
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Mon May 1 08:13:27 2023 -0700

    add data gen

commit 206de01311
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

commit 6564f4fa73
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

commit e5d7595822
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon May 1 10:09:03 2023 +0100

    Connected Custom Bogey Particle Types To CarriageParticles

commit e91753a33c
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sun Apr 30 19:51:26 2023 -0700

    Fix up some problems

commit 9815f1490f
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 21:12:43 2023 +0100

    Implemented default data when shifting styles

commit da30e78815
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 21:12:14 2023 +0100

    Added Particles To Bogey Style (And Respective Builder)

commit 08c000b8ba
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 21:01:19 2023 +0100

    Added Backup Rendering If A Size Is Not Present

commit 2b76e8d7b3
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 21:00:40 2023 +0100

    Added Common Renderer To Remove Function

commit 411ec36f57
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:59:50 2023 +0100

    Added Display Name To Standard Bogey Style

commit 112306d5d4
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:59:30 2023 +0100

    Displayed new style name when changing betweeen them

commit 5634670b27
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:06:00 2023 +0100

    General Cleanup

commit 0f7a8b7b24
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:05:50 2023 +0100

    Implemented Changes To Remaining Classes

commit 8aedc00f96
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:02:06 2023 +0100

    Removed Bogey Style Handling From Registrate

commit edf8079abf
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:01:40 2023 +0100

    Removed Unused Registry Handling

commit 6a185c4e72
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:01:16 2023 +0100

    Refactored Bogey Sizes

commit e10d07ddc3
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:01:00 2023 +0100

    Overhauled Bogey Style

commit 74d98a2ad5
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

commit e629d02f50
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sun Apr 9 07:18:22 2023 -0700

    Track API

    Clean up code a bit

commit d9ce6ce995
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sun Apr 9 07:14:46 2023 -0700

    Track API?

    Fix placement

commit 7fbf08ba54
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sat Apr 8 11:11:24 2023 -0700

    Track API?

    Fix up some placement issues

commit 35644f1434
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

commit f7c56b867a
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

commit 2a59fd7e8a
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

commit 5ba30d6a85
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

commit d52065808c
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

commit 53240bd42f
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 21:42:29 2023 +0100

    Corrected Bogey InteractionResult To Pass

commit 69326e361a
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 21:30:28 2023 +0100

    Fixed Default Values When Used Styles Are Removed

commit 4f176979de
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 19:33:17 2023 +0100

    Fixed Carriage Sounds (Again)

commit 1e80af3303
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 19:27:58 2023 +0100

    Refactored Bogey Sizes To Seperate Class

commit 129be61fee
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 17:20:17 2023 +0100

    Fixed Bogey Sound Loading

commit 2543185a55
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 09:45:23 2023 +0100

    Added Bogey Sound Customisation

commit 1ad5ae9514
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

commit 96566b1614
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

commit eedd984738
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 2 16:53:55 2023 +0100

    Fixed Large Bogey Size

commit 68ca0974c6
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 2 16:47:58 2023 +0100

    Implemented Style Cycling & Default Values

commit a55ba4267a
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 2 16:46:15 2023 +0100

    Implemented renderer instance creator

commit 43523302c2
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 2 16:45:33 2023 +0100

    Removed Unused Standard Bogey Instance

commit 773e084422
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

commit 0c0b5a1ed6
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sat Apr 1 18:39:58 2023 +0100

    Linked Style Registry To Bogey Blocks

commit 71f839ee51
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sat Apr 1 18:39:03 2023 +0100

    Replaced size boolean with direct use of size enum

commit 50ff081704
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 30 18:47:13 2023 +0100

    Added Resource Location To NBT helper methods

commit d1e1f7ec5a
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 30 18:47:13 2023 +0100

    Re-worked BogeyStyles

commit da593fccb1
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 30 18:46:02 2023 +0100

    Refactored IBogeyBlock to AbstractBogeyBlock and extracted relevant StandardBogeyBlock implementations

commit 17432c9113
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sat Mar 25 10:20:50 2023 +0000

    Fixed Incorrect Registry Loading

commit c7d899369a
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:44:03 2023 +0000

    Registered Registers

commit 6d862290d7
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:43:23 2023 +0000

    Added BogeyStyleBuilder To Registrate

commit 3dfb9e3b3b
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:43:08 2023 +0000

    Implemented AllBogeyStyles

commit c9e71b462d
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:42:56 2023 +0000

    Created BogeyStyleBuilder

commit a90977d642
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:42:25 2023 +0000

    Created AllRegistries and BogeyStyle Registry

commit 154d455f3f
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:41:56 2023 +0000

    Added BogeyStyle Wrapper

commit dfb7640bfc
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 18:50:41 2023 +0000

    Removed left over logging statement

commit 9920536cc3
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 18:50:18 2023 +0000

    Implemented Secondary Shaft To Large Renderer

commit 6cd40cc6f9
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

commit 06fb901144
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 18:39:11 2023 +0000

    Implemented Common Rendering For StandardBogeyRenderer

commit 435b0f8266
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 18:38:40 2023 +0000

    Added Common Renderer

commit 96a0623dab
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 18:38:29 2023 +0000

    Implemented BlockState Models For Rendering

commit 469d9d592b
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 17:42:28 2023 +0000

    Added Standard Bogey Instance (Might be redundant)

commit 2661d260d8
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 17:42:06 2023 +0000

    Refactored Changes To Existing Methods

commit 9ded16fbab
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 17:41:15 2023 +0000

    Integrated BogeyRenderer To BogeyInstance (Also Corrected Rendering In Contraption)

commit 4a82fcbca1
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 17:40:13 2023 +0000

    Implemented Changes To StandardBogeyBlock

commit 7238fb93f3
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 17:39:51 2023 +0000

    Added Renderer To IBogeyBlock

commit ded4c1f613
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

commit 91727cc84a
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Wed Mar 22 17:03:28 2023 +0000

    Implemented Model Data Initializer to StandardBogeyRenderer

commit 6d98a1f469
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Wed Mar 22 17:03:00 2023 +0000

    Added Contraption Model Instance Initializer

commit 3c02fe6ecc
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com>
Date:   Tue Mar 21 22:45:34 2023 +0000

    Added missing render type check

commit 6672c49649
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Tue Mar 21 22:37:36 2023 +0000

    Re-created standard bogey with test api

commit a8a9491fa0
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Tue Mar 21 22:34:54 2023 +0000

    Implemented Proof Of Concept Generic Bogey Renderer

commit e4e5ac1c40
Author: SpottyTheTurtle <69260662+SpottyTheTurtle@users.noreply.github.com>
Date:   Sat Mar 11 21:34:59 2023 +0000

    init
2023-05-09 18:23:47 +02:00

605 lines
19 KiB
Java

package com.simibubi.create.content.logistics.trains;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointManager;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointStorage;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackEdgeIntersection;
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.foundation.utility.Color;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.phys.Vec3;
public class TrackGraph {
public static final AtomicInteger graphNetIdGenerator = new AtomicInteger();
public static final AtomicInteger nodeNetIdGenerator = new AtomicInteger();
public UUID id;
public Color color;
Map<TrackNodeLocation, TrackNode> nodes;
Map<Integer, TrackNode> nodesById;
Map<TrackNode, Map<TrackNode, TrackEdge>> connectionsByNode;
EdgePointStorage edgePoints;
Map<ResourceKey<Level>, TrackGraphBounds> bounds;
List<TrackEdge> deferredIntersectionUpdates;
int netId;
int checksum = 0;
public TrackGraph() {
this(UUID.randomUUID());
}
public TrackGraph(UUID graphID) {
setId(graphID);
nodes = new HashMap<>();
nodesById = new HashMap<>();
bounds = new HashMap<>();
connectionsByNode = new IdentityHashMap<>();
edgePoints = new EdgePointStorage();
deferredIntersectionUpdates = new ArrayList<>();
netId = nextGraphId();
}
//
public <T extends TrackEdgePoint> void addPoint(EdgePointType<T> type, T point) {
edgePoints.put(type, point);
EdgePointManager.onEdgePointAdded(this, point, type);
Create.RAILWAYS.sync.pointAdded(this, point);
markDirty();
}
public <T extends TrackEdgePoint> T getPoint(EdgePointType<T> type, UUID id) {
return edgePoints.get(type, id);
}
public <T extends TrackEdgePoint> Collection<T> getPoints(EdgePointType<T> type) {
return edgePoints.values(type);
}
public <T extends TrackEdgePoint> T removePoint(EdgePointType<T> type, UUID id) {
T removed = edgePoints.remove(type, id);
if (removed == null)
return null;
EdgePointManager.onEdgePointRemoved(this, removed, type);
Create.RAILWAYS.sync.pointRemoved(this, removed);
markDirty();
return removed;
}
public void tickPoints(boolean preTrains) {
edgePoints.tick(this, preTrains);
}
//
public TrackGraphBounds getBounds(Level level) {
return bounds.computeIfAbsent(level.dimension(), dim -> new TrackGraphBounds(this, dim));
}
public void invalidateBounds() {
checksum = 0;
bounds.clear();
}
//
public Set<TrackNodeLocation> getNodes() {
return nodes.keySet();
}
public TrackNode locateNode(Level level, Vec3 position) {
return locateNode(new TrackNodeLocation(position).in(level));
}
public TrackNode locateNode(TrackNodeLocation position) {
return nodes.get(position);
}
public TrackNode getNode(int netId) {
return nodesById.get(netId);
}
public boolean createNodeIfAbsent(DiscoveredLocation location) {
if (!addNodeIfAbsent(new TrackNode(location, nextNodeId(), location.normal)))
return false;
TrackNode newNode = nodes.get(location);
Create.RAILWAYS.sync.nodeAdded(this, newNode);
invalidateBounds();
markDirty();
return true;
}
public void loadNode(TrackNodeLocation location, int netId, Vec3 normal) {
addNode(new TrackNode(location, netId, normal));
}
public void addNode(TrackNode node) {
TrackNodeLocation location = node.getLocation();
if (nodes.containsKey(location))
removeNode(null, location);
nodes.put(location, node);
nodesById.put(node.getNetId(), node);
}
public boolean addNodeIfAbsent(TrackNode node) {
if (nodes.putIfAbsent(node.getLocation(), node) != null)
return false;
nodesById.put(node.getNetId(), node);
return true;
}
public boolean removeNode(@Nullable LevelAccessor level, TrackNodeLocation location) {
TrackNode removed = nodes.remove(location);
if (removed == null)
return false;
Map<UUID, Train> trains = Create.RAILWAYS.trains;
for (Iterator<UUID> iterator = trains.keySet()
.iterator(); iterator.hasNext();) {
UUID uuid = iterator.next();
Train train = trains.get(uuid);
if (train.graph != this)
continue;
if (train.isTravellingOn(removed))
train.detachFromTracks();
}
nodesById.remove(removed.netId);
invalidateBounds();
if (!connectionsByNode.containsKey(removed))
return true;
Map<TrackNode, TrackEdge> connections = connectionsByNode.remove(removed);
for (Entry<TrackNode, TrackEdge> entry : connections.entrySet()) {
TrackEdge trackEdge = entry.getValue();
EdgeData edgeData = trackEdge.getEdgeData();
for (TrackEdgePoint point : edgeData.getPoints()) {
if (level != null)
point.invalidate(level);
edgePoints.remove(point.getType(), point.getId());
}
if (level != null) {
TrackNode otherNode = entry.getKey();
for (TrackEdgeIntersection intersection : edgeData.getIntersections()) {
Couple<TrackNodeLocation> target = intersection.target;
TrackGraph graph = Create.RAILWAYS.getGraph(level, target.getFirst());
if (graph != null)
graph.removeIntersection(intersection, removed, otherNode);
}
}
}
for (TrackNode railNode : connections.keySet())
if (connectionsByNode.containsKey(railNode))
connectionsByNode.get(railNode)
.remove(removed);
return true;
}
private void removeIntersection(TrackEdgeIntersection intersection, TrackNode targetNode1, TrackNode targetNode2) {
TrackNode node1 = locateNode(intersection.target.getFirst());
TrackNode node2 = locateNode(intersection.target.getSecond());
if (node1 == null || node2 == null)
return;
Map<TrackNode, TrackEdge> from1 = getConnectionsFrom(node1);
if (from1 != null) {
TrackEdge edge = from1.get(node2);
if (edge != null)
edge.getEdgeData()
.removeIntersection(this, intersection.id);
}
Map<TrackNode, TrackEdge> from2 = getConnectionsFrom(node2);
if (from2 != null) {
TrackEdge edge = from2.get(node1);
if (edge != null)
edge.getEdgeData()
.removeIntersection(this, intersection.id);
}
}
public static int nextNodeId() {
return nodeNetIdGenerator.incrementAndGet();
}
public static int nextGraphId() {
return graphNetIdGenerator.incrementAndGet();
}
public void transferAll(TrackGraph toOther) {
nodes.forEach((loc, node) -> {
if (toOther.addNodeIfAbsent(node))
Create.RAILWAYS.sync.nodeAdded(toOther, node);
});
connectionsByNode.forEach((node1, map) -> map.forEach((node2, edge) -> {
TrackNode n1 = toOther.locateNode(node1.location);
TrackNode n2 = toOther.locateNode(node2.location);
if (n1 == null || n2 == null)
return;
if (toOther.putConnection(n1, n2, edge)) {
Create.RAILWAYS.sync.edgeAdded(toOther, n1, n2, edge);
Create.RAILWAYS.sync.edgeDataChanged(toOther, n1, n2, edge);
}
}));
edgePoints.transferAll(toOther, toOther.edgePoints);
nodes.clear();
connectionsByNode.clear();
toOther.invalidateBounds();
Map<UUID, Train> trains = Create.RAILWAYS.trains;
for (Iterator<UUID> iterator = trains.keySet()
.iterator(); iterator.hasNext();) {
UUID uuid = iterator.next();
Train train = trains.get(uuid);
if (train.graph != this)
continue;
train.graph = toOther;
}
}
public Set<TrackGraph> findDisconnectedGraphs(@Nullable LevelAccessor level,
@Nullable Map<Integer, Pair<Integer, UUID>> splitSubGraphs) {
Set<TrackGraph> dicovered = new HashSet<>();
Set<TrackNodeLocation> vertices = new HashSet<>(nodes.keySet());
List<TrackNodeLocation> frontier = new ArrayList<>();
TrackGraph target = null;
while (!vertices.isEmpty()) {
if (target != null)
dicovered.add(target);
TrackNodeLocation start = vertices.stream()
.findFirst()
.get();
frontier.add(start);
vertices.remove(start);
while (!frontier.isEmpty()) {
TrackNodeLocation current = frontier.remove(0);
TrackNode currentNode = locateNode(current);
Map<TrackNode, TrackEdge> connections = getConnectionsFrom(currentNode);
for (TrackNode connected : connections.keySet())
if (vertices.remove(connected.getLocation()))
frontier.add(connected.getLocation());
if (target != null) {
if (splitSubGraphs != null && splitSubGraphs.containsKey(currentNode.getNetId())) {
Pair<Integer, UUID> ids = splitSubGraphs.get(currentNode.getNetId());
target.setId(ids.getSecond());
target.netId = ids.getFirst();
}
transfer(level, currentNode, target);
}
}
frontier.clear();
target = new TrackGraph();
}
return dicovered;
}
public void setId(UUID id) {
this.id = id;
color = Color.rainbowColor(new Random(id.getLeastSignificantBits()).nextInt());
}
public void setNetId(int id) {
this.netId = id;
}
public int getChecksum() {
if (checksum == 0)
checksum = nodes.values()
.stream()
.collect(Collectors.summingInt(TrackNode::getNetId));
return checksum;
}
public void transfer(LevelAccessor level, TrackNode node, TrackGraph target) {
target.addNode(node);
target.invalidateBounds();
TrackNodeLocation nodeLoc = node.getLocation();
Map<TrackNode, TrackEdge> connections = getConnectionsFrom(node);
Map<UUID, Train> trains = Create.RAILWAYS.sided(level).trains;
if (!connections.isEmpty()) {
target.connectionsByNode.put(node, connections);
for (TrackEdge entry : connections.values()) {
EdgeData edgeData = entry.getEdgeData();
for (TrackEdgePoint trackEdgePoint : edgeData.getPoints()) {
target.edgePoints.put(trackEdgePoint.getType(), trackEdgePoint);
edgePoints.remove(trackEdgePoint.getType(), trackEdgePoint.getId());
}
}
}
if (level != null)
for (Iterator<UUID> iterator = trains.keySet()
.iterator(); iterator.hasNext();) {
UUID uuid = iterator.next();
Train train = trains.get(uuid);
if (train.graph != this)
continue;
if (!train.isTravellingOn(node))
continue;
train.graph = target;
}
nodes.remove(nodeLoc);
nodesById.remove(node.getNetId());
connectionsByNode.remove(node);
invalidateBounds();
}
public boolean isEmpty() {
return nodes.isEmpty();
}
public Map<TrackNode, TrackEdge> getConnectionsFrom(TrackNode node) {
if (node == null)
return null;
return connectionsByNode.getOrDefault(node, new HashMap<>());
}
public TrackEdge getConnection(Couple<TrackNode> nodes) {
Map<TrackNode, TrackEdge> connectionsFrom = getConnectionsFrom(nodes.getFirst());
if (connectionsFrom == null)
return null;
return connectionsFrom.get(nodes.getSecond());
}
public void connectNodes(LevelAccessor reader, DiscoveredLocation location, DiscoveredLocation location2,
@Nullable BezierConnection turn) {
TrackNode node1 = nodes.get(location);
TrackNode node2 = nodes.get(location2);
boolean bezier = turn != null;
TrackMaterial material = bezier ? turn.getMaterial() : location2.materialA;
TrackEdge edge = new TrackEdge(node1, node2, turn, material);
TrackEdge edge2 = new TrackEdge(node2, node1, bezier ? turn.secondary() : null, material);
for (TrackGraph graph : Create.RAILWAYS.trackNetworks.values()) {
for (TrackNode otherNode1 : graph.nodes.values()) {
Map<TrackNode, TrackEdge> connections = graph.connectionsByNode.get(otherNode1);
if (connections == null)
continue;
for (Entry<TrackNode, TrackEdge> entry : connections.entrySet()) {
TrackNode otherNode2 = entry.getKey();
TrackEdge otherEdge = entry.getValue();
if (graph == this)
if (otherNode1 == node1 || otherNode2 == node1 || otherNode1 == node2 || otherNode2 == node2)
continue;
if (edge == otherEdge)
continue;
if (!bezier && !otherEdge.isTurn())
continue;
if (otherEdge.isTurn() && otherEdge.turn.isPrimary())
continue;
Collection<double[]> intersections =
edge.getIntersection(node1, node2, otherEdge, otherNode1, otherNode2);
UUID id = UUID.randomUUID();
for (double[] intersection : intersections) {
double s = intersection[0];
double t = intersection[1];
edge.edgeData.addIntersection(this, id, s, otherNode1, otherNode2, t);
edge2.edgeData.addIntersection(this, id, edge.getLength() - s, otherNode1, otherNode2, t);
otherEdge.edgeData.addIntersection(graph, id, t, node1, node2, s);
TrackEdge otherEdge2 = graph.getConnection(Couple.create(otherNode2, otherNode1));
if (otherEdge2 != null)
otherEdge2.edgeData.addIntersection(graph, id, otherEdge.getLength() - t, node1, node2, s);
}
}
}
}
putConnection(node1, node2, edge);
putConnection(node2, node1, edge2);
Create.RAILWAYS.sync.edgeAdded(this, node1, node2, edge);
Create.RAILWAYS.sync.edgeAdded(this, node2, node1, edge2);
markDirty();
}
public void disconnectNodes(TrackNode node1, TrackNode node2) {
Map<TrackNode, TrackEdge> map1 = connectionsByNode.get(node1);
Map<TrackNode, TrackEdge> map2 = connectionsByNode.get(node2);
if (map1 != null)
map1.remove(node2);
if (map2 != null)
map2.remove(node1);
}
public boolean putConnection(TrackNode node1, TrackNode node2, TrackEdge edge) {
Map<TrackNode, TrackEdge> connections = connectionsByNode.computeIfAbsent(node1, n -> new IdentityHashMap<>());
if (connections.containsKey(node2) && connections.get(node2)
.getEdgeData()
.hasPoints())
return false;
return connections.put(node2, edge) == null;
}
public float distanceToLocationSqr(Level level, Vec3 location) {
float nearest = Float.MAX_VALUE;
for (TrackNodeLocation tnl : nodes.keySet()) {
if (!Objects.equals(tnl.dimension, level.dimension()))
continue;
nearest = Math.min(nearest, (float) tnl.getLocation()
.distanceToSqr(location));
}
return nearest;
}
public void deferIntersectionUpdate(TrackEdge edge) {
deferredIntersectionUpdates.add(edge);
}
public void resolveIntersectingEdgeGroups(Level level) {
for (TrackEdge edge : deferredIntersectionUpdates) {
if (!connectionsByNode.containsKey(edge.node1) || edge != connectionsByNode.get(edge.node1)
.get(edge.node2))
continue;
EdgeData edgeData = edge.getEdgeData();
for (TrackEdgeIntersection intersection : edgeData.getIntersections()) {
UUID groupId = edgeData.getGroupAtPosition(this, intersection.location);
Couple<TrackNodeLocation> target = intersection.target;
TrackGraph graph = Create.RAILWAYS.getGraph(level, target.getFirst());
if (graph == null)
continue;
TrackNode node1 = graph.locateNode(target.getFirst());
TrackNode node2 = graph.locateNode(target.getSecond());
Map<TrackNode, TrackEdge> connectionsFrom = graph.getConnectionsFrom(node1);
if (connectionsFrom == null)
continue;
TrackEdge otherEdge = connectionsFrom.get(node2);
if (otherEdge == null)
continue;
UUID otherGroupId = otherEdge.getEdgeData()
.getGroupAtPosition(graph, intersection.targetLocation);
SignalEdgeGroup group = Create.RAILWAYS.signalEdgeGroups.get(groupId);
SignalEdgeGroup otherGroup = Create.RAILWAYS.signalEdgeGroups.get(otherGroupId);
if (group == null || otherGroup == null)
continue;
intersection.groupId = groupId;
group.putIntersection(intersection.id, otherGroupId);
otherGroup.putIntersection(intersection.id, groupId);
}
}
deferredIntersectionUpdates.clear();
}
public void markDirty() {
Create.RAILWAYS.markTracksDirty();
}
public CompoundTag write(DimensionPalette dimensions) {
CompoundTag tag = new CompoundTag();
tag.putUUID("Id", id);
tag.putInt("Color", color.getRGB());
Map<TrackNode, Integer> indexTracker = new HashMap<>();
ListTag nodesList = new ListTag();
int i = 0;
for (TrackNode railNode : nodes.values()) {
indexTracker.put(railNode, i);
CompoundTag nodeTag = new CompoundTag();
nodeTag.put("Location", railNode.getLocation()
.write(dimensions));
nodeTag.put("Normal", VecHelper.writeNBT(railNode.getNormal()));
nodesList.add(nodeTag);
i++;
}
connectionsByNode.forEach((node1, map) -> {
Integer index1 = indexTracker.get(node1);
if (index1 == null)
return;
CompoundTag nodeTag = (CompoundTag) nodesList.get(index1);
ListTag connectionsList = new ListTag();
map.forEach((node2, edge) -> {
CompoundTag connectionTag = new CompoundTag();
Integer index2 = indexTracker.get(node2);
if (index2 == null)
return;
connectionTag.putInt("To", index2);
connectionTag.put("EdgeData", edge.write(dimensions));
connectionsList.add(connectionTag);
});
nodeTag.put("Connections", connectionsList);
});
tag.put("Nodes", nodesList);
tag.put("Points", edgePoints.write(dimensions));
return tag;
}
public static TrackGraph read(CompoundTag tag, DimensionPalette dimensions) {
TrackGraph graph = new TrackGraph(tag.getUUID("Id"));
graph.color = new Color(tag.getInt("Color"));
graph.edgePoints.read(tag.getCompound("Points"), dimensions);
Map<Integer, TrackNode> indexTracker = new HashMap<>();
ListTag nodesList = tag.getList("Nodes", Tag.TAG_COMPOUND);
int i = 0;
for (Tag t : nodesList) {
CompoundTag nodeTag = (CompoundTag) t;
TrackNodeLocation location = TrackNodeLocation.read(nodeTag.getCompound("Location"), dimensions);
Vec3 normal = VecHelper.readNBT(nodeTag.getList("Normal", Tag.TAG_DOUBLE));
graph.loadNode(location, nextNodeId(), normal);
indexTracker.put(i, graph.locateNode(location));
i++;
}
i = 0;
for (Tag t : nodesList) {
CompoundTag nodeTag = (CompoundTag) t;
TrackNode node1 = indexTracker.get(i);
i++;
if (!nodeTag.contains("Connections"))
continue;
NBTHelper.iterateCompoundList(nodeTag.getList("Connections", Tag.TAG_COMPOUND), c -> {
TrackNode node2 = indexTracker.get(c.getInt("To"));
TrackEdge edge = TrackEdge.read(node1, node2, c.getCompound("EdgeData"), graph, dimensions);
graph.putConnection(node1, node2, edge);
});
}
return graph;
}
}